diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 57036cabe..d75f82438 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -221,8 +221,14 @@ private @user.errors.add :phone end - if user_params.key?(:organisation_id) && user_params[:organisation_id].blank? - @user.errors.add :organisation_id, :blank + if user_params.key?(:organisation_id) + if user_params[:organisation_id].blank? + @user.errors.add :organisation_id, :blank + elsif !@user.role_is_allowed_to_be_in_organisation?(override_organisation_id: user_params[:organisation_id].to_i) + # this will also be flagged by the validation in user.rb. + # for convenience we show the error early before they go through the change org flow (involves reassigning logs). + @user.errors.add :organisation_id, I18n.t("validations.user.support_user_in_wrong_organisation.change_organisation") + end end end diff --git a/app/models/user.rb b/app/models/user.rb index ea8289e53..e8b68bac3 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -25,6 +25,7 @@ class User < ApplicationRecord validates :organisation_id, presence: true validate :organisation_not_merged + validate :support_user_is_in_correct_organisation has_paper_trail ignore: %w[last_sign_in_at current_sign_in_at @@ -390,6 +391,11 @@ class User < ApplicationRecord end end + def role_is_allowed_to_be_in_organisation?(override_organisation_id: nil) + return true unless support? && FeatureToggle.support_organisation_allow_list.present? + FeatureToggle.support_organisation_allow_list.include?(override_organisation_id || organisation_id) + end + protected # Checks whether a password is needed or not. For validations only. @@ -407,6 +413,16 @@ private end end + def support_user_is_in_correct_organisation + return if role_is_allowed_to_be_in_organisation? + + if role_changed? + errors.add :organisation_id, I18n.t("validations.user.support_user_in_wrong_organisation.change_role") + else + errors.add :organisation_id, I18n.t("validations.user.support_user_in_wrong_organisation.change_organisation") + end + end + def send_data_protection_confirmation_reminder return unless persisted? return unless is_dpo? diff --git a/app/services/feature_toggle.rb b/app/services/feature_toggle.rb index 2f301294c..3fcd15a74 100644 --- a/app/services/feature_toggle.rb +++ b/app/services/feature_toggle.rb @@ -34,4 +34,11 @@ class FeatureToggle def self.sales_export_enabled? Time.zone.now >= Time.zone.local(2025, 4, 1) || (Rails.env.review? || Rails.env.staging?) end + + # IDs of organisations a user must be in to be allowed the support role + # if nil this feature will be disabled + def self.support_organisation_allow_list + return [1] if Rails.env.production? + return [1] if Rails.env.development? + end end diff --git a/config/locales/en.yml b/config/locales/en.yml index 26a834e5d..843d1da8b 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -260,6 +260,10 @@ en: blank: "Enter an email address." role: invalid: "Role must be data accessor, data provider or data coordinator." + user: + support_user_in_wrong_organisation: + change_role: "You cannot create a support account type for a user in this organisation. Support accounts should only be created for MHCLG and contractor staff as they are administrator level accounts with access to all organisations' data. Any support accounts for housing organisations would be a data protection breach." + change_organisation: "You cannot move a user with a support account to a non-MHCLG organisation. If you need to move the user, change their role type to data coordinator or data provider." setup: saledate: