mirror of
https://github.com/meineerde/redmine.git
synced 2025-12-19 15:01:14 +00: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:
parent
34bb545e4f
commit
13f9ccaed8
@ -152,7 +152,7 @@ module RepositoriesHelper
|
|||||||
def subversion_field_tags(form, repository)
|
def subversion_field_tags(form, repository)
|
||||||
content_tag('p', form.text_field(:url, :size => 60, :required => true,
|
content_tag('p', form.text_field(:url, :size => 60, :required => true,
|
||||||
:disabled => !repository.safe_attribute?('url')) +
|
: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.text_field(:login, :size => 30)) +
|
||||||
content_tag('p', form.password_field(
|
content_tag('p', form.password_field(
|
||||||
:password, :size => 30, :name => 'ignore',
|
:password, :size => 30, :name => 'ignore',
|
||||||
@ -165,7 +165,8 @@ module RepositoriesHelper
|
|||||||
content_tag('p', form.text_field(
|
content_tag('p', form.text_field(
|
||||||
:url, :label => l(:field_path_to_repository),
|
:url, :label => l(:field_path_to_repository),
|
||||||
:size => 60, :required => true,
|
: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)
|
scm_log_encoding_tag(form, repository)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -175,7 +176,7 @@ module RepositoriesHelper
|
|||||||
:size => 60, :required => true,
|
:size => 60, :required => true,
|
||||||
:disabled => !repository.safe_attribute?('url')
|
: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)
|
scm_path_encoding_tag(form, repository)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -185,7 +186,7 @@ module RepositoriesHelper
|
|||||||
:size => 60, :required => true,
|
:size => 60, :required => true,
|
||||||
:disabled => !repository.safe_attribute?('url')
|
: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) +
|
scm_path_encoding_tag(form, repository) +
|
||||||
content_tag('p', form.check_box(
|
content_tag('p', form.check_box(
|
||||||
:extra_report_last_commit,
|
:extra_report_last_commit,
|
||||||
@ -198,7 +199,8 @@ module RepositoriesHelper
|
|||||||
:root_url,
|
:root_url,
|
||||||
:label => l(:field_cvsroot),
|
:label => l(:field_cvsroot),
|
||||||
:size => 60, :required => true,
|
: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(
|
content_tag('p', form.text_field(
|
||||||
:url,
|
:url,
|
||||||
:label => l(:field_cvs_module),
|
:label => l(:field_cvs_module),
|
||||||
@ -212,7 +214,8 @@ module RepositoriesHelper
|
|||||||
content_tag('p', form.text_field(
|
content_tag('p', form.text_field(
|
||||||
:url, :label => l(:field_path_to_repository),
|
:url, :label => l(:field_path_to_repository),
|
||||||
:size => 60, :required => true,
|
: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)
|
scm_log_encoding_tag(form, repository)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -220,10 +223,29 @@ module RepositoriesHelper
|
|||||||
content_tag('p', form.text_field(
|
content_tag('p', form.text_field(
|
||||||
:url, :label => l(:field_root_directory),
|
:url, :label => l(:field_root_directory),
|
||||||
:size => 60, :required => true,
|
: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)
|
scm_path_encoding_tag(form, repository)
|
||||||
end
|
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)
|
def scm_log_encoding_tag(form, repository)
|
||||||
select = form.select(
|
select = form.select(
|
||||||
:log_encoding,
|
:log_encoding,
|
||||||
|
|||||||
@ -45,6 +45,7 @@ class Repository < ActiveRecord::Base
|
|||||||
validates_format_of :identifier, :with => /\A(?!\d+$)[a-z0-9\-_]*\z/, :allow_blank => true
|
validates_format_of :identifier, :with => /\A(?!\d+$)[a-z0-9\-_]*\z/, :allow_blank => true
|
||||||
# Checks if the SCM is enabled when creating a repository
|
# Checks if the SCM is enabled when creating a repository
|
||||||
validate :repo_create_validation, :on => :create
|
validate :repo_create_validation, :on => :create
|
||||||
|
validate :validate_repository_path
|
||||||
attr_protected :id
|
attr_protected :id
|
||||||
|
|
||||||
safe_attributes 'identifier',
|
safe_attributes 'identifier',
|
||||||
@ -458,6 +459,18 @@ class Repository < ActiveRecord::Base
|
|||||||
|
|
||||||
protected
|
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
|
def check_default
|
||||||
if !is_default? && set_as_default?
|
if !is_default? && set_as_default?
|
||||||
self.is_default = true
|
self.is_default = true
|
||||||
|
|||||||
@ -192,6 +192,14 @@ class Repository::Cvs < Repository
|
|||||||
@current_revision_number = nil
|
@current_revision_number = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
|
# Overrides Repository#validate_repository_path to validate
|
||||||
|
# against root_url attribute.
|
||||||
|
def validate_repository_path(attribute=:root_url)
|
||||||
|
super(attribute)
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
# Returns the next revision number to assign to a CVS changeset
|
# Returns the next revision number to assign to a CVS changeset
|
||||||
|
|||||||
@ -108,6 +108,33 @@ default:
|
|||||||
scm_bazaar_command:
|
scm_bazaar_command:
|
||||||
scm_darcs_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.
|
# Absolute path to the SCM commands errors (stderr) log file.
|
||||||
# The default is to log in the 'log' directory of your Redmine instance.
|
# The default is to log in the 'log' directory of your Redmine instance.
|
||||||
# Example:
|
# Example:
|
||||||
|
|||||||
@ -1052,6 +1052,7 @@ en:
|
|||||||
text_zoom_out: Zoom out
|
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_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_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_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_mercurial_repository_note: Local repository (e.g. /hgrepo, c:\hgrepo)
|
||||||
text_scm_command: Command
|
text_scm_command: Command
|
||||||
|
|||||||
@ -1072,8 +1072,9 @@ fr:
|
|||||||
text_zoom_out: Zoom arrière
|
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_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_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_subversion_repository_note: "Exemples (en fonction des protocoles supportés) : file:///, http://, https://, svn://, svn+[tunnelscheme]://"
|
||||||
text_mercurial_repository_note: "Dépôt local (exemples : /hgrepo, c:\\hgrepo)"
|
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: Commande
|
||||||
text_scm_command_version: Version
|
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.
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
check_regular_expressions
|
||||||
@config
|
@config
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -112,6 +113,20 @@ module Redmine
|
|||||||
@config.merge!({'email_delivery' => load_from_yaml(deprecated_email_conf, env)})
|
@config.merge!({'email_delivery' => load_from_yaml(deprecated_email_conf, env)})
|
||||||
end
|
end
|
||||||
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
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -93,6 +93,24 @@ class RepositoryCvsTest < ActiveSupport::TestCase
|
|||||||
assert_include str, repo.errors.full_messages
|
assert_include str, repo.errors.full_messages
|
||||||
end
|
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)
|
if File.directory?(REPOSITORY_PATH)
|
||||||
def test_fetch_changesets_from_scratch
|
def test_fetch_changesets_from_scratch
|
||||||
assert_equal 0, @repository.changesets.count
|
assert_equal 0, @repository.changesets.count
|
||||||
|
|||||||
@ -57,6 +57,37 @@ class RepositorySubversionTest < ActiveSupport::TestCase
|
|||||||
end
|
end
|
||||||
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')
|
if repository_configured?('subversion')
|
||||||
def test_fetch_changesets_from_scratch
|
def test_fetch_changesets_from_scratch
|
||||||
assert_equal 0, @repository.changesets.count
|
assert_equal 0, @repository.changesets.count
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user