diff --git a/CHANGELOG.md b/CHANGELOG.md
index 316543c013..edf09fef7e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,9 @@
# Changelog
All notable changes to this project will be documented in this file.
+## 2020-06-12
+- Users of all teams added to a case can now view complainant contact details on the case activity page.
+
## 2020-06-05
– Added the ability to view the details of correspondence added to the case on their own page.
diff --git a/psd-web/Gemfile b/psd-web/Gemfile
index 4bc806b8b4..9f5fb0c512 100644
--- a/psd-web/Gemfile
+++ b/psd-web/Gemfile
@@ -63,7 +63,7 @@ group :development, :test do
gem "rspec-mocks"
gem "rspec-rails"
gem "rubocop"
- gem "rubocop-govuk", "~> 3.14.0"
+ gem "rubocop-govuk", "~> 3.16.0"
gem "rubocop-performance"
gem "rubocop-rspec", "~> 1.39", require: false
gem "ruby-debug-ide"
diff --git a/psd-web/Gemfile.lock b/psd-web/Gemfile.lock
index 47f0864b47..a934b4a438 100644
--- a/psd-web/Gemfile.lock
+++ b/psd-web/Gemfile.lock
@@ -72,7 +72,7 @@ GEM
public_suffix (>= 2.0.2, < 5.0)
ansi (1.5.0)
arel (9.0.0)
- ast (2.4.0)
+ ast (2.4.1)
awesome_print (1.8.0)
aws-eventstream (1.1.0)
aws-partitions (1.323.0)
@@ -391,24 +391,28 @@ GEM
rspec-mocks (~> 3.9)
rspec-support (~> 3.9)
rspec-support (3.9.3)
- rubocop (0.83.0)
+ rubocop (0.85.1)
parallel (~> 1.10)
parser (>= 2.7.0.1)
rainbow (>= 2.2.2, < 4.0)
+ regexp_parser (>= 1.7)
rexml
+ rubocop-ast (>= 0.0.3)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 2.0)
- rubocop-govuk (3.14.0)
- rubocop (= 0.83.0)
- rubocop-rails (~> 2)
- rubocop-rake (~> 0.5.1)
- rubocop-rspec (~> 1.28)
+ rubocop-ast (0.0.3)
+ parser (>= 2.7.0.1)
+ rubocop-govuk (3.16.0)
+ rubocop (= 0.85.1)
+ rubocop-rails (= 2.6.0)
+ rubocop-rake (= 0.5.1)
+ rubocop-rspec (= 1.39.0)
rubocop-performance (1.6.1)
rubocop (>= 0.71.0)
- rubocop-rails (2.5.2)
- activesupport
+ rubocop-rails (2.6.0)
+ activesupport (>= 4.2.0)
rack (>= 1.1)
- rubocop (>= 0.72.0)
+ rubocop (>= 0.82.0)
rubocop-rake (0.5.1)
rubocop
rubocop-rspec (1.39.0)
@@ -588,7 +592,7 @@ DEPENDENCIES
rspec-mocks
rspec-rails
rubocop
- rubocop-govuk (~> 3.14.0)
+ rubocop-govuk (~> 3.16.0)
rubocop-performance
rubocop-rspec (~> 1.39)
ruby-debug-ide
diff --git a/psd-web/app/controllers/investigations/ownership_controller.rb b/psd-web/app/controllers/investigations/ownership_controller.rb
index dc638ff805..516bbebad2 100644
--- a/psd-web/app/controllers/investigations/ownership_controller.rb
+++ b/psd-web/app/controllers/investigations/ownership_controller.rb
@@ -2,42 +2,37 @@ class Investigations::OwnershipController < ApplicationController
include Wicked::Wizard
before_action :set_investigation
before_action :authorize_user
- before_action :potential_owner, only: %i[show create]
- before_action :store_owner, only: %i[update]
steps :"select-owner", :confirm
def show
- @potential_owner = potential_owner&.decorate
+ @potential_owner = form.owner&.decorate
render_wizard
end
def new
- clear_session
+ session[session_store_key] = nil
redirect_to wizard_path(steps.first, request.query_parameters)
end
def update
- if owner_valid?
- redirect_to next_wizard_path
- else
- render_wizard
- end
+ return render_wizard unless form.valid?
+
+ session[session_store_key] = form.attributes.compact
+ redirect_to next_wizard_path
end
def create
- @investigation.owner = potential_owner
- @investigation.owner_rationale = params[:investigation][:owner_rationale]
- @investigation.save
- redirect_to investigation_path(@investigation), flash: { success: "#{@investigation.case_type.upcase_first} owner changed to #{potential_owner.decorate.display_name}" }
- end
+ ChangeCaseOwner.call!(investigation: @investigation, owner: form.owner, rationale: form.owner_rationale, user: current_user)
-private
+ session[session_store_key] = nil
- def clear_session
- session[:owner_id] = nil
+ message = "#{@investigation.case_type.upcase_first} owner changed to #{form.owner.decorate.display_name(viewer: current_user)}"
+ redirect_to investigation_path(@investigation), flash: { success: message }
end
+private
+
def set_investigation
@investigation = Investigation.find_by!(pretty_id: params[:investigation_pretty_id]).decorate
end
@@ -46,7 +41,12 @@ def authorize_user
authorize @investigation, :change_owner_or_status?
end
- def owner_params
+ def session_store_key
+ "update_case_owner_#{@investigation.pretty_id}_params"
+ end
+
+ def form_params
+ params[:investigation] ||= {}
params[:investigation][:owner_id] = case params[:investigation][:owner_id]
when "someone_in_your_team"
params[:investigation][:select_team_member]
@@ -59,23 +59,14 @@ def owner_params
else
params[:investigation][:owner_id]
end
- params.require(:investigation).permit(:owner_id)
- end
-
- def store_owner
- session[:owner_id] = owner_params[:owner_id]
+ params.require(:investigation).permit(:owner_id, :owner_rationale).merge(session_params)
end
- def owner_valid?
- if step == :"select-owner"
- if potential_owner.nil?
- @investigation.errors.add(:owner_id, :invalid, message: "Select case owner")
- end
- end
- @investigation.errors.empty?
+ def session_params
+ session[session_store_key] || {}
end
- def potential_owner
- User.find_by(id: session[:owner_id]) || Team.find_by(id: session[:owner_id])
+ def form
+ @form ||= ChangeCaseOwnerForm.new(form_params)
end
end
diff --git a/psd-web/app/controllers/investigations_controller.rb b/psd-web/app/controllers/investigations_controller.rb
index 7f5902298e..123209de30 100644
--- a/psd-web/app/controllers/investigations_controller.rb
+++ b/psd-web/app/controllers/investigations_controller.rb
@@ -124,6 +124,6 @@ def build_breadcrumbs
end
def set_suggested_previous_owners
- @suggested_previous_owners = suggested_previous_owners
+ @suggested_previous_owners = suggested_previous_owners(@investigation)
end
end
diff --git a/psd-web/app/decorators/user_decorator.rb b/psd-web/app/decorators/user_decorator.rb
index 87cfb0fc13..df0d0a594b 100644
--- a/psd-web/app/decorators/user_decorator.rb
+++ b/psd-web/app/decorators/user_decorator.rb
@@ -13,7 +13,7 @@ def full_name
end
# viewer could be a Team or User
- def display_name(viewer: User.current)
+ def display_name(viewer:)
suffix = " (#{team.name})" if team != viewer&.team
"#{name}#{suffix}#{deleted_suffix}"
end
diff --git a/psd-web/app/forms/change_case_owner_form.rb b/psd-web/app/forms/change_case_owner_form.rb
new file mode 100644
index 0000000000..76e76c1f1b
--- /dev/null
+++ b/psd-web/app/forms/change_case_owner_form.rb
@@ -0,0 +1,28 @@
+class ChangeCaseOwnerForm
+ include ActiveModel::Model
+ include ActiveModel::Attributes
+
+ attribute :owner_id
+ attribute :owner_rationale
+
+ validates_presence_of :owner_id
+ validate :new_owner_must_be_active_user_or_team, if: -> { owner_id.present? }
+
+ def owner
+ user || team
+ end
+
+private
+
+ def new_owner_must_be_active_user_or_team
+ errors.add(:owner_id, :not_found) unless owner
+ end
+
+ def user
+ @user ||= User.active.find_by(id: owner_id)
+ end
+
+ def team
+ @team ||= Team.find_by(id: owner_id)
+ end
+end
diff --git a/psd-web/app/helpers/investigations/display_text_helper.rb b/psd-web/app/helpers/investigations/display_text_helper.rb
index 211b008705..cc21aa81e0 100644
--- a/psd-web/app/helpers/investigations/display_text_helper.rb
+++ b/psd-web/app/helpers/investigations/display_text_helper.rb
@@ -91,7 +91,7 @@ def gdpr_restriction_text
def should_be_hidden(result, source, investigation)
return true if correspondence_should_be_hidden(result, source, investigation)
- return true if (source.include? "complainant") && !investigation&.complainant&.can_be_displayed?(current_user)
+ return true if (source.include? "complainant") && !policy(investigation).view_protected_details?
false
end
diff --git a/psd-web/app/helpers/investigations/user_filters_helper.rb b/psd-web/app/helpers/investigations/user_filters_helper.rb
index 76614b8473..3b650034d2 100644
--- a/psd-web/app/helpers/investigations/user_filters_helper.rb
+++ b/psd-web/app/helpers/investigations/user_filters_helper.rb
@@ -27,7 +27,7 @@ def other_owner(form)
render "form_components/govuk_select",
key: :case_owner_is_someone_else_id,
form: form,
- items: entities.map { |e| { text: e.display_name, value: e.id } },
+ items: entities.map { |e| { text: e.display_name(viewer: current_user), value: e.id } },
label: { text: "Name" },
is_autocomplete: true
end
@@ -36,7 +36,7 @@ def other_creator(form)
render "form_components/govuk_select",
key: :created_by_someone_else_id,
form: form,
- items: entities.map { |e| { text: e.display_name, value: e.id } },
+ items: entities.map { |e| { text: e.display_name(viewer: current_user), value: e.id } },
label: { text: "Name" },
is_autocomplete: true
end
diff --git a/psd-web/app/helpers/investigations_helper.rb b/psd-web/app/helpers/investigations_helper.rb
index d01280995c..874b172a17 100644
--- a/psd-web/app/helpers/investigations_helper.rb
+++ b/psd-web/app/helpers/investigations_helper.rb
@@ -241,8 +241,8 @@ def user_ids_from_team(team)
[team.id] + team.users.map(&:id)
end
- def suggested_previous_owners
- all_past_owners = @investigation.past_owners + @investigation.past_teams
+ def suggested_previous_owners(investigation)
+ all_past_owners = investigation.past_owners
return [] if all_past_owners.empty? || all_past_owners == [current_user]
all_past_owners || []
diff --git a/psd-web/app/models/activity.rb b/psd-web/app/models/activity.rb
index 16aaa5f493..c78365f4a9 100644
--- a/psd-web/app/models/activity.rb
+++ b/psd-web/app/models/activity.rb
@@ -17,8 +17,13 @@ def attachments
{}
end
- def subtitle
- "#{subtitle_slug} by #{source&.show}, #{pretty_date_stamp}"
+ # Can be overridden by child classes but sometimes need to pass in user
+ def title(_user)
+ super()
+ end
+
+ def subtitle(viewer)
+ "#{subtitle_slug} by #{source&.show(viewer)}, #{pretty_date_stamp}"
end
def search_index; end
@@ -31,7 +36,7 @@ def can_display_all_data?(_user)
true
end
- def restricted_title
+ def restricted_title(_user)
# where necessary should be implemented by subclasses
end
diff --git a/psd-web/app/models/audit_activity/correspondence/add_email.rb b/psd-web/app/models/audit_activity/correspondence/add_email.rb
index 7955ab660f..a9ac92087e 100644
--- a/psd-web/app/models/audit_activity/correspondence/add_email.rb
+++ b/psd-web/app/models/audit_activity/correspondence/add_email.rb
@@ -48,7 +48,7 @@ def self.build_email_address(correspondence)
output + "
"
end
- def restricted_title
+ def restricted_title(_user)
"Email added"
end
diff --git a/psd-web/app/models/audit_activity/correspondence/add_meeting.rb b/psd-web/app/models/audit_activity/correspondence/add_meeting.rb
index 585be78a56..4cc9b660c2 100644
--- a/psd-web/app/models/audit_activity/correspondence/add_meeting.rb
+++ b/psd-web/app/models/audit_activity/correspondence/add_meeting.rb
@@ -23,7 +23,7 @@ def activity_type
"meeting"
end
- def restricted_title
+ def restricted_title(_user)
"Meeting added"
end
diff --git a/psd-web/app/models/audit_activity/correspondence/add_phone_call.rb b/psd-web/app/models/audit_activity/correspondence/add_phone_call.rb
index 88adf4a726..a0d6a828c2 100644
--- a/psd-web/app/models/audit_activity/correspondence/add_phone_call.rb
+++ b/psd-web/app/models/audit_activity/correspondence/add_phone_call.rb
@@ -39,7 +39,7 @@ def self.build_file_body(correspondence)
file.attached? ? "Attached: #{sanitize_text file.filename}
" : ""
end
- def restricted_title
+ def restricted_title(_user)
"Phone call added"
end
diff --git a/psd-web/app/models/audit_activity/document/add.rb b/psd-web/app/models/audit_activity/document/add.rb
index fb10d31cfd..27da39f938 100644
--- a/psd-web/app/models/audit_activity/document/add.rb
+++ b/psd-web/app/models/audit_activity/document/add.rb
@@ -8,7 +8,7 @@ def email_update_text(viewer = nil)
"Document was attached to the #{investigation.case_type.upcase_first} by #{source&.show(viewer)}."
end
- def restricted_title
+ def restricted_title(_user)
"Document added"
end
diff --git a/psd-web/app/models/audit_activity/document/base.rb b/psd-web/app/models/audit_activity/document/base.rb
index 2a4bb3168e..ac713fb088 100644
--- a/psd-web/app/models/audit_activity/document/base.rb
+++ b/psd-web/app/models/audit_activity/document/base.rb
@@ -21,7 +21,7 @@ def attached_image?
attachment.image?
end
- def restricted_title; end
+ def restricted_title(_user); end
def can_display_all_data?(user)
can_be_displayed?(attachment, investigation, user)
diff --git a/psd-web/app/models/audit_activity/document/destroy.rb b/psd-web/app/models/audit_activity/document/destroy.rb
index 16b19991d5..9d6fd6cfb2 100644
--- a/psd-web/app/models/audit_activity/document/destroy.rb
+++ b/psd-web/app/models/audit_activity/document/destroy.rb
@@ -4,7 +4,7 @@ def self.from(document, investigation)
super(document, investigation, title)
end
- def restricted_title
+ def restricted_title(_user)
"Document deleted"
end
diff --git a/psd-web/app/models/audit_activity/document/update.rb b/psd-web/app/models/audit_activity/document/update.rb
index dc3dd004cb..25b1ef6192 100644
--- a/psd-web/app/models/audit_activity/document/update.rb
+++ b/psd-web/app/models/audit_activity/document/update.rb
@@ -22,7 +22,7 @@ def self.description_changed?(document, previous_data)
document.metadata[:description] != previous_data[:description]
end
- def restricted_title
+ def restricted_title(_user)
"Document updated"
end
diff --git a/psd-web/app/models/audit_activity/investigation/add.rb b/psd-web/app/models/audit_activity/investigation/add.rb
index ab016d82dd..321a7f4a7c 100644
--- a/psd-web/app/models/audit_activity/investigation/add.rb
+++ b/psd-web/app/models/audit_activity/investigation/add.rb
@@ -31,7 +31,7 @@ def complainant
# title may change after investigation was created, so we retrieve from the
# metadata stored at the time of creation
- def title
+ def title(_user)
return self[:title] if self[:title] # older activities stored this in the database
"#{investigation.case_type.titleize} logged: #{metadata['investigation']['title']}"
@@ -45,12 +45,12 @@ def title
def can_display_all_data?(user)
return true if self[:metadata].present? || investigation.complainant.blank?
- investigation.complainant.can_be_displayed?(user)
+ Pundit.policy(user, investigation).view_protected_details?
end
# Only used for old records prior to metadata implementation
- def restricted_title
- title
+ def restricted_title(user)
+ title(user)
end
private
diff --git a/psd-web/app/models/audit_activity/investigation/automatically_update_owner.rb b/psd-web/app/models/audit_activity/investigation/automatically_update_owner.rb
index 073245e6f8..302b8e58bf 100644
--- a/psd-web/app/models/audit_activity/investigation/automatically_update_owner.rb
+++ b/psd-web/app/models/audit_activity/investigation/automatically_update_owner.rb
@@ -1,31 +1,30 @@
class AuditActivity::Investigation::AutomaticallyUpdateOwner < AuditActivity::Investigation::Base
- def self.from(investigation)
- title = investigation.owner.id.to_s
- super(investigation, title)
+ def self.from(*)
+ raise "Deprecated - use DeleteUser.call instead"
end
- def owner_id
- # We store owner_id in title field, this is getting it back
- # Using alias for accessing parent method causes errors elsewhere :(
- AuditActivity::Investigation::Base.instance_method(:title).bind(self).call
+ def self.build_metadata(owner)
+ {
+ owner_id: owner.id
+ }
end
- # We store owner_id in title field, this is computing title based on that
- def title
+ def title(user)
type = investigation.case_type.capitalize
- new_owner = (User.find_by(id: owner_id) || Team.find_by(id: owner_id))&.decorate&.display_name
+ new_owner = owner.decorate.display_name(viewer: user)
"Case owner automatically changed on #{type} to #{new_owner}"
end
- def subtitle
+ def subtitle(_viewer)
"Case owner automatically changed, #{pretty_date_stamp}"
end
- def entities_to_notify
- []
- end
+private
- def email_subject_text; end
+ def owner
+ User.find_by(id: metadata["owner_id"]) || Team.find_by(id: metadata["owner_id"])
+ end
- def email_update_text(viewer = nil); end
+ # Do not send investigation_updated mail. This is handled by the DeleteUser service
+ def notify_relevant_users; end
end
diff --git a/psd-web/app/models/audit_activity/investigation/team_added.rb b/psd-web/app/models/audit_activity/investigation/team_added.rb
index 2641221a82..a0ca4ade04 100644
--- a/psd-web/app/models/audit_activity/investigation/team_added.rb
+++ b/psd-web/app/models/audit_activity/investigation/team_added.rb
@@ -1,6 +1,6 @@
class AuditActivity::Investigation::TeamAdded < AuditActivity::Investigation::Base
- def subtitle
- "Team added by #{source&.show}, #{pretty_date_stamp}"
+ def subtitle(viewer)
+ "Team added by #{source&.show(viewer)}, #{pretty_date_stamp}"
end
private
diff --git a/psd-web/app/models/audit_activity/investigation/team_deleted.rb b/psd-web/app/models/audit_activity/investigation/team_deleted.rb
index 715d5497d8..806031e8cd 100644
--- a/psd-web/app/models/audit_activity/investigation/team_deleted.rb
+++ b/psd-web/app/models/audit_activity/investigation/team_deleted.rb
@@ -1,6 +1,6 @@
class AuditActivity::Investigation::TeamDeleted < AuditActivity::Investigation::Base
- def subtitle
- "Team removed by #{source&.show}, #{pretty_date_stamp}"
+ def subtitle(viewer)
+ "Team removed by #{source&.show(viewer)}, #{pretty_date_stamp}"
end
private
diff --git a/psd-web/app/models/audit_activity/investigation/update_owner.rb b/psd-web/app/models/audit_activity/investigation/update_owner.rb
index 59d9aed90d..a23684a185 100644
--- a/psd-web/app/models/audit_activity/investigation/update_owner.rb
+++ b/psd-web/app/models/audit_activity/investigation/update_owner.rb
@@ -1,37 +1,25 @@
class AuditActivity::Investigation::UpdateOwner < AuditActivity::Investigation::Base
- include NotifyHelper
-
- def self.from(investigation)
- title = investigation.owner.id.to_s
- body = investigation.owner_rationale
- super(investigation, title, sanitize_text(body))
+ def self.from(*)
+ raise "Deprecated - use ChangeCaseOwner.call instead"
end
- def owner_id
- # We store owner_id in title field, this is getting it back
- # Using alias for accessing parent method causes errors elsewhere :(
- AuditActivity::Investigation::Base.instance_method(:title).bind(self).call
+ def self.build_metadata(owner, rationale)
+ {
+ owner_id: owner.id,
+ rationale: rationale
+ }
end
- def title
- # We store owner_id in title field, this is computing title based on that
- "Case owner changed to #{(User.find_by(id: owner_id) || Team.find_by(id: owner_id))&.decorate&.display_name}"
+ def title(user)
+ "Case owner changed to #{owner.decorate.display_name(viewer: user)}"
end
- def email_update_text(viewer = nil)
- body = []
- body << "Case owner changed on #{investigation.case_type} to #{investigation.owner.decorate.display_name(viewer: viewer)} by #{source&.show(viewer)}."
-
- if investigation.owner_rationale.present?
- body << "Message from #{source&.show(viewer)}:"
- body << inset_text_for_notify(investigation.owner_rationale)
- end
-
- body.join("\n\n")
+ def body
+ metadata["rationale"]
end
- def email_subject_text
- "Case owner changed for #{investigation.case_type}"
+ def owner
+ User.find_by(id: metadata["owner_id"]) || Team.find_by(id: metadata["owner_id"])
end
private
@@ -40,27 +28,6 @@ def subtitle_slug
"Changed"
end
- def users_to_notify
- compute_relevant_entities(model: User, compute_users_from_entity: proc { |user| [user] })
- end
-
- def teams_to_notify
- compute_relevant_entities(model: Team, compute_users_from_entity: proc { |team| team.users })
- end
-
- def compute_relevant_entities(model:, compute_users_from_entity:)
- return [] unless investigation.saved_changes.key?("owner_id")
-
- previous_owner_id = investigation.saved_changes["owner_id"][0]
- previous_owner = model.find_by(id: previous_owner_id)
- new_owner = investigation.owner
- owner_changed_by = source.user
-
- old_users = previous_owner.present? ? compute_users_from_entity.call(previous_owner) : []
- old_entities = previous_owner.present? ? [previous_owner] : []
- new_entities = new_owner.is_a?(model) ? [new_owner] : []
- return new_entities if old_users.include? owner_changed_by
-
- (new_entities + old_entities).uniq
- end
+ # Do not send investigation_updated mail. This is handled by the ChangeCaseOwner service
+ def notify_relevant_users; end
end
diff --git a/psd-web/app/models/comment_activity.rb b/psd-web/app/models/comment_activity.rb
index cd9b92c896..cc753d64c6 100644
--- a/psd-web/app/models/comment_activity.rb
+++ b/psd-web/app/models/comment_activity.rb
@@ -4,7 +4,7 @@ class CommentActivity < Activity
validates :body, presence: true
validates :body, length: { maximum: 10_000 }
- def title
+ def title(_user)
"Comment added"
end
diff --git a/psd-web/app/models/complainant.rb b/psd-web/app/models/complainant.rb
index 07eb278a8f..fa416dc06e 100644
--- a/psd-web/app/models/complainant.rb
+++ b/psd-web/app/models/complainant.rb
@@ -19,16 +19,4 @@ class Complainant < ApplicationRecord
validates :name, length: { maximum: 100 }
validates :other_details, length: { maximum: 10_000 }
-
- def can_be_displayed?(user)
- can_be_seen_by_user?(user) || investigation.child_should_be_displayed?(user)
- end
-
-private
-
- def can_be_seen_by_user?(user)
- return true if investigation.creator_user.has_gdpr_access?(user)
-
- complainant_type != "Consumer"
- end
end
diff --git a/psd-web/app/models/investigation.rb b/psd-web/app/models/investigation.rb
index 27bddccfad..b66e6f8f67 100644
--- a/psd-web/app/models/investigation.rb
+++ b/psd-web/app/models/investigation.rb
@@ -20,15 +20,17 @@ class Investigation < ApplicationRecord
validates :type, presence: true # Prevent saving instances of Investigation; must use a subclass instead
validates :description, presence: true, on: :update
- validates :owner_id, presence: { message: "Select case owner" }, on: :update
+
+ # Can currently only validate owner_id on update since create case wizards
+ # validate partially-built Investigation instances
+ validates :owner_id, presence: true, on: :update
validates :user_title, length: { maximum: 100 }
validates :description, length: { maximum: 10_000 }
validates :non_compliant_reason, length: { maximum: 10_000 }
validates :hazard_description, length: { maximum: 10_000 }
- after_update :create_audit_activity_for_owner,
- :create_audit_activity_for_status,
+ after_update :create_audit_activity_for_status,
:create_audit_activity_for_visibility,
:create_audit_activity_for_summary
@@ -116,8 +118,7 @@ def important_owner_people
def past_owners
activities = AuditActivity::Investigation::UpdateOwner.where(investigation_id: id)
- user_id_list = activities.map(&:owner_id)
- User.where(id: user_id_list)
+ activities.map(&:owner)
end
def important_owner_teams
@@ -130,12 +131,6 @@ def important_owner_teams
teams
end
- def past_teams
- activities = AuditActivity::Investigation::UpdateOwner.where(investigation_id: id)
- team_id_list = activities.map(&:owner_id)
- Team.where(id: team_id_list)
- end
-
def enquiry?
is_a?(Investigation::Enquiry)
end
@@ -191,14 +186,6 @@ def create_audit_activity_for_visibility
end
end
- def create_audit_activity_for_owner
- # TODO: User.current check is here to avoid triggering activity and emails from migrations
- # Can be safely removed once the migration PopulateAssigneeAndDescription has run
- if ((saved_changes.key? :owner_id) || (saved_changes.key? :owner_type)) && User.current
- AuditActivity::Investigation::UpdateOwner.from(self)
- end
- end
-
def create_audit_activity_for_summary
# TODO: User.current check is here to avoid triggering activity and emails from migrations
# Can be safely removed once the migration PopulateAssigneeAndDescription has run
diff --git a/psd-web/app/services/change_case_owner.rb b/psd-web/app/services/change_case_owner.rb
new file mode 100644
index 0000000000..3e6dccb6ea
--- /dev/null
+++ b/psd-web/app/services/change_case_owner.rb
@@ -0,0 +1,74 @@
+class ChangeCaseOwner
+ include Interactor
+ include NotifyHelper
+
+ delegate :investigation, :owner, :rationale, :user, :old_owner, to: :context
+
+ def call
+ context.fail!(error: "No investigation supplied") unless investigation.is_a?(Investigation)
+ context.fail!(error: "No owner supplied") unless owner.is_a?(User) || owner.is_a?(Team)
+ context.fail!(error: "No user supplied") unless user.is_a?(User)
+
+ context.old_owner = investigation.owner
+
+ return if old_owner == owner
+
+ ActiveRecord::Base.transaction do
+ investigation.update!(owner: owner)
+ create_audit_activity_for_case_owner_changed
+ end
+
+ send_notification_email
+ end
+
+private
+
+ def create_audit_activity_for_case_owner_changed
+ metadata = activity_class.build_metadata(owner, rationale)
+
+ activity_class.create!(
+ source: UserSource.new(user: user),
+ investigation: investigation,
+ title: nil,
+ body: nil,
+ metadata: metadata
+ )
+ end
+
+ def activity_class
+ AuditActivity::Investigation::UpdateOwner
+ end
+
+ def send_notification_email
+ entities_to_notify.each do |recipient|
+ email = recipient.is_a?(Team) ? recipient.team_recipient_email : recipient.email
+
+ NotifyMailer.investigation_updated(
+ investigation.pretty_id,
+ recipient.name,
+ email,
+ email_body(recipient),
+ "Case owner changed for #{investigation.case_type}"
+ ).deliver_later
+ end
+ end
+
+ # Notify the new owner, and the old one if it's not the user making the change
+ def entities_to_notify
+ entities = [owner]
+ entities << old_owner if old_owner != user
+
+ entities.map { |entity|
+ return entity.users.active if entity.is_a?(Team) && !entity.team_recipient_email
+
+ entity
+ }.flatten.uniq
+ end
+
+ def email_body(viewer = nil)
+ user_name = user.decorate.display_name(viewer: viewer)
+ body = "Case owner changed on #{investigation.case_type} to #{owner.decorate.display_name(viewer: viewer)} by #{user_name}."
+ body << "\n\nMessage from #{user_name}: #{inset_text_for_notify(rationale)}" if rationale
+ body
+ end
+end
diff --git a/psd-web/app/services/delete_user.rb b/psd-web/app/services/delete_user.rb
index e8c28d3e4c..c1328e002f 100644
--- a/psd-web/app/services/delete_user.rb
+++ b/psd-web/app/services/delete_user.rb
@@ -1,12 +1,14 @@
class DeleteUser
include Interactor
+ delegate :user, to: :context
+
def call
- context.fail!(error: "No user supplied") unless context.user
- context.fail!(error: "User already deleted") if context.user.deleted?
+ context.fail!(error: "No user supplied") unless user.is_a?(User)
+ context.fail!(error: "User already deleted") if user.deleted?
ActiveRecord::Base.transaction do
- context.user.mark_as_deleted!
+ user.mark_as_deleted!
change_user_investigations_ownership_to_their_team
end
end
@@ -16,10 +18,27 @@ def call
def change_user_investigations_ownership_to_their_team
context.team = context.user.team
- context.user.investigations.each do |investigation|
+ user.investigations.each do |investigation|
investigation.owner = context.team
investigation.save!
- AuditActivity::Investigation::AutomaticallyUpdateOwner.from(investigation)
+
+ create_audit_activity_for_case_owner_automatically_changed(investigation)
end
end
+
+ def create_audit_activity_for_case_owner_automatically_changed(investigation)
+ metadata = activity_class.build_metadata(investigation.owner)
+
+ activity_class.create!(
+ source: nil, # DeleteUser is called from rake user:delete where no user source is available
+ investigation: investigation,
+ title: nil,
+ body: nil,
+ metadata: metadata
+ )
+ end
+
+ def activity_class
+ AuditActivity::Investigation::AutomaticallyUpdateOwner
+ end
end
diff --git a/psd-web/app/views/investigations/activities/_activity_card.html.erb b/psd-web/app/views/investigations/activities/_activity_card.html.erb
index f4232c1036..4eba9a9ec2 100644
--- a/psd-web/app/views/investigations/activities/_activity_card.html.erb
+++ b/psd-web/app/views/investigations/activities/_activity_card.html.erb
@@ -1,12 +1,12 @@
<%
restricted = !activity.can_display_all_data?(current_user)
- title = restricted ? activity.restricted_title : activity.title
+ title = restricted ? activity.restricted_title(current_user) : activity.title(current_user)
%>
<%= activity.subtitle %>
+<%= activity.subtitle(current_user) %>
<% if restricted %> <%= render "restricted", activity: activity %> diff --git a/psd-web/app/views/investigations/activities/_restricted.html.erb b/psd-web/app/views/investigations/activities/_restricted.html.erb index 9ac14dcc0e..15e432a24e 100644 --- a/psd-web/app/views/investigations/activities/_restricted.html.erb +++ b/psd-web/app/views/investigations/activities/_restricted.html.erb @@ -1,5 +1,5 @@ <% - creator = activity.source&.user&.organisation&.name || activity.source&.show + creator = activity.source&.user&.organisation&.name || activity.source&.show(current_user) %><%= render "components/hmcts_badge", text: "Restricted access", classes: "hmcts-badge--grey" %>
diff --git a/psd-web/app/views/investigations/activities/investigation/_add_project.html.erb b/psd-web/app/views/investigations/activities/investigation/_add_project.html.erb index f197c42b84..5af490aa7c 100644 --- a/psd-web/app/views/investigations/activities/investigation/_add_project.html.erb +++ b/psd-web/app/views/investigations/activities/investigation/_add_project.html.erb @@ -1,7 +1,5 @@<%= t("audit_activity.investigation.coronavirus_related") %> diff --git a/psd-web/app/views/investigations/activities/investigation/_automatically_update_owner.html.erb b/psd-web/app/views/investigations/activities/investigation/_automatically_update_owner.html.erb new file mode 100644 index 0000000000..e4b1b26b90 --- /dev/null +++ b/psd-web/app/views/investigations/activities/investigation/_automatically_update_owner.html.erb @@ -0,0 +1 @@ +<%# Nothing to show %> diff --git a/psd-web/app/views/investigations/activities/investigation/_complainant.html.erb b/psd-web/app/views/investigations/activities/investigation/_complainant.html.erb index 94895a107a..9e38454fdc 100644 --- a/psd-web/app/views/investigations/activities/investigation/_complainant.html.erb +++ b/psd-web/app/views/investigations/activities/investigation/_complainant.html.erb @@ -8,11 +8,10 @@ <% end %> <%# Teams not involved in a case shouldn't complianant contact details %> -<% if !complainant.can_be_displayed?(current_user) %> - <%= render "restricted", activity: activity %> +<% if !policy(@investigation).view_protected_details? %> +
<%= t("case.protected_details", data_type: "#{@investigation.case_type} contact details") %>
<% else %> - <% complainant_info = [] %> <% if complainant.name.present? %> diff --git a/psd-web/app/views/investigations/activities/investigation/_update_owner.html.erb b/psd-web/app/views/investigations/activities/investigation/_update_owner.html.erb new file mode 100644 index 0000000000..f3490c588e --- /dev/null +++ b/psd-web/app/views/investigations/activities/investigation/_update_owner.html.erb @@ -0,0 +1 @@ +<%= markdown simple_format(activity.body) %> diff --git a/psd-web/app/views/investigations/index.xlsx.axlsx b/psd-web/app/views/investigations/index.xlsx.axlsx index f179dd4a9b..3ec334683b 100644 --- a/psd-web/app/views/investigations/index.xlsx.axlsx +++ b/psd-web/app/views/investigations/index.xlsx.axlsx @@ -15,7 +15,7 @@ book.add_worksheet name: "Cases" do |sheet_investigations| # rubocop:disable Met investigation.product_category, investigation.hazard_type, investigation.coronavirus_related?, - investigation.owner ? investigation.owner.decorate.display_name : "No case owner", + investigation.owner ? investigation.owner.decorate.display_name(viewer: current_user) : "No case owner", investigation.creator_user&.name, complainant.present? ? complainant&.name : "", complainant.present? ? complainant&.email_address : "", diff --git a/psd-web/app/views/investigations/ownership/_owner_form.html.slim b/psd-web/app/views/investigations/ownership/_owner_form.html.slim index 856d8ff94f..ce02fd400c 100644 --- a/psd-web/app/views/investigations/ownership/_owner_form.html.slim +++ b/psd-web/app/views/investigations/ownership/_owner_form.html.slim @@ -4,7 +4,7 @@ ruby: items = investigation.important_owner_people.map do |user| - { text: user.decorate.display_name, value: user.id, checked: investigation.owner == user } + { text: user.decorate.display_name(viewer: current_user), value: user.id, checked: investigation.owner == user } end someone_in_your_team = capture do @@ -35,7 +35,7 @@ items.push divider: "Teams" teams = investigation.important_owner_teams.map do |team| - { text: team.decorate.display_name, value: team.id, checked: investigation.owner == team } + { text: team.decorate.display_name(viewer: current_user), value: team.id, checked: investigation.owner == team } end items.concat teams diff --git a/psd-web/app/views/investigations/ownership/_owner_selection.html.slim b/psd-web/app/views/investigations/ownership/_owner_selection.html.slim index 78b3fc74f5..c024572902 100644 --- a/psd-web/app/views/investigations/ownership/_owner_selection.html.slim +++ b/psd-web/app/views/investigations/ownership/_owner_selection.html.slim @@ -1,7 +1,7 @@ ruby: actual_items = items.map do |item| { - text: item.decorate.display_name, + text: item.decorate.display_name(viewer: current_user), value: item.id } end diff --git a/psd-web/app/views/investigations/ownership/confirm.html.erb b/psd-web/app/views/investigations/ownership/confirm.html.erb index f1afe83b5a..7bd8d3dc5d 100644 --- a/psd-web/app/views/investigations/ownership/confirm.html.erb +++ b/psd-web/app/views/investigations/ownership/confirm.html.erb @@ -21,7 +21,7 @@ <%= render "minimal_investigation_heading", investigation: @investigation, title: page_heading %>You are changing the case owner to: - <%= @potential_owner.display_name || @potential_owner.name %> + <%= @potential_owner.decorate.display_name(viewer: current_user) %>