##// END OF EJS Templates
Code cleanup....
Jean-Philippe Lang -
r9532:aa18cd54c7ec
parent child
Show More
@@ -1,177 +1,185
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2012 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 class Role < ActiveRecord::Base
19 19 # Built-in roles
20 20 BUILTIN_NON_MEMBER = 1
21 21 BUILTIN_ANONYMOUS = 2
22 22
23 23 ISSUES_VISIBILITY_OPTIONS = [
24 24 ['all', :label_issues_visibility_all],
25 25 ['default', :label_issues_visibility_public],
26 26 ['own', :label_issues_visibility_own]
27 27 ]
28 28
29 scope :sorted, {:order => 'builtin, position'}
30 scope :givable, { :conditions => "builtin = 0", :order => 'position' }
29 scope :sorted, order("#{table_name}.builtin ASC, #{table_name}.position ASC")
30 scope :givable, order("#{table_name}.position ASC").where(:builtin => 0)
31 31 scope :builtin, lambda { |*args|
32 compare = 'not' if args.first == true
33 { :conditions => "#{compare} builtin = 0" }
32 compare = (args.first == true ? 'not' : '')
33 where("#{compare} builtin = 0")
34 34 }
35 35
36 36 before_destroy :check_deletable
37 37 has_many :workflows, :dependent => :delete_all do
38 38 def copy(source_role)
39 39 Workflow.copy(nil, source_role, nil, proxy_association.owner)
40 40 end
41 41 end
42 42
43 43 has_many :member_roles, :dependent => :destroy
44 44 has_many :members, :through => :member_roles
45 45 acts_as_list
46 46
47 47 serialize :permissions, Array
48 48 attr_protected :builtin
49 49
50 50 validates_presence_of :name
51 51 validates_uniqueness_of :name
52 52 validates_length_of :name, :maximum => 30
53 53 validates_inclusion_of :issues_visibility,
54 54 :in => ISSUES_VISIBILITY_OPTIONS.collect(&:first),
55 55 :if => lambda {|role| role.respond_to?(:issues_visibility)}
56 56
57 57 def permissions
58 58 read_attribute(:permissions) || []
59 59 end
60 60
61 61 def permissions=(perms)
62 62 perms = perms.collect {|p| p.to_sym unless p.blank? }.compact.uniq if perms
63 63 write_attribute(:permissions, perms)
64 64 end
65 65
66 66 def add_permission!(*perms)
67 67 self.permissions = [] unless permissions.is_a?(Array)
68 68
69 69 permissions_will_change!
70 70 perms.each do |p|
71 71 p = p.to_sym
72 72 permissions << p unless permissions.include?(p)
73 73 end
74 74 save!
75 75 end
76 76
77 77 def remove_permission!(*perms)
78 78 return unless permissions.is_a?(Array)
79 79 permissions_will_change!
80 80 perms.each { |p| permissions.delete(p.to_sym) }
81 81 save!
82 82 end
83 83
84 84 # Returns true if the role has the given permission
85 85 def has_permission?(perm)
86 86 !permissions.nil? && permissions.include?(perm.to_sym)
87 87 end
88 88
89 89 def <=>(role)
90 role ? position <=> role.position : -1
90 if role
91 if builtin == role.builtin
92 position <=> role.position
93 else
94 builtin <=> role.builtin
95 end
96 else
97 -1
98 end
91 99 end
92 100
93 101 def to_s
94 102 name
95 103 end
96 104
97 105 def name
98 106 case builtin
99 107 when 1; l(:label_role_non_member, :default => read_attribute(:name))
100 108 when 2; l(:label_role_anonymous, :default => read_attribute(:name))
101 109 else; read_attribute(:name)
102 110 end
103 111 end
104 112
105 113 # Return true if the role is a builtin role
106 114 def builtin?
107 115 self.builtin != 0
108 116 end
109 117
110 118 # Return true if the role is a project member role
111 119 def member?
112 120 !self.builtin?
113 121 end
114 122
115 123 # Return true if role is allowed to do the specified action
116 124 # action can be:
117 125 # * a parameter-like Hash (eg. :controller => 'projects', :action => 'edit')
118 126 # * a permission Symbol (eg. :edit_project)
119 127 def allowed_to?(action)
120 128 if action.is_a? Hash
121 129 allowed_actions.include? "#{action[:controller]}/#{action[:action]}"
122 130 else
123 131 allowed_permissions.include? action
124 132 end
125 133 end
126 134
127 135 # Return all the permissions that can be given to the role
128 136 def setable_permissions
129 137 setable_permissions = Redmine::AccessControl.permissions - Redmine::AccessControl.public_permissions
130 138 setable_permissions -= Redmine::AccessControl.members_only_permissions if self.builtin == BUILTIN_NON_MEMBER
131 139 setable_permissions -= Redmine::AccessControl.loggedin_only_permissions if self.builtin == BUILTIN_ANONYMOUS
132 140 setable_permissions
133 141 end
134 142
135 143 # Find all the roles that can be given to a project member
136 144 def self.find_all_givable
137 find(:all, :conditions => {:builtin => 0}, :order => 'position')
145 Role.givable.all
138 146 end
139 147
140 148 # Return the builtin 'non member' role. If the role doesn't exist,
141 149 # it will be created on the fly.
142 150 def self.non_member
143 151 find_or_create_system_role(BUILTIN_NON_MEMBER, 'Non member')
144 152 end
145 153
146 154 # Return the builtin 'anonymous' role. If the role doesn't exist,
147 155 # it will be created on the fly.
148 156 def self.anonymous
149 157 find_or_create_system_role(BUILTIN_ANONYMOUS, 'Anonymous')
150 158 end
151 159
152 160 private
153 161
154 162 def allowed_permissions
155 163 @allowed_permissions ||= permissions + Redmine::AccessControl.public_permissions.collect {|p| p.name}
156 164 end
157 165
158 166 def allowed_actions
159 167 @actions_allowed ||= allowed_permissions.inject([]) { |actions, permission| actions += Redmine::AccessControl.allowed_actions(permission) }.flatten
160 168 end
161 169
162 170 def check_deletable
163 171 raise "Can't delete role" if members.any?
164 172 raise "Can't delete builtin role" if builtin?
165 173 end
166 174
167 175 def self.find_or_create_system_role(builtin, name)
168 role = first(:conditions => {:builtin => builtin})
176 role = where(:builtin => builtin).first
169 177 if role.nil?
170 178 role = create(:name => name, :position => 0) do |r|
171 179 r.builtin = builtin
172 180 end
173 181 raise "Unable to create the #{name} role." if role.new_record?
174 182 end
175 183 role
176 184 end
177 185 end
@@ -1,89 +1,89
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2012 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 class Workflow < ActiveRecord::Base
19 19 belongs_to :role
20 20 belongs_to :old_status, :class_name => 'IssueStatus', :foreign_key => 'old_status_id'
21 21 belongs_to :new_status, :class_name => 'IssueStatus', :foreign_key => 'new_status_id'
22 22
23 23 validates_presence_of :role, :old_status, :new_status
24 24
25 25 # Returns workflow transitions count by tracker and role
26 26 def self.count_by_tracker_and_role
27 27 counts = connection.select_all("SELECT role_id, tracker_id, count(id) AS c FROM #{Workflow.table_name} GROUP BY role_id, tracker_id")
28 roles = Role.find(:all, :order => 'builtin, position')
29 trackers = Tracker.find(:all, :order => 'position')
28 roles = Role.sorted.all
29 trackers = Tracker.sorted.all
30 30
31 31 result = []
32 32 trackers.each do |tracker|
33 33 t = []
34 34 roles.each do |role|
35 35 row = counts.detect {|c| c['role_id'].to_s == role.id.to_s && c['tracker_id'].to_s == tracker.id.to_s}
36 36 t << [role, (row.nil? ? 0 : row['c'].to_i)]
37 37 end
38 38 result << [tracker, t]
39 39 end
40 40
41 41 result
42 42 end
43 43
44 44 # Copies workflows from source to targets
45 45 def self.copy(source_tracker, source_role, target_trackers, target_roles)
46 46 unless source_tracker.is_a?(Tracker) || source_role.is_a?(Role)
47 47 raise ArgumentError.new("source_tracker or source_role must be specified")
48 48 end
49 49
50 50 target_trackers = [target_trackers].flatten.compact
51 51 target_roles = [target_roles].flatten.compact
52 52
53 53 target_trackers = Tracker.sorted.all if target_trackers.empty?
54 54 target_roles = Role.all if target_roles.empty?
55 55
56 56 target_trackers.each do |target_tracker|
57 57 target_roles.each do |target_role|
58 58 copy_one(source_tracker || target_tracker,
59 59 source_role || target_role,
60 60 target_tracker,
61 61 target_role)
62 62 end
63 63 end
64 64 end
65 65
66 66 # Copies a single set of workflows from source to target
67 67 def self.copy_one(source_tracker, source_role, target_tracker, target_role)
68 68 unless source_tracker.is_a?(Tracker) && !source_tracker.new_record? &&
69 69 source_role.is_a?(Role) && !source_role.new_record? &&
70 70 target_tracker.is_a?(Tracker) && !target_tracker.new_record? &&
71 71 target_role.is_a?(Role) && !target_role.new_record?
72 72
73 73 raise ArgumentError.new("arguments can not be nil or unsaved objects")
74 74 end
75 75
76 76 if source_tracker == target_tracker && source_role == target_role
77 77 false
78 78 else
79 79 transaction do
80 80 delete_all :tracker_id => target_tracker.id, :role_id => target_role.id
81 81 connection.insert "INSERT INTO #{Workflow.table_name} (tracker_id, role_id, old_status_id, new_status_id, author, assignee)" +
82 82 " SELECT #{target_tracker.id}, #{target_role.id}, old_status_id, new_status_id, author, assignee" +
83 83 " FROM #{Workflow.table_name}" +
84 84 " WHERE tracker_id = #{source_tracker.id} AND role_id = #{source_role.id}"
85 85 end
86 86 true
87 87 end
88 88 end
89 89 end
@@ -1,111 +1,128
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2012 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 require File.expand_path('../../test_helper', __FILE__)
19 19
20 20 class RoleTest < ActiveSupport::TestCase
21 21 fixtures :roles, :workflows
22 22
23 def test_sorted_scope
24 assert_equal Role.all.sort, Role.sorted.all
25 end
26
27 def test_givable_scope
28 assert_equal Role.all.reject(&:builtin?).sort, Role.givable.all
29 end
30
31 def test_builtin_scope
32 assert_equal Role.all.select(&:builtin?).sort, Role.builtin(true).all.sort
33 assert_equal Role.all.reject(&:builtin?).sort, Role.builtin(false).all.sort
34 end
35
23 36 def test_copy_workflows
24 37 source = Role.find(1)
25 38 assert_equal 90, source.workflows.size
26 39
27 40 target = Role.new(:name => 'Target')
28 41 assert target.save
29 42 target.workflows.copy(source)
30 43 target.reload
31 44 assert_equal 90, target.workflows.size
32 45 end
33 46
34 47 def test_add_permission
35 48 role = Role.find(1)
36 49 size = role.permissions.size
37 50 role.add_permission!("apermission", "anotherpermission")
38 51 role.reload
39 52 assert role.permissions.include?(:anotherpermission)
40 53 assert_equal size + 2, role.permissions.size
41 54 end
42 55
43 56 def test_remove_permission
44 57 role = Role.find(1)
45 58 size = role.permissions.size
46 59 perm = role.permissions[0..1]
47 60 role.remove_permission!(*perm)
48 61 role.reload
49 62 assert ! role.permissions.include?(perm[0])
50 63 assert_equal size - 2, role.permissions.size
51 64 end
52 65
53 66 def test_name
54 67 I18n.locale = 'fr'
55 68 assert_equal 'Manager', Role.find(1).name
56 69 assert_equal 'Anonyme', Role.anonymous.name
57 70 assert_equal 'Non membre', Role.non_member.name
58 71 end
59 72
73 def test_find_all_givable
74 assert_equal Role.all.reject(&:builtin?).sort, Role.find_all_givable
75 end
76
60 77 context "#anonymous" do
61 78 should "return the anonymous role" do
62 79 role = Role.anonymous
63 80 assert role.builtin?
64 81 assert_equal Role::BUILTIN_ANONYMOUS, role.builtin
65 82 end
66 83
67 84 context "with a missing anonymous role" do
68 85 setup do
69 86 Role.delete_all("builtin = #{Role::BUILTIN_ANONYMOUS}")
70 87 end
71 88
72 89 should "create a new anonymous role" do
73 90 assert_difference('Role.count') do
74 91 Role.anonymous
75 92 end
76 93 end
77 94
78 95 should "return the anonymous role" do
79 96 role = Role.anonymous
80 97 assert role.builtin?
81 98 assert_equal Role::BUILTIN_ANONYMOUS, role.builtin
82 99 end
83 100 end
84 101 end
85 102
86 103 context "#non_member" do
87 104 should "return the non-member role" do
88 105 role = Role.non_member
89 106 assert role.builtin?
90 107 assert_equal Role::BUILTIN_NON_MEMBER, role.builtin
91 108 end
92 109
93 110 context "with a missing non-member role" do
94 111 setup do
95 112 Role.delete_all("builtin = #{Role::BUILTIN_NON_MEMBER}")
96 113 end
97 114
98 115 should "create a new non-member role" do
99 116 assert_difference('Role.count') do
100 117 Role.non_member
101 118 end
102 119 end
103 120
104 121 should "return the non-member role" do
105 122 role = Role.non_member
106 123 assert role.builtin?
107 124 assert_equal Role::BUILTIN_NON_MEMBER, role.builtin
108 125 end
109 126 end
110 127 end
111 128 end
General Comments 0
You need to be logged in to leave comments. Login now