diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb index 2d78dc9d77..cd18ac7db9 100644 --- a/app/controllers/omniauth_callbacks_controller.rb +++ b/app/controllers/omniauth_callbacks_controller.rb @@ -1,37 +1,52 @@ # frozen_string_literal: true class OmniauthCallbacksController < ApplicationController - class LoginError < StandardError + class OmniauthError < StandardError end def login_dot_gov + try_to_login + rescue LandingPageFinder::Error => e + flash[:error] = e.message + redirect_to('/login') + rescue OmniauthError => e + Rails.logger.error e.message + flash[:error] = 'Error logging in. Please reach out to' \ + ' search@support.digitalgov.gov if the problem persists' + redirect_to('/login') + end + + private + + def try_to_login + @return_to = session[:return_to] reset_session set_id_token set_user_session - redirect_to(admin_home_page_path) - rescue LoginError => e - flash[:error] = "login internal error: #{e.message}" - redirect_to('/login') + redirect_to(destination) end - def user - @user ||= User.from_omniauth(omniauth_data) + def destination + LandingPageFinder.new(user, @return_to).landing_page + end - raise LoginError, "can't find user #{omniauth_data.info.email}" unless @user + def user + return @user if @user - raise LoginError, "login not allowed for #{@user.email}" unless @user.login_allowed? + @user = User.from_omniauth(omniauth_data) + raise OmniauthError, 'db error creating user' unless @user.persisted? @user end def omniauth_data - raise LoginError, 'no omniauth data' unless request.env['omniauth.auth'] + raise OmniauthError, 'no omniauth data' unless request.env['omniauth.auth'] request.env['omniauth.auth'] end def credentials - raise LoginError, 'no user credentials' unless omniauth_data['credentials'] + raise OmniauthError, 'no user credentials' unless omniauth_data['credentials'] omniauth_data['credentials'] end diff --git a/app/controllers/user_sessions_controller.rb b/app/controllers/user_sessions_controller.rb index 0de439a00e..dcb656606d 100644 --- a/app/controllers/user_sessions_controller.rb +++ b/app/controllers/user_sessions_controller.rb @@ -4,30 +4,20 @@ class UserSessionsController < ApplicationController before_action :require_user, only: :destroy def security_notification - redirect_to(account_path) if current_user && current_user&.complete? + return unless current_user + + landing_page = LandingPageFinder.new(current_user, params[:return_to]).landing_page + redirect_to(landing_page) end def destroy id_token = session[:id_token] reset_session current_user_session.destroy - redirect_to(logout_redirect_uri(id_token)) + redirect_to(LoginDotGovSettings.logout_redirect_uri(id_token, login_uri)) end def login_uri "#{request.protocol}#{request.host_with_port}/login" end - - def logout_redirect_uri(id_token) - base_uri = URI(Rails.application.secrets.login_dot_gov[:idp_base_url]) - URI::HTTPS.build( - host: base_uri.host, - path: '/openid_connect/logout', - query: { - id_token_hint: id_token, - post_logout_redirect_uri: login_uri, - state: '1234567890123456789012' - }.to_query - ).to_s - end end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 03224505c2..1a625a89d7 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -1,13 +1,23 @@ +# frozen_string_literal: true + class UsersController < ApplicationController layout 'sites' - before_action :require_user, :only => [:show, :edit, :update] + before_action :require_user, only: [:show, :edit, :update] before_action :set_user, except: :create + before_action :complain_if_non_gov_email, only: [:show, :edit] + + NON_GOV_EMAIL_MESSAGE = <<~MESSAGE + Because you don't have a .gov or .mil email address, we need additional information. + If you are a contractor on an active contract, please use your .gov or .mil email + address on this account, or have your federal POC email search@support.digitalgov.gov + to confirm your status. + MESSAGE def create @user = User.new(user_params) - if verify_recaptcha(:model => @user, :message => 'Word verification is incorrect') && @user.save + if verify_recaptcha(model: @user, message: 'Word verification is incorrect') && @user.save if @user.has_government_affiliated_email? - flash[:success] = "Thank you for signing up. To continue the signup process, check your inbox, so we may verify your email address." + flash[:success] = 'Thank you for signing up. To continue the signup process, check your inbox, so we may verify your email address.' else flash[:success] = "Sorry! You don't have a .gov or .mil email address so we need some more information from you before approving your account." end @@ -18,20 +28,6 @@ def create end end - def show - message = <<~MESSAGE - Because you don't have a .gov or .mil email address, we need additional information. - If you are a contractor on an active contract, please use your .gov or .mil email - address on this account, or have your federal POC email search@support.digitalgov.gov - to confirm your status. - MESSAGE - - flash[:notice] = message unless @user.has_government_affiliated_email? || - @user.approval_status == 'approved' - end - - def edit; end - def update_account @user.attributes = user_params if @user.save(context: :update_account) @@ -42,9 +38,13 @@ def update_account end end + def show; end + + def edit; end + def update - if @user.update_attributes(user_params) - flash[:success] = "Account updated!" + if @user.update(user_params) + flash[:success] = 'Account updated!' redirect_to account_url else render :edit @@ -55,8 +55,15 @@ def developer_redirect; end private + def complain_if_non_gov_email + return if @user.has_government_affiliated_email? || + @user.approval_status == 'approved' + + flash[:notice] = NON_GOV_EMAIL_MESSAGE + end + def require_user - redirect_to developer_redirect_url if super.nil? and current_user.is_developer? + redirect_to developer_redirect_url if super.nil? && current_user.is_developer? end def set_user diff --git a/app/poros/landing_page_finder.rb b/app/poros/landing_page_finder.rb new file mode 100644 index 0000000000..91d12babaf --- /dev/null +++ b/app/poros/landing_page_finder.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true + +class LandingPageFinder + include Rails.application.routes.url_helpers + + ACCESS_DENIED_TEXT = + 'Access Denied: These credentials are not recognized as valid' \ + ' for accessing Search.gov. Please reach out to' \ + ' search@support.digitalgov.gov if you believe this is in error.' + + class Error < StandardError + end + + def initialize(user, return_to) + @user = user + @return_to = return_to + end + + def landing_page + raise(Error, ACCESS_DENIED_TEXT) unless @user.login_allowed? + + destination_edit_account || + destination_original || + destination_affiliate_admin || + destination_site_page || + new_site_path + end + + private + + def destination_edit_account + edit_account_path if @user.approval_status == 'pending_approval' || !@user.complete? + end + + def destination_original + @return_to + end + + def destination_affiliate_admin + admin_home_page_path if @user.is_affiliate_admin? + end + + def destination_site_page + if @user.default_affiliate + site_path(@user.default_affiliate) + elsif !@user.affiliates.empty? + site_path(@user.affiliates.first) + end + end +end diff --git a/features/admin.feature b/features/admin.feature index 257b8a1b3d..958be258f4 100644 --- a/features/admin.feature +++ b/features/admin.feature @@ -13,12 +13,6 @@ Feature: Administration When I follow "Super Admin" in the main navigation bar Then I should be on the admin home page - # SRCH-1552 - # Commented out until we figure out how to get login.gov out of - # the loop during testing. - # When I follow "Sign Out" - # Then I should be on the login page - Scenario: Visiting the admin home page as an admin who is also an affiliate Given "affiliate_admin@fixtures.org" is an affiliate When I go to the admin home page diff --git a/features/step_definitions/user_steps.rb b/features/step_definitions/user_steps.rb index 498a36bc87..3d59406748 100644 --- a/features/step_definitions/user_steps.rb +++ b/features/step_definitions/user_steps.rb @@ -1,21 +1,8 @@ -Given /^I am logged in with email "([^"]*)"$/ do |email| - OmniAuth.config.test_mode = true - - omniauth_hash = { - uid: 'test_123', - info: { - email: email - }, - credentials: { - id_token: 'fake_id_token', - }, - } - - OmniAuth.config.add_mock('logindotgov', omniauth_hash) - visit '/auth/logindotgov' +Given /^I (?:log in|am logged in) with email "([^"]*)"$/ do |email| + mock_user_auth(email) + visit '/auth/logindotgov/callback' end - When /^I sign out$/ do email = find '#nav-auth-menu a[data-toggle=dropdown]' click_link email.text diff --git a/features/support/env.rb b/features/support/env.rb index 7c2deb78f8..dac96bf6bc 100644 --- a/features/support/env.rb +++ b/features/support/env.rb @@ -75,6 +75,11 @@ class << self end require_relative '../../spec/test_services.rb' +require_relative '../../spec/support/omniauth_helpers.rb' + +World OmniauthHelpers + +After { OmniAuth.config.mock_auth[:default] = OmniAuth::AuthHash.new({}) } EmailTemplate.load_default_templates OutboundRateLimit.load_defaults diff --git a/features/support/paths.rb b/features/support/paths.rb index 166e6e1897..72c61401fe 100644 --- a/features/support/paths.rb +++ b/features/support/paths.rb @@ -58,6 +58,8 @@ def path_to(page_name) signup_path when /the user account page/ account_path + when /the user edit account page/ + edit_account_path when /the reports homepage/ monthly_reports_path when /the affiliate analytics query search results page/ diff --git a/features/user_sessions.feature b/features/user_sessions.feature index 48538fce0d..828f6671ea 100644 --- a/features/user_sessions.feature +++ b/features/user_sessions.feature @@ -4,37 +4,21 @@ Feature: User sessions Scenario: Already logged-in user visits login page Given I am logged in with email "affiliate_admin@fixtures.org" And I go to the login page - Then I should see "Contact Information" + Then I should be on the admin home page - # to be updated in SRCH-947 for login.gov - @wip - Scenario: Affiliate admin should be on the site home page upon successful login - Given I am on the login page - Then I should see the browser page titled "Search.gov Login" - And I log in with email "affiliate_admin@fixtures.org" and password "test1234!" - Then I should be on the new site page - - # to be updated in SRCH-947 for login.gov - @wip Scenario: Affiliate manager should be on the site home page upon successful login - When I am logged in with email "affiliate_manager@fixtures.org" + When I log in with email "affiliate_manager@fixtures.org" Then I should be on the gobiernousa's Dashboard page - # to be updated in SRCH-946 for login.gov - @wip - Scenario: Affiliate manager with not approved status should not be able to login - When I log in with email "affiliate_manager_with_not_approved_status@fixtures.org" and password "test1234!" - Then I should not see "Admin Center" + Scenario: Affiliate admin should be on the admin home page upon successful login + When I log in with email "affiliate_admin@fixtures.org" + Then I should be on the admin home page - # to be updated in SRCH-946 for login.gov - @wip Scenario: User is not approved - Given I am logged in with email "affiliate_manager_with_not_approved_status@fixtures.org" - Then I should be on the user session page - And I should see "These credentials are not recognized as valid for accessing Search.gov. Please contact search@support.digitalgov.gov if you believe this is in error." + When I log in with email "affiliate_manager_with_not_approved_status@fixtures.org" + Then I should see "Security Notification" + And I should see "These credentials are not recognized as valid for accessing Search.gov. Please reach out to search@support.digitalgov.gov if you believe this is in error." - # to be updated in SRCH-945 for login.gov - @wip Scenario: User's session expires after 1 hour Given the following Users exist: | first_name | last_name | email | approval_status | diff --git a/features/users.feature b/features/users.feature index 7eff887710..941a2445b1 100644 --- a/features/users.feature +++ b/features/users.feature @@ -1,6 +1,5 @@ Feature: Users - @javascript Scenario: Logged-in, approved non-developer user visits account page Given I am logged in with email "affiliate_admin@fixtures.org" When I go to the user account page @@ -11,7 +10,6 @@ Feature: Users And I should see "Agency" And I should see "Email" - @javascript Scenario: User goes to login page and is directed to the security notification first Given I go to the login page Then I should see "Security Notification" @@ -41,23 +39,21 @@ Feature: Users When I open the email Then I should see "Welcome to Search.gov" in the email subject - @javascript Scenario: Registering as a new affiliate user without government affiliated email address Given the following Users exist: | first_name | last_name | email | | Joe | Schno | jschmo@random.com | And I am logged in with email "jschmo@random.com" - Then I should be on the user account page + Then I should be on the user edit account page And I should see "Because you don't have a .gov or .mil email address, we need additional information." - @javascript Scenario: Logging in as a new approved affiliate user without government affiliated email address Given the following Users exist: | first_name | last_name | email | approval_status | | Joe | Schmo | jschmo@random.com | approved | And I am logged in with email "jschmo@random.com" - Then I should be on the user account page + Then I should be on the new site page And I should not see "Because you don't have a .gov or .mil email address, we need additional information." @javascript @@ -101,7 +97,7 @@ Feature: Users And I should see "Because you don't have a .gov or .mil email address, your account is pending approval." And I should be on the user account page - Scenario: Logging in as a developer user + Scenario: Logging in as a developer user Given I am logged in with email "developer@fixtures.org" When I go to the user account page Then I should see "Our Recalls API Has Moved" diff --git a/lib/login_dot_gov_settings.rb b/lib/login_dot_gov_settings.rb new file mode 100644 index 0000000000..dd3be7ab82 --- /dev/null +++ b/lib/login_dot_gov_settings.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +# Central place for holding login.gov settings. Ideally, the authlogic +# plugin would handle everything, but it doesn't. Long-term, we should +# be trying to move everything to one place. + +class LoginDotGovSettings + # login.gov requires us to specify a 'state' parameter for some API + # calls, which it then passes back to us in the response. We make no + # use of that whatsoever, so here's a constant value that we always + # use when making such API calls. + UNUSED_STATE_DATA = '1234567890123456789012' + HOST = URI(Rails.application.secrets.login_dot_gov[:idp_base_url]).host + + def self.logout_redirect_uri(id_token, login_uri) + query = { + id_token_hint: id_token, + post_logout_redirect_uri: login_uri, + state: UNUSED_STATE_DATA + } + + URI::HTTPS.build( + host: HOST, + path: '/openid_connect/logout', + query: query.to_query + ).to_s + end +end diff --git a/spec/controllers/omniauth_callbacks_controller_spec.rb b/spec/controllers/omniauth_callbacks_controller_spec.rb index 203c00e716..7816c49ba2 100644 --- a/spec/controllers/omniauth_callbacks_controller_spec.rb +++ b/spec/controllers/omniauth_callbacks_controller_spec.rb @@ -11,14 +11,15 @@ end it 'calls reset_session' do - expect_any_instance_of(ActionController::Metal).to receive(:reset_session) + allow(controller).to receive(:reset_session) get_login_dot_gov + + expect(controller).to have_received(:reset_session) end context 'when the login is successful' do before { get_login_dot_gov } - it { is_expected.to redirect_to(admin_home_page_path) } it { is_expected.to assign_to(:user).with(user) } end @@ -33,11 +34,12 @@ before do allow(UserSession).to receive(:create).with(user).and_return(session) + allow(session).to receive(:secure=).with(secure_cookies) + get_login_dot_gov end it 'sets the session security' do - expect(session).to receive(:secure=).with(secure_cookies) - get_login_dot_gov + expect(session).to have_received(:secure=).with(secure_cookies) end end diff --git a/spec/controllers/user_sessions_controller_spec.rb b/spec/controllers/user_sessions_controller_spec.rb index 48beb3bfb5..5bb475990d 100644 --- a/spec/controllers/user_sessions_controller_spec.rb +++ b/spec/controllers/user_sessions_controller_spec.rb @@ -15,7 +15,9 @@ before { get :security_notification } - it { is_expected.to redirect_to(account_path) } + let(:expected_site_path) { site_path(id: current_user.affiliates.first.id) } + + it { is_expected.to redirect_to(expected_site_path) } end end diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb index 8b1db7a265..b55f9639b2 100644 --- a/spec/controllers/users_controller_spec.rb +++ b/spec/controllers/users_controller_spec.rb @@ -133,7 +133,7 @@ expect(current_user).to receive(:save). with( context: :update_account ).and_return(false) - update_account + update_account end it { is_expected.to assign_to(:user).with(current_user) } @@ -162,9 +162,9 @@ for(:update, params: { user: update_params }) end - context 'when the User#update_attributes was successfully' do + context 'when the User#update was successfully' do before do - expect(current_user).to receive(:update_attributes). + expect(current_user).to receive(:update). with(update_params).and_return(true) update_user @@ -175,9 +175,9 @@ it { is_expected.to set_flash.to('Account updated!') } end - context 'when the User#update_attributes failed' do + context 'when the User#update failed' do before do - expect(current_user).to receive(:update_attributes).with(update_params). + expect(current_user).to receive(:update).with(update_params). and_return(false) update_user diff --git a/spec/fixtures/affiliates.yml b/spec/fixtures/affiliates.yml index 9dac988b8c..6266b76dc2 100644 --- a/spec/fixtures/affiliates.yml +++ b/spec/fixtures/affiliates.yml @@ -135,4 +135,9 @@ i14y_affiliate: <<: *DEFAULTS display_name: I14y Affiliate name: i14y_affiliate - gets_i14y_results: true \ No newline at end of file + gets_i14y_results: true + +affiliate_for_user_with_default_site: + <<: *DEFAULTS + display_name: Default Site + name: default_site diff --git a/spec/fixtures/memberships.yml b/spec/fixtures/memberships.yml index e469b2807b..20f823baa1 100644 --- a/spec/fixtures/memberships.yml +++ b/spec/fixtures/memberships.yml @@ -29,3 +29,6 @@ nine: ten: affiliate: :site_with_one_user user: :affiliate_manager_with_one_site +eleven: + affiliate: :affiliate_for_user_with_default_site + user: :affiliate_manager_with_a_default_site diff --git a/spec/fixtures/users.yml b/spec/fixtures/users.yml index a3382abb5a..f9b49088cd 100644 --- a/spec/fixtures/users.yml +++ b/spec/fixtures/users.yml @@ -79,6 +79,16 @@ affiliate_without_contact_info: last_name: Smith welcome_email_sent: true +affiliate_manager_with_a_default_site: + <<: *DEFAULTS + email: affiliate_with_a_default_site@fixtures.org + is_affiliate_admin: false + is_affiliate: true + first_name: Has A Default Site + last_name: Smith + welcome_email_sent: true + default_affiliate: :affiliate_for_user_with_default_site + marilyn: <<: *DEFAULTS email: marilyn@fixtures.org diff --git a/spec/lib/tasks/reports_spec.rb b/spec/lib/tasks/reports_spec.rb index 4b861b0955..79f19579b4 100644 --- a/spec/lib/tasks/reports_spec.rb +++ b/spec/lib/tasks/reports_spec.rb @@ -57,21 +57,21 @@ end it 'should deliver an email to each user' do - expect(Emailer).to receive(:affiliate_monthly_report).with(anything(), Date.yesterday).exactly(3).times.and_return @emailer + expect(Emailer).to receive(:affiliate_monthly_report).with(anything(), Date.yesterday).exactly(4).times.and_return @emailer @rake[task_name].invoke end context 'when a year/month is passed as a parameter' do it 'should deliver the affiliate monthly report to each user with the specified date' do - expect(Emailer).to receive(:affiliate_monthly_report).with(anything(), Date.parse('2012-04-01')).exactly(3).times.and_return @emailer + expect(Emailer).to receive(:affiliate_monthly_report).with(anything(), Date.parse('2012-04-01')).exactly(4).times.and_return @emailer @rake[task_name].invoke('2012-04') end end context 'when Emailer raises an exception' do it 'should log it and proceed to the next user' do - expect(Emailer).to receive(:affiliate_monthly_report).with(anything(), Date.parse('2012-04-01')).exactly(3).times.and_raise Net::SMTPFatalError - expect(Rails.logger).to receive(:warn).exactly(3).times + expect(Emailer).to receive(:affiliate_monthly_report).with(anything(), Date.parse('2012-04-01')).exactly(4).times.and_raise Net::SMTPFatalError + expect(Rails.logger).to receive(:warn).exactly(4).times @rake[task_name].invoke('2012-04') end end @@ -91,21 +91,21 @@ end it 'should deliver an email to each user' do - expect(Emailer).to receive(:affiliate_yearly_report).with(anything(), Date.current.year).exactly(3).times.and_return @emailer + expect(Emailer).to receive(:affiliate_yearly_report).with(anything(), Date.current.year).exactly(4).times.and_return @emailer @rake[task_name].invoke end context 'when a year is passed as a parameter' do it 'should deliver the affiliate yearly report to each user for the specified year' do - expect(Emailer).to receive(:affiliate_yearly_report).with(anything(), 2011).exactly(3).times.and_return @emailer + expect(Emailer).to receive(:affiliate_yearly_report).with(anything(), 2011).exactly(4).times.and_return @emailer @rake[task_name].invoke('2011') end end context 'when Emailer raises an exception' do it 'should log it and proceed to the next user' do - expect(Emailer).to receive(:affiliate_yearly_report).with(anything(), Date.current.year).exactly(3).times.and_raise Net::SMTPFatalError - expect(Rails.logger).to receive(:warn).exactly(3).times + expect(Emailer).to receive(:affiliate_yearly_report).with(anything(), Date.current.year).exactly(4).times.and_raise Net::SMTPFatalError + expect(Rails.logger).to receive(:warn).exactly(4).times @rake[task_name].invoke end end diff --git a/spec/poros/landing_page_finder_spec.rb b/spec/poros/landing_page_finder_spec.rb new file mode 100644 index 0000000000..6b234d0588 --- /dev/null +++ b/spec/poros/landing_page_finder_spec.rb @@ -0,0 +1,126 @@ +# frozen_string_literal: true + +describe LandingPageFinder do + describe '#landing_page' do + include Rails.application.routes.url_helpers + + let(:user) { nil } + let(:return_to) { nil } + let(:finder) { described_class.new(user, return_to) } + + context 'with a user who is not approved' do + let(:user) { users(:affiliate_manager_with_not_approved_status) } + + it 'raises an error' do + expect { finder.landing_page }. + to raise_error(LandingPageFinder::Error, + /Access Denied: These credentials are not recognized as valid/) + end + end + + context 'with a user who is pending approval' do + let(:user) { users(:affiliate_manager_with_pending_approval_status) } + + it 'says they go to the "edit account" page' do + expect(finder.landing_page).to eq(edit_account_path) + end + + context 'when if there is a return_to page' do + let(:return_to) { '/elsewhere' } + + it 'says they go to the edit account page ' do + expect(finder.landing_page).to eq(edit_account_path) + end + end + end + + context 'with a user who is incomplete' do + let(:user) { users(:no_last_name) } + + it 'says they go to the "edit account" page' do + expect(finder.landing_page).to eq(edit_account_path) + end + + context 'when there is a return_to page' do + let(:return_to) { '/oz' } + + it 'says they go to the edit account page ' do + expect(finder.landing_page).to eq(edit_account_path) + end + end + end + + context 'with a valid user and a return_to page' do + let(:user) { users(:affiliate_manager) } + let(:return_to) { '/barsoom' } + + it 'says they should go to the return_to page' do + expect(finder.landing_page).to eq(return_to) + end + end + + context 'with a user who is an affiliate admin' do + let(:user) { users(:affiliate_admin) } + + it 'says they go to the "admin home" page' do + expect(finder.landing_page).to eq(admin_home_page_path) + end + + context 'when is a return_to page' do + let(:return_to) { '/nyc' } + + it 'says they go to the return_to page ' do + expect(finder.landing_page).to eq(return_to) + end + end + end + + context 'with a user who has a default site set' do + let(:user) { users(:affiliate_manager_with_a_default_site) } + + it 'says they go to the page for the site' do + expect(finder.landing_page).to eq(site_path(user.default_affiliate)) + end + + context 'when there is a return_to page' do + let(:return_to) { '/pittsburgh' } + + it 'says they go to the return_to page ' do + expect(finder.landing_page).to eq(return_to) + end + end + end + + context 'with a user who has no default site, but is an affiliate' do + let(:user) { users(:affiliate_manager_with_one_site) } + + context 'when there is a return_to page' do + let(:return_to) { '/reno' } + + it 'says they go to the return_to page ' do + expect(finder.landing_page).to eq(return_to) + end + end + + it 'says they go to the page for the first site they are affiliated with' do + expect(finder.landing_page).to eq(site_path(user.affiliates.first)) + end + end + + context 'with a user who is not affiliated with any sites' do + let(:user) { users(:affiliate_manager_with_no_affiliates) } + + it 'says they go to the new site page' do + expect(finder.landing_page).to eq(new_site_path) + end + + context 'when there is a return_to page' do + let(:return_to) { '/rockville' } + + it 'says they go to the return_to page ' do + expect(finder.landing_page).to eq(return_to) + end + end + end + end +end diff --git a/spec/support/landing_page_behavior.rb b/spec/support/landing_page_behavior.rb new file mode 100644 index 0000000000..2624db800b --- /dev/null +++ b/spec/support/landing_page_behavior.rb @@ -0,0 +1,135 @@ +# frozen_string_literal: true + +shared_examples 'a landing page' do + context 'when the user is pending approval' do + let(:user_approval_status) { 'pending_approval' } + + it 'is the users account page' do + expect(page).to have_current_path(edit_account_path, ignore_query: true) + end + + context 'when they specified an explicit destination' do + let(:explicit_destination) { '/sites/new' } + + it 'is the users account page' do + expect(page).to have_current_path(edit_account_path, ignore_query: true) + end + end + end + + context 'when the user is not complete because missing a first name' do + let(:user_first_name) { nil } + + it 'is the users account page' do + expect(page).to have_current_path(edit_account_path, ignore_query: true) + end + + context 'when they specified an explicit destination' do + let(:explicit_destination) { '/sites/new' } + + it 'is the users account page' do + expect(page).to have_current_path(edit_account_path, ignore_query: true) + end + end + end + + context 'when the user is not complete because missing a last name' do + let(:user_last_name) { nil } + + it 'is the users account page' do + expect(page).to have_current_path(edit_account_path, ignore_query: true) + end + + context 'when they specified an explicit destination' do + let(:explicit_destination) { '/sites/new' } + + it 'is the users account page' do + expect(page).to have_current_path(edit_account_path, ignore_query: true) + end + end + end + + context 'when the user is not complete because missing an organization name' do + let(:user_organization_name) { nil } + + it 'is the users account page' do + expect(page).to have_current_path(edit_account_path, ignore_query: true) + end + + context 'when they specified an explicit destination' do + let(:explicit_destination) { '/sites/new' } + + it 'is the users account page' do + expect(page).to have_current_path(edit_account_path, ignore_query: true) + end + end + end + + context 'when the user is not associated with any affiliates' do + let(:user_affiliates) { [] } + + it 'is the new site page' do + expect(page).to have_current_path(new_site_path, ignore_query: true) + end + + context 'when they specified an explicit destination' do + let(:explicit_destination) { '/sites/new' } + + it 'is the specified destination' do + expect(page).to have_current_path(explicit_destination) + end + end + end + + context 'when the user is a member of at least one affiliate' do + let(:user_affiliates) { [first_affiliate, second_affiliate] } + + it 'is the first affiliate the user is a member of' do + expect(page).to have_current_path(site_path(first_affiliate), ignore_query: true) + end + + context 'when they specified an explicit destination' do + let(:explicit_destination) { '/sites/new' } + + it 'is the specified destination' do + expect(page).to have_current_path(explicit_destination) + end + end + end + + context 'when the user has a default affiliate' do + let(:user_affiliates) { [first_affiliate, second_affiliate] } + let(:user_default_affiliate) { second_affiliate } + + it 'is the default affiliate' do + expect(page).to have_current_path( + site_path(user_default_affiliate), + ignore_query: true + ) + end + + context 'when they specified an explicit destination' do + let(:explicit_destination) { '/sites/new' } + + it 'is the specified destination' do + expect(page).to have_current_path(explicit_destination) + end + end + end + + context 'when the user is a super admin' do + let(:user_is_super_admin) { true } + + it 'is the admin page' do + expect(page).to have_current_path(admin_home_page_path, ignore_query: true) + end + + context 'when they specified an explicit destination' do + let(:explicit_destination) { '/sites/new' } + + it 'is the specified destination' do + expect(page).to have_current_path(explicit_destination) + end + end + end +end diff --git a/spec/support/login_user_context.rb b/spec/support/login_user_context.rb new file mode 100644 index 0000000000..728ce5dabb --- /dev/null +++ b/spec/support/login_user_context.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true + +shared_context 'with a logged in user' do + let(:explicit_destination) { nil } + + before do + stub_const('ACCESS_DENIED_TEXT', 'Access Denied') + login(user) if user + end + + let(:first_affiliate) do + Affiliate.create(website: 'https://first-affiliate.gov', + display_name: 'First Affiliate', + name: 'first') + end + + let(:second_affiliate) do + Affiliate.create(website: 'https://second-affiliate.gov', + display_name: 'Second Affiliate', + name: 'second') + end + + let(:user_approval_status) { 'approved' } + let(:user_first_name) { 'firstname' } + let(:user_last_name) { 'lastname' } + let(:user_organization_name) { 'organization' } + let(:user_affiliates) { [] } + let(:user_default_affiliate) { nil } + let(:user_is_super_admin) { false } + + let(:user) do + user = User.create( + email: 'fake.user@agency.gov', + first_name: user_first_name, + last_name: user_last_name, + organization_name: user_organization_name, + approval_status: user_approval_status, + is_affiliate_admin: user_is_super_admin + ) + + user.inviter = user + user.approval_status = user_approval_status + user.affiliates = user_affiliates + user.default_affiliate = user_default_affiliate + user.save! + + user + end +end diff --git a/spec/support/shared_sites_controller_shared_behavior.rb b/spec/support/shared_sites_controller_shared_behavior.rb index 3893bffdce..94dfb9065d 100644 --- a/spec/support/shared_sites_controller_shared_behavior.rb +++ b/spec/support/shared_sites_controller_shared_behavior.rb @@ -1,5 +1,6 @@ -shared_examples 'restricted to approved user' do |request_method, action, parameters = nil| +# frozen_string_literal: true +shared_examples 'restricted to approved user' do |request_method, action, parameters = nil| context 'when user is not logged in' do it 'should redirect to login page' do send request_method, action, params: parameters @@ -16,8 +17,7 @@ end end - # login.gov - commented out till SRCH-862 - pending 'when user is pending contact information status' do + describe 'when user is pending contact information status' do before { UserSession.create(users(:affiliate_manager_with_pending_contact_information_status)) } it 'should redirect to affiliates page' do diff --git a/spec/system/authorization_spec.rb b/spec/system/authorization_spec.rb new file mode 100644 index 0000000000..707c97ccf6 --- /dev/null +++ b/spec/system/authorization_spec.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +context 'when a user is logged in' do + include_context 'log in site admin' + + context 'when the user is set to not_approved' do + before do + user.update!(approval_status: 'not_approved') + end + + it 'prevents the user from visiting more pages' do + visit new_site_path + expect(page).to have_content('Security Notification') + end + end +end diff --git a/spec/system/login_dot_gov_callback_spec.rb b/spec/system/login_dot_gov_callback_spec.rb new file mode 100644 index 0000000000..70306f86b3 --- /dev/null +++ b/spec/system/login_dot_gov_callback_spec.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'The login.gov callback page (GET auth_logindotgov_callback)' do + include_context 'with a logged in user' + + before do + allow_any_instance_of(ActionDispatch::Request::Session).to receive(:[]). + and_call_original + allow_any_instance_of(ActionDispatch::Request::Session).to receive(:[]). + with(:return_to). + and_return(explicit_destination) + + visit auth_logindotgov_callback_path + end + + it_behaves_like 'a landing page' +end diff --git a/spec/system/login_page_spec.rb b/spec/system/login_page_spec.rb new file mode 100644 index 0000000000..2c459dfead --- /dev/null +++ b/spec/system/login_page_spec.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'The login page (GET login_dot_gov)' do + include_context 'with a logged in user' + + before do + if explicit_destination + visit "#{login_path}?return_to=#{explicit_destination}" + else + visit login_path + end + end + + it_behaves_like 'a landing page' +end