Feature #2647 » repository_auth.patch
| app/helpers/repositories_helper.rb (working copy) | ||
|---|---|---|
| 146 | 146 | end | 
| 147 | 147 | |
| 148 | 148 | def subversion_field_tags(form, repository) | 
| 149 |  | |
| 150 |       login_options = [["--- #{l(:actionview_instancetag_blank_option)} ---", '']] | |
| 151 |       login_options << [l("repository_login_usernamepassword"), 0]  | |
| 152 |       login_options << [l("repository_login_current_username"), 1]  | |
| 153 |       login_options << [l("repository_login_current_role"), 2]  | |
| 154 |  | |
| 149 | 155 |       content_tag('p', form.text_field(:url, :size => 60, :required => true, :disabled => (repository && !repository.root_url.blank?)) + | 
| 150 | 156 | '<br />(http://, https://, svn://, file:///)') + | 
| 157 |       content_tag('p', form.select(:login_method, login_options)) + | |
| 151 | 158 |       content_tag('p', form.text_field(:login, :size => 30)) + | 
| 152 | 159 |       content_tag('p', form.password_field(:password, :size => 30, :name => 'ignore', | 
| 153 | 160 |                                            :value => ((repository.new_record? || repository.password.blank?) ? '' : ('x'*15)), | 
| 154 | 161 | :onfocus => "this.value=''; this.name='repository[password]';", | 
| 155 | :onchange => "this.name='repository[password]';")) | |
| 162 | :onchange => "this.name='repository[password]';")) + | |
| 163 |       content_tag('p', form.password_field(:security_token, :size => 30, :name => 'ignore', | |
| 164 |                                            :value => ((repository.new_record? || repository.security_token.blank?) ? '' : ('x'*15)), | |
| 165 | :onfocus => "this.value=''; this.name='repository[security_token]';", | |
| 166 | :onchange => "this.name='repository[security_token]';")) | |
| 156 | 167 | end | 
| 157 | 168 | |
| 169 | #      select_tag('login_method', options_for_select(login_method, repository.class.name.demodulize), | |
| 170 | #               :onchange => remote_function(:url => { :controller => 'repositories', :action => 'edit', :id => @project }, :method => :get, :with => "Form.serialize(this.form)") ) + | |
| 171 | ||
| 158 | 172 | def darcs_field_tags(form, repository) | 
| 159 | 173 |       content_tag('p', form.text_field(:url, :label => 'Root directory', :size => 60, :required => true, :disabled => (repository && !repository.new_record?))) | 
| 160 | 174 | end | 
| app/models/repository.rb (working copy) | ||
|---|---|---|
| 38 | 38 | end | 
| 39 | 39 | |
| 40 | 40 | def scm | 
| 41 | @scm ||= self.scm_adapter.new url, root_url, login, password | |
| 41 |     @scm ||= self.scm_adapter.new url, root_url, login, password, login_method, security_token, project | |
| 42 | 42 | update_attribute(:root_url, @scm.root_url) if root_url.blank? | 
| 43 | 43 | @scm | 
| 44 | 44 | end | 
| db/migrate/107_add_special_repository_security.rb (revision 0) | ||
|---|---|---|
| 1 | class AddSpecialRepositorySecurity < ActiveRecord::Migration | |
| 2 | def self.down | |
| 3 | remove_column :repositories, :login_method | |
| 4 | remove_column :repositories, :security_token | |
| 5 | end | |
| 6 | ||
| 7 | def self.up | |
| 8 | add_column :repositories, :login_method, :int, :default => 0, :null => true | |
| 9 | add_column :repositories, :security_token, :string, :limit => 60, :default => "", :null => true | |
| 10 | end | |
| 11 | end | |
| extra/svn/Redmine.pm (working copy) | ||
|---|---|---|
| 5 | 5 | Redmine - a mod_perl module to authenticate webdav subversion users | 
| 6 | 6 | against redmine database | 
| 7 | 7 | |
| 8 | In addition this module allows to authenticate a redmine server | |
| 9 | for webdav subversion access, bypassing full authentication, still a | |
| 10 | llowing to apply repository based security (e.g. .authz files) | |
| 11 | ||
| 12 | ||
| 8 | 13 | =head1 SYNOPSIS | 
| 9 | 14 | |
| 10 | 15 | This module allow anonymous users to browse public project and | 
| ... | ... | |
| 73 | 78 | Order deny,allow | 
| 74 | 79 | Deny from all | 
| 75 | 80 | # only allow reading orders | 
| 81 |  | |
| 82 | AuthType Basic | |
| 83 | AuthName redmine | |
| 84 | Require valid-user | |
| 85 | ||
| 86 | PerlAccessHandler Apache::Authn::Redmine::redmine_access_handler | |
| 87 | PerlAuthenHandler Apache::Authn::Redmine::redmine_authen_handler | |
| 88 |  | |
| 89 | RedmineSecurityToken "redmine" | |
| 90 |  | |
| 76 | 91 | <Limit GET PROPFIND OPTIONS REPORT> | 
| 77 | 92 | Allow from redmine.server.ip | 
| 78 | 93 | </Limit> | 
| ... | ... | |
| 142 | 157 | args_how => TAKE1, | 
| 143 | 158 | errmsg => 'RedmineCacheCredsMax must be decimal number', | 
| 144 | 159 | }, | 
| 160 |   { | |
| 161 | name => 'RedmineSecurityToken', | |
| 162 | req_override => OR_AUTHCFG, | |
| 163 | args_how => TAKE1, | |
| 164 | errmsg => 'RedmineSecurityToken additional authentication token', | |
| 165 | }, | |
| 145 | 166 | ); | 
| 146 | 167 | |
| 147 | 168 | sub RedmineDSN {  | 
| ... | ... | |
| 161 | 182 | } | 
| 162 | 183 | sub RedmineDbUser { set_val('RedmineDbUser', @_); } | 
| 163 | 184 | sub RedmineDbPass { set_val('RedmineDbPass', @_); } | 
| 185 | sub RedmineSecurityToken { set_val('RedmineSecurityToken', @_); } | |
| 164 | 186 | sub RedmineDbWhereClause {  | 
| 165 | 187 | my ($self, $parms, $arg) = @_; | 
| 166 | 188 |   $self->{RedmineQuery} = trim($self->{RedmineQuery}.($arg ? $arg : "")." "); | 
| ... | ... | |
| 340 | 362 |     return DBI->connect($cfg->{RedmineDSN}, $cfg->{RedmineDbUser}, $cfg->{RedmineDbPass}); | 
| 341 | 363 | } | 
| 342 | 364 | |
| 365 | ||
| 366 | sub redmine_access_handler { | |
| 367 | my $r = shift; | |
| 368 | ||
| 369 |   unless ($r->some_auth_required) { | |
| 370 |       $r->log_reason("No authentication has been configured"); | |
| 371 | return FORBIDDEN; | |
| 372 | } | |
| 373 | ||
| 374 | my $method = $r->method; | |
| 375 |   return OK unless defined $read_only_methods{$method}; | |
| 376 | ||
| 377 | my $project_id = get_project_identifier($r); | |
| 378 | ||
| 379 | $r->set_handlers(PerlAuthenHandler => [\&OK]) | |
| 380 | if is_public_project($project_id, $r); | |
| 381 | ||
| 382 | return OK | |
| 383 | } | |
| 384 | ||
| 385 | sub redmine_authen_handler { | |
| 386 | my $r = shift; | |
| 387 |  | |
| 388 | my ($res, $redmine_pass) = $r->get_basic_auth_pw(); | |
| 389 | return $res unless $res == OK; | |
| 390 |  | |
| 391 | my $cfg = Apache2::Module::get_config(__PACKAGE__, $r->server, $r->per_dir_config); | |
| 392 |  | |
| 393 |   if ($cfg->{RedmineSecurityToken}) { | |
| 394 |     my $securityToken = $cfg->{RedmineSecurityToken}; | |
| 395 | ||
| 396 |     if ($securityToken ne $redmine_pass) { | |
| 397 |       $r->log_error("Apache::Authn::Redmine - Provided SecurityToken did not match"); | |
| 398 | $r->note_auth_failure(); | |
| 399 | return AUTH_REQUIRED; | |
| 400 | } | |
| 401 | } | |
| 402 |  | |
| 403 | return OK; | |
| 404 | } | |
| 405 | ||
| 343 | 406 | 1; | 
| lang/en.yml (working copy) | ||
|---|---|---|
| 187 | 187 | field_comments_sorting: Display comments | 
| 188 | 188 | field_parent_title: Parent page | 
| 189 | 189 | field_editable: Editable | 
| 190 | field_login_method: Authentication method | |
| 191 | field_security_token: Security token | |
| 190 | 192 | |
| 193 | repository_login_usernamepassword: Provided credentials | |
| 194 | repository_login_current_username: Name of current user | |
| 195 | repository_login_current_role: Role of current user | |
| 196 | ||
| 191 | 197 | setting_app_title: Application title | 
| 192 | 198 | setting_app_subtitle: Application subtitle | 
| 193 | 199 | setting_welcome_text: Welcome text | 
| lib/redmine/scm/adapters/abstract_adapter.rb (working copy) | ||
|---|---|---|
| 47 | 47 | end | 
| 48 | 48 | end | 
| 49 | 49 |  | 
| 50 | def initialize(url, root_url=nil, login=nil, password=nil) | |
| 50 |         def initialize(url, root_url=nil, login=nil, password=nil, login_method=nil, security_token=nil, project=nil) | |
| 51 | 51 | @url = url | 
| 52 | 52 | @login = login if login && !login.empty? | 
| 53 | 53 | @password = (password || "") if @login | 
| 54 | 54 | @root_url = root_url.blank? ? retrieve_root_url : root_url | 
| 55 | @login_method = login_method.blank? ? 0 : login_method | |
| 56 | @security_token = security_token.blank? ? "" : security_token | |
| 57 | @project = project | |
| 55 | 58 | end | 
| 56 | 59 |  | 
| 57 | 60 | def adapter_name | 
| ... | ... | |
| 65 | 68 | def supports_annotate? | 
| 66 | 69 |           respond_to?('annotate') | 
| 67 | 70 | end | 
| 68 |  | |
| 71 | ||
| 72 | def use_current_user | |
| 73 | @use_current_user | |
| 74 | end | |
| 75 |  | |
| 69 | 76 | def root_url | 
| 70 | 77 | @root_url | 
| 71 | 78 | end | 
| lib/redmine/scm/adapters/subversion_adapter.rb (working copy) | ||
|---|---|---|
| 222 | 222 | private | 
| 223 | 223 |  | 
| 224 | 224 | def credentials_string | 
| 225 | str = '' | |
| 226 |           str << " --username #{shell_quote(@login)}" unless @login.blank?
 | |
