Add write control on repository from Redmine interface

* new methods to add/remove rights in app/models/role.rb
  * some unit tests
  * add write check in Redmine.pm

To keep compatibility migration add write rights to non builtin roles
but default clean install give write access only to manager and
developer, not to reporter.


git-svn-id: http://redmine.rubyforge.org/svn/branches/nbc@1791 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
Nicolas Chuche
2008-09-08 13:01:40 +00:00
parent 473869db6b
commit f5f51f4f83
6 changed files with 66 additions and 9 deletions
+20 -2
View File
@@ -36,7 +36,7 @@ class Role < ActiveRecord::Base
has_many :members has_many :members
acts_as_list acts_as_list
serialize :permissions serialize :permissions, Array
attr_protected :builtin attr_protected :builtin
validates_presence_of :name validates_presence_of :name
@@ -49,9 +49,27 @@ class Role < ActiveRecord::Base
end end
def permissions=(perms) def permissions=(perms)
perms = perms.collect {|p| p.to_sym unless p.blank? }.compact if perms perms = perms.collect {|p| p.to_sym unless p.blank? }.compact.uniq if perms
write_attribute(:permissions, perms) write_attribute(:permissions, perms)
end end
def add_permission!(*perms)
self.permissions = [] unless permissions.is_a?(Array)
permissions_will_change!
perms.each do |p|
p = p.to_sym
permissions << p unless permissions.include?(p)
end
save!
end
def remove_permission!(*perms)
return unless permissions.is_a?(Array)
permissions_will_change!
perms.each { |p| permissions.delete(p.to_sym) }
save!
end
def <=>(role) def <=>(role)
position <=> role.position position <=> role.position
@@ -0,0 +1,14 @@
class AddRepositoryWriteAccess < ActiveRecord::Migration
def self.up
Role.find(:all).select { |r| not r.builtin? }.each do |r|
r.add_permission!(:commit_access)
end
end
def self.down
Role.find(:all).select { |r| not r.builtin? }.each do |r|
r.remove_permission!(:commit_access)
end
end
end
+9 -6
View File
@@ -148,11 +148,12 @@ sub RedmineDSN {
my ($self, $parms, $arg) = @_; my ($self, $parms, $arg) = @_;
$self->{RedmineDSN} = $arg; $self->{RedmineDSN} = $arg;
my $query = "SELECT my $query = "SELECT
hashed_password, auth_source_id hashed_password, auth_source_id, permissions
FROM members, projects, users FROM members, projects, users, roles
WHERE WHERE
projects.id=members.project_id projects.id=members.project_id
AND users.id=members.user_id AND users.id=members.user_id
AND roles.id=members.role_id
AND users.status=1 AND users.status=1
AND login=? AND login=?
AND identifier=? "; AND identifier=? ";
@@ -277,9 +278,11 @@ sub is_member {
$sth->execute($redmine_user, $project_id); $sth->execute($redmine_user, $project_id);
my $ret; my $ret;
while (my @row = $sth->fetchrow_array) { while (my ($hashed_password, $auth_source_id, $permissions) = $sth->fetchrow_array) {
unless ($row[1]) {
if ($row[0] eq $pass_digest) { unless ($auth_source_id) {
my $method = $r->method;
if ($hashed_password eq $pass_digest && (defined $read_only_methods{$method} || $permissions =~ /:commit_access/) ) {
$ret = 1; $ret = 1;
last; last;
} }
@@ -287,7 +290,7 @@ sub is_member {
my $sthldap = $dbh->prepare( my $sthldap = $dbh->prepare(
"SELECT host,port,tls,account,account_password,base_dn,attr_login from auth_sources WHERE id = ?;" "SELECT host,port,tls,account,account_password,base_dn,attr_login from auth_sources WHERE id = ?;"
); );
$sthldap->execute($row[1]); $sthldap->execute($auth_source_id);
while (my @rowldap = $sthldap->fetchrow_array) { while (my @rowldap = $sthldap->fetchrow_array) {
my $ldap = Authen::Simple::LDAP->new( my $ldap = Authen::Simple::LDAP->new(
host => ($rowldap[2] == 1 || $rowldap[2] eq "t") ? "ldaps://$rowldap[0]" : $rowldap[0], host => ($rowldap[2] == 1 || $rowldap[2] eq "t") ? "ldaps://$rowldap[0]" : $rowldap[0],
+1
View File
@@ -88,6 +88,7 @@ Redmine::AccessControl.map do |map|
map.permission :manage_repository, {:repositories => [:edit, :destroy]}, :require => :member map.permission :manage_repository, {:repositories => [:edit, :destroy]}, :require => :member
map.permission :browse_repository, :repositories => [:show, :browse, :entry, :annotate, :changes, :diff, :stats, :graph] map.permission :browse_repository, :repositories => [:show, :browse, :entry, :annotate, :changes, :diff, :stats, :graph]
map.permission :view_changesets, :repositories => [:show, :revisions, :revision] map.permission :view_changesets, :repositories => [:show, :revisions, :revision]
map.permission :commit_access, {}
end end
map.project_module :boards do |map| map.project_module :boards do |map|
+2 -1
View File
@@ -67,7 +67,8 @@ module Redmine
:view_files, :view_files,
:manage_files, :manage_files,
:browse_repository, :browse_repository,
:view_changesets] :view_changesets,
:commit_access]
reporter = Role.create! :name => l(:default_role_reporter), reporter = Role.create! :name => l(:default_role_reporter),
:position => 3, :position => 3,
+20
View File
@@ -30,4 +30,24 @@ class RoleTest < Test::Unit::TestCase
target.reload target.reload
assert_equal 90, target.workflows.size assert_equal 90, target.workflows.size
end end
def test_add_permission
role = Role.find(1)
size = role.permissions.size
role.add_permission!("apermission", "anotherpermission")
role.reload
assert role.permissions.include?(:anotherpermission)
assert_equal size + 2, role.permissions.size
end
def test_remove_permission
role = Role.find(1)
size = role.permissions.size
perm = role.permissions[0..1]
role.remove_permission!(*perm)
role.reload
assert ! role.permissions.include?(perm[0])
assert_equal size - 2, role.permissions.size
end
end end