Index: app/helpers/journals_helper.rb =================================================================== --- app/helpers/journals_helper.rb (revision 8212) +++ app/helpers/journals_helper.rb (working copy) @@ -39,4 +39,12 @@ onclick = "new Ajax.Request('#{url_for(url)}', {asynchronous:true, evalScripts:true, method:'get'}); return false;" link_to text, '#', options.merge(:onclick => onclick) end + + def only_private_messages?(journals) + journals.each do |journal| + return false if ! journal.private + end + + true + end end Index: app/models/mailer.rb =================================================================== --- app/models/mailer.rb (revision 8212) +++ app/models/mailer.rb (working copy) @@ -58,6 +58,7 @@ # Mailer.deliver_issue_edit(journal) => sends an email to issue recipients def issue_edit(journal) issue = journal.journalized.reload + private = journal[:private] redmine_headers 'Project' => issue.project.identifier, 'Issue-Id' => issue.id, 'Issue-Author' => issue.author.login @@ -65,11 +66,19 @@ message_id journal references issue @author = journal.user - recipients issue.recipients + + @recipients ||= [] + watchers = issue.watcher_recipients - @recipients + + processed_recipients = prepare_receivers issue.recipients, issue.project, private + processed_watchers = prepare_receivers watchers, issue.project, private + + recipients processed_recipients # Watchers in cc - cc(issue.watcher_recipients - @recipients) + cc(processed_watchers) s = "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}] " s << "(#{issue.status.name}) " if journal.new_value_for('status_id') + s << "[PRIVATE] " if journal.private s << issue.subject subject s body :issue => issue, @@ -463,6 +472,25 @@ def mylogger Rails.logger end + + # Method for recipients or watchers preparation + def prepare_receivers(receivers, project, private) + processed_receivers = Array.new() + + receivers.each do |recepient| + current_user = User.find_by_mail(recepient) + can_see_private_messages = current_user.allowed_to?(:view_private_messages, project) + + if private + next if ! can_see_private_messages + end + + processed_receivers << recepient + end + + processed_receivers + end + end # Patch TMail so that message_id is not overwritten Index: app/models/mail_handler.rb =================================================================== --- app/models/mail_handler.rb (revision 8212) +++ app/models/mail_handler.rb (working copy) @@ -159,6 +159,7 @@ 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 + journal.private = 1 if !email.subject.to_s.index('[PRIVATE]').nil? add_attachments(issue) issue.save! logger.info "MailHandler: issue ##{issue.id} updated by #{user}" if logger && logger.info Index: app/models/issue.rb =================================================================== --- app/models/issue.rb (revision 8212) +++ app/models/issue.rb (working copy) @@ -391,8 +391,8 @@ end end - def init_journal(user, notes = "") - @current_journal ||= Journal.new(:journalized => self, :user => user, :notes => notes) + def init_journal(user, notes = "", private = false) + @current_journal ||= Journal.new(:journalized => self, :user => user, :notes => notes, :private => private) @issue_before_change = self.clone @issue_before_change.status = self.status @custom_values_before_change = {} Index: app/controllers/issues_controller.rb =================================================================== --- app/controllers/issues_controller.rb (revision 8212) +++ app/controllers/issues_controller.rb (working copy) @@ -291,7 +291,8 @@ @time_entry.attributes = params[:time_entry] @notes = params[:notes] || (params[:issue].present? ? params[:issue][:notes] : nil) - @issue.init_journal(User.current, @notes) + @private_message = params[:private_message] || false + @issue.init_journal(User.current, @notes, @private_message) @issue.safe_attributes = params[:issue] end Index: app/controllers/journals_controller.rb =================================================================== --- app/controllers/journals_controller.rb (revision 8212) +++ app/controllers/journals_controller.rb (working copy) @@ -83,6 +83,7 @@ (render_403; return false) unless @journal.editable_by?(User.current) if request.post? @journal.update_attributes(:notes => params[:notes]) if params[:notes] + @journal.update_attributes(:private => params[:private_message] || false) @journal.destroy if @journal.details.empty? && @journal.notes.blank? call_hook(:controller_journals_edit_post, { :journal => @journal, :params => params}) respond_to do |format| Index: app/controllers/activities_controller.rb =================================================================== --- app/controllers/activities_controller.rb (revision 8212) +++ app/controllers/activities_controller.rb (working copy) @@ -40,6 +40,8 @@ events = @activity.events(@date_from, @date_to) + events.delete_if { |e| e.is_a?(Journal) && e.private && !User.current.allowed_to?(:view_private_messages, @project) } + if events.empty? || stale?(:etag => [@activity.scope, @date_to, @date_from, @with_subprojects, @author, events.first, User.current, current_language]) respond_to do |format| format.html { Index: app/views/journals/_notes_form.html.erb =================================================================== --- app/views/journals/_notes_form.html.erb (revision 8212) +++ app/views/journals/_notes_form.html.erb (working copy) @@ -17,6 +17,9 @@ <%= link_to l(:button_cancel), '#', :onclick => "Element.remove('journal-#{@journal.id}-form'); " + "Element.show('journal-#{@journal.id}-notes'); return false;" %>

