comparison app/models/.svn/text-base/issue.rb.svn-base @ 119:8661b858af72

* Update to Redmine trunk rev 4705
author Chris Cannam
date Thu, 13 Jan 2011 14:12:06 +0000
parents 94944d00e43c
children 07fa8a8b56a8
comparison
equal deleted inserted replaced
39:150ceac17a8d 119:8661b858af72
14 # You should have received a copy of the GNU General Public License 14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software 15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 class Issue < ActiveRecord::Base 18 class Issue < ActiveRecord::Base
19 include Redmine::SafeAttributes
20
19 belongs_to :project 21 belongs_to :project
20 belongs_to :tracker 22 belongs_to :tracker
21 belongs_to :status, :class_name => 'IssueStatus', :foreign_key => 'status_id' 23 belongs_to :status, :class_name => 'IssueStatus', :foreign_key => 'status_id'
22 belongs_to :author, :class_name => 'User', :foreign_key => 'author_id' 24 belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
23 belongs_to :assigned_to, :class_name => 'User', :foreign_key => 'assigned_to_id' 25 belongs_to :assigned_to, :class_name => 'User', :foreign_key => 'assigned_to_id'
66 named_scope :with_limit, lambda { |limit| { :limit => limit} } 68 named_scope :with_limit, lambda { |limit| { :limit => limit} }
67 named_scope :on_active_project, :include => [:status, :project, :tracker], 69 named_scope :on_active_project, :include => [:status, :project, :tracker],
68 :conditions => ["#{Project.table_name}.status=#{Project::STATUS_ACTIVE}"] 70 :conditions => ["#{Project.table_name}.status=#{Project::STATUS_ACTIVE}"]
69 named_scope :for_gantt, lambda { 71 named_scope :for_gantt, lambda {
70 { 72 {
71 :include => [:tracker, :status, :assigned_to, :priority, :project, :fixed_version], 73 :include => [:tracker, :status, :assigned_to, :priority, :project, :fixed_version]
72 :order => "#{Issue.table_name}.due_date ASC, #{Issue.table_name}.start_date ASC, #{Issue.table_name}.id ASC"
73 } 74 }
74 } 75 }
75 76
76 named_scope :without_version, lambda { 77 named_scope :without_version, lambda {
77 { 78 {
213 214
214 def estimated_hours=(h) 215 def estimated_hours=(h)
215 write_attribute :estimated_hours, (h.is_a?(String) ? h.to_hours : h) 216 write_attribute :estimated_hours, (h.is_a?(String) ? h.to_hours : h)
216 end 217 end
217 218
218 SAFE_ATTRIBUTES = %w( 219 safe_attributes 'tracker_id',
219 tracker_id 220 'status_id',
220 status_id 221 'parent_issue_id',
221 parent_issue_id 222 'category_id',
222 category_id 223 'assigned_to_id',
223 assigned_to_id 224 'priority_id',
224 priority_id 225 'fixed_version_id',
225 fixed_version_id 226 'subject',
226 subject 227 'description',
227 description 228 'start_date',
228 start_date 229 'due_date',
229 due_date 230 'done_ratio',
230 done_ratio 231 'estimated_hours',
231 estimated_hours 232 'custom_field_values',
232 custom_field_values 233 'custom_fields',
233 lock_version 234 'lock_version',
234 ) unless const_defined?(:SAFE_ATTRIBUTES) 235 :if => lambda {|issue, user| issue.new_record? || user.allowed_to?(:edit_issues, issue.project) }
235 236
236 SAFE_ATTRIBUTES_ON_TRANSITION = %w( 237 safe_attributes 'status_id',
237 status_id 238 'assigned_to_id',
238 assigned_to_id 239 'fixed_version_id',
239 fixed_version_id 240 'done_ratio',
240 done_ratio 241 :if => lambda {|issue, user| issue.new_statuses_allowed_to(user).any? }
241 ) unless const_defined?(:SAFE_ATTRIBUTES_ON_TRANSITION)
242 242
243 # Safely sets attributes 243 # Safely sets attributes
244 # Should be called from controllers instead of #attributes= 244 # Should be called from controllers instead of #attributes=
245 # attr_accessible is too rough because we still want things like 245 # attr_accessible is too rough because we still want things like
246 # Issue.new(:project => foo) to work 246 # Issue.new(:project => foo) to work
247 # TODO: move workflow/permission checks from controllers to here 247 # TODO: move workflow/permission checks from controllers to here
248 def safe_attributes=(attrs, user=User.current) 248 def safe_attributes=(attrs, user=User.current)
249 return unless attrs.is_a?(Hash) 249 return unless attrs.is_a?(Hash)
250 250
251 # User can change issue attributes only if he has :edit permission or if a workflow transition is allowed 251 # User can change issue attributes only if he has :edit permission or if a workflow transition is allowed
252 if new_record? || user.allowed_to?(:edit_issues, project) 252 attrs = delete_unsafe_attributes(attrs, user)
253 attrs = attrs.reject {|k,v| !SAFE_ATTRIBUTES.include?(k)} 253 return if attrs.empty?
254 elsif new_statuses_allowed_to(user).any?
255 attrs = attrs.reject {|k,v| !SAFE_ATTRIBUTES_ON_TRANSITION.include?(k)}
256 else
257 return
258 end
259 254
260 # Tracker must be set before since new_statuses_allowed_to depends on it. 255 # Tracker must be set before since new_statuses_allowed_to depends on it.
261 if t = attrs.delete('tracker_id') 256 if t = attrs.delete('tracker_id')
262 self.tracker_id = t 257 self.tracker_id = t
263 end 258 end
274 269
275 if attrs.has_key?('parent_issue_id') 270 if attrs.has_key?('parent_issue_id')
276 if !user.allowed_to?(:manage_subtasks, project) 271 if !user.allowed_to?(:manage_subtasks, project)
277 attrs.delete('parent_issue_id') 272 attrs.delete('parent_issue_id')
278 elsif !attrs['parent_issue_id'].blank? 273 elsif !attrs['parent_issue_id'].blank?
279 attrs.delete('parent_issue_id') unless Issue.visible(user).exists?(attrs['parent_issue_id']) 274 attrs.delete('parent_issue_id') unless Issue.visible(user).exists?(attrs['parent_issue_id'].to_i)
280 end 275 end
281 end 276 end
282 277
283 self.attributes = attrs 278 self.attributes = attrs
284 end 279 end