Browse Source

Update banner to handle all possible permutations

pull/1710/head
Jack S 3 years ago
parent
commit
362e913bd8
  1. 12
      app/components/data_protection_confirmation_banner_component.html.erb
  2. 52
      app/components/data_protection_confirmation_banner_component.rb
  3. 11
      app/models/user.rb
  4. 128
      spec/components/data_protection_confirmation_banner_component_spec.rb
  5. 1
      spec/models/user_spec.rb

12
app/components/data_protection_confirmation_banner_component.html.erb

@ -1,16 +1,8 @@
<% if display_banner? %> <% if display_banner? %>
<%= govuk_notification_banner(title_text: "Important") do %> <%= govuk_notification_banner(title_text: "Important") do %>
<p class="govuk-notification-banner__heading govuk-!-width-full" style="max-width: fit-content"> <p class="govuk-notification-banner__heading govuk-!-width-full" style="max-width: fit-content">
<%= I18n.t("validations.organisation.data_sharing_agreement_not_signed") %> <%= header_text %>
<p> <p>
<% if user.is_dpo? %> <%= second_row %>
<%= govuk_link_to(
"Read the Data Sharing Agreement",
data_sharing_agreement_href,
class: "govuk-notification-banner__link govuk-!-font-weight-bold",
) %>
<% else %>
<%= data_protection_officers_text %>
<% end %>
<% end %> <% end %>
<% end %> <% end %>

52
app/components/data_protection_confirmation_banner_component.rb

@ -3,6 +3,8 @@ class DataProtectionConfirmationBannerComponent < ViewComponent::Base
attr_reader :user, :organisation attr_reader :user, :organisation
HELPDESK_URL = "https://digital.dclg.gov.uk/jira/servicedesk/customer/portal/4/group/21".freeze
def initialize(user:, organisation: nil) def initialize(user:, organisation: nil)
@user = user @user = user
@organisation = organisation @organisation = organisation
@ -13,26 +15,62 @@ class DataProtectionConfirmationBannerComponent < ViewComponent::Base
def display_banner? def display_banner?
return false unless FeatureToggle.new_data_protection_confirmation? return false unless FeatureToggle.new_data_protection_confirmation?
return false if user.support? && organisation.blank? return false if user.support? && organisation.blank?
return true if org_without_dpo?
!org_or_user_org.data_protection_confirmed?
end
def header_text
if org_without_dpo?
"To create logs your organisation must state a data protection officer. They must sign the Data Sharing Agreement."
elsif user.is_dpo?
"Your organisation must accept the Data Sharing Agreement before you can create any logs."
else
"Your data protection officer must accept the Data Sharing Agreement on CORE before you can create any logs."
end
end
!DataProtectionConfirmation.exists?( def second_row
organisation: org_or_user_org, if org_without_dpo? || user.is_dpo?
confirmed: true, govuk_link_to(
) link_text,
link_href,
class: "govuk-notification-banner__link govuk-!-font-weight-bold",
)
else
tag.p data_protection_officers_text
end
end end
private
def data_protection_officers_text def data_protection_officers_text
if org_or_user_org.data_protection_officers.any? if org_or_user_org.data_protection_officers.any?
"You can ask: #{org_or_user_org.data_protection_officers.map(&:name).sort_by(&:downcase).join(', ')}" "You can ask: #{org_or_user_org.data_protection_officers.map(&:name).sort_by(&:downcase).join(', ')}"
end end
end end
def data_sharing_agreement_href def link_text
data_sharing_agreement_organisation_path(org_or_user_org) if dpo_required?
"Contact helpdesk to assign a data protection officer"
else
"Read the Data Sharing Agreement"
end
end end
private def link_href
dpo_required? ? HELPDESK_URL : data_sharing_agreement_organisation_path(org_or_user_org)
end
def dpo_required?
org_or_user_org.data_protection_officers.empty?
end
def org_or_user_org def org_or_user_org
organisation.presence || user.organisation organisation.presence || user.organisation
end end
def org_without_dpo?
org_or_user_org.data_protection_officers.empty?
end
end end

11
app/models/user.rb

@ -20,6 +20,9 @@ class User < ApplicationRecord
validates :password, presence: { if: :password_required? } validates :password, presence: { if: :password_required? }
validates :password, confirmation: { if: :password_required? } validates :password, confirmation: { if: :password_required? }
validates :password, length: { within: Devise.password_length, allow_blank: true } validates :password, length: { within: Devise.password_length, allow_blank: true }
after_save :send_data_protection_confirmation_reminder, if: :is_dpo_changed?
validates :organisation_id, presence: true validates :organisation_id, presence: true
has_paper_trail ignore: %w[last_sign_in_at has_paper_trail ignore: %w[last_sign_in_at
@ -179,4 +182,12 @@ protected
def password_required? def password_required?
!persisted? || !password.nil? || !password_confirmation.nil? !persisted? || !password.nil? || !password_confirmation.nil?
end end
private
def send_data_protection_confirmation_reminder
return unless is_dpo?
DataProtectionConfirmationMailer.send_confirmation_email(user)
end
end end

128
spec/components/data_protection_confirmation_banner_component_spec.rb

@ -1,6 +1,8 @@
require "rails_helper" require "rails_helper"
RSpec.describe DataProtectionConfirmationBannerComponent, type: :component do RSpec.describe DataProtectionConfirmationBannerComponent, type: :component do
include GovukComponent
let(:component) { described_class.new(user:, organisation:) } let(:component) { described_class.new(user:, organisation:) }
let(:render) { render_inline(component) } let(:render) { render_inline(component) }
let(:user) { create(:user) } let(:user) { create(:user) }
@ -13,114 +15,74 @@ RSpec.describe DataProtectionConfirmationBannerComponent, type: :component do
it "does not display banner" do it "does not display banner" do
expect(component.display_banner?).to eq(false) expect(component.display_banner?).to eq(false)
expect(render.content).to be_empty
end end
end end
context "when flag enabled" do context "when flag enabled", :aggregate_failures do
before do before do
allow(FeatureToggle).to receive(:new_data_protection_confirmation?).and_return(true) allow(FeatureToggle).to receive(:new_data_protection_confirmation?).and_return(true)
end end
describe "#data_protection_officers_text" do context "when user is support and organisation is blank" do
it "returns the correct text" do let(:user) { create(:user, :support) }
expect(component.data_protection_officers_text).to eq("You can ask: Danny Rojas") let(:organisation) { nil }
end
context "with two DPOs" do
before do
create(:user, organisation:, is_dpo: true, name: "Test McTest")
end
it "returns the correct list of names, in alphabetical order)" do it "does not display banner" do
expect(component.data_protection_officers_text).to eq("You can ask: Danny Rojas, Test McTest") expect(component.display_banner?).to eq(false)
end expect(render.content).to be_empty
end end
end end
context "when user is not support and not dpo" do context "when org does not have a DPO" do
let(:user) { create(:user) } before do
organisation.users.where(is_dpo: true).destroy_all
context "when org blank" do end
let(:organisation) { nil }
before do it "displays the banner" do
allow(DataProtectionConfirmation).to receive(:exists?).and_call_original expect(component.display_banner?).to eq(true)
end expect(render).to have_link(
"Contact helpdesk to assign a data protection officer",
href: "https://digital.dclg.gov.uk/jira/servicedesk/customer/portal/4/group/21",
)
expect(render).to have_selector("p", text: "To create logs your organisation must state a data protection officer. They must sign the Data Sharing Agreement.")
end
end
context "when data sharing agreement present" do context "when org has a DPO" do
it "does not display banner" do context "when org does not have a signed data sharing agreement" do
expect(component.display_banner?).to eq(false) context "when user is not a DPO" do
end let(:organisation) { create(:organisation, :without_dpc) }
let(:user) { create(:user, organisation:) }
let!(:dpo) { create(:user, :data_protection_officer, organisation:) }
it "verifies DSA exists for organisation" do it "displays the banner and shows DPOs" do
render expect(component.display_banner?).to eq(true)
expect(DataProtectionConfirmation).to have_received(:exists?).with(organisation: user.organisation, confirmed: true) expect(render.css("a")).to be_empty
expect(render).to have_selector("p", text: "Your data protection officer must accept the Data Sharing Agreement on CORE before you can create any logs.")
expect(render).to have_selector("p", text: "You can ask: #{dpo.name}")
end end
end end
context "when data sharing agreement not present" do context "when user is a DPO" do
let(:user) { create(:user, organisation: create(:organisation, :without_dpc)) } let(:organisation) { create(:organisation, :without_dpc) }
let(:user) { create(:user, :data_protection_officer, organisation:) }
it "displays the banner" do it "displays the banner and asks to sign" do
expect(component.display_banner?).to eq(true) expect(component.display_banner?).to eq(true)
end expect(render).to have_link(
"Read the Data Sharing Agreement",
it "produces the correct link" do href: "/organisations/#{organisation.id}/data-sharing-agreement",
render )
expect(component.data_sharing_agreement_href).to eq("/organisations/#{user.organisation.id}/data-sharing-agreement") expect(render).to have_selector("p", text: "Your organisation must accept the Data Sharing Agreement before you can create any logs.")
end
it "verifies DSA exists for organisation" do
render
expect(DataProtectionConfirmation).to have_received(:exists?).with(organisation: user.organisation, confirmed: true)
end end
end end
end end
end
context "when user is support" do
let(:user) { create(:user, :support) }
context "when org blank" do
let(:organisation) { nil }
context "when org has a signed data sharing agremeent" do
it "does not display banner" do it "does not display banner" do
expect(component.display_banner?).to eq(false) expect(component.display_banner?).to eq(false)
end expect(render.content).to be_empty
end
context "when org present" do
before do
allow(DataProtectionConfirmation).to receive(:exists?).and_call_original
end
context "when data sharing agreement present" do
it "does not display banner" do
expect(component.display_banner?).to eq(false)
end
it "verifies DSA exists for organisation" do
render
expect(DataProtectionConfirmation).to have_received(:exists?).with(organisation:, confirmed: true)
end
end
context "when data sharing agreement not present" do
let(:organisation) { create(:organisation, :without_dpc) }
it "displays the banner" do
expect(component.display_banner?).to eq(true)
end
it "produces the correct link" do
render
expect(component.data_sharing_agreement_href).to eq("/organisations/#{organisation.id}/data-sharing-agreement")
end
it "verifies DSA exists for organisation" do
render
expect(DataProtectionConfirmation).to have_received(:exists?).with(organisation:, confirmed: true)
end
end end
end end
end end

1
spec/models/user_spec.rb

@ -176,7 +176,6 @@ RSpec.describe User, type: :model do
) )
end end
it "has access to logs from all organisations" do it "has access to logs from all organisations" do
expect(user.lettings_logs.to_a).to match_array([owned_lettings_log, managed_lettings_log, other_orgs_log]) expect(user.lettings_logs.to_a).to match_array([owned_lettings_log, managed_lettings_log, other_orgs_log])
end end

Loading…
Cancel
Save