Commit 6ca5cc83 authored by Robert Hunt's avatar Robert Hunt Committed by Mayra Cabrera

Add revoke button to managed groups credentials inventory

- Updated revoke_button_available? restriction to check for group
feature flag
- Added new routes for managed groups revoke
- Updated the revoke service to support no token being passed
- Updated the inventory actions to properly render 404
- Added tests
parent 84bfd7a7
...@@ -14,6 +14,7 @@ class PersonalAccessTokensFinder ...@@ -14,6 +14,7 @@ class PersonalAccessTokensFinder
tokens = PersonalAccessToken.all tokens = PersonalAccessToken.all
tokens = by_current_user(tokens) tokens = by_current_user(tokens)
tokens = by_user(tokens) tokens = by_user(tokens)
tokens = by_users(tokens)
tokens = by_impersonation(tokens) tokens = by_impersonation(tokens)
tokens = by_state(tokens) tokens = by_state(tokens)
...@@ -37,6 +38,12 @@ class PersonalAccessTokensFinder ...@@ -37,6 +38,12 @@ class PersonalAccessTokensFinder
tokens.for_user(@params[:user]) tokens.for_user(@params[:user])
end end
def by_users(tokens)
return tokens unless @params[:users]
tokens.for_users(@params[:users])
end
def sort(tokens) def sort(tokens)
available_sort_orders = PersonalAccessToken.simple_sorts.keys available_sort_orders = PersonalAccessToken.simple_sorts.keys
......
...@@ -26,6 +26,7 @@ class PersonalAccessToken < ApplicationRecord ...@@ -26,6 +26,7 @@ class PersonalAccessToken < ApplicationRecord
scope :revoked, -> { where(revoked: true) } scope :revoked, -> { where(revoked: true) }
scope :not_revoked, -> { where(revoked: [false, nil]) } scope :not_revoked, -> { where(revoked: [false, nil]) }
scope :for_user, -> (user) { where(user: user) } scope :for_user, -> (user) { where(user: user) }
scope :for_users, -> (users) { where(user: users) }
scope :preload_users, -> { preload(:user) } scope :preload_users, -> { preload(:user) }
scope :order_expires_at_asc, -> { reorder(expires_at: :asc) } scope :order_expires_at_asc, -> { reorder(expires_at: :asc) }
scope :order_expires_at_desc, -> { reorder(expires_at: :desc) } scope :order_expires_at_desc, -> { reorder(expires_at: :desc) }
......
...@@ -48,4 +48,9 @@ class Admin::CredentialsController < Admin::ApplicationController ...@@ -48,4 +48,9 @@ class Admin::CredentialsController < Admin::ApplicationController
def users def users
nil nil
end end
override :revocable
def revocable
nil
end
end end
...@@ -30,13 +30,16 @@ module CredentialsInventoryActions ...@@ -30,13 +30,16 @@ module CredentialsInventoryActions
end end
def revoke def revoke
personal_access_token = PersonalAccessTokensFinder.new({ user: users, impersonation: false }, current_user).find(params[:id]) personal_access_token = personal_access_token_finder.find_by_id(params[:id])
service = PersonalAccessTokens::RevokeService.new(current_user, token: personal_access_token).execute return render_404 unless personal_access_token
if service.success?
flash[:notice] = service.message result = revoke_service(personal_access_token).execute
if result.success?
flash[:notice] = result.message
notify_deleted_or_revoked_credential(personal_access_token) notify_deleted_or_revoked_credential(personal_access_token)
else else
flash[:alert] = service.message flash[:alert] = result.message
end end
redirect_to credentials_inventory_path(page: params[:page]) redirect_to credentials_inventory_path(page: params[:page])
...@@ -46,7 +49,7 @@ module CredentialsInventoryActions ...@@ -46,7 +49,7 @@ module CredentialsInventoryActions
def filter_credentials def filter_credentials
if show_personal_access_tokens? if show_personal_access_tokens?
::PersonalAccessTokensFinder.new({ user: users, impersonation: false, sort: 'id_desc' }).execute ::PersonalAccessTokensFinder.new({ users: users, impersonation: false, sort: 'id_desc' }).execute
elsif show_ssh_keys? elsif show_ssh_keys?
::KeysFinder.new({ users: users, key_type: 'ssh' }).execute ::KeysFinder.new({ users: users, key_type: 'ssh' }).execute
end end
...@@ -67,7 +70,27 @@ module CredentialsInventoryActions ...@@ -67,7 +70,27 @@ module CredentialsInventoryActions
end end
end end
def personal_access_token_finder
if revocable.instance_of?(Group)
::PersonalAccessTokensFinder.new({ impersonation: false, users: users })
else
::PersonalAccessTokensFinder.new({ impersonation: false }, current_user)
end
end
def revoke_service(token)
if revocable.instance_of?(Group)
::PersonalAccessTokens::RevokeService.new(current_user, token: token, group: revocable)
else
::PersonalAccessTokens::RevokeService.new(current_user, token: token)
end
end
def users def users
raise NotImplementedError, "#{self.class} does not implement #{__method__}" raise NotImplementedError, "#{self.class} does not implement #{__method__}"
end end
def revocable
raise NotImplementedError, "#{self.class} does not implement #{__method__}"
end
end end
...@@ -7,9 +7,9 @@ class Groups::Security::CredentialsController < Groups::ApplicationController ...@@ -7,9 +7,9 @@ class Groups::Security::CredentialsController < Groups::ApplicationController
include CredentialsInventoryActions include CredentialsInventoryActions
include Groups::SecurityFeaturesHelper include Groups::SecurityFeaturesHelper
helper_method :credentials_inventory_path, :user_detail_path, :ssh_key_delete_path helper_method :credentials_inventory_path, :user_detail_path, :personal_access_token_revoke_path, :revoke_button_available?, :ssh_key_delete_path
before_action :validate_group_level_credentials_inventory_available!, only: [:index, :destroy] before_action :validate_group_level_credentials_inventory_available!, only: [:index, :revoke, :destroy]
feature_category :compliance_management feature_category :compliance_management
...@@ -34,8 +34,23 @@ class Groups::Security::CredentialsController < Groups::ApplicationController ...@@ -34,8 +34,23 @@ class Groups::Security::CredentialsController < Groups::ApplicationController
user_path(user) user_path(user)
end end
override :personal_access_token_revoke_path
def personal_access_token_revoke_path(token)
revoke_group_security_credential_path(group, token)
end
override :revoke_button_available?
def revoke_button_available?
::Feature.enabled?(:revoke_managed_users_token, group)
end
override :users override :users
def users def users
group.managed_users group.managed_users
end end
override :revocable
def revocable
group
end
end end
...@@ -21,14 +21,17 @@ module EE ...@@ -21,14 +21,17 @@ module EE
end end
def managed_user_revocation_allowed? def managed_user_revocation_allowed?
return unless token.present?
return unless ::Feature.enabled?(:revoke_managed_users_token, group) return unless ::Feature.enabled?(:revoke_managed_users_token, group)
token.user.group_managed_account? && token.user&.group_managed_account? &&
token.user.managing_group == group && token.user&.managing_group == group &&
can?(current_user, :admin_group_credentials_inventory, group) can?(current_user, :admin_group_credentials_inventory, group)
end end
def log_audit_event(token, response) def log_audit_event(token, response)
return unless token.present?
audit_event_service(token, response).for_user(full_path: token.user.username, entity_id: token.user.id).security_event audit_event_service(token, response).for_user(full_path: token.user.username, entity_id: token.user.id).security_event
end end
......
...@@ -139,7 +139,11 @@ constraints(::Constraints::GroupUrlConstrainer.new) do ...@@ -139,7 +139,11 @@ constraints(::Constraints::GroupUrlConstrainer.new) do
resources :vulnerabilities, only: [:index] resources :vulnerabilities, only: [:index]
resource :compliance_dashboard, only: [:show] resource :compliance_dashboard, only: [:show]
resource :discover, only: [:show], controller: :discover resource :discover, only: [:show], controller: :discover
resources :credentials, only: [:index, :destroy] resources :credentials, only: [:index, :destroy] do
member do
put :revoke
end
end
resources :merge_commit_reports, only: [:index], constraints: { format: :csv } resources :merge_commit_reports, only: [:index], constraints: { format: :csv }
end end
......
...@@ -102,6 +102,32 @@ RSpec.describe Admin::CredentialsController do ...@@ -102,6 +102,32 @@ RSpec.describe Admin::CredentialsController do
end end
describe 'PUT #revoke' do describe 'PUT #revoke' do
shared_examples_for 'responds with 404' do
it do
put :revoke, params: { id: token_id }
expect(response).to have_gitlab_http_status(:not_found)
end
end
shared_examples_for 'displays the flash success message' do
it do
put :revoke, params: { id: token_id }
expect(response).to redirect_to(admin_credentials_path)
expect(flash[:notice]).to start_with 'Revoked personal access token '
end
end
shared_examples_for 'displays the flash error message' do
it do
put :revoke, params: { id: token_id }
expect(response).to redirect_to(admin_credentials_path)
expect(flash[:alert]).to eql 'Not permitted to revoke'
end
end
context 'admin user' do context 'admin user' do
before do before do
sign_in(admin) sign_in(admin)
...@@ -113,11 +139,9 @@ RSpec.describe Admin::CredentialsController do ...@@ -113,11 +139,9 @@ RSpec.describe Admin::CredentialsController do
end end
context 'non-existent personal access token specified' do context 'non-existent personal access token specified' do
it 'returns 404' do let(:token_id) { 999999999999999999999999999999999 }
put :revoke, params: { id: 999999999999999999999999999999999 }
expect(response).to have_gitlab_http_status(:not_found) it_behaves_like 'responds with 404'
end
end end
describe 'with an existing personal access token' do describe 'with an existing personal access token' do
...@@ -127,43 +151,27 @@ RSpec.describe Admin::CredentialsController do ...@@ -127,43 +151,27 @@ RSpec.describe Admin::CredentialsController do
allow(Ability).to receive(:allowed?).with(admin, :revoke_token, personal_access_token) { false } allow(Ability).to receive(:allowed?).with(admin, :revoke_token, personal_access_token) { false }
end end
it 'returns the flash error message' do let(:token_id) { personal_access_token.id }
put :revoke, params: { id: personal_access_token.id }
expect(response).to redirect_to(admin_credentials_path) it_behaves_like 'displays the flash error message'
expect(flash[:alert]).to eql 'Not permitted to revoke'
end
end end
context 'personal access token is already revoked' do context 'personal access token is already revoked' do
let_it_be(:personal_access_token) { create(:personal_access_token, revoked: true, user: user) } let_it_be(:token_id) { create(:personal_access_token, revoked: true, user: user).id }
it 'returns the flash success message' do
put :revoke, params: { id: personal_access_token.id }
expect(response).to redirect_to(admin_credentials_path) it_behaves_like 'displays the flash success message'
expect(flash[:notice]).to eql 'Revoked personal access token %{personal_access_token_name}!' % { personal_access_token_name: personal_access_token.name }
end
end end
context 'personal access token is already expired' do context 'personal access token is already expired' do
let_it_be(:personal_access_token) { create(:personal_access_token, expires_at: 5.days.ago, user: user) } let_it_be(:token_id) { create(:personal_access_token, expires_at: 5.days.ago, user: user).id }
it 'returns the flash success message' do it_behaves_like 'displays the flash success message'
put :revoke, params: { id: personal_access_token.id }
expect(response).to redirect_to(admin_credentials_path)
expect(flash[:notice]).to eql 'Revoked personal access token %{personal_access_token_name}!' % { personal_access_token_name: personal_access_token.name }
end
end end
context 'personal access token is not revoked or expired' do context 'personal access token is not revoked or expired' do
it 'returns the flash success message' do let(:token_id) { personal_access_token.id }
put :revoke, params: { id: personal_access_token.id }
expect(response).to redirect_to(admin_credentials_path) it_behaves_like 'displays the flash success message'
expect(flash[:notice]).to eql 'Revoked personal access token %{personal_access_token_name}!' % { personal_access_token_name: personal_access_token.name }
end
it 'informs the token owner' do it 'informs the token owner' do
expect(CredentialsInventoryMailer).to receive_message_chain(:personal_access_token_revoked_email, :deliver_later) expect(CredentialsInventoryMailer).to receive_message_chain(:personal_access_token_revoked_email, :deliver_later)
...@@ -179,11 +187,9 @@ RSpec.describe Admin::CredentialsController do ...@@ -179,11 +187,9 @@ RSpec.describe Admin::CredentialsController do
stub_licensed_features(credentials_inventory: false) stub_licensed_features(credentials_inventory: false)
end end
it 'returns 404' do let(:token_id) { personal_access_token.id }
put :revoke, params: { id: personal_access_token.id }
expect(response).to have_gitlab_http_status(:not_found) it_behaves_like 'responds with 404'
end
end end
end end
...@@ -192,11 +198,9 @@ RSpec.describe Admin::CredentialsController do ...@@ -192,11 +198,9 @@ RSpec.describe Admin::CredentialsController do
sign_in(user) sign_in(user)
end end
it 'returns 404' do let(:token_id) { personal_access_token.id }
put :revoke, params: { id: personal_access_token.id }
expect(response).to have_gitlab_http_status(:not_found) it_behaves_like 'responds with 404'
end
end end
end end
end end
...@@ -5,21 +5,24 @@ require 'spec_helper' ...@@ -5,21 +5,24 @@ require 'spec_helper'
RSpec.describe Groups::Security::CredentialsController do RSpec.describe Groups::Security::CredentialsController do
let_it_be(:group_with_managed_accounts) { create(:group_with_managed_accounts, :private) } let_it_be(:group_with_managed_accounts) { create(:group_with_managed_accounts, :private) }
let_it_be(:managed_users) { create_list(:user, 2, :group_managed, managing_group: group_with_managed_accounts) } let_it_be(:managed_users) { create_list(:user, 2, :group_managed, managing_group: group_with_managed_accounts) }
let_it_be(:owner) { managed_users.first }
let_it_be(:maintainer) { managed_users.last }
let_it_be(:group_id) { group_with_managed_accounts.to_param }
let_it_be(:personal_access_token) { create(:personal_access_token, user: maintainer) }
before do before do
allow_next_instance_of(Gitlab::Auth::GroupSaml::SsoEnforcer) do |sso_enforcer| allow_next_instance_of(Gitlab::Auth::GroupSaml::SsoEnforcer) do |sso_enforcer|
allow(sso_enforcer).to receive(:active_session?).and_return(true) allow(sso_enforcer).to receive(:active_session?).and_return(true)
end end
owner = managed_users.first
group_with_managed_accounts.add_owner(owner) group_with_managed_accounts.add_owner(owner)
group_with_managed_accounts.add_maintainer(maintainer)
sign_in(owner) sign_in(owner)
end end
describe 'GET #index' do describe 'GET #index' do
let(:filter) {} let(:filter) {}
let(:group_id) { group_with_managed_accounts.to_param }
subject { get :index, params: { group_id: group_id.to_param, filter: filter } } subject { get :index, params: { group_id: group_id.to_param, filter: filter } }
...@@ -98,10 +101,6 @@ RSpec.describe Groups::Security::CredentialsController do ...@@ -98,10 +101,6 @@ RSpec.describe Groups::Security::CredentialsController do
context 'for a user without access to view credentials inventory' do context 'for a user without access to view credentials inventory' do
before do before do
maintainer = managed_users.last
group_with_managed_accounts.add_maintainer(maintainer)
sign_in(maintainer) sign_in(maintainer)
end end
...@@ -115,7 +114,7 @@ RSpec.describe Groups::Security::CredentialsController do ...@@ -115,7 +114,7 @@ RSpec.describe Groups::Security::CredentialsController do
end end
context 'for a group that does not enforce group managed accounts' do context 'for a group that does not enforce group managed accounts' do
let(:group_id) { create(:group).to_param } let_it_be(:group_id) { create(:group).id }
it 'responds with 404' do it 'responds with 404' do
subject subject
...@@ -143,4 +142,168 @@ RSpec.describe Groups::Security::CredentialsController do ...@@ -143,4 +142,168 @@ RSpec.describe Groups::Security::CredentialsController do
it_behaves_like 'credentials inventory controller delete SSH key', group_managed_account: true it_behaves_like 'credentials inventory controller delete SSH key', group_managed_account: true
end end
describe 'PUT #revoke' do
shared_examples_for 'responds with 404' do
it do
put :revoke, params: { group_id: group_id.to_param, id: token_id }
expect(response).to have_gitlab_http_status(:not_found)
end
end
shared_examples_for 'displays the flash success message' do
it do
put :revoke, params: { group_id: group_id.to_param, id: token_id }
expect(response).to redirect_to(group_security_credentials_path)
expect(flash[:notice]).to start_with 'Revoked personal access token '
end
end
shared_examples_for 'displays the flash error message' do
it do
put :revoke, params: { group_id: group_id.to_param, id: token_id }
expect(response).to redirect_to(group_security_credentials_path)
expect(flash[:alert]).to eql 'Not permitted to revoke'
end
end
context 'when `credentials_inventory` feature is enabled' do
before do
stub_licensed_features(credentials_inventory: true, group_saml: true)
stub_feature_flags(revoke_managed_users_token: true)
end
context 'for a group that enforces group managed accounts' do
context 'when `revoke_managed_users_token` feature is enabled' do
before_all do
stub_feature_flags(revoke_managed_users_token: true)
end
context 'for a user with access to view credentials inventory' do
context 'non-existent personal access token specified' do
let(:token_id) { 999999999999999999999999999999999 }
it_behaves_like 'responds with 404'
end
describe 'with an existing personal access token' do
context 'personal access token is already revoked' do
let_it_be(:token_id) { create(:personal_access_token, revoked: true, user: maintainer).id }
it_behaves_like 'displays the flash success message'
end
context 'personal access token is already expired' do
let_it_be(:token_id) { create(:personal_access_token, expires_at: 5.days.ago, user: maintainer).id }
it_behaves_like 'displays the flash success message'
end
context 'does not have permissions to revoke the credential' do
let_it_be(:token_id) { create(:personal_access_token, user: create(:user)).id }
it_behaves_like 'responds with 404'
end
context 'personal access token is already revoked' do
let_it_be(:token_id) { create(:personal_access_token, revoked: true, user: maintainer).id }
it_behaves_like 'displays the flash success message'
end
context 'personal access token is already expired' do
let_it_be(:token_id) { create(:personal_access_token, expires_at: 5.days.ago, user: maintainer).id }
it_behaves_like 'displays the flash success message'
end
context 'personal access token is not revoked or expired' do
let_it_be(:token_id) { personal_access_token.id }
it_behaves_like 'displays the flash success message'
it 'informs the token owner' do
expect(CredentialsInventoryMailer).to receive_message_chain(:personal_access_token_revoked_email, :deliver_later)
put :revoke, params: { group_id: group_id.to_param, id: personal_access_token.id }
end
context 'when credentials_inventory_revocation_emails flag is disabled' do
before do
stub_feature_flags(credentials_inventory_revocation_emails: false)
end
it 'does not inform the token owner' do
expect do
put :revoke, params: { group_id: group_id.to_param, id: personal_access_token.id }
end.not_to change { ActionMailer::Base.deliveries.size }
end
end
end
end
end
context 'for a user without access to view credentials inventory' do
let_it_be(:token_id) { create(:personal_access_token, user: owner).id }
before do
sign_in(maintainer)
end
it_behaves_like 'responds with 404'
end
end
context 'when `revoke_managed_users_token` feature is disabled' do
before_all do
stub_feature_flags(revoke_managed_users_token: false)
end
context 'for a user with access to view credentials inventory' do
context 'non-existent personal access token specified' do
let(:token_id) { 999999999999999999999999999999999 }
it_behaves_like 'responds with 404'
end
context 'valid personal access token specified' do
let_it_be(:token_id) { create(:personal_access_token, user: create(:user)).id }
it_behaves_like 'responds with 404'
end
end
context 'for a user without access to view credentials inventory' do
let_it_be(:token_id) { create(:personal_access_token, user: owner).id }
before do
sign_in(maintainer)
end
it_behaves_like 'responds with 404'
end
end
end
context 'for a group that does not enforce group managed accounts' do
let_it_be(:token_id) { personal_access_token.id }
let_it_be(:group_id) { create(:group).id }
it_behaves_like 'responds with 404'
end
end
context 'when `credentials_inventory` feature is disabled' do
let_it_be(:token_id) { create(:personal_access_token, user: owner).id }
before do
stub_licensed_features(credentials_inventory: false)
end
it_behaves_like 'responds with 404'
end
end
end end
...@@ -6,7 +6,7 @@ RSpec.describe 'Groups::Security::Credentials' do ...@@ -6,7 +6,7 @@ RSpec.describe 'Groups::Security::Credentials' do
include Spec::Support::Helpers::Features::ResponsiveTableHelpers include Spec::Support::Helpers::Features::ResponsiveTableHelpers
let_it_be(:group_with_managed_accounts) { create(:group_with_managed_accounts, :private) } let_it_be(:group_with_managed_accounts) { create(:group_with_managed_accounts, :private) }
let_it_be(:managed_user) { create(:user, :group_managed, managing_group: group_with_managed_accounts, name: 'David') } let_it_be(:managed_user) { create(:user, :group_managed, managing_group: group_with_managed_accounts, name: 'abc') }
let(:group_id) { group_with_managed_accounts.to_param } let(:group_id) { group_with_managed_accounts.to_param }
before do before do
...@@ -44,13 +44,13 @@ RSpec.describe 'Groups::Security::Credentials' do ...@@ -44,13 +44,13 @@ RSpec.describe 'Groups::Security::Credentials' do
context 'by Personal Access Tokens' do context 'by Personal Access Tokens' do
let(:credentials_path) { group_security_credentials_path(group_id: group_id, filter: 'personal_access_tokens') } let(:credentials_path) { group_security_credentials_path(group_id: group_id, filter: 'personal_access_tokens') }
it_behaves_like 'credentials inventory personal access tokens', group_managed_account: true it_behaves_like 'credentials inventory personal access tokens'
end end
context 'by SSH Keys' do context 'by SSH Keys' do
let(:credentials_path) { group_security_credentials_path(group_id: group_id, filter: 'ssh_keys') } let(:credentials_path) { group_security_credentials_path(group_id: group_id, filter: 'ssh_keys') }
it_behaves_like 'credentials inventory SSH keys', group_managed_account: true it_behaves_like 'credentials inventory SSH keys'
end end
end end
end end
......
...@@ -34,6 +34,12 @@ RSpec.describe EE::PersonalAccessTokens::RevokeService do ...@@ -34,6 +34,12 @@ RSpec.describe EE::PersonalAccessTokens::RevokeService do
let_it_be(:token) { create(:personal_access_token, user: managed_user) } let_it_be(:token) { create(:personal_access_token, user: managed_user) }
it_behaves_like 'a successfully revoked token' it_behaves_like 'a successfully revoked token'
context 'and an empty token is given' do
let_it_be(:token) { nil }
it { expect(subject.success?).to be false }
end
end end
context 'when feature flag is disabled' do context 'when feature flag is disabled' do
......
# frozen_string_literal: true # frozen_string_literal: true
RSpec.shared_examples_for 'credentials inventory controller delete SSH key' do |group_managed_account: false| RSpec.shared_examples_for 'credentials inventory controller delete SSH key' do |group_managed_account: false|
let_it_be(:user) { group_managed_account ? managed_users.last : create(:user, name: 'David') } let_it_be(:user) { group_managed_account ? managed_users.last : create(:user, name: 'abc') }
let_it_be(:ssh_key) { create(:personal_key, user: user) } let_it_be(:ssh_key) { create(:personal_key, user: user) }
let(:ssh_key_id) { ssh_key.id } let(:ssh_key_id) { ssh_key.id }
......
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
require 'spec_helper' require 'spec_helper'
RSpec.shared_examples_for 'credentials inventory personal access tokens' do |group_managed_account: false| RSpec.shared_examples_for 'credentials inventory personal access tokens' do
let_it_be(:user) { group_managed_account ? managed_user : create(:user, name: 'David') } let_it_be(:user) { defined?(managed_user) ? managed_user : create(:user, name: 'abc') }
context 'when a personal access token is active' do context 'when a personal access token is active' do
before_all do before_all do
...@@ -19,17 +19,14 @@ RSpec.shared_examples_for 'credentials inventory personal access tokens' do |gro ...@@ -19,17 +19,14 @@ RSpec.shared_examples_for 'credentials inventory personal access tokens' do |gro
end end
it 'shows the details', :aggregate_failures do it 'shows the details', :aggregate_failures do
expect(first_row.text).to include('David') expect(first_row.text).to include('abc')
expect(first_row.text).to include('api') expect(first_row.text).to include('api')
expect(first_row.text).to include('2019-12-10') expect(first_row.text).to include('2019-12-10')
expect(first_row.text).to include('Never') expect(first_row.text).to include('Never')
expect(first_row.text).not_to include('2020-06-22') expect(first_row.text).not_to include('2020-06-22')
unless group_managed_account
expect(first_row).to have_selector('a.btn', text: 'Revoke') expect(first_row).to have_selector('a.btn', text: 'Revoke')
end end
end end
end
context 'when a personal access token has an expiry' do context 'when a personal access token has an expiry' do
let_it_be(:expiry_date) { 1.day.since.to_date.to_s } let_it_be(:expiry_date) { 1.day.since.to_date.to_s }
...@@ -71,16 +68,13 @@ RSpec.shared_examples_for 'credentials inventory personal access tokens' do |gro ...@@ -71,16 +68,13 @@ RSpec.shared_examples_for 'credentials inventory personal access tokens' do |gro
it 'shows the details with a revoked date', :aggregate_failures do it 'shows the details with a revoked date', :aggregate_failures do
expect(first_row.text).to include('2020-06-22') expect(first_row.text).to include('2020-06-22')
unless group_managed_account
expect(first_row).not_to have_selector('a.btn', text: 'Revoke') expect(first_row).not_to have_selector('a.btn', text: 'Revoke')
end end
end end
end
end end
RSpec.shared_examples_for 'credentials inventory SSH keys' do |group_managed_account: false| RSpec.shared_examples_for 'credentials inventory SSH keys' do
let_it_be(:user) { group_managed_account ? managed_user : create(:user, name: 'David') } let_it_be(:user) { defined?(managed_user) ? managed_user : create(:user, name: 'abc') }
context 'when a SSH key is active' do context 'when a SSH key is active' do
before_all do before_all do
...@@ -96,7 +90,7 @@ RSpec.shared_examples_for 'credentials inventory SSH keys' do |group_managed_acc ...@@ -96,7 +90,7 @@ RSpec.shared_examples_for 'credentials inventory SSH keys' do |group_managed_acc
end end
it 'shows the details', :aggregate_failures do it 'shows the details', :aggregate_failures do
expect(first_row.text).to include('David') expect(first_row.text).to include('abc')
expect(first_row.text).to include('2019-12-09') expect(first_row.text).to include('2019-12-09')
expect(first_row.text).to include('2019-12-10') expect(first_row.text).to include('2019-12-10')
expect(first_row.text).to include('Never') expect(first_row.text).to include('Never')
......
...@@ -62,6 +62,27 @@ RSpec.describe PersonalAccessTokensFinder do ...@@ -62,6 +62,27 @@ RSpec.describe PersonalAccessTokensFinder do
revoked_impersonation_token, expired_impersonation_token) revoked_impersonation_token, expired_impersonation_token)
end end
describe 'with users' do
let(:user2) { create(:user) }
before do
create(:personal_access_token, user: user2)
create(:personal_access_token, :expired, user: user2)
create(:personal_access_token, :revoked, user: user2)
create(:personal_access_token, :impersonation, user: user2)
create(:personal_access_token, :expired, :impersonation, user: user2)
create(:personal_access_token, :revoked, :impersonation, user: user2)
params[:users] = [user]
end
it {
is_expected.to contain_exactly(active_personal_access_token, active_impersonation_token,
revoked_personal_access_token, expired_personal_access_token,
revoked_impersonation_token, expired_impersonation_token)
}
end
describe 'with sort order' do describe 'with sort order' do
before do before do
params[:sort] = 'id_asc' params[:sort] = 'id_asc'
......
...@@ -31,6 +31,18 @@ RSpec.describe PersonalAccessToken do ...@@ -31,6 +31,18 @@ RSpec.describe PersonalAccessToken do
expect(described_class.for_user(user_1)).to contain_exactly(token_of_user_1) expect(described_class.for_user(user_1)).to contain_exactly(token_of_user_1)
end end
end end
describe '.for_users' do
it 'returns personal access tokens for the specified users only' do
user_1 = create(:user)
user_2 = create(:user)
token_of_user_1 = create(:personal_access_token, user: user_1)
token_of_user_2 = create(:personal_access_token, user: user_2)
create_list(:personal_access_token, 3)
expect(described_class.for_users([user_1, user_2])).to contain_exactly(token_of_user_1, token_of_user_2)
end
end
end end
describe ".active?" do describe ".active?" do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment