mirror of
				https://github.com/redmine/redmine.git
				synced 2025-11-03 20:06:24 +01:00 
			
		
		
		
	Adds configuration settings to limit valid repository path (#1415).
git-svn-id: http://svn.redmine.org/redmine/trunk@13573 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
		@@ -152,7 +152,7 @@ module RepositoriesHelper
 | 
			
		||||
  def subversion_field_tags(form, repository)
 | 
			
		||||
      content_tag('p', form.text_field(:url, :size => 60, :required => true,
 | 
			
		||||
                       :disabled => !repository.safe_attribute?('url')) +
 | 
			
		||||
                       content_tag('em', '(file:///, http://, https://, svn://, svn+[tunnelscheme]://)', :class => 'info')) +
 | 
			
		||||
                       scm_path_info_tag(repository)) +
 | 
			
		||||
      content_tag('p', form.text_field(:login, :size => 30)) +
 | 
			
		||||
      content_tag('p', form.password_field(
 | 
			
		||||
                            :password, :size => 30, :name => 'ignore',
 | 
			
		||||
@@ -165,7 +165,8 @@ module RepositoriesHelper
 | 
			
		||||
    content_tag('p', form.text_field(
 | 
			
		||||
                     :url, :label => l(:field_path_to_repository),
 | 
			
		||||
                     :size => 60, :required => true,
 | 
			
		||||
                     :disabled => !repository.safe_attribute?('url'))) +
 | 
			
		||||
                     :disabled => !repository.safe_attribute?('url')) +
 | 
			
		||||
                     scm_path_info_tag(repository)) +
 | 
			
		||||
    scm_log_encoding_tag(form, repository)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
@@ -175,7 +176,7 @@ module RepositoriesHelper
 | 
			
		||||
                       :size => 60, :required => true,
 | 
			
		||||
                       :disabled => !repository.safe_attribute?('url')
 | 
			
		||||
                         ) +
 | 
			
		||||
                     content_tag('em', l(:text_mercurial_repository_note), :class => 'info')) +
 | 
			
		||||
                     scm_path_info_tag(repository)) +
 | 
			
		||||
    scm_path_encoding_tag(form, repository)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
@@ -185,7 +186,7 @@ module RepositoriesHelper
 | 
			
		||||
                       :size => 60, :required => true,
 | 
			
		||||
                       :disabled => !repository.safe_attribute?('url')
 | 
			
		||||
                         ) +
 | 
			
		||||
                      content_tag('em', l(:text_git_repository_note), :class => 'info')) +
 | 
			
		||||
                      scm_path_info_tag(repository)) +
 | 
			
		||||
    scm_path_encoding_tag(form, repository) +
 | 
			
		||||
    content_tag('p', form.check_box(
 | 
			
		||||
                        :extra_report_last_commit,
 | 
			
		||||
@@ -198,7 +199,8 @@ module RepositoriesHelper
 | 
			
		||||
                     :root_url,
 | 
			
		||||
                     :label => l(:field_cvsroot),
 | 
			
		||||
                     :size => 60, :required => true,
 | 
			
		||||
                     :disabled => !repository.safe_attribute?('root_url'))) +
 | 
			
		||||
                     :disabled => !repository.safe_attribute?('root_url')) +
 | 
			
		||||
                     scm_path_info_tag(repository)) +
 | 
			
		||||
    content_tag('p', form.text_field(
 | 
			
		||||
                     :url,
 | 
			
		||||
                     :label => l(:field_cvs_module),
 | 
			
		||||
@@ -212,7 +214,8 @@ module RepositoriesHelper
 | 
			
		||||
    content_tag('p', form.text_field(
 | 
			
		||||
                     :url, :label => l(:field_path_to_repository),
 | 
			
		||||
                     :size => 60, :required => true,
 | 
			
		||||
                     :disabled => !repository.safe_attribute?('url'))) +
 | 
			
		||||
                     :disabled => !repository.safe_attribute?('url')) +
 | 
			
		||||
                     scm_path_info_tag(repository)) +
 | 
			
		||||
    scm_log_encoding_tag(form, repository)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
@@ -220,10 +223,29 @@ module RepositoriesHelper
 | 
			
		||||
    content_tag('p', form.text_field(
 | 
			
		||||
                     :url, :label => l(:field_root_directory),
 | 
			
		||||
                     :size => 60, :required => true,
 | 
			
		||||
                     :disabled => !repository.safe_attribute?('url'))) +
 | 
			
		||||
                     :disabled => !repository.safe_attribute?('url')) +
 | 
			
		||||
                     scm_path_info_tag(repository)) +
 | 
			
		||||
    scm_path_encoding_tag(form, repository)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def scm_path_info_tag(repository)
 | 
			
		||||
    text = scm_path_info(repository)
 | 
			
		||||
    if text.present?
 | 
			
		||||
      content_tag('em', text, :class => 'info')
 | 
			
		||||
    else
 | 
			
		||||
      ''
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def scm_path_info(repository)
 | 
			
		||||
    scm_name = repository.scm_name.to_s.downcase
 | 
			
		||||
 | 
			
		||||
    info_from_config = Redmine::Configuration["scm_#{scm_name}_path_info"].presence
 | 
			
		||||
    return info_from_config.html_safe if info_from_config
 | 
			
		||||
 | 
			
		||||
    l("text_#{scm_name}_repository_note", :default => '')
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def scm_log_encoding_tag(form, repository)
 | 
			
		||||
    select = form.select(
 | 
			
		||||
      :log_encoding,
 | 
			
		||||
 
 | 
			
		||||
@@ -45,6 +45,7 @@ class Repository < ActiveRecord::Base
 | 
			
		||||
  validates_format_of :identifier, :with => /\A(?!\d+$)[a-z0-9\-_]*\z/, :allow_blank => true
 | 
			
		||||
  # Checks if the SCM is enabled when creating a repository
 | 
			
		||||
  validate :repo_create_validation, :on => :create
 | 
			
		||||
  validate :validate_repository_path
 | 
			
		||||
  attr_protected :id
 | 
			
		||||
 | 
			
		||||
  safe_attributes 'identifier',
 | 
			
		||||
@@ -458,6 +459,18 @@ class Repository < ActiveRecord::Base
 | 
			
		||||
 | 
			
		||||
  protected
 | 
			
		||||
 | 
			
		||||
  # Validates repository url based against an optional regular expression
 | 
			
		||||
  # that can be set in the Redmine configuration file.
 | 
			
		||||
  def validate_repository_path(attribute=:url)
 | 
			
		||||
    regexp = Redmine::Configuration["scm_#{scm_name.to_s.downcase}_path_regexp"]
 | 
			
		||||
    if changes[attribute] && regexp.present?
 | 
			
		||||
      regexp = regexp.to_s.strip.gsub('%project%') {Regexp.escape(project.try(:identifier).to_s)}
 | 
			
		||||
      unless send(attribute).to_s.match(Regexp.new("\\A#{regexp}\\z"))
 | 
			
		||||
        errors.add(attribute, :invalid)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def check_default
 | 
			
		||||
    if !is_default? && set_as_default?
 | 
			
		||||
      self.is_default = true
 | 
			
		||||
 
 | 
			
		||||
@@ -192,6 +192,14 @@ class Repository::Cvs < Repository
 | 
			
		||||
    @current_revision_number = nil
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  protected
 | 
			
		||||
 | 
			
		||||
  # Overrides Repository#validate_repository_path to validate
 | 
			
		||||
  # against root_url attribute.
 | 
			
		||||
  def validate_repository_path(attribute=:root_url)
 | 
			
		||||
    super(attribute)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  private
 | 
			
		||||
 | 
			
		||||
  # Returns the next revision number to assign to a CVS changeset
 | 
			
		||||
 
 | 
			
		||||
@@ -108,6 +108,33 @@ default:
 | 
			
		||||
  scm_bazaar_command:
 | 
			
		||||
  scm_darcs_command:
 | 
			
		||||
 | 
			
		||||
  # SCM paths validation.
 | 
			
		||||
  #
 | 
			
		||||
  # You can configure a regular expression for each SCM that will be used to
 | 
			
		||||
  # validate the path of new repositories (eg. path entered by users with the
 | 
			
		||||
  # "Manage repositories" permission and path returned by reposman.rb).
 | 
			
		||||
  # The regexp will be wrapped with \A \z, so it must match the whole path.
 | 
			
		||||
  # And the regexp is case sensitive.
 | 
			
		||||
  #
 | 
			
		||||
  # You can match the project identifier by using %project% in the regexp.
 | 
			
		||||
  #
 | 
			
		||||
  # You can also set a custom hint message for each SCM that will be displayed
 | 
			
		||||
  # on the repository form instead of the default one.
 | 
			
		||||
  #
 | 
			
		||||
  # Examples:
 | 
			
		||||
  # scm_subversion_path_regexp: file:///svnpath/[a-z0-9_]+
 | 
			
		||||
  # scm_subversion_path_info: SVN URL (eg. file:///svnpath/foo)
 | 
			
		||||
  #
 | 
			
		||||
  # scm_git_path_regexp: /gitpath/%project%(\.[a-z0-9_])?/
 | 
			
		||||
  #
 | 
			
		||||
  scm_subversion_path_regexp:
 | 
			
		||||
  scm_mercurial_path_regexp:
 | 
			
		||||
  scm_git_path_regexp:
 | 
			
		||||
  scm_cvs_path_regexp:
 | 
			
		||||
  scm_bazaar_path_regexp:
 | 
			
		||||
  scm_darcs_path_regexp:
 | 
			
		||||
  scm_filesystem_path_regexp:
 | 
			
		||||
 | 
			
		||||
  # Absolute path to the SCM commands errors (stderr) log file.
 | 
			
		||||
  # The default is to log in the 'log' directory of your Redmine instance.
 | 
			
		||||
  # Example:
 | 
			
		||||
 
 | 
			
		||||
@@ -1052,6 +1052,7 @@ en:
 | 
			
		||||
  text_zoom_out: Zoom out
 | 
			
		||||
  text_warn_on_leaving_unsaved: "The current page contains unsaved text that will be lost if you leave this page."
 | 
			
		||||
  text_scm_path_encoding_note: "Default: UTF-8"
 | 
			
		||||
  text_subversion_repository_note: "Examples: file:///, http://, https://, svn://, svn+[tunnelscheme]://"
 | 
			
		||||
  text_git_repository_note: Repository is bare and local (e.g. /gitrepo, c:\gitrepo)
 | 
			
		||||
  text_mercurial_repository_note: Local repository (e.g. /hgrepo, c:\hgrepo)
 | 
			
		||||
  text_scm_command: Command
 | 
			
		||||
 
 | 
			
		||||
@@ -1072,8 +1072,9 @@ fr:
 | 
			
		||||
  text_zoom_out: Zoom arrière
 | 
			
		||||
  text_warn_on_leaving_unsaved: "Cette page contient du texte non sauvegardé qui sera perdu si vous quittez la page."
 | 
			
		||||
  text_scm_path_encoding_note: "Défaut : UTF-8"
 | 
			
		||||
  text_git_repository_note: "Le dépôt est vide et local (exemples : /gitrepo, c:\\gitrepo)"
 | 
			
		||||
  text_mercurial_repository_note: "Dépôt local (exemples : /hgrepo, c:\\hgrepo)"
 | 
			
		||||
  text_subversion_repository_note: "Exemples (en fonction des protocoles supportés) : file:///, http://, https://, svn://, svn+[tunnelscheme]://"
 | 
			
		||||
  text_git_repository_note: "Chemin vers un dépôt vide et local (exemples : /gitrepo, c:\\gitrepo)"
 | 
			
		||||
  text_mercurial_repository_note: "Chemin vers un dépôt local (exemples : /hgrepo, c:\\hgrepo)"
 | 
			
		||||
  text_scm_command: Commande
 | 
			
		||||
  text_scm_command_version: Version
 | 
			
		||||
  text_scm_config: Vous pouvez configurer les commandes des SCM dans config/configuration.yml. Redémarrer l'application après modification.
 | 
			
		||||
 
 | 
			
		||||
@@ -58,6 +58,7 @@ module Redmine
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        check_regular_expressions
 | 
			
		||||
        @config
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
@@ -112,6 +113,20 @@ module Redmine
 | 
			
		||||
          @config.merge!({'email_delivery' => load_from_yaml(deprecated_email_conf, env)})
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      # Checks the validness of regular expressions set for repository paths at startup
 | 
			
		||||
      def check_regular_expressions
 | 
			
		||||
        @config.each do |name, value|
 | 
			
		||||
          if value.present? && name =~ /^scm_.+_path_regexp$/
 | 
			
		||||
            begin
 | 
			
		||||
              Regexp.new value.to_s.strip
 | 
			
		||||
            rescue => e
 | 
			
		||||
              $stderr.puts "Invalid regular expression set as #{name} setting in your Redmine configuration file:\n#{e.message}"
 | 
			
		||||
              exit 1
 | 
			
		||||
            end
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 
 | 
			
		||||
@@ -93,6 +93,24 @@ class RepositoryCvsTest < ActiveSupport::TestCase
 | 
			
		||||
    assert_include str, repo.errors.full_messages
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def test_root_url_should_be_validated_against_regexp_set_in_configuration
 | 
			
		||||
    Redmine::Configuration.with 'scm_cvs_path_regexp' => '/cvspath/[a-z]+' do
 | 
			
		||||
      repo = Repository::Cvs.new(
 | 
			
		||||
        :project       => @project,
 | 
			
		||||
        :identifier    => 'test',
 | 
			
		||||
        :log_encoding  => 'UTF-8',
 | 
			
		||||
        :path_encoding => '',
 | 
			
		||||
        :url           => MODULE_NAME
 | 
			
		||||
      )
 | 
			
		||||
      repo.root_url = '/wrong_path'
 | 
			
		||||
      assert !repo.valid?
 | 
			
		||||
      assert repo.errors[:root_url].present?
 | 
			
		||||
 | 
			
		||||
      repo.root_url = '/cvspath/foo'
 | 
			
		||||
      assert repo.valid?
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  if File.directory?(REPOSITORY_PATH)
 | 
			
		||||
    def test_fetch_changesets_from_scratch
 | 
			
		||||
      assert_equal 0, @repository.changesets.count
 | 
			
		||||
 
 | 
			
		||||
@@ -57,6 +57,37 @@ class RepositorySubversionTest < ActiveSupport::TestCase
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def test_url_should_be_validated_against_regexp_set_in_configuration
 | 
			
		||||
    Redmine::Configuration.with 'scm_subversion_path_regexp' => 'file:///svnpath/[a-z]+' do
 | 
			
		||||
      repo = Repository::Subversion.new(:project => @project, :identifier => 'test')
 | 
			
		||||
      repo.url = 'http://foo'
 | 
			
		||||
      assert !repo.valid?
 | 
			
		||||
      assert repo.errors[:url].present?
 | 
			
		||||
 | 
			
		||||
      repo.url = 'file:///svnpath/foo/bar'
 | 
			
		||||
      assert !repo.valid?
 | 
			
		||||
      assert repo.errors[:url].present?
 | 
			
		||||
 | 
			
		||||
      repo.url = 'file:///svnpath/foo'
 | 
			
		||||
      assert repo.valid?
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def test_url_should_be_validated_against_regexp_set_in_configuration_with_project_identifier
 | 
			
		||||
    Redmine::Configuration.with 'scm_subversion_path_regexp' => 'file:///svnpath/%project%(\.[a-z]+)?' do
 | 
			
		||||
      repo = Repository::Subversion.new(:project => @project, :identifier => 'test')
 | 
			
		||||
      repo.url = 'file:///svnpath/invalid'
 | 
			
		||||
      assert !repo.valid?
 | 
			
		||||
      assert repo.errors[:url].present?
 | 
			
		||||
 | 
			
		||||
      repo.url = 'file:///svnpath/subproject1'
 | 
			
		||||
      assert repo.valid?
 | 
			
		||||
 | 
			
		||||
      repo.url = 'file:///svnpath/subproject1.foo'
 | 
			
		||||
      assert repo.valid?
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  if repository_configured?('subversion')
 | 
			
		||||
    def test_fetch_changesets_from_scratch
 | 
			
		||||
      assert_equal 0, @repository.changesets.count
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user