+ <%= check_box_tag :private_message, true, @journal.private, :id => "private_message_#{@journal.id}" %> + <%= label_tag "private_message_#{@journal.id}", 'Private message', :style => 'font-weight:bold;' %> +
<% end %> <%= wikitoolbar_for "journal_#{@journal.id}_notes" %> Index: app/views/issues/show.html.erb =================================================================== --- app/views/issues/show.html.erb (revision 8212) +++ app/views/issues/show.html.erb (working copy) @@ -90,10 +90,13 @@ <% end %> <% if @journals.present? %> -
-

<%=l(:label_history)%>

-<%= render :partial => 'history', :locals => { :issue => @issue, :journals => @journals } %> -
+ <% view_private = User.current.allowed_to?(:view_private_messages, @project) %> + <% if ! only_private_messages?(@journals) || view_private %> +
+

<%=l(:label_history)%>

+ <%= render :partial => 'history', :locals => { :issue => @issue, :journals => @journals } %> +
+ <% end %> <% end %> Index: app/views/issues/_edit.html.erb =================================================================== --- app/views/issues/_edit.html.erb (revision 8212) +++ app/views/issues/_edit.html.erb (working copy) @@ -5,6 +5,9 @@ :method => :put, :multipart => true} do |f| %> <%= error_messages_for 'issue', 'time_entry' %> + + <% view_private = User.current.allowed_to?(:view_private_messages, @project) %> +
<% if @edit_allowed || !@allowed_statuses.empty? %>
<%= l(:label_change_properties) %> @@ -37,6 +40,11 @@ <%= wikitoolbar_for 'notes' %> <%= call_hook(:view_issues_edit_notes_bottom, { :issue => @issue, :notes => @notes, :form => f }) %> + <% if view_private %> + <%= check_box_tag :private_message, true, false %> + <%= label_tag :private_message, 'Private message', :style => 'font-weight:bold;' %> + <% end %> +

<%=l(:label_attachment_plural)%>
<%= render :partial => 'attachments/form' %>

@@ -52,4 +60,4 @@ }, :accesskey => accesskey(:preview) %> <% end %> -
+
\ No newline at end of file Index: app/views/issues/_history.html.erb =================================================================== --- app/views/issues/_history.html.erb (revision 8212) +++ app/views/issues/_history.html.erb (working copy) @@ -1,10 +1,27 @@ <% reply_links = authorize_for('issues', 'edit') -%> +<% view_private = User.current.allowed_to?(:view_private_messages, @project) %> +<% @skipped = 0 %> + <% for journal in journals %> -
-

+ +<% private = journal.private %> + +<% if private %> + <% if ! view_private %> + <% @skipped += 1 %> + <% next %> + <% end %> +<% end %> + +
+

<%= avatar(journal.user, :size => "24") %> - <%= content_tag('a', '', :name => "note-#{journal.indice}")%> - <%= authoring journal.created_on, journal.user, :label => :label_updated_time_by %>

+ <%= content_tag('a', '', :name => "note-#{journal.indice - @skipped}")%> + <%= authoring journal.created_on, journal.user, :label => :label_updated_time_by %> + <% if journal.private %> + [PRIVATE] + <% end %> +

<% if journal.details.any? %>