From f6168d5afb5e5cfeab6445faec61e55199ad09ab Mon Sep 17 00:00:00 2001 From: Bruce Bolt Date: Tue, 14 Feb 2023 11:05:42 +0000 Subject: [PATCH 1/5] Update seed data to include more examples This includes an organisation with mandatory 2SV and creates an application, allowing us to demonstrate the assignment of permissions to users in the development environment. --- db/seeds.rb | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/db/seeds.rb b/db/seeds.rb index f42ba928e..0f2d78c6f 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -16,11 +16,20 @@ organisation: gds, ) -test_organisation = Organisation.create!( - name: "Test Organisation", +test_organisation_without_2sv = Organisation.create!( + name: "Test Organisation without mandatory 2SV", content_id: SecureRandom.uuid, organisation_type: :ministerial_department, slug: "test-organisation", + require_2sv: false, +) + +test_organisation_with_2sv = Organisation.create!( + name: "Test Organisation with mandatory 2SV", + content_id: SecureRandom.uuid, + organisation_type: :ministerial_department, + slug: "test-organisation-with-2sv", + require_2sv: true, ) User.create!( @@ -29,7 +38,7 @@ password: "6fe552ca-d406-4c54-b7a6-041ed1ade6cd", role: :normal, confirmed_at: Time.zone.now, - organisation: test_organisation, + organisation: test_organisation_without_2sv, ) # The following user has 2SV enabled by default. Scan the QR code with your authenticator app to generate a code to login. @@ -65,7 +74,18 @@ password: "6fe552ca-d406-4c54-b7a6-041ed1ade6cd", role: :normal, confirmed_at: Time.zone.now, - organisation: test_organisation, + organisation: test_organisation_without_2sv, + require_2sv: true, + otp_secret_key: "I5X6Y3VN3CAATYQRBPAZ7KMFLK2RWYJ5", +) + +User.create!( + name: "Test User from organisation with mandatory 2SV", + email: "test.user.2sv.organisation@gov.uk", + password: "6fe552ca-d406-4c54-b7a6-041ed1ade6cd", + role: :normal, + confirmed_at: Time.zone.now, + organisation: test_organisation_with_2sv, require_2sv: true, otp_secret_key: "I5X6Y3VN3CAATYQRBPAZ7KMFLK2RWYJ5", ) @@ -79,3 +99,13 @@ confirmed_at: Time.zone.now, require_2sv: false, ) + +application = Doorkeeper::Application.create!( + name: "Test Application 1", + redirect_uri: "https://www.gov.uk", +) + +SupportedPermission.create!( + name: "Editor", + application:, +) From 435e42fd81ddaa91ec0f369b28ddfd07b6d8b315 Mon Sep 17 00:00:00 2001 From: Bruce Bolt Date: Mon, 6 Feb 2023 14:30:25 +0000 Subject: [PATCH 2/5] Allow `require_2sv` to be set for all users from an organisation This allows us to set `require_2sv` on an organisation, which will then force all their users to use 2SV, even if it is not enabled on their account. Exemptions will continue to work as before, even if a department has been mandated for 2SV. Users without an organisation (e.g. those from local authorities) are not affected. --- app/models/user.rb | 6 ++++++ test/models/user_test.rb | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/app/models/user.rb b/app/models/user.rb index 0669869ff..2d0e1355a 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -96,6 +96,12 @@ class User < ApplicationRecord end } + def require_2sv? + return require_2sv unless organisation + + (organisation.require_2sv? && !exempt_from_2sv?) || require_2sv + end + def prompt_for_2sv? return false if has_2sv? diff --git a/test/models/user_test.rb b/test/models/user_test.rb index baad2e3a1..0c2ca9678 100644 --- a/test/models/user_test.rb +++ b/test/models/user_test.rb @@ -64,6 +64,24 @@ def setup assert_nil user.reason_for_2sv_exemption assert_nil user.expiry_date_for_2sv_exemption end + + should "require 2SV for the user when it is switched on for their organisation and they are not exempt" do + organisation = create(:organisation, require_2sv: false) + user = create(:user, organisation:) + assert_not user.require_2sv? + + organisation.update!(require_2sv: true) + assert user.require_2sv? + end + + should "not require 2SV for the user when it is switched on for their organisation and they are exempt" do + organisation = create(:organisation, require_2sv: false) + user = create(:two_step_exempted_user, organisation:) + assert_not user.require_2sv? + + organisation.update!(require_2sv: true) + assert_not user.require_2sv? + end end context "#send_two_step_mandated_notification?" do From c5a4fedc5740c43ccc04cd31a351574d96456f0e Mon Sep 17 00:00:00 2001 From: Bruce Bolt Date: Mon, 6 Feb 2023 15:10:21 +0000 Subject: [PATCH 3/5] Require 2SV for new users from 2SV mandatory organisations If a user is created and they are assigned to an organisation with mandatory 2SV, this will ensure they have it enabled on their account. In a later commit, we'll stop new users being created in 2SV mandatory organisations without 2SV, but this will provide a certain block for all routes (e.g. if users are created in bulk, such as through a rake task). --- app/models/user.rb | 5 +++++ test/models/user_test.rb | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/app/models/user.rb b/app/models/user.rb index 2d0e1355a..534ab401a 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -40,6 +40,7 @@ class User < ApplicationRecord validate :organisation_admin_belongs_to_organisation validate :email_is_ascii_only validate :exemption_from_2sv_data_is_complete + validate :organisation_has_mandatory_2sv, on: :create has_many :authorisations, class_name: "Doorkeeper::AccessToken", foreign_key: :resource_owner_id has_many :application_permissions, class_name: "UserApplicationPermission", inverse_of: :user @@ -368,6 +369,10 @@ def exemption_from_2sv_data_is_complete errors.add(:reason_for_2sv_exemption, "must be present if exemption expiry date is present") if expiry_date_for_2sv_exemption.present? && reason_for_2sv_exemption.nil? end + def organisation_has_mandatory_2sv + errors.add(:require_2sv, "2-step verification is mandatory for all users from this organisation") if organisation && organisation.require_2sv? && !require_2sv + end + def fix_apostrophe_in_email email.tr!("’", "'") if email.present? && email_changed? end diff --git a/test/models/user_test.rb b/test/models/user_test.rb index 0c2ca9678..e9077d941 100644 --- a/test/models/user_test.rb +++ b/test/models/user_test.rb @@ -82,6 +82,12 @@ def setup organisation.update!(require_2sv: true) assert_not user.require_2sv? end + + should "be invalid if a new user from an organisation with mandatory 2SV but 2SV is not selected" do + organisation = create(:organisation, require_2sv: true) + user = build(:user, organisation:) + assert_not user.valid? + end end context "#send_two_step_mandated_notification?" do From 764cf8292f9c6c4938bb54243e32fdb8e70998d3 Mon Sep 17 00:00:00 2001 From: Bruce Bolt Date: Thu, 9 Feb 2023 12:27:56 +0000 Subject: [PATCH 4/5] Move 2SV checkbox to an intermediate page for new users This moves the checkbox to set up 2SV on a new account away from the form (where the name, organisation, etc) are chosen and onto another page. By doing this, we do not show the checkbox if the user is assigned to an organisation where 2SV is mandatory. When the second page is loaded, the user has already been created in the database and we only update the affected field. As we have logic in `UserUpdate` to assume that no permissions selected means we want to remove all the user's permissions, we need to add a parameter to skip that logic when updating only the 2SV options. This retains validations on the original form, so errors are notified before being taken to the second page. --- app/controllers/invitations_controller.rb | 21 +++- app/controllers/users_controller.rb | 8 +- app/policies/user_policy.rb | 1 + app/views/users/_form_fields.html.erb | 2 +- app/views/users/require_2sv.html.erb | 16 ++++ config/routes.rb | 1 + .../invitations_controller_test.rb | 18 ++++ test/integration/inviting_users_test.rb | 96 +++++++++++++++---- 8 files changed, 137 insertions(+), 26 deletions(-) create mode 100644 app/views/users/require_2sv.html.erb diff --git a/app/controllers/invitations_controller.rb b/app/controllers/invitations_controller.rb index 9e23a37fc..80c0a82c8 100644 --- a/app/controllers/invitations_controller.rb +++ b/app/controllers/invitations_controller.rb @@ -18,14 +18,17 @@ def create if (self.resource = User.find_by(email: params[:user][:email])) authorize resource flash[:alert] = "User already invited. If you want to, you can click 'Resend signup email'." - respond_with resource, location: after_invite_path_for(resource) + respond_with resource, location: users_path else # workaround for invitatable not providing a build_invitation which could be authorised before saving - user = User.new(resource_params) - user.organisation_id = resource_params[:organisation_id] + all_params = resource_params + all_params[:require_2sv] = new_user_requires_2sv(all_params.symbolize_keys) + + user = User.new(all_params) + user.organisation_id = all_params[:organisation_id] authorize user - self.resource = resource_class.invite!(resource_params, current_inviter) + self.resource = resource_class.invite!(all_params, current_inviter) if resource.errors.empty? grant_default_permissions(resource) set_flash_message :notice, :send_instructions, email: resource.email @@ -50,7 +53,11 @@ def resend private def after_invite_path_for(_resource) - users_path + if new_user_requires_2sv(resource) + users_path + else + require_2sv_user_path(resource) + end end # TODO: remove this method when we're on a version of devise_invitable which @@ -122,4 +129,8 @@ def grant_default_permissions(user) user.grant_permission(default_permission) end end + + def new_user_requires_2sv(params) + params[:organisation_id].present? && Organisation.find(params[:organisation_id]).require_2sv? + end end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index e3522e5fc..185168274 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -123,6 +123,8 @@ def reset_two_step_verification redirect_to :root, notice: "Reset 2-step verification for #{@user.email}" end + def require_2sv; end + private def load_and_authorize_user @@ -200,6 +202,10 @@ def allow_no_application_access end def user_params + if permitted_user_params[:skip_update_user_permissions] + permitted_user_params[:supported_permission_ids] = @user.supported_permission_ids + end + UserParameterSanitiser.new( user_params: permitted_user_params, current_user_role: current_user.role.to_sym, @@ -207,7 +213,7 @@ def user_params end def permitted_user_params - params.require(:user).permit(:user, :name, :email, :organisation_id, :require_2sv, :role, supported_permission_ids: []).to_h + @permitted_user_params ||= params.require(:user).permit(:user, :name, :email, :organisation_id, :require_2sv, :role, :skip_update_user_permissions, supported_permission_ids: []).to_h end def password_params diff --git a/app/policies/user_policy.rb b/app/policies/user_policy.rb index 2565fe672..26c6b0a4a 100644 --- a/app/policies/user_policy.rb +++ b/app/policies/user_policy.rb @@ -41,6 +41,7 @@ def edit_email_or_password? alias_method :update_email?, :edit_email_or_password? alias_method :update_password?, :edit_email_or_password? alias_method :mandate_2sv?, :edit? + alias_method :require_2sv?, :edit? alias_method :reset_2sv?, :edit? alias_method :reset_two_step_verification?, :edit? diff --git a/app/views/users/_form_fields.html.erb b/app/views/users/_form_fields.html.erb index 1423113fe..d296b0b8b 100644 --- a/app/views/users/_form_fields.html.erb +++ b/app/views/users/_form_fields.html.erb @@ -40,7 +40,7 @@

This user's role is set to <%= @user.role %>. They are currently exempted from 2sv, meaning that their role cannot be changed as admins are required to have 2sv.

<% end %> -<% if policy(current_user).mandate_2sv? %> +<% if policy(current_user).mandate_2sv? && @user.persisted? %>
Account security
diff --git a/app/views/users/require_2sv.html.erb b/app/views/users/require_2sv.html.erb new file mode 100644 index 000000000..4f99c2575 --- /dev/null +++ b/app/views/users/require_2sv.html.erb @@ -0,0 +1,16 @@ +<% content_for :title, "Create new user" %> + +

2-step verification settings for new user

+ +<%= form_for @user, :html => {:class => 'well'} do |f| %> + <%= f.hidden_field :skip_update_user_permissions, value: "true" %> +

+ <%= f.label :require_2sv do %> + <%= f.check_box :require_2sv %> Mandate 2-step verification for this user <%= "(this will remove their exemption)" if @user.exempt_from_2sv? %> + <% end %> +
+ User will be prompted to set up 2-step verification again the next time they sign in. +

+ + <%= f.submit "Update user", :class => 'btn btn-success' %> +<% end %> diff --git a/config/routes.rb b/config/routes.rb index 39d21481d..d26f04beb 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -42,6 +42,7 @@ delete :cancel_email_change get :event_logs patch :reset_two_step_verification + get :require_2sv end end resource :user, only: [:show] diff --git a/test/controllers/invitations_controller_test.rb b/test/controllers/invitations_controller_test.rb index 5943d0dbc..de1c452a6 100644 --- a/test/controllers/invitations_controller_test.rb +++ b/test/controllers/invitations_controller_test.rb @@ -60,6 +60,24 @@ class InvitationsControllerTest < ActionController::TestCase post :create, params: { user: { name: "Testing Org Admins", email: "testing_org_admins@example.com" } } assert_redirected_to root_path end + + should "save user and render 2SV form when user assigned to organisation that does not require 2SV" do + organisation = create(:organisation, require_2sv: false) + + post :create, params: { user: { name: "User Name", email: "person@gov.uk", organisation_id: organisation.id } } + + assert_redirected_to require_2sv_user_path(User.last) + assert_equal "User Name", User.last.name + end + + should "save user and not render 2SV form when user assigned to organisation that requires 2SV" do + organisation = create(:organisation, require_2sv: true) + + post :create, params: { user: { name: "User Name", email: "person@gov.uk", organisation_id: organisation.id } } + + assert_redirected_to users_path + assert_equal "User Name", User.last.name + end end context "POST resend" do diff --git a/test/integration/inviting_users_test.rb b/test/integration/inviting_users_test.rb index da0c59c5c..e875bba05 100644 --- a/test/integration/inviting_users_test.rb +++ b/test/integration/inviting_users_test.rb @@ -27,21 +27,70 @@ class InvitingUsersTest < ActionDispatch::IntegrationTest assert has_no_select?("Role") end - should "displays the 2SV mandating checkbox" do - visit new_user_invitation_path - assert has_field?("Mandate 2-step verification for this user") - end + context "for an organisation without mandatory 2SV" do + setup do + create(:organisation, name: "Test Organisation without 2SV", require_2sv: false) + end - should "create and notify the user" do - perform_enqueued_jobs do - visit new_user_invitation_path - fill_in "Name", with: "Fred Bloggs" - fill_in "Email", with: "fred@example.com" - click_button "Create user and send email" + should "create and notify the user with 2SV selected" do + perform_enqueued_jobs do + visit new_user_invitation_path + fill_in "Name", with: "Fred Bloggs" + fill_in "Email", with: "fred@example.com" + select "Test Organisation without 2SV", from: "Organisation" + click_button "Create user and send email" - assert_not_nil User.where(email: "fred@example.com", role: "normal").first - assert_equal "fred@example.com", last_email.to[0] - assert_match "Please confirm your account", last_email.subject + assert_equal "fred@example.com", last_email.to[0] + assert_match "Please confirm your account", last_email.subject + + assert has_field?("Mandate 2-step verification for this user") + check "Mandate 2-step verification for this user" + click_button "Update user" + + assert_not_nil User.where(email: "fred@example.com", role: "normal").last + assert_equal "fred@example.com", last_email.to[0] + assert_match "Make your Signon account more secure", last_email.subject + assert User.where(email: "fred@example.com", role: "normal").last.require_2sv? + end + end + + should "create and notify the user without 2SV selected" do + perform_enqueued_jobs do + visit new_user_invitation_path + fill_in "Name", with: "Fred Bloggs" + fill_in "Email", with: "fred@example.com" + select "Test Organisation without 2SV", from: "Organisation" + click_button "Create user and send email" + + assert has_field?("Mandate 2-step verification for this user") + click_button "Update user" + + assert_not_nil User.where(email: "fred@example.com", role: "normal").last + assert_equal "fred@example.com", last_email.to[0] + assert_match "Please confirm your account", last_email.subject + assert_equal false, User.where(email: "fred@example.com", role: "normal").last.require_2sv? + end + end + + context "for an organisation with mandatory 2SV" do + setup do + create(:organisation, name: "Test Organisation with 2SV", require_2sv: true) + end + + should "create and notify the user" do + perform_enqueued_jobs do + visit new_user_invitation_path + fill_in "Name", with: "Fred Bloggs" + fill_in "Email", with: "fred@example.com" + select "Test Organisation with 2SV", from: "Organisation" + click_button "Create user and send email" + + assert_not_nil User.where(email: "fred@example.com", role: "normal").last + assert_equal "fred@example.com", last_email.to[0] + assert_match "Please confirm your account", last_email.subject + assert User.where(email: "fred@example.com", role: "normal").last.require_2sv? + end + end end end @@ -52,6 +101,8 @@ class InvitingUsersTest < ActionDispatch::IntegrationTest fill_in "Email", with: "fred@example.com" click_button "Create user and send email" + click_button "Update user" + user = User.find_by(email: "fred@example.com") visit edit_user_path(user) @@ -80,6 +131,8 @@ class InvitingUsersTest < ActionDispatch::IntegrationTest click_button "Create user and send email" + click_button "Update user" + u = User.find_by(email: "alicia@example.com") assert_not u.has_access_to? application_one assert_includes u.permissions_for(application_one), "editor" @@ -98,6 +151,8 @@ class InvitingUsersTest < ActionDispatch::IntegrationTest fill_in "Email", with: "alicia@example.com" click_button "Create user and send email" + click_button "Update user" + u = User.find_by(email: "alicia@example.com") assert u.has_access_to? application_two assert_equal %w[editor], u.permissions_for(application_one) @@ -124,20 +179,18 @@ class InvitingUsersTest < ActionDispatch::IntegrationTest assert has_select?("Role") end - should "display the 2SV mandating checkbox" do - visit new_user_invitation_path - assert has_field?("Mandate 2-step verification for this user") - end - should "create and notify the user" do perform_enqueued_jobs do visit new_user_invitation_path fill_in "Name", with: "Fred Bloggs" select "Admin", from: "Role" fill_in "Email", with: "fred_admin@example.com" - check "Mandate 2-step verification for this user" click_button "Create user and send email" + assert has_field?("Mandate 2-step verification for this user") + check "Mandate 2-step verification for this user" + click_button "Update user" + assert_not_nil User.find_by( email: "fred_admin@example.com", role: "admin", @@ -165,6 +218,8 @@ class InvitingUsersTest < ActionDispatch::IntegrationTest click_button "Create user and send email" + click_button "Update user" + u = User.find_by(email: "alicia@example.com") assert_not u.has_access_to? application_one assert_includes u.permissions_for(application_one), "editor" @@ -183,6 +238,9 @@ class InvitingUsersTest < ActionDispatch::IntegrationTest fill_in "Email", with: "alicia@example.com" click_button "Create user and send email" + check "Mandate 2-step verification for this user" + click_button "Update user" + u = User.find_by(email: "alicia@example.com") assert u.has_access_to? application_two assert_equal %w[editor], u.permissions_for(application_one) From 525b03cd672fb01677b7967bbcd3f3a6faaf0425 Mon Sep 17 00:00:00 2001 From: Bruce Bolt Date: Thu, 9 Feb 2023 14:27:48 +0000 Subject: [PATCH 5/5] Do not show 2SV checkbox for new admin/superadmin users At the moment, we require new admin and superadmin users to have 2SV set up on their account. However we also show a checkbox to select whether 2SV is required for this user or not. The checkbox is useless, as we enable 2SV on the user's account regardless of whether the box was checked or not. This removes the checkbox for admin and superadmin users, which makes the flow match the actual behaviour. --- app/controllers/invitations_controller.rb | 2 +- .../invitations_controller_test.rb | 20 ++- test/integration/inviting_users_test.rb | 114 +++++++++++++++--- 3 files changed, 117 insertions(+), 19 deletions(-) diff --git a/app/controllers/invitations_controller.rb b/app/controllers/invitations_controller.rb index 80c0a82c8..652c0c5d6 100644 --- a/app/controllers/invitations_controller.rb +++ b/app/controllers/invitations_controller.rb @@ -131,6 +131,6 @@ def grant_default_permissions(user) end def new_user_requires_2sv(params) - params[:organisation_id].present? && Organisation.find(params[:organisation_id]).require_2sv? + (params[:organisation_id].present? && Organisation.find(params[:organisation_id]).require_2sv?) || %w[superadmin admin].include?(params[:role]) end end diff --git a/test/controllers/invitations_controller_test.rb b/test/controllers/invitations_controller_test.rb index de1c452a6..bdbc90b21 100644 --- a/test/controllers/invitations_controller_test.rb +++ b/test/controllers/invitations_controller_test.rb @@ -3,7 +3,7 @@ class InvitationsControllerTest < ActionController::TestCase setup do request.env["devise.mapping"] = Devise.mappings[:user] - @user = create(:admin_user) + @user = create(:superadmin_user) sign_in @user end @@ -78,6 +78,24 @@ class InvitationsControllerTest < ActionController::TestCase assert_redirected_to users_path assert_equal "User Name", User.last.name end + + should "not render 2SV form and saves user when user is a superadmin" do + organisation = create(:organisation, require_2sv: false) + + post :create, params: { user: { name: "User Name", email: "person@gov.uk", organisation_id: organisation.id, role: "superadmin" } } + + assert_redirected_to users_path + assert_equal "User Name", User.last.name + end + + should "not render 2SV form and saves user when user is an admin" do + organisation = create(:organisation, require_2sv: false) + + post :create, params: { user: { name: "User Name", email: "person@gov.uk", organisation_id: organisation.id, role: "admin" } } + + assert_redirected_to users_path + assert_equal "User Name", User.last.name + end end context "POST resend" do diff --git a/test/integration/inviting_users_test.rb b/test/integration/inviting_users_test.rb index e875bba05..f28e9a493 100644 --- a/test/integration/inviting_users_test.rb +++ b/test/integration/inviting_users_test.rb @@ -179,25 +179,105 @@ class InvitingUsersTest < ActionDispatch::IntegrationTest assert has_select?("Role") end - should "create and notify the user" do - perform_enqueued_jobs do - visit new_user_invitation_path - fill_in "Name", with: "Fred Bloggs" - select "Admin", from: "Role" - fill_in "Email", with: "fred_admin@example.com" - click_button "Create user and send email" + context "for roles that do not have mandatory 2SV" do + should "create and notify the user" do + perform_enqueued_jobs do + visit new_user_invitation_path + fill_in "Name", with: "Fred Bloggs" + fill_in "Email", with: "fred_admin@example.com" + click_button "Create user and send email" - assert has_field?("Mandate 2-step verification for this user") - check "Mandate 2-step verification for this user" - click_button "Update user" + assert_equal "fred_admin@example.com", last_email.to[0] + assert_match "Please confirm your account", last_email.subject + + assert has_field?("Mandate 2-step verification for this user") + check "Mandate 2-step verification for this user" + click_button "Update user" + + assert_not_nil User.find_by( + email: "fred_admin@example.com", + role: "normal", + require_2sv: true, + ) + assert_equal "fred_admin@example.com", last_email.to[0] + assert_match "Make your Signon account more secure", last_email.subject + end + end + end + + context "for user roles that have mandatory 2SV" do + setup do + create(:organisation, name: "Test Organisation without 2SV", require_2sv: false) + end + + should "create and notify the user for a superadmin" do + perform_enqueued_jobs do + visit new_user_invitation_path + fill_in "Name", with: "Fred Bloggs" + fill_in "Email", with: "fred@example.com" + select "Superadmin", from: "Role" + select "Test Organisation without 2SV", from: "Organisation" + click_button "Create user and send email" + + assert_not_nil User.where(email: "fred@example.com", role: "superadmin").last + assert_equal "fred@example.com", last_email.to[0] + assert_match "Please confirm your account", last_email.subject + assert User.where(email: "fred@example.com", role: "superadmin").last.require_2sv? + end + end + + should "create and notify the user for an admin" do + perform_enqueued_jobs do + visit new_user_invitation_path + fill_in "Name", with: "Fred Bloggs" + fill_in "Email", with: "fred@example.com" + select "Admin", from: "Role" + select "Test Organisation without 2SV", from: "Organisation" + click_button "Create user and send email" - assert_not_nil User.find_by( - email: "fred_admin@example.com", - role: "admin", - require_2sv: true, - ) - assert_equal "fred_admin@example.com", last_email.to[0] - assert_match "Please confirm your account", last_email.subject + assert_not_nil User.where(email: "fred@example.com", role: "admin").last + assert_equal "fred@example.com", last_email.to[0] + assert_match "Please confirm your account", last_email.subject + assert User.where(email: "fred@example.com", role: "admin").last.require_2sv? + end + end + end + + context "for user roles that have mandatory 2SV" do + setup do + create(:organisation, name: "Test Organisation without 2SV", require_2sv: false) + end + + should "create and notify the user for a superadmin" do + perform_enqueued_jobs do + visit new_user_invitation_path + fill_in "Name", with: "Fred Bloggs" + fill_in "Email", with: "fred@example.com" + select "Superadmin", from: "Role" + select "Test Organisation without 2SV", from: "Organisation" + click_button "Create user and send email" + + assert_not_nil User.where(email: "fred@example.com", role: "superadmin").last + assert_equal "fred@example.com", last_email.to[0] + assert_match "Please confirm your account", last_email.subject + assert User.where(email: "fred@example.com", role: "superadmin").last.require_2sv? + end + end + + should "create and notify the user for an admin" do + perform_enqueued_jobs do + visit new_user_invitation_path + fill_in "Name", with: "Fred Bloggs" + fill_in "Email", with: "fred@example.com" + select "Admin", from: "Role" + select "Test Organisation without 2SV", from: "Organisation" + click_button "Create user and send email" + + assert_not_nil User.where(email: "fred@example.com", role: "admin").last + assert_equal "fred@example.com", last_email.to[0] + assert_match "Please confirm your account", last_email.subject + assert User.where(email: "fred@example.com", role: "admin").last.require_2sv? + end end end