diff --git a/app/controllers/registrar/current_user_controller.rb b/app/controllers/registrar/current_user_controller.rb new file mode 100644 index 000000000..4661318e7 --- /dev/null +++ b/app/controllers/registrar/current_user_controller.rb @@ -0,0 +1,12 @@ +class Registrar + class CurrentUserController < BaseController + skip_authorization_check + + def switch + new_user = ApiUser.find(params[:new_user_id]) + sign_in(new_user) if new_user.identity_code == current_user.identity_code + + redirect_to :back, notice: t('.switched', new_user: new_user) + end + end +end diff --git a/app/controllers/registrar/sessions_controller.rb b/app/controllers/registrar/sessions_controller.rb index a9317e701..6bf31b03a 100644 --- a/app/controllers/registrar/sessions_controller.rb +++ b/app/controllers/registrar/sessions_controller.rb @@ -61,27 +61,6 @@ class Registrar end end - # rubocop:enable Metrics/MethodLength - # rubocop:enable Metrics/AbcSize - - def switch_user - @api_user = ApiUser.find(params[:id]) - - unless Rails.env.development? - unless @api_user.registrar.registrar_ip_white?(request.ip) - flash[:alert] = I18n.t(:ip_is_not_whitelisted) - redirect_to :back and return - end - end - - sign_in @api_user if @api_user.identity_code == current_user.identity_code - - redirect_to registrar_root_url - end - - # rubocop:enable Metrics/CyclomaticComplexity - # rubocop:enable Metrics/PerceivedComplexity - def id @user = ApiUser.find_by_idc_data(request.env['SSL_CLIENT_S_DN']) diff --git a/app/models/api_user.rb b/app/models/api_user.rb index 6928a933f..a5030c096 100644 --- a/app/models/api_user.rb +++ b/app/models/api_user.rb @@ -51,11 +51,6 @@ class ApiUser < User find_by(identity_code: identity_code) end - - def all_by_identity_code(identity_code) - ApiUser.where(identity_code: identity_code) - .where("identity_code is NOT NULL and identity_code != ''").includes(:registrar) - end end def registrar_typeahead @@ -93,4 +88,10 @@ class ApiUser < User md5 = OpenSSL::Digest::MD5.new(cert.to_der).to_s certificates.api.exists?(md5: md5, common_name: cn) end + + def linked_users + self.class.where(identity_code: identity_code) + .where("identity_code is NOT NULL and identity_code != ''") + .where.not(id: id) + end end diff --git a/app/views/registrar/base/_navbar.haml b/app/views/registrar/base/_navbar.haml index 608fb9cb4..160b455ed 100644 --- a/app/views/registrar/base/_navbar.haml +++ b/app/views/registrar/base/_navbar.haml @@ -22,7 +22,8 @@ = "#{current_user} (#{current_user.roles.first}) - #{current_user.registrar}" %span.caret %ul.dropdown-menu{role: "menu"} - - ApiUser.all_by_identity_code(current_user.identity_code).each do |x| - %li= link_to "#{x} (#{x.roles.first}) - #{x.registrar}", "/registrar/switch_user/#{x.id}" + - current_user.linked_users.each do |user| + %li= link_to "#{user} (#{user.roles.first}) - #{user.registrar}", registrar_switch_current_user_path(user), + id: "switch-current-user-#{user.id}-btn" - if user_signed_in? %li= link_to t(:log_out_), '/registrar/logout' diff --git a/config/locales/registrar/current_user.en.yml b/config/locales/registrar/current_user.en.yml new file mode 100644 index 000000000..5f25cd81f --- /dev/null +++ b/config/locales/registrar/current_user.en.yml @@ -0,0 +1,5 @@ +en: + registrar: + current_user: + switch: + switched: You are now signed in as a user "%{new_user}" diff --git a/config/routes.rb b/config/routes.rb index e9fb61989..e19028a68 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -47,6 +47,8 @@ Rails.application.routes.draw do get 'logout' => '/devise/sessions#destroy' end + get 'current_user/switch/:new_user_id', to: 'current_user#switch', as: :switch_current_user + resources :domains do collection do post 'update', as: 'update' diff --git a/spec/features/registrar/current_user/switch_spec.rb b/spec/features/registrar/current_user/switch_spec.rb new file mode 100644 index 000000000..a4c19bcba --- /dev/null +++ b/spec/features/registrar/current_user/switch_spec.rb @@ -0,0 +1,16 @@ +require 'rails_helper' + +RSpec.feature 'Registrar area current user switch', settings: false do + given!(:current_user) { create(:api_user, id: 1, identity_code: 'test') } + given!(:new_user) { create(:api_user, id: 2, identity_code: 'test', username: 'new-user-name') } + + background do + sign_in_to_registrar_area(user: current_user) + end + + it 'switches current user' do + visit registrar_root_path + click_link_or_button 'switch-current-user-2-btn' + expect(page).to have_text('You are now signed in as a user "new-user-name"') + end +end diff --git a/spec/models/api_user_spec.rb b/spec/models/api_user_spec.rb index 20ac4afff..fc5388b8c 100644 --- a/spec/models/api_user_spec.rb +++ b/spec/models/api_user_spec.rb @@ -1,24 +1,8 @@ require 'rails_helper' RSpec.describe ApiUser do - context 'class methods' do - before do - Fabricate(:api_user, identity_code: '') - Fabricate(:api_user, identity_code: 14212128025) - end - - it 'should return all api users with given identity code' do - ApiUser.all_by_identity_code('14212128025').size.should == 1 - ApiUser.all_by_identity_code(14212128025).size.should == 1 - end - - it 'should not return any api user with blank identity code' do - ApiUser.all_by_identity_code('').size.should == 0 - end - end - context 'with invalid attribute' do - before :all do + before do @api_user = ApiUser.new end @@ -43,7 +27,7 @@ RSpec.describe ApiUser do end context 'with valid attributes' do - before :all do + before do @api_user = Fabricate(:api_user) end @@ -74,4 +58,39 @@ RSpec.describe ApiUser do expect(described_class.min_password_length).to eq(6) end end + + describe '#linked_users' do + it 'returns users with the same identity code' do + api_user = create(:api_user, id: 1, identity_code: 'test') + create(:api_user, id: 2, identity_code: 'test') + + expect(api_user.linked_users.ids).to include(2) + end + + it 'does not return users with another identity code' do + api_user = create(:api_user, id: 1, identity_code: 'test') + create(:api_user, id: 2, identity_code: 'another') + + expect(api_user.linked_users.ids).to_not include(2) + end + + it 'does not return itself' do + api_user = create(:api_user) + expect(api_user.linked_users).to be_empty + end + + it 'returns none if identity code is absent' do + api_user = create(:api_user, identity_code: nil) + create(:api_user, identity_code: nil) + + expect(api_user.linked_users).to be_empty + end + + it 'returns none if identity code is empty' do + api_user = create(:api_user, identity_code: '') + create(:api_user, identity_code: '') + + expect(api_user.linked_users).to be_empty + end + end end diff --git a/spec/requests/registrar/current_user_spec.rb b/spec/requests/registrar/current_user_spec.rb new file mode 100644 index 000000000..77d69c76b --- /dev/null +++ b/spec/requests/registrar/current_user_spec.rb @@ -0,0 +1,53 @@ +require 'rails_helper' + +RSpec.describe 'Registrar current user', db: false do + describe 'GET /registrar/current_user/switch/2' do + context 'when user is authenticated', db: true do + let!(:current_user) { create(:api_user, id: 1, identity_code: 'test') } + let!(:new_user) { create(:api_user, id: 2, identity_code: 'test') } + + before do + sign_in_to_registrar_area(user: current_user) + end + + context 'when ip is allowed' do + let(:restricted_ip) { instance_double(Authorization::RestrictedIP, + can_access_registrar_area?: true) } + + before do + allow(Authorization::RestrictedIP).to receive(:new).and_return(restricted_ip) + end + + specify do + make_request + expect(response).to redirect_to('http://previous.url') + end + end + + context 'when ip is not allowed' do + let(:restricted_ip) { instance_double(Authorization::RestrictedIP, + can_access_registrar_area?: false) } + + before do + allow(Authorization::RestrictedIP).to receive(:new).and_return(restricted_ip) + end + + specify do + make_request + expect(response).to redirect_to(registrar_login_url) + end + end + end + + context 'when user is not authenticated' do + specify do + make_request + expect(response).to redirect_to(registrar_login_url) + end + end + + def make_request + get '/registrar/current_user/switch/2', nil, { 'HTTP_REFERER' => 'http://previous.url' } + end + end +end