| 227 |           str << " --password #{shell_quote(@password)}" unless @login.blank? || @password.blank?
 | |
| 225 |  | |
| 226 |  | |
| 227 | if !(User.current.is_a?(AnonymousUser)) | |
| 228 |  | |
| 229 | if (@login_method == 1) | |
| 230 | str = '' | |
| 231 |                str << " --username #{shell_quote(User.current.login)}"
 | |
| 232 |                str << " --password #{shell_quote( (@security_token.blank? ? "foo" : @security_token) )}"   
 | |
| 233 | end | |
| 234 |  | |
| 235 | if (@login_method == 2) && (!@project.nil?) | |
| 236 | role = User.current.role_for_project(@project) | |
| 237 |  | |
| 238 | if !role.blank? | |
| 239 | str = '' | |
| 240 |                  str << " --username #{shell_quote(role.name)}"
 | |
| 241 |                  str << " --password #{shell_quote( (@security_token.blank? ? "foo" : @security_token) )}"   
 | |
| 242 | end | |
| 243 | end | |
| 244 |  | |
| 245 | end | |
| 246 |  | |
| 247 | if (str.blank?) | |
| 248 | str = '' | |
| 249 |             str << " --username #{shell_quote(@login)}" unless @login.blank?
 | |
| 250 |             str << " --password #{shell_quote(@password)}" unless @login.blank? || @password.blank?
 | |
| 251 | end | |
| 252 |  | |
| 228 | 253 | str | 
| 229 | 254 | end | 
| 230 | 255 | end |