diff options
author | Jean-Philippe Lang <jp_lang@yahoo.fr> | 2012-10-03 21:36:19 +0000 |
---|---|---|
committer | Jean-Philippe Lang <jp_lang@yahoo.fr> | 2012-10-03 21:36:19 +0000 |
commit | 0178b5a2fe07e1160348b99ac56c19ebf154ca1b (patch) | |
tree | 53f762a779c95b598815864bb674463d90ef64d6 /app/models | |
parent | bb1563f23ffabcf948797e0d8806c3d5344d09a7 (diff) | |
download | redmine-0178b5a2fe07e1160348b99ac56c19ebf154ca1b.tar.gz redmine-0178b5a2fe07e1160348b99ac56c19ebf154ca1b.zip |
Private issue notes (#1554).
Adds 2 new permissions for viewing/adding private comments to issues.
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@10547 e93f8b46-1217-0410-a6f0-8f06a7374b81
Diffstat (limited to 'app/models')
-rw-r--r-- | app/models/issue.rb | 30 | ||||
-rw-r--r-- | app/models/journal.rb | 43 | ||||
-rw-r--r-- | app/models/mail_handler.rb | 8 | ||||
-rw-r--r-- | app/models/mailer.rb | 2 |
4 files changed, 72 insertions, 11 deletions
diff --git a/app/models/issue.rb b/app/models/issue.rb index 2f1021b2d..37a19a9c4 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -28,6 +28,14 @@ class Issue < ActiveRecord::Base belongs_to :category, :class_name => 'IssueCategory', :foreign_key => 'category_id' has_many :journals, :as => :journalized, :dependent => :destroy + has_many :visible_journals, + :class_name => 'Journal', + :as => :journalized, + :conditions => Proc.new { + ["(#{Journal.table_name}.private_notes = ? OR (#{Project.allowed_to_condition(User.current, :view_private_notes)}))", false] + }, + :readonly => true + has_many :time_entries, :dependent => :delete_all has_and_belongs_to_many :changesets, :order => "#{Changeset.table_name}.committed_on ASC, #{Changeset.table_name}.id ASC" @@ -39,7 +47,7 @@ class Issue < ActiveRecord::Base acts_as_customizable acts_as_watchable acts_as_searchable :columns => ['subject', "#{table_name}.description", "#{Journal.table_name}.notes"], - :include => [:project, :journals], + :include => [:project, :visible_journals], # sort by id so that limited eager loading doesn't break with postgresql :order_column => "#{table_name}.id" acts_as_event :title => Proc.new {|o| "#{o.tracker.name} ##{o.id} (#{o.status}): #{o.subject}"}, @@ -52,6 +60,7 @@ class Issue < ActiveRecord::Base DONE_RATIO_OPTIONS = %w(issue_field issue_status) attr_reader :current_journal + delegate :notes, :notes=, :private_notes, :private_notes=, :to => :current_journal, :allow_nil => true validates_presence_of :subject, :priority, :project, :tracker, :author, :status @@ -335,6 +344,7 @@ class Issue < ActiveRecord::Base 'custom_field_values', 'custom_fields', 'lock_version', + 'notes', :if => lambda {|issue, user| issue.new_record? || user.allowed_to?(:edit_issues, issue.project) } safe_attributes 'status_id', @@ -342,8 +352,15 @@ class Issue < ActiveRecord::Base 'fixed_version_id', 'done_ratio', 'lock_version', + 'notes', :if => lambda {|issue, user| issue.new_statuses_allowed_to(user).any? } + safe_attributes 'notes', + :if => lambda {|issue, user| user.allowed_to?(:add_issue_notes, issue.project)} + + safe_attributes 'private_notes', + :if => lambda {|issue, user| !issue.new_record? && user.allowed_to?(:set_notes_private, issue.project)} + safe_attributes 'watcher_user_ids', :if => lambda {|issue, user| issue.new_record? && user.allowed_to?(:add_issue_watchers, issue.project)} @@ -715,8 +732,8 @@ class Issue < ActiveRecord::Base end end - # Returns the mail adresses of users that should be notified - def recipients + # Returns the users that should be notified + def notified_users notified = [] # Author and assignee are always notified unless they have been # locked or don't want to be notified @@ -733,7 +750,12 @@ class Issue < ActiveRecord::Base notified.uniq! # Remove users that can not view the issue notified.reject! {|user| !visible?(user)} - notified.collect(&:mail) + notified + end + + # Returns the email addresses that should be notified + def recipients + notified_users.collect(&:mail) end # Returns the number of hours spent on this issue diff --git a/app/models/journal.rb b/app/models/journal.rb index a6a800e7a..895b8537d 100644 --- a/app/models/journal.rb +++ b/app/models/journal.rb @@ -37,10 +37,15 @@ class Journal < ActiveRecord::Base :conditions => "#{Journal.table_name}.journalized_type = 'Issue' AND" + " (#{JournalDetail.table_name}.prop_key = 'status_id' OR #{Journal.table_name}.notes <> '')"} - scope :visible, lambda {|*args| { - :include => {:issue => :project}, - :conditions => Issue.visible_condition(args.shift || User.current, *args) - }} + before_create :split_private_notes + + scope :visible, lambda {|*args| + user = args.shift || User.current + + includes(:issue => :project). + where(Issue.visible_condition(user, *args)). + where("(#{Journal.table_name}.private_notes = ? OR (#{Project.allowed_to_condition(user, :view_private_notes, *args)}))", false) + } def save(*args) # Do not save an empty journal @@ -75,6 +80,7 @@ class Journal < ActiveRecord::Base s = 'journal' s << ' has-notes' unless notes.blank? s << ' has-details' unless details.blank? + s << ' private-notes' if private_notes? s end @@ -85,4 +91,33 @@ class Journal < ActiveRecord::Base def notify=(arg) @notify = arg end + + def recipients + notified = journalized.notified_users + if private_notes? + notified = notified.select {|user| user.allowed_to?(:view_private_notes, journalized.project)} + end + notified.map(&:mail) + end + + private + + def split_private_notes + if private_notes? + if notes.present? + if details.any? + # Split the journal (notes/changes) so we don't have half-private journals + journal = Journal.new(:journalized => journalized, :user => user, :notes => nil, :private_notes => false) + journal.details = details + journal.save + self.details = [] + self.created_on = journal.created_on + end + else + # Blank notes should not be private + self.private_notes = false + end + end + true + end end diff --git a/app/models/mail_handler.rb b/app/models/mail_handler.rb index 8a5925cab..3eacf3c19 100644 --- a/app/models/mail_handler.rb +++ b/app/models/mail_handler.rb @@ -181,7 +181,7 @@ class MailHandler < ActionMailer::Base end # Adds a note to an existing issue - def receive_issue_reply(issue_id) + def receive_issue_reply(issue_id, from_journal=nil) issue = Issue.find_by_id(issue_id) return unless issue # check permission @@ -196,6 +196,10 @@ class MailHandler < ActionMailer::Base @@handler_options[:issue].clear journal = issue.init_journal(user) + if from_journal && from_journal.private_notes? + # If the received email was a reply to a private note, make the added note private + issue.private_notes = true + end issue.safe_attributes = issue_attributes_from_keywords(issue) issue.safe_attributes = {'custom_field_values' => custom_field_values_from_keywords(issue)} journal.notes = cleaned_up_text_body @@ -211,7 +215,7 @@ class MailHandler < ActionMailer::Base def receive_journal_reply(journal_id) journal = Journal.find_by_id(journal_id) if journal && journal.journalized_type == 'Issue' - receive_issue_reply(journal.journalized_id) + receive_issue_reply(journal.journalized_id, journal) end end diff --git a/app/models/mailer.rb b/app/models/mailer.rb index 65ca9ea08..91b58dda2 100644 --- a/app/models/mailer.rb +++ b/app/models/mailer.rb @@ -62,7 +62,7 @@ class Mailer < ActionMailer::Base message_id journal references issue @author = journal.user - recipients = issue.recipients + recipients = journal.recipients # Watchers in cc cc = issue.watcher_recipients - recipients s = "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}] " |