lock_version
) unless const_defined?(:SAFE_ATTRIBUTES)
+ SAFE_ATTRIBUTES_ON_TRANSITION = %w(
+ status_id
+ assigned_to_id
+ fixed_version_id
+ done_ratio
+ ) unless const_defined?(:SAFE_ATTRIBUTES_ON_TRANSITION)
+
# Safely sets attributes
# Should be called from controllers instead of #attributes=
# attr_accessible is too rough because we still want things like
# Issue.new(:project => foo) to work
# TODO: move workflow/permission checks from controllers to here
def safe_attributes=(attrs, user=User.current)
- return if attrs.nil?
- attrs = attrs.reject {|k,v| !SAFE_ATTRIBUTES.include?(k)}
+ return unless attrs.is_a?(Hash)
+
+ new_statuses_allowed = new_statuses_allowed_to(user)
+
+ # User can change issue attributes only if he has :edit permission or if a workflow transition is allowed
+ if new_record? || user.allowed_to?(:edit_issues, project)
+ attrs = attrs.reject {|k,v| !SAFE_ATTRIBUTES.include?(k)}
+ elsif new_statuses_allowed.any?
+ attrs = attrs.reject {|k,v| !SAFE_ATTRIBUTES_ON_TRANSITION.include?(k)}
+ else
+ return
+ end
+
if attrs['status_id']
- unless new_statuses_allowed_to(user).collect(&:id).include?(attrs['status_id'].to_i)
+ unless new_statuses_allowed.collect(&:id).include?(attrs['status_id'].to_i)
attrs.delete('status_id')
end
end
context "without workflow privilege" do
setup do
Workflow.delete_all(["role_id = ?", Role.anonymous.id])
- Role.anonymous.add_permission! :add_issues
+ Role.anonymous.add_permission! :add_issues, :add_issue_notes
end
context "#new" do
assert_equal IssueStatus.default, issue.status
end
+ should "accept default status" do
+ assert_difference 'Issue.count' do
+ post :create, :project_id => 1,
+ :issue => {:tracker_id => 1,
+ :subject => 'This is an issue',
+ :status_id => 1}
+ end
+ issue = Issue.last(:order => 'id')
+ assert_equal IssueStatus.default, issue.status
+ end
+
should "ignore unauthorized status" do
assert_difference 'Issue.count' do
post :create, :project_id => 1,
assert_equal IssueStatus.default, issue.status
end
end
+
+ context "#update" do
+ should "ignore status change" do
+ assert_difference 'Journal.count' do
+ put :update, :id => 1, :notes => 'just trying', :issue => {:status_id => 3}
+ end
+ assert_equal 1, Issue.find(1).status_id
+ end
+
+ should "ignore attributes changes" do
+ assert_difference 'Journal.count' do
+ put :update, :id => 1, :notes => 'just trying', :issue => {:subject => 'changed', :assigned_to_id => 2}
+ end
+ issue = Issue.find(1)
+ assert_equal "Can't print recipes", issue.subject
+ assert_nil issue.assigned_to
+ end
+ end
+ end
+
+ context "with workflow privilege" do
+ setup do
+ Workflow.delete_all(["role_id = ?", Role.anonymous.id])
+ Workflow.create!(:role => Role.anonymous, :tracker_id => 1, :old_status_id => 1, :new_status_id => 3)
+ Workflow.create!(:role => Role.anonymous, :tracker_id => 1, :old_status_id => 1, :new_status_id => 4)
+ Role.anonymous.add_permission! :add_issues, :add_issue_notes
+ end
+
+ context "#update" do
+ should "accept authorized status" do
+ assert_difference 'Journal.count' do
+ put :update, :id => 1, :notes => 'just trying', :issue => {:status_id => 3}
+ end
+ assert_equal 3, Issue.find(1).status_id
+ end
+
+ should "ignore unauthorized status" do
+ assert_difference 'Journal.count' do
+ put :update, :id => 1, :notes => 'just trying', :issue => {:status_id => 2}
+ end
+ assert_equal 1, Issue.find(1).status_id
+ end
+
+ should "accept authorized attributes changes" do
+ assert_difference 'Journal.count' do
+ put :update, :id => 1, :notes => 'just trying', :issue => {:assigned_to_id => 2}
+ end
+ issue = Issue.find(1)
+ assert_equal 2, issue.assigned_to_id
+ end
+
+ should "ignore unauthorized attributes changes" do
+ assert_difference 'Journal.count' do
+ put :update, :id => 1, :notes => 'just trying', :issue => {:subject => 'changed'}
+ end
+ issue = Issue.find(1)
+ assert_equal "Can't print recipes", issue.subject
+ end
+ end
+
+ context "and :edit_issues permission" do
+ setup do
+ Role.anonymous.add_permission! :add_issues, :edit_issues
+ end
+
+ should "accept authorized status" do
+ assert_difference 'Journal.count' do
+ put :update, :id => 1, :notes => 'just trying', :issue => {:status_id => 3}
+ end
+ assert_equal 3, Issue.find(1).status_id
+ end
+
+ should "ignore unauthorized status" do
+ assert_difference 'Journal.count' do
+ put :update, :id => 1, :notes => 'just trying', :issue => {:status_id => 2}
+ end
+ assert_equal 1, Issue.find(1).status_id
+ end
+
+ should "accept authorized attributes changes" do
+ assert_difference 'Journal.count' do
+ put :update, :id => 1, :notes => 'just trying', :issue => {:subject => 'changed', :assigned_to_id => 2}
+ end
+ issue = Issue.find(1)
+ assert_equal "changed", issue.subject
+ assert_equal 2, issue.assigned_to_id
+ end
+ end
end
def test_copy_issue