Index: app/apis/sys_api.rb =================================================================== --- app/apis/sys_api.rb (revision 2643) +++ app/apis/sys_api.rb (working copy) @@ -20,6 +20,7 @@ member :identifier, :string member :name, :string member :is_public, :bool + member :public_repo, :bool member :repository, Repository end Index: app/controllers/projects_controller.rb =================================================================== --- app/controllers/projects_controller.rb (revision 2643) +++ app/controllers/projects_controller.rb (working copy) @@ -70,6 +70,7 @@ @project.identifier = Project.next_identifier if Setting.sequential_project_identifiers? @project.trackers = Tracker.all @project.is_public = Setting.default_projects_public? + @project.public_repo = Setting.default_projects_public? @project.enabled_module_names = Redmine::AccessControl.available_project_modules else @project.enabled_module_names = params[:enabled_modules] Index: app/views/projects/_form.rhtml =================================================================== --- app/views/projects/_form.rhtml (revision 2643) +++ app/views/projects/_form.rhtml (working copy) @@ -15,6 +15,8 @@ <% end %>

<%= f.text_field :homepage, :size => 60 %>

<%= f.check_box :is_public %>

+

<%= f.check_box :create_repo, :disabled => !Setting.sys_api_enabled? %>

+

<%= f.check_box :public_repo, :disabled => !Setting.sys_api_enabled? %>

<%= wikitoolbar_for 'project_description' %> <% @project.custom_field_values.each do |value| %> Index: extra/svn/Redmine.pm =================================================================== --- extra/svn/Redmine.pm (revision 2643) +++ extra/svn/Redmine.pm (working copy) @@ -206,7 +206,7 @@ my $project_id = get_project_identifier($r); $r->set_handlers(PerlAuthenHandler => [\&OK]) - if is_public_project($project_id, $r); + if (is_public_project($project_id, $r) && public_repository($project_id, $r)); return OK } @@ -217,7 +217,7 @@ my ($res, $redmine_pass) = $r->get_basic_auth_pw(); return $res unless $res == OK; - if (is_member($r->user, $redmine_pass, $r)) { + if (is_member($r->user, $redmine_pass, $r) && can_browse($r->user, $redmine_pass, $r)) { return OK; } else { $r->note_auth_failure(); @@ -257,6 +257,23 @@ # return 1 if (stat($repos_path))[2] & 00007; # } +sub public_repository { + my $project_id = shift; + my $r = shift; + + my $dbh = connect_database($r); + my $sth = $dbh->prepare( + "SELECT * FROM projects WHERE projects.identifier=? and projects.public_repo=true;" + ); + + $sth->execute($project_id); + my $ret = $sth->fetchrow_array ? 1 : 0; + $sth->finish(); + $dbh->disconnect(); + + $ret; +} + sub is_member { my $redmine_user = shift; my $redmine_pass = shift; @@ -325,6 +342,74 @@ $ret; } +sub can_browse { + my $redmine_user = shift; + my $redmine_pass = shift; + my $r = shift; + + my $dbh = connect_database($r); + my $project_id = get_project_identifier($r); + + my $pass_digest = Digest::SHA1::sha1_hex($redmine_pass); + + my $cfg = Apache2::Module::get_config(__PACKAGE__, $r->server, $r->per_dir_config); + my $usrprojpass; + if ($cfg->{RedmineCacheCredsMax}) { + $usrprojpass = $cfg->{RedmineCacheCreds}->get($redmine_user.":".$project_id); + return 1 if (defined $usrprojpass and ($usrprojpass eq $pass_digest)); + } + my $query = $cfg->{RedmineQuery}; + my $sth = $dbh->prepare($query); + $sth->execute($redmine_user, $project_id); + + my $ret; + while (my ($hashed_password, $auth_source_id, $permissions) = $sth->fetchrow_array) { + + unless ($auth_source_id) { + my $method = $r->method; + if ($hashed_password eq $pass_digest && $permissions =~ /:browse_repository/) { + $ret = 1; + last; + } + } elsif ($CanUseLDAPAuth) { + my $sthldap = $dbh->prepare( + "SELECT host,port,tls,account,account_password,base_dn,attr_login from auth_sources WHERE id = ?;" + ); + $sthldap->execute($auth_source_id); + while (my @rowldap = $sthldap->fetchrow_array) { + my $ldap = Authen::Simple::LDAP->new( + host => ($rowldap[2] == 1 || $rowldap[2] eq "t") ? "ldaps://$rowldap[0]" : $rowldap[0], + port => $rowldap[1], + basedn => $rowldap[5], + binddn => $rowldap[3] ? $rowldap[3] : "", + bindpw => $rowldap[4] ? $rowldap[4] : "", + filter => "(".$rowldap[6]."=%s)" + ); + $ret = 1 if ($ldap->authenticate($redmine_user, $redmine_pass)); + } + $sthldap->finish(); + } + } + $sth->finish(); + $dbh->disconnect(); + + if ($cfg->{RedmineCacheCredsMax} and $ret) { + if (defined $usrprojpass) { + $cfg->{RedmineCacheCreds}->set($redmine_user.":".$project_id, $pass_digest); + } else { + if ($cfg->{RedmineCacheCredsCount} < $cfg->{RedmineCacheCredsMax}) { + $cfg->{RedmineCacheCreds}->set($redmine_user.":".$project_id, $pass_digest); + $cfg->{RedmineCacheCredsCount}++; + } else { + $cfg->{RedmineCacheCreds}->clear(); + $cfg->{RedmineCacheCredsCount} = 0; + } + } + } + + $ret; +} + sub get_project_identifier { my $r = shift; Index: extra/svn/reposman.rb =================================================================== --- extra/svn/reposman.rb (revision 2643) +++ extra/svn/reposman.rb (working copy) @@ -190,7 +190,7 @@ yield if block_given? else uid, gid = Etc.getpwnam($svn_owner).uid, ($use_groupid ? Etc.getgrnam(project.identifier).gid : 0) - right = project.is_public ? 0775 : 0770 + right = project.public_repo ? 0775 : 0770 yield if block_given? Find.find(repos_path) do |f| File.chmod right, f @@ -228,7 +228,7 @@ # rights before leaving other_read = other_read_right?(repos_path) owner = owner_name(repos_path) - next if project.is_public == other_read and owner == $svn_owner + next if project.public_repo == other_read and owner == $svn_owner if $test log("\tchange mode on #{repos_path}") @@ -252,7 +252,7 @@ next end - project.is_public ? File.umask(0002) : File.umask(0007) + project.public_repo ? File.umask(0002) : File.umask(0007) if $test log("\tcreate repository #{repos_path}") Index: lang/en.yml =================================================================== --- lang/en.yml (revision 2643) +++ lang/en.yml (working copy) @@ -139,6 +139,8 @@ field_role: Role field_homepage: Homepage field_is_public: Public +field_create_repo: Create Repository +field_public_repo: Public Repository field_parent: Subproject of field_is_in_chlog: Issues displayed in changelog field_is_in_roadmap: Issues displayed in roadmap