2019-07-07 11:18:12 +05:30
# frozen_string_literal: true
2014-09-02 18:07:02 +05:30
require 'spec_helper'
2020-07-28 23:09:34 +05:30
RSpec . describe User do
2018-03-17 18:26:18 +05:30
include ProjectForksHelper
2018-10-15 14:42:47 +05:30
include TermsHelper
2020-04-22 19:07:51 +05:30
include ExclusiveLeaseHelpers
2021-12-11 22:18:48 +05:30
include LdapHelpers
2015-09-11 14:41:01 +05:30
2019-02-15 15:39:39 +05:30
it_behaves_like 'having unique enum values'
2015-09-11 14:41:01 +05:30
describe 'modules' do
subject { described_class }
it { is_expected . to include_module ( Gitlab :: ConfigHelper ) }
it { is_expected . to include_module ( Referable ) }
it { is_expected . to include_module ( Sortable ) }
it { is_expected . to include_module ( TokenAuthenticatable ) }
2022-05-07 20:08:51 +05:30
it { is_expected . to include_module ( BlocksUnsafeSerialization ) }
2020-05-24 23:13:21 +05:30
it { is_expected . to include_module ( AsyncDeviseEmail ) }
2015-09-11 14:41:01 +05:30
end
2021-06-08 01:23:25 +05:30
describe 'constants' do
it { expect ( described_class :: COUNT_CACHE_VALIDITY_PERIOD ) . to be_a ( Integer ) }
2021-09-04 01:27:46 +05:30
it { expect ( described_class :: MAX_USERNAME_LENGTH ) . to be_a ( Integer ) }
it { expect ( described_class :: MIN_USERNAME_LENGTH ) . to be_a ( Integer ) }
2021-06-08 01:23:25 +05:30
end
2017-09-10 17:25:29 +05:30
describe 'delegations' do
it { is_expected . to delegate_method ( :path ) . to ( :namespace ) . with_prefix }
2020-03-13 15:44:24 +05:30
2020-06-23 00:09:42 +05:30
it { is_expected . to delegate_method ( :notes_filter_for ) . to ( :user_preference ) }
it { is_expected . to delegate_method ( :set_notes_filter ) . to ( :user_preference ) }
it { is_expected . to delegate_method ( :first_day_of_week ) . to ( :user_preference ) }
it { is_expected . to delegate_method ( :first_day_of_week = ) . to ( :user_preference ) . with_arguments ( :args ) }
it { is_expected . to delegate_method ( :timezone ) . to ( :user_preference ) }
it { is_expected . to delegate_method ( :timezone = ) . to ( :user_preference ) . with_arguments ( :args ) }
it { is_expected . to delegate_method ( :time_display_relative ) . to ( :user_preference ) }
it { is_expected . to delegate_method ( :time_display_relative = ) . to ( :user_preference ) . with_arguments ( :args ) }
it { is_expected . to delegate_method ( :time_format_in_24h ) . to ( :user_preference ) }
it { is_expected . to delegate_method ( :time_format_in_24h = ) . to ( :user_preference ) . with_arguments ( :args ) }
it { is_expected . to delegate_method ( :show_whitespace_in_diffs ) . to ( :user_preference ) }
it { is_expected . to delegate_method ( :show_whitespace_in_diffs = ) . to ( :user_preference ) . with_arguments ( :args ) }
2021-04-17 20:07:23 +05:30
it { is_expected . to delegate_method ( :view_diffs_file_by_file ) . to ( :user_preference ) }
it { is_expected . to delegate_method ( :view_diffs_file_by_file = ) . to ( :user_preference ) . with_arguments ( :args ) }
2020-03-13 15:44:24 +05:30
it { is_expected . to delegate_method ( :tab_width ) . to ( :user_preference ) }
2020-06-23 00:09:42 +05:30
it { is_expected . to delegate_method ( :tab_width = ) . to ( :user_preference ) . with_arguments ( :args ) }
it { is_expected . to delegate_method ( :sourcegraph_enabled ) . to ( :user_preference ) }
it { is_expected . to delegate_method ( :sourcegraph_enabled = ) . to ( :user_preference ) . with_arguments ( :args ) }
2020-11-24 15:15:51 +05:30
it { is_expected . to delegate_method ( :gitpod_enabled ) . to ( :user_preference ) }
it { is_expected . to delegate_method ( :gitpod_enabled = ) . to ( :user_preference ) . with_arguments ( :args ) }
2020-06-23 00:09:42 +05:30
it { is_expected . to delegate_method ( :setup_for_company ) . to ( :user_preference ) }
it { is_expected . to delegate_method ( :setup_for_company = ) . to ( :user_preference ) . with_arguments ( :args ) }
it { is_expected . to delegate_method ( :render_whitespace_in_code ) . to ( :user_preference ) }
it { is_expected . to delegate_method ( :render_whitespace_in_code = ) . to ( :user_preference ) . with_arguments ( :args ) }
2021-04-17 20:07:23 +05:30
it { is_expected . to delegate_method ( :markdown_surround_selection ) . to ( :user_preference ) }
it { is_expected . to delegate_method ( :markdown_surround_selection = ) . to ( :user_preference ) . with_arguments ( :args ) }
2022-11-25 23:54:43 +05:30
it { is_expected . to delegate_method ( :markdown_automatic_lists ) . to ( :user_preference ) }
it { is_expected . to delegate_method ( :markdown_automatic_lists = ) . to ( :user_preference ) . with_arguments ( :args ) }
2022-06-21 17:19:12 +05:30
it { is_expected . to delegate_method ( :diffs_deletion_color ) . to ( :user_preference ) }
it { is_expected . to delegate_method ( :diffs_deletion_color = ) . to ( :user_preference ) . with_arguments ( :args ) }
it { is_expected . to delegate_method ( :diffs_addition_color ) . to ( :user_preference ) }
it { is_expected . to delegate_method ( :diffs_addition_color = ) . to ( :user_preference ) . with_arguments ( :args ) }
2022-11-25 23:54:43 +05:30
it { is_expected . to delegate_method ( :use_legacy_web_ide ) . to ( :user_preference ) }
it { is_expected . to delegate_method ( :use_legacy_web_ide = ) . to ( :user_preference ) . with_arguments ( :args ) }
2020-06-23 00:09:42 +05:30
it { is_expected . to delegate_method ( :job_title ) . to ( :user_detail ) . allow_nil }
it { is_expected . to delegate_method ( :job_title = ) . to ( :user_detail ) . with_arguments ( :args ) . allow_nil }
2020-07-28 23:09:34 +05:30
2021-09-04 01:27:46 +05:30
it { is_expected . to delegate_method ( :pronouns ) . to ( :user_detail ) . allow_nil }
it { is_expected . to delegate_method ( :pronouns = ) . to ( :user_detail ) . with_arguments ( :args ) . allow_nil }
2021-10-27 15:23:28 +05:30
it { is_expected . to delegate_method ( :pronunciation ) . to ( :user_detail ) . allow_nil }
it { is_expected . to delegate_method ( :pronunciation = ) . to ( :user_detail ) . with_arguments ( :args ) . allow_nil }
2020-07-28 23:09:34 +05:30
it { is_expected . to delegate_method ( :bio ) . to ( :user_detail ) . allow_nil }
it { is_expected . to delegate_method ( :bio = ) . to ( :user_detail ) . with_arguments ( :args ) . allow_nil }
2021-11-18 22:05:49 +05:30
it { is_expected . to delegate_method ( :registration_objective ) . to ( :user_detail ) . allow_nil }
it { is_expected . to delegate_method ( :registration_objective = ) . to ( :user_detail ) . with_arguments ( :args ) . allow_nil }
2022-03-02 08:16:31 +05:30
it { is_expected . to delegate_method ( :requires_credit_card_verification ) . to ( :user_detail ) . allow_nil }
it { is_expected . to delegate_method ( :requires_credit_card_verification = ) . to ( :user_detail ) . with_arguments ( :args ) . allow_nil }
2017-09-10 17:25:29 +05:30
end
2015-09-11 14:41:01 +05:30
describe 'associations' do
2015-04-26 12:48:37 +05:30
it { is_expected . to have_one ( :namespace ) }
2018-11-18 11:00:15 +05:30
it { is_expected . to have_one ( :status ) }
2020-04-08 14:13:33 +05:30
it { is_expected . to have_one ( :user_detail ) }
2020-11-24 15:15:51 +05:30
it { is_expected . to have_one ( :atlassian_identity ) }
2020-04-08 14:13:33 +05:30
it { is_expected . to have_one ( :user_highest_role ) }
2021-06-08 01:23:25 +05:30
it { is_expected . to have_one ( :credit_card_validation ) }
2022-11-25 23:54:43 +05:30
it { is_expected . to have_one ( :phone_number_validation ) }
2021-10-27 15:23:28 +05:30
it { is_expected . to have_one ( :banned_user ) }
2017-08-17 22:00:37 +05:30
it { is_expected . to have_many ( :snippets ) . dependent ( :destroy ) }
2018-03-17 18:26:18 +05:30
it { is_expected . to have_many ( :members ) }
it { is_expected . to have_many ( :project_members ) }
it { is_expected . to have_many ( :group_members ) }
2015-04-26 12:48:37 +05:30
it { is_expected . to have_many ( :groups ) }
it { is_expected . to have_many ( :keys ) . dependent ( :destroy ) }
2021-12-11 22:18:48 +05:30
it { is_expected . to have_many ( :expired_today_and_unnotified_keys ) }
2018-05-09 12:01:36 +05:30
it { is_expected . to have_many ( :deploy_keys ) . dependent ( :nullify ) }
2020-10-24 23:57:45 +05:30
it { is_expected . to have_many ( :group_deploy_keys ) }
2019-12-04 20:38:33 +05:30
it { is_expected . to have_many ( :events ) . dependent ( :delete_all ) }
2017-09-10 17:25:29 +05:30
it { is_expected . to have_many ( :issues ) . dependent ( :destroy ) }
2015-04-26 12:48:37 +05:30
it { is_expected . to have_many ( :notes ) . dependent ( :destroy ) }
it { is_expected . to have_many ( :merge_requests ) . dependent ( :destroy ) }
it { is_expected . to have_many ( :identities ) . dependent ( :destroy ) }
2016-04-02 18:10:28 +05:30
it { is_expected . to have_many ( :spam_logs ) . dependent ( :destroy ) }
2018-03-17 18:26:18 +05:30
it { is_expected . to have_many ( :todos ) }
2016-06-16 23:09:34 +05:30
it { is_expected . to have_many ( :award_emoji ) . dependent ( :destroy ) }
2022-01-26 12:08:38 +05:30
it { is_expected . to have_many ( :builds ) }
it { is_expected . to have_many ( :pipelines ) }
2017-08-17 22:00:37 +05:30
it { is_expected . to have_many ( :chat_names ) . dependent ( :destroy ) }
2022-05-07 20:08:51 +05:30
it { is_expected . to have_many ( :saved_replies ) . class_name ( '::Users::SavedReply' ) }
2018-11-08 19:23:39 +05:30
it { is_expected . to have_many ( :uploads ) }
2017-08-17 22:00:37 +05:30
it { is_expected . to have_many ( :reported_abuse_reports ) . dependent ( :destroy ) . class_name ( 'AbuseReport' ) }
2018-03-17 18:26:18 +05:30
it { is_expected . to have_many ( :custom_attributes ) . class_name ( 'UserCustomAttribute' ) }
2019-02-15 15:39:39 +05:30
it { is_expected . to have_many ( :releases ) . dependent ( :nullify ) }
2020-05-24 23:13:21 +05:30
it { is_expected . to have_many ( :metrics_users_starred_dashboards ) . inverse_of ( :user ) }
2020-06-23 00:09:42 +05:30
it { is_expected . to have_many ( :reviews ) . inverse_of ( :author ) }
2021-02-22 17:27:13 +05:30
it { is_expected . to have_many ( :merge_request_assignees ) . inverse_of ( :assignee ) }
it { is_expected . to have_many ( :merge_request_reviewers ) . inverse_of ( :reviewer ) }
2021-04-17 20:07:23 +05:30
it { is_expected . to have_many ( :created_custom_emoji ) . inverse_of ( :creator ) }
2021-04-29 21:17:54 +05:30
it { is_expected . to have_many ( :in_product_marketing_emails ) }
2021-10-27 15:23:28 +05:30
it { is_expected . to have_many ( :timelogs ) }
2022-01-26 12:08:38 +05:30
it { is_expected . to have_many ( :callouts ) . class_name ( 'Users::Callout' ) }
2021-11-11 11:23:49 +05:30
it { is_expected . to have_many ( :group_callouts ) . class_name ( 'Users::GroupCallout' ) }
2022-08-27 11:52:29 +05:30
it { is_expected . to have_many ( :project_callouts ) . class_name ( 'Users::ProjectCallout' ) }
2017-08-17 22:00:37 +05:30
2021-11-18 22:05:49 +05:30
describe '#user_detail' do
2020-07-28 23:09:34 +05:30
it 'does not persist `user_detail` by default' do
expect ( create ( :user ) . user_detail ) . not_to be_persisted
2020-04-22 19:07:51 +05:30
end
2020-07-28 23:09:34 +05:30
it 'creates `user_detail` when `bio` is given' do
user = create ( :user , bio : 'my bio' )
2020-04-22 19:07:51 +05:30
2020-07-28 23:09:34 +05:30
expect ( user . user_detail ) . to be_persisted
expect ( user . user_detail . bio ) . to eq ( 'my bio' )
2020-04-22 19:07:51 +05:30
end
2020-07-28 23:09:34 +05:30
it 'delegates `bio` to `user_detail`' do
user = create ( :user , bio : 'my bio' )
2020-04-22 19:07:51 +05:30
expect ( user . bio ) . to eq ( user . user_detail . bio )
end
2021-09-04 01:27:46 +05:30
it 'delegates `pronouns` to `user_detail`' do
user = create ( :user , pronouns : 'they/them' )
expect ( user . pronouns ) . to eq ( user . user_detail . pronouns )
end
2021-10-27 15:23:28 +05:30
it 'delegates `pronunciation` to `user_detail`' do
user = create ( :user , name : 'Example' , pronunciation : 'uhg-zaam-pl' )
expect ( user . pronunciation ) . to eq ( user . user_detail . pronunciation )
end
2020-07-28 23:09:34 +05:30
it 'creates `user_detail` when `bio` is first updated' do
user = create ( :user )
2020-04-22 19:07:51 +05:30
2021-06-08 01:23:25 +05:30
expect { user . update! ( bio : 'my bio' ) } . to change { user . user_detail . persisted? } . from ( false ) . to ( true )
2020-04-22 19:07:51 +05:30
end
end
2021-11-18 22:05:49 +05:30
describe '#abuse_report' do
2017-08-17 22:00:37 +05:30
let ( :current_user ) { create ( :user ) }
let ( :other_user ) { create ( :user ) }
it { is_expected . to have_one ( :abuse_report ) }
2021-11-18 22:05:49 +05:30
it 'refers to the abuse report whose user_id is the current user' do
2017-08-17 22:00:37 +05:30
abuse_report = create ( :abuse_report , reporter : other_user , user : current_user )
expect ( current_user . abuse_report ) . to eq ( abuse_report )
end
2021-11-18 22:05:49 +05:30
it 'does not refer to the abuse report whose reporter_id is the current user' do
2017-08-17 22:00:37 +05:30
create ( :abuse_report , reporter : current_user , user : other_user )
expect ( current_user . abuse_report ) . to be_nil
end
2021-11-18 22:05:49 +05:30
it 'does not update the user_id of an abuse report when the user is updated' do
2017-08-17 22:00:37 +05:30
abuse_report = create ( :abuse_report , reporter : current_user , user : other_user )
current_user . block
expect ( abuse_report . reload . user ) . to eq ( other_user )
end
end
2016-08-24 12:49:21 +05:30
describe '#group_members' do
it 'does not include group memberships for which user is a requester' do
user = create ( :user )
2019-12-21 20:55:43 +05:30
group = create ( :group , :public )
2016-08-24 12:49:21 +05:30
group . request_access ( user )
expect ( user . group_members ) . to be_empty
end
end
describe '#project_members' do
it 'does not include project memberships for which user is a requester' do
user = create ( :user )
2019-12-21 20:55:43 +05:30
project = create ( :project , :public )
2016-08-24 12:49:21 +05:30
project . request_access ( user )
expect ( user . project_members ) . to be_empty
end
end
2014-09-02 18:07:02 +05:30
end
2020-05-24 23:13:21 +05:30
describe 'Devise emails' do
let! ( :user ) { create ( :user ) }
describe 'behaviour' do
it 'sends emails asynchronously' do
expect do
user . update! ( email : 'hello@hello.com' )
end . to have_enqueued_job . on_queue ( 'mailers' ) . exactly ( :twice )
end
end
2020-11-24 15:15:51 +05:30
context 'emails sent on changing password' do
context 'when password is updated' do
context 'default behaviour' do
it 'enqueues the `password changed` email' do
user . password = User . random_password
expect { user . save! } . to have_enqueued_mail ( DeviseMailer , :password_change )
end
it 'does not enqueue the `admin changed your password` email' do
user . password = User . random_password
expect { user . save! } . not_to have_enqueued_mail ( DeviseMailer , :password_change_by_admin )
end
end
context '`admin changed your password` email' do
it 'is enqueued only when explicitly allowed' do
user . password = User . random_password
user . send_only_admin_changed_your_password_notification!
expect { user . save! } . to have_enqueued_mail ( DeviseMailer , :password_change_by_admin )
end
it '`password changed` email is not enqueued if it is explicitly allowed' do
user . password = User . random_password
user . send_only_admin_changed_your_password_notification!
expect { user . save! } . not_to have_enqueued_mail ( DeviseMailer , :password_changed )
end
it 'is not enqueued if sending notifications on password updates is turned off as per Devise config' do
user . password = User . random_password
user . send_only_admin_changed_your_password_notification!
allow ( Devise ) . to receive ( :send_password_change_notification ) . and_return ( false )
expect { user . save! } . not_to have_enqueued_mail ( DeviseMailer , :password_change_by_admin )
end
end
end
context 'when password is not updated' do
it 'does not enqueue the `admin changed your password` email even if explicitly allowed' do
user . name = 'John'
user . send_only_admin_changed_your_password_notification!
expect { user . save! } . not_to have_enqueued_mail ( DeviseMailer , :password_change_by_admin )
end
end
end
2023-01-10 11:22:00 +05:30
describe 'confirmation instructions for unconfirmed email' do
let ( :unconfirmed_email ) { 'first-unconfirmed-email@example.com' }
let ( :another_unconfirmed_email ) { 'another-unconfirmed-email@example.com' }
context 'when email is changed to another before performing the job that sends confirmation instructions for previous email change request' do
it " mentions the recipient's email in the message body " , :aggregate_failures do
same_user = User . find ( user . id )
same_user . update! ( email : unconfirmed_email )
user . update! ( email : another_unconfirmed_email )
perform_enqueued_jobs
confirmation_instructions_for_unconfirmed_email = ActionMailer :: Base . deliveries . find do | message |
message . subject == 'Confirmation instructions' && message . to . include? ( unconfirmed_email )
end
expect ( confirmation_instructions_for_unconfirmed_email . html_part . body . encoded ) . to match same_user . unconfirmed_email
expect ( confirmation_instructions_for_unconfirmed_email . text_part . body . encoded ) . to match same_user . unconfirmed_email
confirmation_instructions_for_another_unconfirmed_email = ActionMailer :: Base . deliveries . find do | message |
message . subject == 'Confirmation instructions' && message . to . include? ( another_unconfirmed_email )
end
expect ( confirmation_instructions_for_another_unconfirmed_email . html_part . body . encoded ) . to match user . unconfirmed_email
expect ( confirmation_instructions_for_another_unconfirmed_email . text_part . body . encoded ) . to match user . unconfirmed_email
end
end
end
2020-05-24 23:13:21 +05:30
end
2014-09-02 18:07:02 +05:30
describe 'validations' do
2020-01-01 13:55:28 +05:30
describe 'password' do
2020-07-28 23:09:34 +05:30
let! ( :user ) { build_stubbed ( :user ) }
2020-01-01 13:55:28 +05:30
before do
allow ( Devise ) . to receive ( :password_length ) . and_return ( 8 .. 128 )
allow ( described_class ) . to receive ( :password_length ) . and_return ( 10 .. 130 )
end
context 'length' do
it { is_expected . to validate_length_of ( :password ) . is_at_least ( 10 ) . is_at_most ( 130 ) }
end
context 'length validator' do
context 'for a short password' do
before do
user . password = user . password_confirmation = 'abc'
end
it 'does not run the default Devise password length validation' do
expect ( user ) . to be_invalid
expect ( user . errors . full_messages . join ) . not_to include ( 'is too short (minimum is 8 characters)' )
end
it 'runs the custom password length validator' do
expect ( user ) . to be_invalid
expect ( user . errors . full_messages . join ) . to include ( 'is too short (minimum is 10 characters)' )
end
end
context 'for a long password' do
before do
user . password = user . password_confirmation = 'a' * 140
end
it 'does not run the default Devise password length validation' do
expect ( user ) . to be_invalid
expect ( user . errors . full_messages . join ) . not_to include ( 'is too long (maximum is 128 characters)' )
end
it 'runs the custom password length validator' do
expect ( user ) . to be_invalid
expect ( user . errors . full_messages . join ) . to include ( 'is too long (maximum is 130 characters)' )
end
end
end
2022-10-11 01:57:18 +05:30
context 'check_password_weakness' do
let ( :weak_password ) { " qwertyuiop " }
context 'when feature flag is disabled' do
before do
stub_feature_flags ( block_weak_passwords : false )
end
it 'does not add an error when password is weak' do
expect ( Security :: WeakPasswords ) . not_to receive ( :weak_for_user? )
user . password = weak_password
expect ( user ) . to be_valid
end
end
context 'when feature flag is enabled' do
before do
stub_feature_flags ( block_weak_passwords : true )
end
it 'checks for password weakness when password changes' do
expect ( Security :: WeakPasswords ) . to receive ( :weak_for_user? )
. with ( weak_password , user ) . and_call_original
user . password = weak_password
expect ( user ) . not_to be_valid
end
it 'adds an error when password is weak' do
user . password = weak_password
expect ( user ) . not_to be_valid
expect ( user . errors ) . to be_of_kind ( :password , 'must not contain commonly used combinations of words and letters' )
end
it 'is valid when password is not weak' do
user . password = :: User . random_password
expect ( user ) . to be_valid
end
it 'is valid when weak password was already set' do
user = build ( :user , password : weak_password )
user . save! ( validate : false )
expect ( Security :: WeakPasswords ) . not_to receive ( :weak_for_user? )
# Change an unrelated value
user . name = " Example McExampleFace "
expect ( user ) . to be_valid
end
end
end
2020-01-01 13:55:28 +05:30
end
2019-07-07 11:18:12 +05:30
describe 'name' do
it { is_expected . to validate_presence_of ( :name ) }
2020-03-13 15:44:24 +05:30
it { is_expected . to validate_length_of ( :name ) . is_at_most ( 255 ) }
2019-07-07 11:18:12 +05:30
end
2019-12-04 20:38:33 +05:30
describe 'first name' do
2020-03-13 15:44:24 +05:30
it { is_expected . to validate_length_of ( :first_name ) . is_at_most ( 127 ) }
2019-12-04 20:38:33 +05:30
end
describe 'last name' do
2020-03-13 15:44:24 +05:30
it { is_expected . to validate_length_of ( :last_name ) . is_at_most ( 127 ) }
2019-12-04 20:38:33 +05:30
end
2020-10-24 23:57:45 +05:30
describe 'preferred_language' do
context 'when its value is nil in the database' do
let ( :user ) { build ( :user , preferred_language : nil ) }
it 'falls back to I18n.default_locale when empty in the database' do
expect ( user . preferred_language ) . to eq I18n . default_locale . to_s
end
it 'falls back to english when I18n.default_locale is not an available language' do
I18n . default_locale = :kl
2021-11-18 22:05:49 +05:30
default_preferred_language = user . send ( :default_preferred_language )
2020-10-24 23:57:45 +05:30
2021-11-18 22:05:49 +05:30
expect ( user . preferred_language ) . to eq default_preferred_language
2020-10-24 23:57:45 +05:30
end
end
end
2015-12-23 02:04:40 +05:30
describe 'username' do
it 'validates presence' do
expect ( subject ) . to validate_presence_of ( :username )
end
2021-01-29 00:20:46 +05:30
it 'rejects denied names' do
2015-12-23 02:04:40 +05:30
user = build ( :user , username : 'dashboard' )
expect ( user ) . not_to be_valid
2018-03-17 18:26:18 +05:30
expect ( user . errors . messages [ :username ] ) . to eq [ 'dashboard is a reserved name' ]
2015-12-23 02:04:40 +05:30
end
2017-08-17 22:00:37 +05:30
it 'allows child names' do
user = build ( :user , username : 'avatar' )
expect ( user ) . to be_valid
end
it 'allows wildcard names' do
user = build ( :user , username : 'blob' )
expect ( user ) . to be_valid
end
2018-03-17 18:26:18 +05:30
context 'when username is changed' do
2021-11-18 22:05:49 +05:30
let ( :user ) { build_stubbed ( :user , username : 'old_path' , namespace : build_stubbed ( :user_namespace ) ) }
2017-09-10 17:25:29 +05:30
2018-03-17 18:26:18 +05:30
it 'validates move_dir is allowed for the namespace' do
expect ( user . namespace ) . to receive ( :any_project_has_container_registry_tags? ) . and_return ( true )
user . username = 'new_path'
expect ( user ) . to be_invalid
2020-01-01 13:55:28 +05:30
expect ( user . errors . messages [ :username ] . first ) . to eq ( _ ( 'cannot be changed if a personal project has container registry tags.' ) )
2018-03-17 18:26:18 +05:30
end
end
context 'when the username is in use by another user' do
let ( :username ) { 'foo' }
let! ( :other_user ) { create ( :user , username : username ) }
it 'is invalid' do
user = build ( :user , username : username )
expect ( user ) . not_to be_valid
expect ( user . errors . full_messages ) . to eq ( [ 'Username has already been taken' ] )
end
2015-12-23 02:04:40 +05:30
end
2021-07-02 01:05:55 +05:30
it 'validates format' do
Mime :: EXTENSION_LOOKUP . keys . each do | type |
user = build ( :user , username : " test. #{ type } " )
expect ( user ) . not_to be_valid
2021-11-18 22:05:49 +05:30
expect ( user . errors . full_messages ) . to include ( 'Username ending with a reserved file extension is not allowed.' )
2021-09-04 01:27:46 +05:30
expect ( build ( :user , username : " test #{ type } " ) ) . to be_valid
2021-07-02 01:05:55 +05:30
end
end
it 'validates format on updated record' do
expect ( create ( :user ) . update ( username : 'profile.html' ) ) . to be_falsey
end
2015-12-23 02:04:40 +05:30
end
2018-03-17 18:26:18 +05:30
it 'has a DB-level NOT NULL constraint on projects_limit' do
user = create ( :user )
expect ( user . persisted? ) . to eq ( true )
expect do
user . update_columns ( projects_limit : nil )
end . to raise_error ( ActiveRecord :: StatementInvalid )
end
2015-04-26 12:48:37 +05:30
it { is_expected . to validate_presence_of ( :projects_limit ) }
it { is_expected . to validate_numericality_of ( :projects_limit ) }
it { is_expected . to allow_value ( 0 ) . for ( :projects_limit ) }
it { is_expected . not_to allow_value ( - 1 ) . for ( :projects_limit ) }
2017-08-17 22:00:37 +05:30
it { is_expected . not_to allow_value ( Gitlab :: Database :: MAX_INT_VALUE + 1 ) . for ( :projects_limit ) }
2014-09-02 18:07:02 +05:30
2021-04-17 20:07:23 +05:30
it_behaves_like 'an object with email-formatted attributes' , :email do
2016-04-02 18:10:28 +05:30
subject { build ( :user ) }
end
2014-09-02 18:07:02 +05:30
2022-03-02 08:16:31 +05:30
it_behaves_like 'an object with email-formatted attributes' , :public_email , :notification_email do
2020-05-30 21:06:31 +05:30
subject { create ( :user ) . tap { | user | user . emails << build ( :email , email : email_value , confirmed_at : Time . current ) } }
2016-04-02 18:10:28 +05:30
end
2015-09-11 14:41:01 +05:30
2021-11-11 11:23:49 +05:30
describe '#commit_email_or_default' do
2018-12-05 23:21:45 +05:30
subject ( :user ) { create ( :user ) }
it 'defaults to the primary email' do
expect ( user . email ) . to be_present
2021-11-11 11:23:49 +05:30
expect ( user . commit_email_or_default ) . to eq ( user . email )
2018-12-05 23:21:45 +05:30
end
it 'defaults to the primary email when the column in the database is null' do
user . update_column ( :commit_email , nil )
found_user = described_class . find_by ( id : user . id )
2021-11-11 11:23:49 +05:30
expect ( found_user . commit_email_or_default ) . to eq ( user . email )
2018-12-05 23:21:45 +05:30
end
2018-12-13 13:39:08 +05:30
it 'returns the private commit email when commit_email has _private' do
user . update_column ( :commit_email , Gitlab :: PrivateCommitEmail :: TOKEN )
2021-11-11 11:23:49 +05:30
expect ( user . commit_email_or_default ) . to eq ( user . private_commit_email )
2018-12-13 13:39:08 +05:30
end
2021-11-11 11:23:49 +05:30
end
describe '#commit_email=' do
subject ( :user ) { create ( :user ) }
2018-12-13 13:39:08 +05:30
2018-12-05 23:21:45 +05:30
it 'can be set to a confirmed email' do
confirmed = create ( :email , :confirmed , user : user )
user . commit_email = confirmed . email
expect ( user ) . to be_valid
end
it 'can not be set to an unconfirmed email' do
unconfirmed = create ( :email , user : user )
user . commit_email = unconfirmed . email
2021-11-11 11:23:49 +05:30
expect ( user ) . not_to be_valid
2018-12-05 23:21:45 +05:30
end
it 'can not be set to a non-existent email' do
user . commit_email = 'non-existent-email@nonexistent.nonexistent'
2021-11-11 11:23:49 +05:30
expect ( user ) . not_to be_valid
2018-12-05 23:21:45 +05:30
end
it 'can not be set to an invalid email, even if confirmed' do
confirmed = create ( :email , :confirmed , :skip_validate , user : user , email : 'invalid' )
user . commit_email = confirmed . email
expect ( user ) . not_to be_valid
end
end
2016-04-02 18:10:28 +05:30
describe 'email' do
2022-05-07 20:08:51 +05:30
let ( :expected_error ) { _ ( 'is not allowed for sign-up. Please use your regular email address. Check with your administrator.' ) }
2021-11-18 22:05:49 +05:30
2021-01-29 00:20:46 +05:30
context 'when no signup domains allowed' do
2016-06-16 23:09:34 +05:30
before do
2021-10-27 15:23:28 +05:30
stub_application_setting ( domain_allowlist : [ ] )
2016-06-16 23:09:34 +05:30
end
2015-09-11 14:41:01 +05:30
it 'accepts any email' do
user = build ( :user , email : " info@example.com " )
expect ( user ) . to be_valid
end
end
2020-03-13 15:44:24 +05:30
context 'bad regex' do
before do
2021-10-27 15:23:28 +05:30
stub_application_setting ( domain_allowlist : [ '([a-zA-Z0-9]+)+\.com' ] )
2020-03-13 15:44:24 +05:30
end
it 'does not hang on evil input' do
user = build ( :user , email : 'user@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!.com' )
expect do
Timeout . timeout ( 2 . seconds ) { user . valid? }
end . not_to raise_error
end
end
2021-01-29 00:20:46 +05:30
context 'when a signup domain is allowed and subdomains are allowed' do
2016-06-16 23:09:34 +05:30
before do
2021-10-27 15:23:28 +05:30
stub_application_setting ( domain_allowlist : [ 'example.com' , '*.example.com' ] )
2016-06-16 23:09:34 +05:30
end
2015-09-11 14:41:01 +05:30
it 'accepts info@example.com' do
user = build ( :user , email : " info@example.com " )
expect ( user ) . to be_valid
end
it 'accepts info@test.example.com' do
user = build ( :user , email : " info@test.example.com " )
expect ( user ) . to be_valid
end
it 'rejects example@test.com' do
user = build ( :user , email : " example@test.com " )
expect ( user ) . to be_invalid
2021-11-18 22:05:49 +05:30
expect ( user . errors . messages [ :email ] . first ) . to eq ( expected_error )
2015-09-11 14:41:01 +05:30
end
2022-03-02 08:16:31 +05:30
it 'does not allow user to update email to a non-allowlisted domain' do
user = create ( :user , email : " info@test.example.com " )
expect { user . update! ( email : " test@notexample.com " ) }
2022-05-07 20:08:51 +05:30
. to raise_error ( StandardError , 'Validation failed: Email is not allowed. Please use your regular email address. Check with your administrator.' )
2022-03-02 08:16:31 +05:30
end
2015-09-11 14:41:01 +05:30
end
2021-01-29 00:20:46 +05:30
context 'when a signup domain is allowed and subdomains are not allowed' do
2016-06-16 23:09:34 +05:30
before do
2021-10-27 15:23:28 +05:30
stub_application_setting ( domain_allowlist : [ 'example.com' ] )
2016-06-16 23:09:34 +05:30
end
2015-09-11 14:41:01 +05:30
it 'accepts info@example.com' do
user = build ( :user , email : " info@example.com " )
expect ( user ) . to be_valid
end
it 'rejects info@test.example.com' do
user = build ( :user , email : " info@test.example.com " )
expect ( user ) . to be_invalid
2021-11-18 22:05:49 +05:30
expect ( user . errors . messages [ :email ] . first ) . to eq ( expected_error )
2015-09-11 14:41:01 +05:30
end
it 'rejects example@test.com' do
user = build ( :user , email : " example@test.com " )
expect ( user ) . to be_invalid
2021-11-18 22:05:49 +05:30
expect ( user . errors . messages [ :email ] . first ) . to eq ( expected_error )
2015-09-11 14:41:01 +05:30
end
2017-08-17 22:00:37 +05:30
it 'accepts example@test.com when added by another user' do
user = build ( :user , email : " example@test.com " , created_by_id : 1 )
expect ( user ) . to be_valid
end
2015-09-11 14:41:01 +05:30
end
2016-06-02 11:05:42 +05:30
2021-01-29 00:20:46 +05:30
context 'domain denylist' do
2016-08-24 12:49:21 +05:30
before do
2021-10-27 15:23:28 +05:30
stub_application_setting ( domain_denylist_enabled : true )
stub_application_setting ( domain_denylist : [ 'example.com' ] )
2016-08-24 12:49:21 +05:30
end
2020-03-13 15:44:24 +05:30
context 'bad regex' do
before do
2021-10-27 15:23:28 +05:30
stub_application_setting ( domain_denylist : [ '([a-zA-Z0-9]+)+\.com' ] )
2020-03-13 15:44:24 +05:30
end
it 'does not hang on evil input' do
user = build ( :user , email : 'user@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!.com' )
expect do
Timeout . timeout ( 2 . seconds ) { user . valid? }
end . not_to raise_error
end
end
2021-01-29 00:20:46 +05:30
context 'when a signup domain is denied' do
2016-08-24 12:49:21 +05:30
it 'accepts info@test.com' do
user = build ( :user , email : 'info@test.com' )
expect ( user ) . to be_valid
end
it 'rejects info@example.com' do
user = build ( :user , email : 'info@example.com' )
expect ( user ) . not_to be_valid
2021-11-18 22:05:49 +05:30
expect ( user . errors . messages [ :email ] . first ) . to eq ( expected_error )
2016-08-24 12:49:21 +05:30
end
2017-08-17 22:00:37 +05:30
it 'accepts info@example.com when added by another user' do
user = build ( :user , email : 'info@example.com' , created_by_id : 1 )
expect ( user ) . to be_valid
end
2022-03-02 08:16:31 +05:30
it 'does not allow user to update email to a denied domain' do
user = create ( :user , email : 'info@test.com' )
expect { user . update! ( email : 'info@example.com' ) }
2022-05-07 20:08:51 +05:30
. to raise_error ( StandardError , 'Validation failed: Email is not allowed. Please use your regular email address. Check with your administrator.' )
2022-03-02 08:16:31 +05:30
end
2016-08-24 12:49:21 +05:30
end
2021-01-29 00:20:46 +05:30
context 'when a signup domain is denied but a wildcard subdomain is allowed' do
2016-08-24 12:49:21 +05:30
before do
2021-10-27 15:23:28 +05:30
stub_application_setting ( domain_denylist : [ 'test.example.com' ] )
stub_application_setting ( domain_allowlist : [ '*.example.com' ] )
2016-08-24 12:49:21 +05:30
end
2021-01-29 00:20:46 +05:30
it 'gives priority to allowlist and allow info@test.example.com' do
2016-08-24 12:49:21 +05:30
user = build ( :user , email : 'info@test.example.com' )
expect ( user ) . to be_valid
end
end
context 'with both lists containing a domain' do
before do
2021-10-27 15:23:28 +05:30
stub_application_setting ( domain_allowlist : [ 'test.com' ] )
2016-08-24 12:49:21 +05:30
end
it 'accepts info@test.com' do
user = build ( :user , email : 'info@test.com' )
expect ( user ) . to be_valid
end
it 'rejects info@example.com' do
user = build ( :user , email : 'info@example.com' )
expect ( user ) . not_to be_valid
2021-11-18 22:05:49 +05:30
expect ( user . errors . messages [ :email ] . first ) . to eq ( expected_error )
2016-08-24 12:49:21 +05:30
end
end
end
2020-04-08 14:13:33 +05:30
context 'email restrictions' do
context 'when email restriction is disabled' do
before do
stub_application_setting ( email_restrictions_enabled : false )
stub_application_setting ( email_restrictions : '\+' )
end
it 'does accept email address' do
user = build ( :user , email : 'info+1@test.com' )
expect ( user ) . to be_valid
end
end
context 'when email restrictions is enabled' do
before do
stub_application_setting ( email_restrictions_enabled : true )
stub_application_setting ( email_restrictions : '([\+]|\b(\w*gitlab.com\w*)\b)' )
end
it 'does not accept email address with + characters' do
user = build ( :user , email : 'info+1@test.com' )
expect ( user ) . not_to be_valid
end
it 'does not accept email with a gitlab domain' do
user = build ( :user , email : 'info@gitlab.com' )
expect ( user ) . not_to be_valid
end
it 'adds an error message when email is not accepted' do
user = build ( :user , email : 'info@gitlab.com' )
expect ( user ) . not_to be_valid
2021-11-18 22:05:49 +05:30
expect ( user . errors . messages [ :email ] . first ) . to eq ( expected_error )
2020-04-08 14:13:33 +05:30
end
2022-03-02 08:16:31 +05:30
it 'does not allow user to update email to a restricted domain' do
user = create ( :user , email : 'info@test.com' )
expect { user . update! ( email : 'info@gitlab.com' ) }
2022-05-07 20:08:51 +05:30
. to raise_error ( StandardError , 'Validation failed: Email is not allowed. Please use your regular email address. Check with your administrator.' )
2022-03-02 08:16:31 +05:30
end
2020-04-08 14:13:33 +05:30
it 'does accept a valid email address' do
user = build ( :user , email : 'info@test.com' )
expect ( user ) . to be_valid
end
context 'when created_by_id is set' do
it 'does accept the email address' do
user = build ( :user , email : 'info+1@test.com' , created_by_id : 1 )
expect ( user ) . to be_valid
end
end
end
end
2021-11-11 11:23:49 +05:30
context 'when secondary email is same as primary' do
let ( :user ) { create ( :user , email : 'user@example.com' ) }
2020-05-30 21:06:31 +05:30
2021-11-11 11:23:49 +05:30
it 'lets user change primary email without failing validations' do
user . commit_email = user . email
user . notification_email = user . email
user . public_email = user . email
user . save!
2020-05-30 21:06:31 +05:30
2021-11-11 11:23:49 +05:30
user . email = 'newemail@example.com'
user . confirm
2020-05-30 21:06:31 +05:30
expect ( user ) . to be_valid
end
2016-06-02 11:05:42 +05:30
end
2018-12-13 13:39:08 +05:30
2021-11-11 11:23:49 +05:30
context 'when commit_email is changed to _private' do
it 'passes user validations' do
user = create ( :user )
user . commit_email = '_private'
2018-12-13 13:39:08 +05:30
expect ( user ) . to be_valid
end
end
2014-09-02 18:07:02 +05:30
end
end
2021-11-18 22:05:49 +05:30
describe 'scopes' do
2021-01-03 14:25:43 +05:30
context 'blocked users' do
let_it_be ( :active_user ) { create ( :user ) }
let_it_be ( :blocked_user ) { create ( :user , :blocked ) }
let_it_be ( :ldap_blocked_user ) { create ( :omniauth_user , :ldap_blocked ) }
let_it_be ( :blocked_pending_approval_user ) { create ( :user , :blocked_pending_approval ) }
2021-06-08 01:23:25 +05:30
let_it_be ( :banned_user ) { create ( :user , :banned ) }
2021-01-03 14:25:43 +05:30
describe '.blocked' do
subject { described_class . blocked }
it 'returns only blocked users' do
expect ( subject ) . to include (
blocked_user ,
ldap_blocked_user
)
2021-06-08 01:23:25 +05:30
expect ( subject ) . not_to include ( active_user , blocked_pending_approval_user , banned_user )
2021-01-03 14:25:43 +05:30
end
end
describe '.blocked_pending_approval' do
subject { described_class . blocked_pending_approval }
it 'returns only pending approval users' do
expect ( subject ) . to contain_exactly ( blocked_pending_approval_user )
end
end
2021-06-08 01:23:25 +05:30
describe '.banned' do
subject { described_class . banned }
it 'returns only banned users' do
expect ( subject ) . to contain_exactly ( banned_user )
end
end
2021-01-03 14:25:43 +05:30
end
2021-11-18 22:05:49 +05:30
describe '.with_two_factor' do
it 'returns users with 2fa enabled via OTP' do
2016-06-16 23:09:34 +05:30
user_with_2fa = create ( :user , :two_factor_via_otp )
user_without_2fa = create ( :user )
2017-09-10 17:25:29 +05:30
users_with_two_factor = described_class . with_two_factor . pluck ( :id )
2016-06-16 23:09:34 +05:30
expect ( users_with_two_factor ) . to include ( user_with_2fa . id )
expect ( users_with_two_factor ) . not_to include ( user_without_2fa . id )
end
2021-11-18 22:05:49 +05:30
shared_examples 'returns the right users' do | trait |
it 'returns users with 2fa enabled via hardware token' do
2020-11-24 15:15:51 +05:30
user_with_2fa = create ( :user , trait )
user_without_2fa = create ( :user )
users_with_two_factor = described_class . with_two_factor . pluck ( :id )
2016-06-16 23:09:34 +05:30
2020-11-24 15:15:51 +05:30
expect ( users_with_two_factor ) . to include ( user_with_2fa . id )
expect ( users_with_two_factor ) . not_to include ( user_without_2fa . id )
end
2016-06-16 23:09:34 +05:30
2021-11-18 22:05:49 +05:30
it 'returns users with 2fa enabled via OTP and hardware token' do
2020-11-24 15:15:51 +05:30
user_with_2fa = create ( :user , :two_factor_via_otp , trait )
user_without_2fa = create ( :user )
users_with_two_factor = described_class . with_two_factor . pluck ( :id )
2016-06-16 23:09:34 +05:30
2020-11-24 15:15:51 +05:30
expect ( users_with_two_factor ) . to eq ( [ user_with_2fa . id ] )
expect ( users_with_two_factor ) . not_to include ( user_without_2fa . id )
end
it 'works with ORDER BY' do
user_with_2fa = create ( :user , :two_factor_via_otp , trait )
expect ( described_class
. with_two_factor
. reorder_by_name ) . to eq ( [ user_with_2fa ] )
end
2016-06-16 23:09:34 +05:30
end
2018-11-20 20:47:30 +05:30
2021-11-18 22:05:49 +05:30
describe 'and U2F' do
2020-11-24 15:15:51 +05:30
it_behaves_like " returns the right users " , :two_factor_via_u2f
end
2018-11-20 20:47:30 +05:30
2021-11-18 22:05:49 +05:30
describe 'and WebAuthn' do
2020-11-24 15:15:51 +05:30
it_behaves_like " returns the right users " , :two_factor_via_webauthn
2018-11-20 20:47:30 +05:30
end
2016-06-16 23:09:34 +05:30
end
2021-11-18 22:05:49 +05:30
describe '.without_two_factor' do
it 'excludes users with 2fa enabled via OTP' do
2016-06-16 23:09:34 +05:30
user_with_2fa = create ( :user , :two_factor_via_otp )
user_without_2fa = create ( :user )
2017-09-10 17:25:29 +05:30
users_without_two_factor = described_class . without_two_factor . pluck ( :id )
2016-06-16 23:09:34 +05:30
expect ( users_without_two_factor ) . to include ( user_without_2fa . id )
expect ( users_without_two_factor ) . not_to include ( user_with_2fa . id )
end
2021-11-18 22:05:49 +05:30
describe 'and u2f' do
it 'excludes users with 2fa enabled via U2F' do
2020-11-24 15:15:51 +05:30
user_with_2fa = create ( :user , :two_factor_via_u2f )
user_without_2fa = create ( :user )
users_without_two_factor = described_class . without_two_factor . pluck ( :id )
2016-06-16 23:09:34 +05:30
2020-11-24 15:15:51 +05:30
expect ( users_without_two_factor ) . to include ( user_without_2fa . id )
expect ( users_without_two_factor ) . not_to include ( user_with_2fa . id )
end
2021-11-18 22:05:49 +05:30
it 'excludes users with 2fa enabled via OTP and U2F' do
2020-11-24 15:15:51 +05:30
user_with_2fa = create ( :user , :two_factor_via_otp , :two_factor_via_u2f )
user_without_2fa = create ( :user )
users_without_two_factor = described_class . without_two_factor . pluck ( :id )
expect ( users_without_two_factor ) . to include ( user_without_2fa . id )
expect ( users_without_two_factor ) . not_to include ( user_with_2fa . id )
end
2016-06-16 23:09:34 +05:30
end
2021-11-18 22:05:49 +05:30
describe 'and webauthn' do
it 'excludes users with 2fa enabled via WebAuthn' do
2020-11-24 15:15:51 +05:30
user_with_2fa = create ( :user , :two_factor_via_webauthn )
user_without_2fa = create ( :user )
users_without_two_factor = described_class . without_two_factor . pluck ( :id )
2016-06-16 23:09:34 +05:30
2020-11-24 15:15:51 +05:30
expect ( users_without_two_factor ) . to include ( user_without_2fa . id )
expect ( users_without_two_factor ) . not_to include ( user_with_2fa . id )
end
2021-11-18 22:05:49 +05:30
it 'excludes users with 2fa enabled via OTP and WebAuthn' do
2020-11-24 15:15:51 +05:30
user_with_2fa = create ( :user , :two_factor_via_otp , :two_factor_via_webauthn )
user_without_2fa = create ( :user )
users_without_two_factor = described_class . without_two_factor . pluck ( :id )
expect ( users_without_two_factor ) . to include ( user_without_2fa . id )
expect ( users_without_two_factor ) . not_to include ( user_with_2fa . id )
end
2016-06-16 23:09:34 +05:30
end
end
2017-08-17 22:00:37 +05:30
2020-03-13 15:44:24 +05:30
describe '.random_password' do
let ( :random_password ) { described_class . random_password }
before do
expect ( User ) . to receive ( :password_length ) . and_return ( 88 .. 128 )
end
context 'length' do
it 'conforms to the current password length settings' do
expect ( random_password . length ) . to eq ( 128 )
end
end
end
2020-01-01 13:55:28 +05:30
describe '.password_length' do
let ( :password_length ) { described_class . password_length }
it 'is expected to be a Range' do
expect ( password_length ) . to be_a ( Range )
end
context 'minimum value' do
before do
stub_application_setting ( minimum_password_length : 101 )
end
it 'is determined by the current value of `minimum_password_length` attribute of application_setting' do
expect ( password_length . min ) . to eq ( 101 )
end
end
context 'maximum value' do
it 'is determined by the current value of `Devise.password_length.max`' do
2021-11-11 11:23:49 +05:30
expect ( password_length . max ) . to eq ( Devise . password_length . max )
2020-01-01 13:55:28 +05:30
end
end
end
2018-11-20 20:47:30 +05:30
describe '.limit_to_todo_authors' do
context 'when filtering by todo authors' do
let ( :user1 ) { create ( :user ) }
let ( :user2 ) { create ( :user ) }
before do
create ( :todo , user : user1 , author : user1 , state : :done )
create ( :todo , user : user2 , author : user2 , state : :pending )
end
it 'only returns users that have authored todos' do
users = described_class . limit_to_todo_authors (
user : user2 ,
with_todos : true ,
todo_state : :pending
)
expect ( users ) . to eq ( [ user2 ] )
end
it 'ignores users that do not have a todo in the matching state' do
users = described_class . limit_to_todo_authors (
user : user1 ,
with_todos : true ,
todo_state : :pending
)
expect ( users ) . to be_empty
end
end
context 'when not filtering by todo authors' do
it 'returns the input relation' do
user1 = create ( :user )
user2 = create ( :user )
rel = described_class . limit_to_todo_authors ( user : user1 )
expect ( rel ) . to include ( user1 , user2 )
end
end
context 'when no user is provided' do
it 'returns the input relation' do
user1 = create ( :user )
user2 = create ( :user )
rel = described_class . limit_to_todo_authors
expect ( rel ) . to include ( user1 , user2 )
end
end
end
describe '.by_username' do
it 'finds users regardless of the case passed' do
user = create ( :user , username : 'CaMeLcAsEd' )
user2 = create ( :user , username : 'UPPERCASE' )
expect ( described_class . by_username ( %w( CAMELCASED uppercase ) ) )
. to contain_exactly ( user , user2 )
end
it 'finds a single user regardless of the case passed' do
user = create ( :user , username : 'CaMeLcAsEd' )
2017-08-17 22:00:37 +05:30
2018-11-20 20:47:30 +05:30
expect ( described_class . by_username ( 'CAMELCASED' ) )
. to contain_exactly ( user )
2017-08-17 22:00:37 +05:30
end
end
2020-01-01 13:55:28 +05:30
describe '.with_expiring_and_not_notified_personal_access_tokens' do
let_it_be ( :user1 ) { create ( :user ) }
let_it_be ( :user2 ) { create ( :user ) }
let_it_be ( :user3 ) { create ( :user ) }
let_it_be ( :expired_token ) { create ( :personal_access_token , user : user1 , expires_at : 2 . days . ago ) }
let_it_be ( :revoked_token ) { create ( :personal_access_token , user : user1 , revoked : true ) }
2020-06-23 00:09:42 +05:30
let_it_be ( :impersonation_token ) { create ( :personal_access_token , :impersonation , user : user1 , expires_at : 2 . days . from_now ) }
2020-01-01 13:55:28 +05:30
let_it_be ( :valid_token_and_notified ) { create ( :personal_access_token , user : user2 , expires_at : 2 . days . from_now , expire_notification_delivered : true ) }
let_it_be ( :valid_token1 ) { create ( :personal_access_token , user : user2 , expires_at : 2 . days . from_now ) }
let_it_be ( :valid_token2 ) { create ( :personal_access_token , user : user2 , expires_at : 2 . days . from_now ) }
2021-09-30 23:02:18 +05:30
2020-01-01 13:55:28 +05:30
let ( :users ) { described_class . with_expiring_and_not_notified_personal_access_tokens ( from ) }
context 'in one day' do
let ( :from ) { 1 . day . from_now }
it " doesn't include an user " do
expect ( users ) . to be_empty
end
end
context 'in three days' do
let ( :from ) { 3 . days . from_now }
it 'only includes user2' do
expect ( users ) . to contain_exactly ( user2 )
end
end
end
2020-03-13 15:44:24 +05:30
2020-10-24 23:57:45 +05:30
describe '.with_personal_access_tokens_expired_today' do
let_it_be ( :user1 ) { create ( :user ) }
let_it_be ( :expired_today ) { create ( :personal_access_token , user : user1 , expires_at : Date . current ) }
let_it_be ( :user2 ) { create ( :user ) }
let_it_be ( :revoked_token ) { create ( :personal_access_token , user : user2 , expires_at : Date . current , revoked : true ) }
let_it_be ( :user3 ) { create ( :user ) }
let_it_be ( :impersonated_token ) { create ( :personal_access_token , user : user3 , expires_at : Date . current , impersonation : true ) }
let_it_be ( :user4 ) { create ( :user ) }
let_it_be ( :already_notified ) { create ( :personal_access_token , user : user4 , expires_at : Date . current , after_expiry_notification_delivered : true ) }
it 'returns users whose token has expired today' do
expect ( described_class . with_personal_access_tokens_expired_today ) . to contain_exactly ( user1 )
end
end
2021-04-29 21:17:54 +05:30
context 'SSH key expiration scopes' do
let_it_be ( :user1 ) { create ( :user ) }
let_it_be ( :user2 ) { create ( :user ) }
2022-07-16 23:28:13 +05:30
let_it_be ( :expired_today_not_notified ) { create ( :key , :expired_today , user : user1 ) }
let_it_be ( :expired_today_already_notified ) { create ( :key , :expired_today , user : user2 , expiry_notification_delivered_at : Time . current ) }
2021-04-29 21:17:54 +05:30
let_it_be ( :expiring_soon_not_notified ) { create ( :key , expires_at : 2 . days . from_now , user : user2 ) }
let_it_be ( :expiring_soon_notified ) { create ( :key , expires_at : 2 . days . from_now , user : user1 , before_expiry_notification_delivered_at : Time . current ) }
describe '.with_ssh_key_expiring_soon' do
it 'returns users whose keys will expire soon' do
expect ( described_class . with_ssh_key_expiring_soon ) . to contain_exactly ( user2 )
end
end
end
2020-03-13 15:44:24 +05:30
describe '.active_without_ghosts' do
let_it_be ( :user1 ) { create ( :user , :external ) }
let_it_be ( :user2 ) { create ( :user , state : 'blocked' ) }
2020-05-24 23:13:21 +05:30
let_it_be ( :user3 ) { create ( :user , :ghost ) }
2020-03-13 15:44:24 +05:30
let_it_be ( :user4 ) { create ( :user ) }
it 'returns all active users but ghost users' do
expect ( described_class . active_without_ghosts ) . to match_array ( [ user1 , user4 ] )
end
end
describe '.without_ghosts' do
let_it_be ( :user1 ) { create ( :user , :external ) }
let_it_be ( :user2 ) { create ( :user , state : 'blocked' ) }
2020-05-24 23:13:21 +05:30
let_it_be ( :user3 ) { create ( :user , :ghost ) }
2020-03-13 15:44:24 +05:30
it 'returns users without ghosts users' do
expect ( described_class . without_ghosts ) . to match_array ( [ user1 , user2 ] )
end
end
2020-09-03 11:15:55 +05:30
2021-06-08 01:23:25 +05:30
describe '.for_todos' do
let_it_be ( :user1 ) { create ( :user ) }
let_it_be ( :user2 ) { create ( :user ) }
let_it_be ( :issue ) { create ( :issue ) }
let_it_be ( :todo1 ) { create ( :todo , target : issue , author : user1 , user : user1 ) }
let_it_be ( :todo2 ) { create ( :todo , target : issue , author : user1 , user : user1 ) }
let_it_be ( :todo3 ) { create ( :todo , target : issue , author : user2 , user : user2 ) }
it 'returns users for the given todos' do
expect ( described_class . for_todos ( issue . todos ) )
. to contain_exactly ( user1 , user2 )
end
end
2022-08-13 15:12:31 +05:30
describe '.order_recent_last_activity' do
it 'sorts users by activity and id to make the ordes deterministic' do
expect ( described_class . order_recent_last_activity . to_sql ) . to include (
'ORDER BY "users"."last_activity_on" DESC NULLS LAST, "users"."id" ASC' )
end
end
describe '.order_oldest_last_activity' do
it 'sorts users by activity and id to make the ordes deterministic' do
expect ( described_class . order_oldest_last_activity . to_sql ) . to include (
'ORDER BY "users"."last_activity_on" ASC NULLS FIRST, "users"."id" DESC' )
end
end
2022-11-25 23:54:43 +05:30
describe '.order_recent_sign_in' do
it 'sorts users by current_sign_in_at in descending order' do
expect ( described_class . order_recent_sign_in . to_sql ) . to include (
'ORDER BY "users"."current_sign_in_at" DESC NULLS LAST' )
end
end
describe '.order_oldest_sign_in' do
it 'sorts users by current_sign_in_at in ascending order' do
expect ( described_class . order_oldest_sign_in . to_sql ) . to include (
'ORDER BY "users"."current_sign_in_at" ASC NULLS LAST' )
end
end
2016-06-16 23:09:34 +05:30
end
2022-01-26 12:08:38 +05:30
context 'strip attributes' do
context 'name' do
let ( :user ) { User . new ( name : ' John Smith ' ) }
it 'strips whitespaces on validation' do
expect { user . valid? } . to change { user . name } . to ( 'John Smith' )
end
end
end
2021-11-18 22:05:49 +05:30
describe 'Respond to' do
2017-08-17 22:00:37 +05:30
it { is_expected . to respond_to ( :admin? ) }
2015-04-26 12:48:37 +05:30
it { is_expected . to respond_to ( :name ) }
2016-06-02 11:05:42 +05:30
it { is_expected . to respond_to ( :external? ) }
end
describe 'before save hook' do
2020-03-13 15:44:24 +05:30
describe '#default_private_profile_to_false' do
2019-09-30 21:07:59 +05:30
let ( :user ) { create ( :user , private_profile : true ) }
it 'converts nil to false' do
user . private_profile = nil
user . save!
expect ( user . private_profile ) . to eq false
end
end
2016-06-02 11:05:42 +05:30
context 'when saving an external user' do
let ( :user ) { create ( :user ) }
let ( :external_user ) { create ( :user , external : true ) }
2021-11-18 22:05:49 +05:30
it 'sets other properties as well' do
2016-06-02 11:05:42 +05:30
expect ( external_user . can_create_team ) . to be_falsey
expect ( external_user . can_create_group ) . to be_falsey
expect ( external_user . projects_limit ) . to be 0
end
end
2018-03-17 18:26:18 +05:30
describe '#check_for_verified_email' do
let ( :user ) { create ( :user ) }
let ( :secondary ) { create ( :email , :confirmed , email : 'secondary@example.com' , user : user ) }
2021-04-17 20:07:23 +05:30
it 'allows a verified secondary email to be used as the primary without needing reconfirmation' do
2018-11-18 11:00:15 +05:30
user . update! ( email : secondary . email )
2018-03-17 18:26:18 +05:30
user . reload
expect ( user . email ) . to eq secondary . email
expect ( user . unconfirmed_email ) . to eq nil
expect ( user . confirmed? ) . to be_truthy
end
end
2014-09-02 18:07:02 +05:30
end
2018-03-17 18:26:18 +05:30
describe 'after commit hook' do
2021-12-11 22:18:48 +05:30
describe 'when the primary email is updated' do
2018-03-17 18:26:18 +05:30
before do
@user = create ( :user , email : 'primary@example.com' ) . tap do | user |
user . skip_reconfirmation!
end
@secondary = create :email , email : 'secondary@example.com' , user : @user
@user . reload
end
2021-12-11 22:18:48 +05:30
it 'keeps old primary to secondary emails when secondary is a new email' do
2018-11-18 11:00:15 +05:30
@user . update! ( email : 'new_primary@example.com' )
2018-03-17 18:26:18 +05:30
@user . reload
2022-05-07 20:08:51 +05:30
expect ( @user . emails . count ) . to eq 3
expect ( @user . emails . pluck ( :email ) ) . to match_array ( [ @secondary . email , 'primary@example.com' , 'new_primary@example.com' ] )
2018-03-17 18:26:18 +05:30
end
2020-05-30 21:06:31 +05:30
context 'when the first email was unconfirmed and the second email gets confirmed' do
let ( :user ) { create ( :user , :unconfirmed , email : 'should-be-unconfirmed@test.com' ) }
before do
user . update! ( email : 'should-be-confirmed@test.com' )
user . confirm
end
it 'updates user.email' do
expect ( user . email ) . to eq ( 'should-be-confirmed@test.com' )
end
it 'confirms user.email' do
expect ( user ) . to be_confirmed
end
2021-12-11 22:18:48 +05:30
it 'does not add unconfirmed email to secondary' do
expect ( user . emails . map ( & :email ) ) . not_to include ( 'should-be-unconfirmed@test.com' )
2020-05-30 21:06:31 +05:30
end
it 'has only one email association' do
2020-06-23 00:09:42 +05:30
expect ( user . emails . size ) . to eq ( 1 )
2020-05-30 21:06:31 +05:30
end
end
end
context 'when an existing email record is set as primary' do
let ( :user ) { create ( :user , email : 'confirmed@test.com' ) }
context 'when it is unconfirmed' do
let ( :originally_unconfirmed_email ) { 'should-stay-unconfirmed@test.com' }
before do
user . emails << create ( :email , email : originally_unconfirmed_email , confirmed_at : nil )
user . update! ( email : originally_unconfirmed_email )
end
it 'keeps the user confirmed' do
expect ( user ) . to be_confirmed
end
it 'keeps the original email' do
expect ( user . email ) . to eq ( 'confirmed@test.com' )
end
context 'when the email gets confirmed' do
before do
user . confirm
end
it 'keeps the user confirmed' do
expect ( user ) . to be_confirmed
end
it 'updates the email' do
expect ( user . email ) . to eq ( originally_unconfirmed_email )
end
end
end
context 'when it is confirmed' do
let! ( :old_confirmed_email ) { user . email }
let ( :confirmed_email ) { 'already-confirmed@test.com' }
before do
user . emails << create ( :email , :confirmed , email : confirmed_email )
user . update! ( email : confirmed_email )
end
it 'keeps the user confirmed' do
expect ( user ) . to be_confirmed
end
it 'updates the email' do
expect ( user . email ) . to eq ( confirmed_email )
end
2021-12-11 22:18:48 +05:30
it 'keeps the old email' do
2020-05-30 21:06:31 +05:30
email = user . reload . emails . first
expect ( email . email ) . to eq ( old_confirmed_email )
expect ( email ) . to be_confirmed
end
end
end
context 'when unconfirmed user deletes a confirmed additional email' do
let ( :user ) { create ( :user , :unconfirmed ) }
before do
user . emails << create ( :email , :confirmed )
end
it 'does not affect the confirmed status' do
expect { user . emails . confirmed . destroy_all } . not_to change { user . confirmed? } # rubocop: disable Cop/DestroyAll
end
2018-03-17 18:26:18 +05:30
end
2018-11-08 19:23:39 +05:30
2021-11-11 11:23:49 +05:30
describe 'when changing email' do
let ( :user ) { create ( :user ) }
let ( :new_email ) { 'new-email@example.com' }
2018-11-08 19:23:39 +05:30
2021-11-11 11:23:49 +05:30
context 'if notification_email was nil' do
2018-11-08 19:23:39 +05:30
it 'sets :unconfirmed_email' do
expect do
user . tap { | u | u . update! ( email : new_email ) } . reload
end . to change ( user , :unconfirmed_email ) . to ( new_email )
end
2021-11-11 11:23:49 +05:30
it 'does not change notification_email or notification_email_or_default before email is confirmed' do
2018-11-08 19:23:39 +05:30
expect do
user . tap { | u | u . update! ( email : new_email ) } . reload
2021-11-11 11:23:49 +05:30
end . not_to change ( user , :notification_email_or_default )
expect ( user . notification_email ) . to be_nil
2018-11-08 19:23:39 +05:30
end
2021-11-11 11:23:49 +05:30
it 'updates notification_email_or_default to the new email once confirmed' do
2018-11-08 19:23:39 +05:30
user . update! ( email : new_email )
expect do
user . tap ( & :confirm ) . reload
2021-11-11 11:23:49 +05:30
end . to change ( user , :notification_email_or_default ) . to eq ( new_email )
expect ( user . notification_email ) . to be_nil
2018-11-08 19:23:39 +05:30
end
2021-11-11 11:23:49 +05:30
end
2018-11-08 19:23:39 +05:30
2021-11-11 11:23:49 +05:30
context 'when notification_email is set to a secondary email' do
let! ( :email_attrs ) { attributes_for ( :email , :confirmed , user : user ) }
let ( :secondary ) { create ( :email , :confirmed , email : 'secondary@example.com' , user : user ) }
2018-11-08 19:23:39 +05:30
2021-11-11 11:23:49 +05:30
before do
user . emails . create! ( email_attrs )
user . tap { | u | u . update! ( notification_email : email_attrs [ :email ] ) } . reload
end
2018-11-08 19:23:39 +05:30
2021-11-11 11:23:49 +05:30
it 'does not change notification_email to email before email is confirmed' do
expect do
user . tap { | u | u . update! ( email : new_email ) } . reload
end . not_to change ( user , :notification_email )
end
2018-11-08 19:23:39 +05:30
2021-11-11 11:23:49 +05:30
it 'does not change notification_email to email once confirmed' do
user . update! ( email : new_email )
2018-11-08 19:23:39 +05:30
2021-11-11 11:23:49 +05:30
expect do
user . tap ( & :confirm ) . reload
end . not_to change ( user , :notification_email )
2018-11-08 19:23:39 +05:30
end
end
end
describe '#update_invalid_gpg_signatures' do
let ( :user ) do
create ( :user , email : 'tula.torphy@abshire.ca' ) . tap do | user |
user . skip_reconfirmation!
end
end
it 'does nothing when the name is updated' do
expect ( user ) . not_to receive ( :update_invalid_gpg_signatures )
2018-11-18 11:00:15 +05:30
user . update! ( name : 'Bette' )
2018-11-08 19:23:39 +05:30
end
it 'synchronizes the gpg keys when the email is updated' do
expect ( user ) . to receive ( :update_invalid_gpg_signatures ) . at_most ( :twice )
2018-11-18 11:00:15 +05:30
user . update! ( email : 'shawnee.ritchie@denesik.com' )
2018-11-08 19:23:39 +05:30
end
end
2017-09-10 17:25:29 +05:30
end
2019-12-04 20:38:33 +05:30
describe 'name getters' do
let ( :user ) { create ( :user , name : 'Kane Martin William' ) }
it 'derives first name from full name, if not present' do
expect ( user . first_name ) . to eq ( 'Kane' )
end
it 'derives last name from full name, if not present' do
expect ( user . last_name ) . to eq ( 'Martin William' )
end
end
2019-07-07 11:18:12 +05:30
describe '#highest_role' do
2020-04-22 19:07:51 +05:30
let_it_be ( :user ) { create ( :user ) }
2019-07-07 11:18:12 +05:30
2020-04-22 19:07:51 +05:30
context 'when user_highest_role does not exist' do
it 'returns NO_ACCESS' do
expect ( user . highest_role ) . to eq ( Gitlab :: Access :: NO_ACCESS )
2019-07-07 11:18:12 +05:30
end
end
2020-04-22 19:07:51 +05:30
context 'when user_highest_role exists' do
context 'stored highest access level is nil' do
it 'returns Gitlab::Access::NO_ACCESS' do
create ( :user_highest_role , user : user )
2019-07-07 11:18:12 +05:30
2020-04-22 19:07:51 +05:30
expect ( user . highest_role ) . to eq ( Gitlab :: Access :: NO_ACCESS )
end
2019-07-07 11:18:12 +05:30
end
2020-04-22 19:07:51 +05:30
context 'stored highest access level present' do
context 'with association :user_highest_role' do
let ( :another_user ) { create ( :user ) }
2019-07-07 11:18:12 +05:30
2020-04-22 19:07:51 +05:30
before do
create ( :user_highest_role , :maintainer , user : user )
create ( :user_highest_role , :developer , user : another_user )
end
2019-07-07 11:18:12 +05:30
2020-04-22 19:07:51 +05:30
it 'returns the correct highest role' do
users = User . includes ( :user_highest_role ) . where ( id : [ user . id , another_user . id ] )
2019-07-07 11:18:12 +05:30
2020-04-22 19:07:51 +05:30
expect ( users . collect { | u | [ u . id , u . highest_role ] } ) . to contain_exactly (
[ user . id , Gitlab :: Access :: MAINTAINER ] ,
[ another_user . id , Gitlab :: Access :: DEVELOPER ]
)
end
end
2019-07-07 11:18:12 +05:30
end
end
end
2021-06-08 01:23:25 +05:30
describe '#credit_card_validated_at' do
let_it_be ( :user ) { create ( :user ) }
context 'when credit_card_validation does not exist' do
it 'returns nil' do
expect ( user . credit_card_validated_at ) . to be nil
end
end
context 'when credit_card_validation exists' do
it 'returns the credit card validated time' do
credit_card_validated_time = Time . current - 1 . day
create ( :credit_card_validation , credit_card_validated_at : credit_card_validated_time , user : user )
expect ( user . credit_card_validated_at ) . to eq ( credit_card_validated_time )
end
end
end
2017-09-10 17:25:29 +05:30
describe '#update_tracked_fields!' , :clean_gitlab_redis_shared_state do
2022-03-02 08:16:31 +05:30
let ( :request ) { double ( 'request' , remote_ip : " 127.0.0.1 " ) }
2017-09-10 17:25:29 +05:30
let ( :user ) { create ( :user ) }
it 'writes trackable attributes' do
expect do
user . update_tracked_fields! ( request )
end . to change { user . reload . current_sign_in_at }
end
it 'does not write trackable attributes when called a second time within the hour' do
user . update_tracked_fields! ( request )
expect do
user . update_tracked_fields! ( request )
end . not_to change { user . reload . current_sign_in_at }
end
it 'writes trackable attributes for a different user' do
user2 = create ( :user )
user . update_tracked_fields! ( request )
expect do
user2 . update_tracked_fields! ( request )
end . to change { user2 . reload . current_sign_in_at }
end
2018-03-17 18:26:18 +05:30
it 'does not write if the DB is in read-only mode' do
expect ( Gitlab :: Database ) . to receive ( :read_only? ) . and_return ( true )
expect do
user . update_tracked_fields! ( request )
end . not_to change { user . reload . current_sign_in_at }
end
2017-09-10 17:25:29 +05:30
end
2017-08-17 22:00:37 +05:30
shared_context 'user keys' do
let ( :user ) { create ( :user ) }
let! ( :key ) { create ( :key , user : user ) }
let! ( :deploy_key ) { create ( :deploy_key , user : user ) }
end
describe '#keys' do
include_context 'user keys'
context 'with key and deploy key stored' do
it 'returns stored key, but not deploy_key' do
expect ( user . keys ) . to include key
expect ( user . keys ) . not_to include deploy_key
end
end
end
2019-10-12 21:52:04 +05:30
describe '#accessible_deploy_keys' do
let ( :user ) { create ( :user ) }
let ( :project ) { create ( :project ) }
let! ( :private_deploy_keys_project ) { create ( :deploy_keys_project ) }
let! ( :public_deploy_keys_project ) { create ( :deploy_keys_project ) }
let! ( :accessible_deploy_keys_project ) { create ( :deploy_keys_project , project : project ) }
before do
2021-06-08 01:23:25 +05:30
public_deploy_keys_project . deploy_key . update! ( public : true )
2019-10-12 21:52:04 +05:30
project . add_developer ( user )
end
it 'user can only see deploy keys accessible to right projects' do
expect ( user . accessible_deploy_keys ) . to match_array ( [ public_deploy_keys_project . deploy_key ,
accessible_deploy_keys_project . deploy_key ] )
end
end
2017-08-17 22:00:37 +05:30
describe '#deploy_keys' do
include_context 'user keys'
context 'with key and deploy key stored' do
it 'returns stored deploy key, but not normal key' do
expect ( user . deploy_keys ) . to include deploy_key
expect ( user . deploy_keys ) . not_to include key
end
end
end
2015-09-11 14:41:01 +05:30
describe '#confirm' do
2022-03-02 08:16:31 +05:30
let ( :expired_confirmation_sent_at ) { Date . today - described_class . confirm_within - 7 . days }
let ( :extant_confirmation_sent_at ) { Date . today }
2016-06-16 23:09:34 +05:30
before do
allow_any_instance_of ( ApplicationSetting ) . to receive ( :send_user_confirmation_email ) . and_return ( true )
end
2022-03-02 08:16:31 +05:30
let ( :user ) do
create ( :user , :unconfirmed , unconfirmed_email : 'test@gitlab.com' ) . tap do | user |
user . update! ( confirmation_sent_at : confirmation_sent_at )
end
end
2015-09-11 14:41:01 +05:30
2022-03-02 08:16:31 +05:30
shared_examples_for 'unconfirmed user' do
it 'returns unconfirmed' do
expect ( user . confirmed? ) . to be_falsey
end
2015-09-11 14:41:01 +05:30
end
2022-03-02 08:16:31 +05:30
context 'when the confirmation period has expired' do
let ( :confirmation_sent_at ) { expired_confirmation_sent_at }
it_behaves_like 'unconfirmed user'
it 'does not confirm the user' do
user . confirm
expect ( user . confirmed? ) . to be_falsey
end
it 'does not add the confirmed primary email to emails' do
user . confirm
expect ( user . emails . confirmed . map ( & :email ) ) . not_to include ( user . email )
end
2015-09-11 14:41:01 +05:30
end
2021-12-11 22:18:48 +05:30
2022-03-02 08:16:31 +05:30
context 'when the confirmation period has not expired' do
let ( :confirmation_sent_at ) { extant_confirmation_sent_at }
2021-12-11 22:18:48 +05:30
2022-03-02 08:16:31 +05:30
it_behaves_like 'unconfirmed user'
2021-12-11 22:18:48 +05:30
2022-03-02 08:16:31 +05:30
it 'confirms a user' do
user . confirm
expect ( user . confirmed? ) . to be_truthy
end
it 'adds the confirmed primary email to emails' do
2022-06-21 17:19:12 +05:30
expect ( user . emails . confirmed . map ( & :email ) ) . not_to include ( user . unconfirmed_email )
2022-03-02 08:16:31 +05:30
user . confirm
expect ( user . emails . confirmed . map ( & :email ) ) . to include ( user . email )
end
context 'when the primary email is already included in user.emails' do
let ( :expired_confirmation_sent_at_for_email ) { Date . today - Email . confirm_within - 7 . days }
let ( :extant_confirmation_sent_at_for_email ) { Date . today }
let! ( :email ) do
create ( :email , email : user . unconfirmed_email , user : user ) . tap do | email |
email . update! ( confirmation_sent_at : confirmation_sent_at_for_email )
end
end
context 'when the confirmation period of the email record has expired' do
let ( :confirmation_sent_at_for_email ) { expired_confirmation_sent_at_for_email }
it 'does not confirm the email record' do
user . confirm
expect ( email . reload . confirmed? ) . to be_falsey
end
end
context 'when the confirmation period of the email record has not expired' do
let ( :confirmation_sent_at_for_email ) { extant_confirmation_sent_at_for_email }
it 'confirms the email record' do
user . confirm
expect ( email . reload . confirmed? ) . to be_truthy
end
end
end
end
end
2022-05-07 20:08:51 +05:30
describe 'saving primary email to the emails table' do
context 'when calling skip_reconfirmation! while updating the primary email' do
let ( :user ) { create ( :user , email : 'primary@example.com' ) }
it 'adds the new email to emails' do
user . skip_reconfirmation!
user . update! ( email : 'new_primary@example.com' )
expect ( user . email ) . to eq ( 'new_primary@example.com' )
expect ( user . unconfirmed_email ) . to be_nil
expect ( user ) . to be_confirmed
expect ( user . emails . pluck ( :email ) ) . to include ( 'new_primary@example.com' )
expect ( user . emails . find_by ( email : 'new_primary@example.com' ) ) . to be_confirmed
end
end
context 'when the email is changed but not confirmed' do
let ( :user ) { create ( :user , email : 'primary@example.com' ) }
2022-06-21 17:19:12 +05:30
before do
2022-05-07 20:08:51 +05:30
user . update! ( email : 'new_primary@example.com' )
2022-06-21 17:19:12 +05:30
end
2022-05-07 20:08:51 +05:30
2022-06-21 17:19:12 +05:30
it 'does not add the new email to emails yet' do
2022-05-07 20:08:51 +05:30
expect ( user . unconfirmed_email ) . to eq ( 'new_primary@example.com' )
expect ( user . email ) . to eq ( 'primary@example.com' )
expect ( user ) . to be_confirmed
expect ( user . emails . pluck ( :email ) ) . not_to include ( 'new_primary@example.com' )
end
2022-06-21 17:19:12 +05:30
it 'adds the new email to emails upon confirmation' do
user . confirm
expect ( user . email ) . to eq ( 'new_primary@example.com' )
expect ( user ) . to be_confirmed
expect ( user . emails . pluck ( :email ) ) . to include ( 'new_primary@example.com' )
end
2022-05-07 20:08:51 +05:30
end
context 'when the user is created as not confirmed' do
let ( :user ) { create ( :user , :unconfirmed , email : 'primary@example.com' ) }
it 'does not add the email to emails yet' do
expect ( user ) . not_to be_confirmed
expect ( user . emails . pluck ( :email ) ) . not_to include ( 'primary@example.com' )
end
2022-06-21 17:19:12 +05:30
it 'adds the email to emails upon confirmation' do
user . confirm
expect ( user . emails . pluck ( :email ) ) . to include ( 'primary@example.com' )
end
2022-05-07 20:08:51 +05:30
end
context 'when the user is created as confirmed' do
let ( :user ) { create ( :user , email : 'primary@example.com' , confirmed_at : DateTime . now . utc ) }
it 'adds the email to emails' do
expect ( user ) . to be_confirmed
expect ( user . emails . pluck ( :email ) ) . to include ( 'primary@example.com' )
end
end
context 'when skip_confirmation! is called' do
let ( :user ) { build ( :user , :unconfirmed , email : 'primary@example.com' ) }
it 'adds the email to emails' do
user . skip_confirmation!
user . save!
expect ( user ) . to be_confirmed
expect ( user . emails . pluck ( :email ) ) . to include ( 'primary@example.com' )
end
end
end
2022-03-02 08:16:31 +05:30
describe '#force_confirm' do
let ( :expired_confirmation_sent_at ) { Date . today - described_class . confirm_within - 7 . days }
let ( :extant_confirmation_sent_at ) { Date . today }
let ( :user ) do
create ( :user , :unconfirmed , unconfirmed_email : 'test@gitlab.com' ) . tap do | user |
user . update! ( confirmation_sent_at : confirmation_sent_at )
end
end
shared_examples_for 'unconfirmed user' do
it 'returns unconfirmed' do
expect ( user . confirmed? ) . to be_falsey
end
end
shared_examples_for 'confirms the user on force_confirm' do
it 'confirms a user' do
user . force_confirm
expect ( user . confirmed? ) . to be_truthy
end
end
shared_examples_for 'adds the confirmed primary email to emails' do
it 'adds the confirmed primary email to emails' do
expect ( user . emails . confirmed . map ( & :email ) ) . not_to include ( user . email )
user . force_confirm
expect ( user . emails . confirmed . map ( & :email ) ) . to include ( user . email )
end
end
shared_examples_for 'confirms the email record if the primary email was already present in user.emails' do
context 'when the primary email is already included in user.emails' do
let ( :expired_confirmation_sent_at_for_email ) { Date . today - Email . confirm_within - 7 . days }
let ( :extant_confirmation_sent_at_for_email ) { Date . today }
let! ( :email ) do
create ( :email , email : user . unconfirmed_email , user : user ) . tap do | email |
email . update! ( confirmation_sent_at : confirmation_sent_at_for_email )
end
end
shared_examples_for 'confirms the email record' do
it 'confirms the email record' do
user . force_confirm
expect ( email . reload . confirmed? ) . to be_truthy
end
end
context 'when the confirmation period of the email record has expired' do
let ( :confirmation_sent_at_for_email ) { expired_confirmation_sent_at_for_email }
it_behaves_like 'confirms the email record'
end
context 'when the confirmation period of the email record has not expired' do
let ( :confirmation_sent_at_for_email ) { extant_confirmation_sent_at_for_email }
it_behaves_like 'confirms the email record'
end
end
end
context 'when the confirmation period has expired' do
let ( :confirmation_sent_at ) { expired_confirmation_sent_at }
it_behaves_like 'unconfirmed user'
it_behaves_like 'confirms the user on force_confirm'
it_behaves_like 'adds the confirmed primary email to emails'
it_behaves_like 'confirms the email record if the primary email was already present in user.emails'
end
context 'when the confirmation period has not expired' do
let ( :confirmation_sent_at ) { extant_confirmation_sent_at }
it_behaves_like 'unconfirmed user'
it_behaves_like 'confirms the user on force_confirm'
it_behaves_like 'adds the confirmed primary email to emails'
it_behaves_like 'confirms the email record if the primary email was already present in user.emails'
2021-12-11 22:18:48 +05:30
end
end
context 'if the user is created with confirmed_at set to a time' do
let! ( :user ) { create ( :user , email : 'test@gitlab.com' , confirmed_at : Time . now . utc ) }
it 'adds the confirmed primary email to emails upon creation' do
expect ( user . emails . confirmed . map ( & :email ) ) . to include ( user . email )
end
2015-09-11 14:41:01 +05:30
end
describe '#to_reference' do
let ( :user ) { create ( :user ) }
it 'returns a String reference to the object' do
expect ( user . to_reference ) . to eq " @ #{ user . username } "
end
end
2014-09-02 18:07:02 +05:30
describe '#generate_password' do
2021-11-18 22:05:49 +05:30
it 'does not generate password by default' do
2022-08-27 11:52:29 +05:30
password = User . random_password
user = create ( :user , password : password )
2014-09-02 18:07:02 +05:30
2022-08-27 11:52:29 +05:30
expect ( user . password ) . to eq ( password )
2014-09-02 18:07:02 +05:30
end
end
2018-12-13 13:39:08 +05:30
describe 'ensure user preference' do
it 'has user preference upon user initialization' do
user = build ( :user )
expect ( user . user_preference ) . to be_present
expect ( user . user_preference ) . not_to be_persisted
end
end
2017-09-10 17:25:29 +05:30
describe 'ensure incoming email token' do
it 'has incoming email token' do
user = create ( :user )
2018-03-17 18:26:18 +05:30
2017-09-10 17:25:29 +05:30
expect ( user . incoming_email_token ) . not_to be_blank
end
2018-11-18 11:00:15 +05:30
it 'uses SecureRandom to generate the incoming email token' do
2020-04-22 19:07:51 +05:30
allow_next_instance_of ( User ) do | user |
allow ( user ) . to receive ( :update_highest_role )
end
2022-01-26 12:08:38 +05:30
allow_next_instance_of ( Namespaces :: UserNamespace ) do | namespace |
allow ( namespace ) . to receive ( :schedule_sync_event_worker )
end
expect ( SecureRandom ) . to receive ( :hex ) . with ( no_args ) . and_return ( '3b8ca303' )
2018-11-18 11:00:15 +05:30
user = create ( :user )
expect ( user . incoming_email_token ) . to eql ( 'gitlab' )
end
2017-09-10 17:25:29 +05:30
end
describe '#ensure_user_rights_and_limits' do
describe 'with external user' do
let ( :user ) { create ( :user , external : true ) }
it 'receives callback when external changes' do
expect ( user ) . to receive ( :ensure_user_rights_and_limits )
2021-06-08 01:23:25 +05:30
user . update! ( external : false )
2017-09-10 17:25:29 +05:30
end
it 'ensures correct rights and limits for user' do
2022-11-25 23:54:43 +05:30
stub_application_setting ( can_create_group : true )
2017-09-10 17:25:29 +05:30
2022-11-25 23:54:43 +05:30
expect { user . update! ( external : false ) } . to change { user . can_create_group } . from ( false ) . to ( true )
2018-03-17 18:26:18 +05:30
. and change { user . projects_limit } . to ( Gitlab :: CurrentSettings . default_projects_limit )
2017-09-10 17:25:29 +05:30
end
end
describe 'without external user' do
let ( :user ) { create ( :user , external : false ) }
it 'receives callback when external changes' do
expect ( user ) . to receive ( :ensure_user_rights_and_limits )
2021-06-08 01:23:25 +05:30
user . update! ( external : true )
2017-09-10 17:25:29 +05:30
end
it 'ensures correct rights and limits for user' do
2021-06-08 01:23:25 +05:30
expect { user . update! ( external : true ) } . to change { user . can_create_group } . to ( false )
2017-09-10 17:25:29 +05:30
. and change { user . projects_limit } . to ( 0 )
end
end
end
2018-11-08 19:23:39 +05:30
describe 'feed token' do
it 'ensures a feed token on read' do
user = create ( :user , feed_token : nil )
feed_token = user . feed_token
2018-03-17 18:26:18 +05:30
2018-11-08 19:23:39 +05:30
expect ( feed_token ) . not_to be_blank
expect ( user . reload . feed_token ) . to eq feed_token
2017-09-10 17:25:29 +05:30
end
2021-02-22 17:27:13 +05:30
it 'ensures no feed token when disabled' do
allow ( Gitlab :: CurrentSettings ) . to receive ( :disable_feed_token ) . and_return ( true )
user = create ( :user , feed_token : nil )
feed_token = user . feed_token
expect ( feed_token ) . to be_blank
expect ( user . reload . feed_token ) . to be_blank
end
2017-09-10 17:25:29 +05:30
end
2019-12-04 20:38:33 +05:30
describe 'static object token' do
it 'ensures a static object token on read' do
user = create ( :user , static_object_token : nil )
static_object_token = user . static_object_token
expect ( static_object_token ) . not_to be_blank
expect ( user . reload . static_object_token ) . to eq static_object_token
end
2022-03-02 08:16:31 +05:30
it 'generates an encrypted version of the token' do
user = create ( :user , static_object_token : nil )
expect ( user [ :static_object_token ] ) . to be_nil
expect ( user [ :static_object_token_encrypted ] ) . to be_nil
user . static_object_token
expect ( user [ :static_object_token ] ) . to be_nil
expect ( user [ :static_object_token_encrypted ] ) . to be_present
end
it 'prefers an encoded version of the token' do
user = create ( :user , static_object_token : nil )
token = user . static_object_token
user . update_column ( :static_object_token , 'Test' )
expect ( user . static_object_token ) . not_to eq ( 'Test' )
expect ( user . static_object_token ) . to eq ( token )
end
2019-12-04 20:38:33 +05:30
end
2022-01-26 12:08:38 +05:30
describe 'enabled_static_object_token' do
let_it_be ( :static_object_token ) { 'ilqx6jm1u945macft4eff0nw' }
it 'returns incoming email token when supported' do
allow ( Gitlab :: CurrentSettings ) . to receive ( :static_objects_external_storage_enabled? ) . and_return ( true )
user = create ( :user , static_object_token : static_object_token )
expect ( user . enabled_static_object_token ) . to eq ( static_object_token )
end
it 'returns `nil` when not supported' do
allow ( Gitlab :: CurrentSettings ) . to receive ( :static_objects_external_storage_enabled? ) . and_return ( false )
user = create ( :user , static_object_token : static_object_token )
expect ( user . enabled_static_object_token ) . to be_nil
end
end
describe 'enabled_incoming_email_token' do
let_it_be ( :incoming_email_token ) { 'ilqx6jm1u945macft4eff0nw' }
it 'returns incoming email token when supported' do
allow ( Gitlab :: IncomingEmail ) . to receive ( :supports_issue_creation? ) . and_return ( true )
user = create ( :user , incoming_email_token : incoming_email_token )
expect ( user . enabled_incoming_email_token ) . to eq ( incoming_email_token )
end
it 'returns `nil` when not supported' do
allow ( Gitlab :: IncomingEmail ) . to receive ( :supports_issue_creation? ) . and_return ( false )
user = create ( :user , incoming_email_token : incoming_email_token )
expect ( user . enabled_incoming_email_token ) . to be_nil
end
end
2015-10-24 18:46:33 +05:30
describe '#recently_sent_password_reset?' do
it 'is false when reset_password_sent_at is nil' do
user = build_stubbed ( :user , reset_password_sent_at : nil )
expect ( user . recently_sent_password_reset? ) . to eq false
end
it 'is false when sent more than one minute ago' do
user = build_stubbed ( :user , reset_password_sent_at : 5 . minutes . ago )
expect ( user . recently_sent_password_reset? ) . to eq false
end
it 'is true when sent less than one minute ago' do
2020-06-23 00:09:42 +05:30
user = build_stubbed ( :user , reset_password_sent_at : Time . current )
2015-10-24 18:46:33 +05:30
expect ( user . recently_sent_password_reset? ) . to eq true
end
end
2015-09-11 14:41:01 +05:30
describe '#disable_two_factor!' do
it 'clears all 2FA-related fields' do
user = create ( :user , :two_factor )
expect ( user ) . to be_two_factor_enabled
expect ( user . encrypted_otp_secret ) . not_to be_nil
expect ( user . otp_backup_codes ) . not_to be_nil
2016-04-02 18:10:28 +05:30
expect ( user . otp_grace_period_started_at ) . not_to be_nil
2015-09-11 14:41:01 +05:30
user . disable_two_factor!
expect ( user ) . not_to be_two_factor_enabled
expect ( user . encrypted_otp_secret ) . to be_nil
expect ( user . encrypted_otp_secret_iv ) . to be_nil
expect ( user . encrypted_otp_secret_salt ) . to be_nil
expect ( user . otp_backup_codes ) . to be_nil
2016-04-02 18:10:28 +05:30
expect ( user . otp_grace_period_started_at ) . to be_nil
2015-09-11 14:41:01 +05:30
end
end
2021-02-22 17:27:13 +05:30
describe '#two_factor_otp_enabled?' do
let_it_be ( :user ) { create ( :user ) }
context 'when 2FA is enabled by an MFA Device' do
let ( :user ) { create ( :user , :two_factor ) }
it { expect ( user . two_factor_otp_enabled? ) . to eq ( true ) }
end
context 'FortiAuthenticator' do
context 'when enabled via GitLab settings' do
before do
allow ( :: Gitlab . config . forti_authenticator ) . to receive ( :enabled ) . and_return ( true )
end
context 'when feature is disabled for the user' do
before do
stub_feature_flags ( forti_authenticator : false )
end
it { expect ( user . two_factor_otp_enabled? ) . to eq ( false ) }
end
context 'when feature is enabled for the user' do
before do
stub_feature_flags ( forti_authenticator : user )
end
it { expect ( user . two_factor_otp_enabled? ) . to eq ( true ) }
end
end
context 'when disabled via GitLab settings' do
before do
allow ( :: Gitlab . config . forti_authenticator ) . to receive ( :enabled ) . and_return ( false )
end
it { expect ( user . two_factor_otp_enabled? ) . to eq ( false ) }
end
end
context 'FortiTokenCloud' do
context 'when enabled via GitLab settings' do
before do
allow ( :: Gitlab . config . forti_token_cloud ) . to receive ( :enabled ) . and_return ( true )
end
context 'when feature is disabled for the user' do
before do
stub_feature_flags ( forti_token_cloud : false )
end
it { expect ( user . two_factor_otp_enabled? ) . to eq ( false ) }
end
context 'when feature is enabled for the user' do
before do
stub_feature_flags ( forti_token_cloud : user )
end
it { expect ( user . two_factor_otp_enabled? ) . to eq ( true ) }
end
end
context 'when disabled via GitLab settings' do
before do
allow ( :: Gitlab . config . forti_token_cloud ) . to receive ( :enabled ) . and_return ( false )
end
it { expect ( user . two_factor_otp_enabled? ) . to eq ( false ) }
end
end
end
2022-01-26 12:08:38 +05:30
context 'two_factor_u2f_enabled?' do
let_it_be ( :user ) { create ( :user , :two_factor ) }
context 'when webauthn feature flag is enabled' do
context 'user has no U2F registration' do
it { expect ( user . two_factor_u2f_enabled? ) . to eq ( false ) }
end
context 'user has existing U2F registration' do
it 'returns false' do
device = U2F :: FakeU2F . new ( FFaker :: BaconIpsum . characters ( 5 ) )
2022-10-11 01:57:18 +05:30
create ( :u2f_registration ,
name : 'my u2f device' ,
user : user ,
certificate : Base64 . strict_encode64 ( device . cert_raw ) ,
key_handle : U2F . urlsafe_encode64 ( device . key_handle_raw ) ,
public_key : Base64 . strict_encode64 ( device . origin_public_key_raw ) )
2022-01-26 12:08:38 +05:30
expect ( user . two_factor_u2f_enabled? ) . to eq ( false )
end
end
end
context 'when webauthn feature flag is disabled' do
before do
stub_feature_flags ( webauthn : false )
end
context 'user has no U2F registration' do
it { expect ( user . two_factor_u2f_enabled? ) . to eq ( false ) }
end
context 'user has existing U2F registration' do
it 'returns true' do
device = U2F :: FakeU2F . new ( FFaker :: BaconIpsum . characters ( 5 ) )
2022-10-11 01:57:18 +05:30
create ( :u2f_registration ,
name : 'my u2f device' ,
user : user ,
certificate : Base64 . strict_encode64 ( device . cert_raw ) ,
key_handle : U2F . urlsafe_encode64 ( device . key_handle_raw ) ,
public_key : Base64 . strict_encode64 ( device . origin_public_key_raw ) )
2022-01-26 12:08:38 +05:30
expect ( user . two_factor_u2f_enabled? ) . to eq ( true )
end
end
end
end
2022-06-21 17:19:12 +05:30
describe 'needs_new_otp_secret?' , :freeze_time do
let ( :user ) { create ( :user ) }
context 'when two-factor is not enabled' do
it 'returns true if otp_secret_expires_at is nil' do
expect ( user . needs_new_otp_secret? ) . to eq ( true )
end
it 'returns true if the otp_secret_expires_at has passed' do
user . update! ( otp_secret_expires_at : 10 . minutes . ago )
expect ( user . reload . needs_new_otp_secret? ) . to eq ( true )
end
it 'returns false if the otp_secret_expires_at has not passed' do
user . update! ( otp_secret_expires_at : 10 . minutes . from_now )
expect ( user . reload . needs_new_otp_secret? ) . to eq ( false )
end
end
context 'when two-factor is enabled' do
let ( :user ) { create ( :user , :two_factor ) }
it 'returns false even if ttl is expired' do
user . otp_secret_expires_at = 10 . minutes . ago
expect ( user . needs_new_otp_secret? ) . to eq ( false )
end
end
end
describe 'otp_secret_expired?' , :freeze_time do
let ( :user ) { create ( :user ) }
it 'returns true if otp_secret_expires_at is nil' do
expect ( user . otp_secret_expired? ) . to eq ( true )
end
it 'returns true if the otp_secret_expires_at has passed' do
user . otp_secret_expires_at = 10 . minutes . ago
expect ( user . otp_secret_expired? ) . to eq ( true )
end
it 'returns false if the otp_secret_expires_at has not passed' do
user . otp_secret_expires_at = 20 . minutes . from_now
expect ( user . otp_secret_expired? ) . to eq ( false )
end
end
describe 'update_otp_secret!' , :freeze_time do
let ( :user ) { create ( :user ) }
before do
user . update_otp_secret!
end
it 'sets the otp_secret' do
expect ( user . otp_secret ) . to have_attributes ( length : described_class :: OTP_SECRET_LENGTH )
end
it 'updates the otp_secret_expires_at' do
expect ( user . otp_secret_expires_at ) . to eq ( Time . current + described_class :: OTP_SECRET_TTL )
end
end
2014-09-02 18:07:02 +05:30
describe 'projects' do
before do
2017-08-17 22:00:37 +05:30
@user = create ( :user )
2014-09-02 18:07:02 +05:30
2017-09-10 17:25:29 +05:30
@project = create ( :project , namespace : @user . namespace )
@project_2 = create ( :project , group : create ( :group ) ) do | project |
2018-11-18 11:00:15 +05:30
project . add_maintainer ( @user )
2017-08-17 22:00:37 +05:30
end
2017-09-10 17:25:29 +05:30
@project_3 = create ( :project , group : create ( :group ) ) do | project |
2017-08-17 22:00:37 +05:30
project . add_developer ( @user )
end
2014-09-02 18:07:02 +05:30
end
2015-04-26 12:48:37 +05:30
it { expect ( @user . authorized_projects ) . to include ( @project ) }
it { expect ( @user . authorized_projects ) . to include ( @project_2 ) }
it { expect ( @user . authorized_projects ) . to include ( @project_3 ) }
it { expect ( @user . owned_projects ) . to include ( @project ) }
it { expect ( @user . owned_projects ) . not_to include ( @project_2 ) }
it { expect ( @user . owned_projects ) . not_to include ( @project_3 ) }
it { expect ( @user . personal_projects ) . to include ( @project ) }
it { expect ( @user . personal_projects ) . not_to include ( @project_2 ) }
it { expect ( @user . personal_projects ) . not_to include ( @project_3 ) }
2014-09-02 18:07:02 +05:30
end
describe 'groups' do
2018-03-17 18:26:18 +05:30
let ( :user ) { create ( :user ) }
let ( :group ) { create ( :group ) }
2014-09-02 18:07:02 +05:30
before do
2018-03-17 18:26:18 +05:30
group . add_owner ( user )
2014-09-02 18:07:02 +05:30
end
2018-03-17 18:26:18 +05:30
it { expect ( user . several_namespaces? ) . to be_truthy }
it { expect ( user . authorized_groups ) . to eq ( [ group ] ) }
it { expect ( user . owned_groups ) . to eq ( [ group ] ) }
it { expect ( user . namespaces ) . to contain_exactly ( user . namespace , group ) }
2022-03-02 08:16:31 +05:30
it { expect ( user . forkable_namespaces ) . to contain_exactly ( user . namespace , group ) }
2018-03-17 18:26:18 +05:30
2021-10-27 15:23:28 +05:30
context 'with owned groups only' do
before do
other_group = create ( :group )
other_group . add_developer ( user )
end
it { expect ( user . namespaces ( owned_only : true ) ) . to contain_exactly ( user . namespace , group ) }
end
2019-10-12 21:52:04 +05:30
context 'with child groups' do
2018-03-17 18:26:18 +05:30
let! ( :subgroup ) { create ( :group , parent : group ) }
2022-03-02 08:16:31 +05:30
describe '#forkable_namespaces' do
it 'includes all the namespaces the user can fork into' do
developer_group = create ( :group , project_creation_level : :: Gitlab :: Access :: DEVELOPER_MAINTAINER_PROJECT_ACCESS )
developer_group . add_developer ( user )
expect ( user . forkable_namespaces ) . to contain_exactly ( user . namespace , group , subgroup , developer_group )
2018-03-17 18:26:18 +05:30
end
end
describe '#manageable_groups' do
2021-11-11 11:23:49 +05:30
shared_examples 'manageable groups examples' do
it 'includes all the namespaces the user can manage' do
expect ( user . manageable_groups ) . to contain_exactly ( group , subgroup )
end
it 'does not include duplicates if a membership was added for the subgroup' do
subgroup . add_owner ( user )
expect ( user . manageable_groups ) . to contain_exactly ( group , subgroup )
end
2018-03-17 18:26:18 +05:30
end
2021-11-11 11:23:49 +05:30
it_behaves_like 'manageable groups examples'
context 'when feature flag :linear_user_manageable_groups is disabled' do
before do
stub_feature_flags ( linear_user_manageable_groups : false )
end
2018-03-17 18:26:18 +05:30
2021-11-11 11:23:49 +05:30
it_behaves_like 'manageable groups examples'
2018-03-17 18:26:18 +05:30
end
end
2019-07-07 11:18:12 +05:30
describe '#manageable_groups_with_routes' do
it 'eager loads routes from manageable groups' do
control_count =
ActiveRecord :: QueryRecorder . new ( skip_cached : false ) do
user . manageable_groups_with_routes . map ( & :route )
end . count
create ( :group , parent : subgroup )
expect do
user . manageable_groups_with_routes . map ( & :route )
end . not_to exceed_all_query_limit ( control_count )
end
end
2018-03-17 18:26:18 +05:30
end
2014-09-02 18:07:02 +05:30
end
describe 'group multiple owners' do
before do
@user = create :user
@user2 = create :user
@group = create :group
@group . add_owner ( @user )
2022-08-13 15:12:31 +05:30
@group . add_member ( @user2 , GroupMember :: OWNER )
2014-09-02 18:07:02 +05:30
end
2015-04-26 12:48:37 +05:30
it { expect ( @user2 . several_namespaces? ) . to be_truthy }
2014-09-02 18:07:02 +05:30
end
describe 'namespaced' do
before do
@user = create :user
2017-09-10 17:25:29 +05:30
@project = create ( :project , namespace : @user . namespace )
2014-09-02 18:07:02 +05:30
end
2015-04-26 12:48:37 +05:30
it { expect ( @user . several_namespaces? ) . to be_falsey }
2015-09-11 14:41:01 +05:30
it { expect ( @user . namespaces ) . to eq ( [ @user . namespace ] ) }
2014-09-02 18:07:02 +05:30
end
describe 'blocking user' do
2021-04-29 21:17:54 +05:30
let_it_be_with_refind ( :user ) { create ( :user , name : 'John Smith' ) }
2014-09-02 18:07:02 +05:30
2019-09-30 23:59:55 +05:30
it 'blocks user' do
2014-09-02 18:07:02 +05:30
user . block
2018-03-17 18:26:18 +05:30
2015-04-26 12:48:37 +05:30
expect ( user . blocked? ) . to be_truthy
2014-09-02 18:07:02 +05:30
end
2019-09-30 23:59:55 +05:30
context 'when user has running CI pipelines' do
2021-04-29 21:17:54 +05:30
let ( :pipelines ) { build_list ( :ci_pipeline , 3 , :running ) }
2019-09-30 23:59:55 +05:30
2022-01-26 12:08:38 +05:30
it 'drops all running pipelines and related jobs' do
drop_service = double
disable_service = double
2021-04-29 21:17:54 +05:30
expect ( user ) . to receive ( :pipelines ) . and_return ( pipelines )
2022-01-26 12:08:38 +05:30
expect ( Ci :: DropPipelineService ) . to receive ( :new ) . and_return ( drop_service )
expect ( drop_service ) . to receive ( :execute_async_for_all ) . with ( pipelines , :user_blocked , user )
2021-04-29 21:17:54 +05:30
2022-01-26 12:08:38 +05:30
expect ( Ci :: DisableUserPipelineSchedulesService ) . to receive ( :new ) . and_return ( disable_service )
expect ( disable_service ) . to receive ( :execute ) . with ( user )
user . block!
end
it 'does not drop running pipelines if the transaction rolls back' do
expect ( Ci :: DropPipelineService ) . not_to receive ( :new )
expect ( Ci :: DisableUserPipelineSchedulesService ) . not_to receive ( :new )
User . transaction do
user . block
raise ActiveRecord :: Rollback
end
2019-09-30 23:59:55 +05:30
end
2021-04-29 21:17:54 +05:30
end
2019-09-30 23:59:55 +05:30
2021-04-29 21:17:54 +05:30
context 'when user has active CI pipeline schedules' do
let_it_be ( :schedule ) { create ( :ci_pipeline_schedule , active : true , owner : user ) }
2019-09-30 23:59:55 +05:30
2021-04-29 21:17:54 +05:30
it 'disables any pipeline schedules' do
expect { user . block } . to change { schedule . reload . active? } . to ( false )
2019-09-30 23:59:55 +05:30
end
end
2014-09-02 18:07:02 +05:30
end
2019-12-21 20:55:43 +05:30
describe 'deactivating a user' do
let ( :user ) { create ( :user , name : 'John Smith' ) }
2021-11-18 22:05:49 +05:30
context 'an active user' do
it 'can be deactivated' do
2019-12-21 20:55:43 +05:30
user . deactivate
expect ( user . deactivated? ) . to be_truthy
end
2021-09-30 23:02:18 +05:30
2021-11-18 22:05:49 +05:30
context 'when user deactivation emails are disabled' do
2021-11-11 11:23:49 +05:30
before do
stub_application_setting ( user_deactivation_emails_enabled : false )
2021-09-30 23:02:18 +05:30
end
2021-11-11 11:23:49 +05:30
it 'does not send deactivated user an email' do
expect ( NotificationService ) . not_to receive ( :new )
2021-09-30 23:02:18 +05:30
2021-11-11 11:23:49 +05:30
user . deactivate
end
end
2021-11-18 22:05:49 +05:30
context 'when user deactivation emails are enabled' do
2021-11-11 11:23:49 +05:30
it 'sends deactivated user an email' do
expect_next_instance_of ( NotificationService ) do | notification |
allow ( notification ) . to receive ( :user_deactivated ) . with ( user . name , user . notification_email_or_default )
end
user . deactivate
end
2021-09-30 23:02:18 +05:30
end
2019-12-21 20:55:43 +05:30
end
2021-11-18 22:05:49 +05:30
context 'a user who is blocked' do
2019-12-21 20:55:43 +05:30
before do
user . block
end
2021-11-18 22:05:49 +05:30
it 'cannot be deactivated' do
2019-12-21 20:55:43 +05:30
user . deactivate
expect ( user . reload . deactivated? ) . to be_falsy
end
end
end
2021-01-03 14:25:43 +05:30
describe 'blocking a user pending approval' do
let ( :user ) { create ( :user ) }
before do
user . block_pending_approval
end
context 'an active user' do
it 'can be blocked pending approval' do
expect ( user . blocked_pending_approval? ) . to eq ( true )
end
it 'behaves like a blocked user' do
expect ( user . blocked? ) . to eq ( true )
end
end
end
2021-01-29 00:20:46 +05:30
describe '.instance_access_request_approvers_to_be_notified' do
2021-04-17 20:07:23 +05:30
let_it_be ( :admin_issue_board_list ) { create_list ( :user , 12 , :admin , :with_sign_ins ) }
2021-01-29 00:20:46 +05:30
it 'returns up to the ten most recently active instance admins' do
active_admins_in_recent_sign_in_desc_order = User . admins . active . order_recent_sign_in . limit ( 10 )
expect ( User . instance_access_request_approvers_to_be_notified ) . to eq ( active_admins_in_recent_sign_in_desc_order )
end
end
2021-10-27 15:23:28 +05:30
describe 'banning and unbanning a user' , :aggregate_failures do
let ( :user ) { create ( :user ) }
context 'banning a user' do
it 'bans and blocks the user' do
user . ban
expect ( user . banned? ) . to eq ( true )
expect ( user . blocked? ) . to eq ( true )
end
it 'creates a BannedUser record' do
expect { user . ban } . to change { Users :: BannedUser . count } . by ( 1 )
expect ( Users :: BannedUser . last . user_id ) . to eq ( user . id )
end
end
context 'unbanning a user' do
before do
user . ban!
end
2021-11-11 11:23:49 +05:30
it 'unbans the user' do
user . unban
2021-10-27 15:23:28 +05:30
expect ( user . banned? ) . to eq ( false )
expect ( user . active? ) . to eq ( true )
end
it 'deletes the BannedUser record' do
2021-11-11 11:23:49 +05:30
expect { user . unban } . to change { Users :: BannedUser . count } . by ( - 1 )
2021-10-27 15:23:28 +05:30
expect ( Users :: BannedUser . where ( user_id : user . id ) ) . not_to exist
end
end
end
2019-07-07 11:18:12 +05:30
describe '.filter_items' do
2015-09-11 14:41:01 +05:30
let ( :user ) { double }
it 'filters by active users by default' do
2020-03-13 15:44:24 +05:30
expect ( described_class ) . to receive ( :active_without_ghosts ) . and_return ( [ user ] )
2015-09-11 14:41:01 +05:30
2019-07-07 11:18:12 +05:30
expect ( described_class . filter_items ( nil ) ) . to include user
2015-09-11 14:41:01 +05:30
end
it 'filters by admins' do
2017-09-10 17:25:29 +05:30
expect ( described_class ) . to receive ( :admins ) . and_return ( [ user ] )
2015-09-11 14:41:01 +05:30
2019-07-07 11:18:12 +05:30
expect ( described_class . filter_items ( 'admins' ) ) . to include user
2015-09-11 14:41:01 +05:30
end
it 'filters by blocked' do
2017-09-10 17:25:29 +05:30
expect ( described_class ) . to receive ( :blocked ) . and_return ( [ user ] )
2015-09-11 14:41:01 +05:30
2019-07-07 11:18:12 +05:30
expect ( described_class . filter_items ( 'blocked' ) ) . to include user
2015-09-11 14:41:01 +05:30
end
2021-06-08 01:23:25 +05:30
it 'filters by banned' do
expect ( described_class ) . to receive ( :banned ) . and_return ( [ user ] )
expect ( described_class . filter_items ( 'banned' ) ) . to include user
end
2021-01-03 14:25:43 +05:30
it 'filters by blocked pending approval' do
expect ( described_class ) . to receive ( :blocked_pending_approval ) . and_return ( [ user ] )
expect ( described_class . filter_items ( 'blocked_pending_approval' ) ) . to include user
end
2019-12-21 20:55:43 +05:30
it 'filters by deactivated' do
expect ( described_class ) . to receive ( :deactivated ) . and_return ( [ user ] )
expect ( described_class . filter_items ( 'deactivated' ) ) . to include user
end
2015-09-11 14:41:01 +05:30
it 'filters by two_factor_disabled' do
2017-09-10 17:25:29 +05:30
expect ( described_class ) . to receive ( :without_two_factor ) . and_return ( [ user ] )
2015-09-11 14:41:01 +05:30
2019-07-07 11:18:12 +05:30
expect ( described_class . filter_items ( 'two_factor_disabled' ) ) . to include user
2015-09-11 14:41:01 +05:30
end
it 'filters by two_factor_enabled' do
2017-09-10 17:25:29 +05:30
expect ( described_class ) . to receive ( :with_two_factor ) . and_return ( [ user ] )
2015-09-11 14:41:01 +05:30
2019-07-07 11:18:12 +05:30
expect ( described_class . filter_items ( 'two_factor_enabled' ) ) . to include user
2014-09-02 18:07:02 +05:30
end
2015-09-11 14:41:01 +05:30
it 'filters by wop' do
2017-09-10 17:25:29 +05:30
expect ( described_class ) . to receive ( :without_projects ) . and_return ( [ user ] )
2015-09-11 14:41:01 +05:30
2019-07-07 11:18:12 +05:30
expect ( described_class . filter_items ( 'wop' ) ) . to include user
2015-09-11 14:41:01 +05:30
end
2014-09-02 18:07:02 +05:30
end
2017-08-17 22:00:37 +05:30
describe '.without_projects' do
2019-12-21 20:55:43 +05:30
let! ( :project ) { create ( :project , :public ) }
2017-08-17 22:00:37 +05:30
let! ( :user ) { create ( :user ) }
let! ( :user_without_project ) { create ( :user ) }
let! ( :user_without_project2 ) { create ( :user ) }
before do
# add user to project
2018-11-18 11:00:15 +05:30
project . add_maintainer ( user )
2017-08-17 22:00:37 +05:30
2020-11-24 15:15:51 +05:30
# create invite to project
2017-08-17 22:00:37 +05:30
create ( :project_member , :developer , project : project , invite_token : '1234' , invite_email : 'inviteduser1@example.com' )
# create request to join project
project . request_access ( user_without_project2 )
end
2017-09-10 17:25:29 +05:30
it { expect ( described_class . without_projects ) . not_to include user }
it { expect ( described_class . without_projects ) . to include user_without_project }
it { expect ( described_class . without_projects ) . to include user_without_project2 }
2014-09-02 18:07:02 +05:30
end
describe 'user creation' do
describe 'normal user' do
let ( :user ) { create ( :user , name : 'John Smith' ) }
2017-08-17 22:00:37 +05:30
it { expect ( user . admin? ) . to be_falsey }
2015-04-26 12:48:37 +05:30
it { expect ( user . require_ssh_key? ) . to be_truthy }
it { expect ( user . can_create_group? ) . to be_truthy }
it { expect ( user . can_create_project? ) . to be_truthy }
it { expect ( user . first_name ) . to eq ( 'John' ) }
2016-08-24 12:49:21 +05:30
it { expect ( user . external ) . to be_falsey }
2014-09-02 18:07:02 +05:30
end
describe 'with defaults' do
2017-09-10 17:25:29 +05:30
let ( :user ) { described_class . new }
2014-09-02 18:07:02 +05:30
2021-11-18 22:05:49 +05:30
it 'applies defaults to user' do
2015-04-26 12:48:37 +05:30
expect ( user . projects_limit ) . to eq ( Gitlab . config . gitlab . default_projects_limit )
2022-11-25 23:54:43 +05:30
expect ( user . can_create_group ) . to eq ( Gitlab :: CurrentSettings . can_create_group )
2018-03-17 18:26:18 +05:30
expect ( user . theme_id ) . to eq ( Gitlab . config . gitlab . default_theme )
2016-06-02 11:05:42 +05:30
expect ( user . external ) . to be_falsey
2019-12-04 20:38:33 +05:30
expect ( user . private_profile ) . to eq ( false )
2014-09-02 18:07:02 +05:30
end
end
describe 'with default overrides' do
2017-09-10 17:25:29 +05:30
let ( :user ) { described_class . new ( projects_limit : 123 , can_create_group : false , can_create_team : true ) }
2014-09-02 18:07:02 +05:30
2021-11-18 22:05:49 +05:30
it 'applies defaults to user' do
2015-04-26 12:48:37 +05:30
expect ( user . projects_limit ) . to eq ( 123 )
expect ( user . can_create_group ) . to be_falsey
2018-03-17 18:26:18 +05:30
expect ( user . theme_id ) . to eq ( 1 )
end
it 'does not undo projects_limit setting if it matches old DB default of 10' do
# If the real default project limit is 10 then this test is worthless
expect ( Gitlab . config . gitlab . default_projects_limit ) . not_to eq ( 10 )
user = described_class . new ( projects_limit : 10 )
expect ( user . projects_limit ) . to eq ( 10 )
2014-09-02 18:07:02 +05:30
end
end
2016-08-24 12:49:21 +05:30
2018-03-17 18:26:18 +05:30
context 'when Gitlab::CurrentSettings.user_default_external is true' do
2016-08-24 12:49:21 +05:30
before do
stub_application_setting ( user_default_external : true )
end
2021-11-18 22:05:49 +05:30
it 'creates external user by default' do
2018-03-17 18:26:18 +05:30
user = create ( :user )
2016-08-24 12:49:21 +05:30
expect ( user . external ) . to be_truthy
2018-03-17 18:26:18 +05:30
expect ( user . can_create_group ) . to be_falsey
expect ( user . projects_limit ) . to be 0
2016-08-24 12:49:21 +05:30
end
describe 'with default overrides' do
2021-11-18 22:05:49 +05:30
it 'creates a non-external user' do
2018-03-17 18:26:18 +05:30
user = create ( :user , external : false )
2016-08-24 12:49:21 +05:30
expect ( user . external ) . to be_falsey
end
end
end
2017-08-17 22:00:37 +05:30
2018-03-17 18:26:18 +05:30
describe '#require_ssh_key?' , :use_clean_rails_memory_store_caching do
2017-08-17 22:00:37 +05:30
protocol_and_expectation = {
'http' = > false ,
'ssh' = > true ,
2017-09-10 17:25:29 +05:30
'' = > true
2017-08-17 22:00:37 +05:30
}
protocol_and_expectation . each do | protocol , expected |
2021-11-18 22:05:49 +05:30
it 'has correct require_ssh_key?' do
2017-08-17 22:00:37 +05:30
stub_application_setting ( enabled_git_access_protocol : protocol )
user = build ( :user )
expect ( user . require_ssh_key? ) . to eq ( expected )
end
end
2018-03-17 18:26:18 +05:30
it 'returns false when the user has 1 or more SSH keys' do
key = create ( :personal_key )
expect ( key . user . require_ssh_key? ) . to eq ( false )
end
2017-08-17 22:00:37 +05:30
end
2014-09-02 18:07:02 +05:30
end
2018-03-27 19:54:05 +05:30
describe '.find_for_database_authentication' do
it 'strips whitespace from login' do
user = create ( :user )
expect ( described_class . find_for_database_authentication ( { login : " #{ user . username } " } ) ) . to eq user
end
end
2015-09-11 14:41:01 +05:30
describe '.find_by_any_email' do
2018-12-13 13:39:08 +05:30
it 'finds user through private commit email' do
user = create ( :user )
private_email = user . private_commit_email
expect ( described_class . find_by_any_email ( private_email ) ) . to eq ( user )
expect ( described_class . find_by_any_email ( private_email , confirmed : true ) ) . to eq ( user )
end
2022-07-29 17:44:30 +05:30
it 'finds user through private commit email when user is unconfirmed' do
user = create ( :user , :unconfirmed )
private_email = user . private_commit_email
expect ( described_class . find_by_any_email ( private_email ) ) . to eq ( user )
expect ( described_class . find_by_any_email ( private_email , confirmed : true ) ) . to eq ( user )
end
2015-09-11 14:41:01 +05:30
it 'finds by primary email' do
user = create ( :user , email : 'foo@example.com' )
2017-09-10 17:25:29 +05:30
expect ( described_class . find_by_any_email ( user . email ) ) . to eq user
2018-11-18 11:00:15 +05:30
expect ( described_class . find_by_any_email ( user . email , confirmed : true ) ) . to eq user
2015-09-11 14:41:01 +05:30
end
2022-07-29 17:44:30 +05:30
it 'finds by primary email when user is unconfirmed according to confirmed argument' do
user = create ( :user , :unconfirmed , email : 'foo@example.com' )
expect ( described_class . find_by_any_email ( user . email ) ) . to eq user
expect ( described_class . find_by_any_email ( user . email , confirmed : true ) ) . to be_nil
end
2018-12-13 13:39:08 +05:30
it 'finds by uppercased email' do
user = create ( :user , email : 'foo@example.com' )
expect ( described_class . find_by_any_email ( user . email . upcase ) ) . to eq user
expect ( described_class . find_by_any_email ( user . email . upcase , confirmed : true ) ) . to eq user
end
2019-02-15 15:39:39 +05:30
context 'finds by secondary email' do
2022-07-29 17:44:30 +05:30
context 'when primary email is confirmed' do
let ( :user ) { email . user }
2019-02-15 15:39:39 +05:30
2022-07-29 17:44:30 +05:30
context 'when secondary email is confirmed' do
2019-02-15 15:39:39 +05:30
let! ( :email ) { create ( :email , :confirmed , email : 'foo@example.com' ) }
2022-07-29 17:44:30 +05:30
it 'finds user' do
2019-02-15 15:39:39 +05:30
expect ( described_class . find_by_any_email ( email . email ) ) . to eq user
expect ( described_class . find_by_any_email ( email . email , confirmed : true ) ) . to eq user
end
end
2022-07-29 17:44:30 +05:30
context 'when secondary email is unconfirmed' do
2019-02-15 15:39:39 +05:30
let! ( :email ) { create ( :email , email : 'foo@example.com' ) }
2015-09-11 14:41:01 +05:30
2022-07-29 17:44:30 +05:30
it 'does not find user' do
expect ( described_class . find_by_any_email ( email . email ) ) . to be_nil
2019-02-15 15:39:39 +05:30
expect ( described_class . find_by_any_email ( email . email , confirmed : true ) ) . to be_nil
end
end
end
2022-07-29 17:44:30 +05:30
context 'when primary email is unconfirmed' do
2021-12-11 22:18:48 +05:30
let ( :user ) { create ( :user , :unconfirmed ) }
2019-02-15 15:39:39 +05:30
2022-07-29 17:44:30 +05:30
context 'when secondary email is confirmed' do
let! ( :email ) { create ( :email , :confirmed , user : user , email : 'foo@example.com' ) }
it 'finds user according to confirmed argument' do
expect ( described_class . find_by_any_email ( email . email ) ) . to eq user
expect ( described_class . find_by_any_email ( email . email , confirmed : true ) ) . to be_nil
end
end
context 'when secondary email is unconfirmed' do
let! ( :email ) { create ( :email , user : user , email : 'foo@example.com' ) }
it 'does not find user' do
expect ( described_class . find_by_any_email ( email . email ) ) . to be_nil
expect ( described_class . find_by_any_email ( email . email , confirmed : true ) ) . to be_nil
end
2019-02-15 15:39:39 +05:30
end
end
2015-09-11 14:41:01 +05:30
end
it 'returns nil when nothing found' do
2017-09-10 17:25:29 +05:30
expect ( described_class . find_by_any_email ( '' ) ) . to be_nil
2015-09-11 14:41:01 +05:30
end
end
2018-03-17 18:26:18 +05:30
describe '.by_any_email' do
it 'returns an ActiveRecord::Relation' do
expect ( described_class . by_any_email ( 'foo@example.com' ) )
. to be_a_kind_of ( ActiveRecord :: Relation )
end
2022-07-29 17:44:30 +05:30
it 'returns empty relation of users when nothing found' do
expect ( described_class . by_any_email ( '' ) ) . to be_empty
end
it 'returns a relation of users for confirmed primary emails' do
2018-03-17 18:26:18 +05:30
user = create ( :user )
2022-07-29 17:44:30 +05:30
expect ( described_class . by_any_email ( user . email ) ) . to match_array ( [ user ] )
expect ( described_class . by_any_email ( user . email , confirmed : true ) ) . to match_array ( [ user ] )
2018-03-17 18:26:18 +05:30
end
2018-11-18 11:00:15 +05:30
2022-07-29 17:44:30 +05:30
it 'returns a relation of users for unconfirmed primary emails according to confirmed argument' do
user = create ( :user , :unconfirmed )
2018-11-18 11:00:15 +05:30
2022-07-29 17:44:30 +05:30
expect ( described_class . by_any_email ( user . email ) ) . to match_array ( [ user ] )
expect ( described_class . by_any_email ( user . email , confirmed : true ) ) . to be_empty
2018-11-18 11:00:15 +05:30
end
2019-02-15 15:39:39 +05:30
2022-07-29 17:44:30 +05:30
it 'finds users through private commit emails' do
2019-02-15 15:39:39 +05:30
user = create ( :user )
private_email = user . private_commit_email
2022-07-29 17:44:30 +05:30
expect ( described_class . by_any_email ( private_email ) ) . to match_array ( [ user ] )
expect ( described_class . by_any_email ( private_email , confirmed : true ) ) . to match_array ( [ user ] )
end
it 'finds unconfirmed users through private commit emails' do
user = create ( :user , :unconfirmed )
private_email = user . private_commit_email
expect ( described_class . by_any_email ( private_email ) ) . to match_array ( [ user ] )
expect ( described_class . by_any_email ( private_email , confirmed : true ) ) . to match_array ( [ user ] )
2019-02-15 15:39:39 +05:30
end
it 'finds user through a private commit email in an array' do
user = create ( :user )
private_email = user . private_commit_email
2022-07-29 17:44:30 +05:30
expect ( described_class . by_any_email ( [ private_email ] ) ) . to match_array ( [ user ] )
expect ( described_class . by_any_email ( [ private_email ] , confirmed : true ) ) . to match_array ( [ user ] )
end
it 'finds by uppercased email' do
user = create ( :user , email : 'foo@example.com' )
expect ( described_class . by_any_email ( user . email . upcase ) ) . to match_array ( [ user ] )
expect ( described_class . by_any_email ( user . email . upcase , confirmed : true ) ) . to match_array ( [ user ] )
end
context 'finds by secondary email' do
context 'when primary email is confirmed' do
let ( :user ) { email . user }
context 'when secondary email is confirmed' do
let! ( :email ) { create ( :email , :confirmed , email : 'foo@example.com' ) }
it 'finds user' do
expect ( described_class . by_any_email ( email . email ) ) . to match_array ( [ user ] )
expect ( described_class . by_any_email ( email . email , confirmed : true ) ) . to match_array ( [ user ] )
end
end
context 'when secondary email is unconfirmed' do
let! ( :email ) { create ( :email , email : 'foo@example.com' ) }
it 'does not find user' do
expect ( described_class . by_any_email ( email . email ) ) . to be_empty
expect ( described_class . by_any_email ( email . email , confirmed : true ) ) . to be_empty
end
end
end
context 'when primary email is unconfirmed' do
let ( :user ) { create ( :user , :unconfirmed ) }
context 'when secondary email is confirmed' do
let! ( :email ) { create ( :email , :confirmed , user : user , email : 'foo@example.com' ) }
it 'finds user according to confirmed argument' do
expect ( described_class . by_any_email ( email . email ) ) . to match_array ( [ user ] )
expect ( described_class . by_any_email ( email . email , confirmed : true ) ) . to be_empty
end
end
context 'when secondary email is unconfirmed' do
let! ( :email ) { create ( :email , user : user , email : 'foo@example.com' ) }
it 'does not find user' do
expect ( described_class . by_any_email ( email . email ) ) . to be_empty
expect ( described_class . by_any_email ( email . email , confirmed : true ) ) . to be_empty
end
end
end
2019-02-15 15:39:39 +05:30
end
2018-03-17 18:26:18 +05:30
end
2022-08-27 11:52:29 +05:30
describe '.search' do
let_it_be ( :user ) { create ( :user , name : 'user' , username : 'usern' , email : 'email@example.com' ) }
let_it_be ( :public_email ) do
create ( :email , :confirmed , user : user , email : 'publicemail@example.com' ) . tap do | email |
user . update! ( public_email : email . email )
2022-02-05 19:09:49 +05:30
end
2022-08-27 11:52:29 +05:30
end
2022-02-05 19:09:49 +05:30
2022-08-27 11:52:29 +05:30
let_it_be ( :user2 ) { create ( :user , name : 'user name' , username : 'username' , email : 'someemail@example.com' ) }
let_it_be ( :user3 ) { create ( :user , name : 'us' , username : 'se' , email : 'foo@example.com' ) }
let_it_be ( :unconfirmed_user ) { create ( :user , :unconfirmed , name : 'not verified' , username : 'notverified' ) }
2016-06-02 11:05:42 +05:30
2022-08-27 11:52:29 +05:30
let_it_be ( :unconfirmed_secondary_email ) { create ( :email , user : user , email : 'alias@example.com' ) }
let_it_be ( :confirmed_secondary_email ) { create ( :email , :confirmed , user : user , email : 'alias2@example.com' ) }
2022-06-21 17:19:12 +05:30
2022-08-27 11:52:29 +05:30
describe 'name user and email relative ordering' do
let_it_be ( :named_alexander ) { create ( :user , name : 'Alexander Person' , username : 'abcd' , email : 'abcd@example.com' ) }
let_it_be ( :username_alexand ) { create ( :user , name : 'Joao Alexander' , username : 'Alexand' , email : 'joao@example.com' ) }
2022-06-21 17:19:12 +05:30
2022-08-27 11:52:29 +05:30
it 'prioritizes exact matches' do
expect ( described_class . search ( 'Alexand' ) ) . to eq ( [ username_alexand , named_alexander ] )
2022-06-21 17:19:12 +05:30
end
2022-08-27 11:52:29 +05:30
it 'falls back to ordering by name' do
expect ( described_class . search ( 'Alexander' ) ) . to eq ( [ named_alexander , username_alexand ] )
end
end
2018-03-17 18:26:18 +05:30
2022-08-27 11:52:29 +05:30
describe 'name matching' do
it 'returns users with a matching name with exact match first' do
expect ( described_class . search ( user . name ) ) . to eq ( [ user , user2 ] )
end
2018-03-17 18:26:18 +05:30
2022-08-27 11:52:29 +05:30
it 'returns users with a partially matching name' do
expect ( described_class . search ( user . name [ 0 .. 2 ] ) ) . to eq ( [ user , user2 ] )
end
2022-04-04 11:22:00 +05:30
2022-08-27 11:52:29 +05:30
it 'returns users with a matching name regardless of the casing' do
expect ( described_class . search ( user2 . name . upcase ) ) . to eq ( [ user2 ] )
2022-04-04 11:22:00 +05:30
end
2016-06-02 11:05:42 +05:30
2022-08-27 11:52:29 +05:30
it 'returns users with a exact matching name shorter than 3 chars' do
expect ( described_class . search ( user3 . name ) ) . to eq ( [ user3 ] )
end
2014-09-02 18:07:02 +05:30
2022-08-27 11:52:29 +05:30
it 'returns users with a exact matching name shorter than 3 chars regardless of the casing' do
expect ( described_class . search ( user3 . name . upcase ) ) . to eq ( [ user3 ] )
end
2016-06-02 11:05:42 +05:30
2022-08-27 11:52:29 +05:30
context 'when use_minimum_char_limit is false' do
it 'returns users with a partially matching name' do
expect ( described_class . search ( 'u' , use_minimum_char_limit : false ) ) . to eq ( [ user3 , user , user2 ] )
2022-08-13 15:12:31 +05:30
end
2022-08-27 11:52:29 +05:30
end
end
2016-06-02 11:05:42 +05:30
2022-08-27 11:52:29 +05:30
describe 'email matching' do
it 'returns users with a matching public email' do
expect ( described_class . search ( user . public_email ) ) . to match_array ( [ user ] )
end
2021-02-22 17:27:13 +05:30
2022-08-27 11:52:29 +05:30
it 'does not return users with a partially matching public email' do
expect ( described_class . search ( user . public_email [ 1 ... - 1 ] ) ) . to be_empty
end
2022-08-13 15:12:31 +05:30
2022-08-27 11:52:29 +05:30
it 'returns users with a matching public email regardless of the casing' do
expect ( described_class . search ( user . public_email . upcase ) ) . to match_array ( [ user ] )
end
2022-08-13 15:12:31 +05:30
2022-08-27 11:52:29 +05:30
it 'does not return users with a matching private email' do
expect ( described_class . search ( user . email ) ) . to be_empty
2022-08-13 15:12:31 +05:30
2022-08-27 11:52:29 +05:30
expect ( described_class . search ( unconfirmed_secondary_email . email ) ) . to be_empty
expect ( described_class . search ( confirmed_secondary_email . email ) ) . to be_empty
2022-08-13 15:12:31 +05:30
end
2022-07-29 17:44:30 +05:30
2022-08-27 11:52:29 +05:30
context 'with private emails search' do
it 'returns users with matching private primary email' do
expect ( described_class . search ( user . email , with_private_emails : true ) ) . to match_array ( [ user ] )
2022-07-29 17:44:30 +05:30
end
2022-08-27 11:52:29 +05:30
it 'returns users with matching private unconfirmed primary email' do
expect ( described_class . search ( unconfirmed_user . email , with_private_emails : true ) ) . to match_array ( [ unconfirmed_user ] )
2022-02-05 19:09:49 +05:30
end
2021-02-22 17:27:13 +05:30
2022-08-27 11:52:29 +05:30
it 'returns users with matching private confirmed secondary email' do
expect ( described_class . search ( confirmed_secondary_email . email , with_private_emails : true ) ) . to match_array ( [ user ] )
2022-08-13 15:12:31 +05:30
end
2016-06-02 11:05:42 +05:30
2022-08-27 11:52:29 +05:30
it 'does not return users with matching private unconfirmed secondary email' do
expect ( described_class . search ( unconfirmed_secondary_email . email , with_private_emails : true ) ) . to be_empty
2022-08-13 15:12:31 +05:30
end
2022-08-27 11:52:29 +05:30
end
end
2019-12-21 20:55:43 +05:30
2022-08-27 11:52:29 +05:30
describe 'username matching' do
it 'returns users with a matching username' do
expect ( described_class . search ( user . username ) ) . to eq ( [ user , user2 ] )
end
2016-06-02 11:05:42 +05:30
2022-08-27 11:52:29 +05:30
it 'returns users with a matching username starting with a @' do
expect ( described_class . search ( " @ #{ user . username } " ) ) . to eq ( [ user , user2 ] )
end
2019-12-21 20:55:43 +05:30
2022-08-27 11:52:29 +05:30
it 'returns users with a partially matching username' do
expect ( described_class . search ( user . username [ 0 .. 2 ] ) ) . to eq ( [ user , user2 ] )
end
2018-03-17 18:26:18 +05:30
2022-08-27 11:52:29 +05:30
it 'returns users with a partially matching username starting with @' do
expect ( described_class . search ( " @ #{ user . username [ 0 .. 2 ] } " ) ) . to eq ( [ user , user2 ] )
2018-03-17 18:26:18 +05:30
end
2022-08-27 11:52:29 +05:30
it 'returns users with a matching username regardless of the casing' do
expect ( described_class . search ( user2 . username . upcase ) ) . to eq ( [ user2 ] )
2018-03-17 18:26:18 +05:30
end
2021-02-22 17:27:13 +05:30
2022-08-27 11:52:29 +05:30
it 'returns users with a exact matching username shorter than 3 chars' do
expect ( described_class . search ( user3 . username ) ) . to eq ( [ user3 ] )
2022-02-05 19:09:49 +05:30
end
2022-08-27 11:52:29 +05:30
it 'returns users with a exact matching username shorter than 3 chars regardless of the casing' do
expect ( described_class . search ( user3 . username . upcase ) ) . to eq ( [ user3 ] )
end
2017-08-17 22:00:37 +05:30
2022-08-27 11:52:29 +05:30
context 'when use_minimum_char_limit is false' do
it 'returns users with a partially matching username' do
expect ( described_class . search ( 'se' , use_minimum_char_limit : false ) ) . to eq ( [ user3 , user , user2 ] )
end
end
end
2022-08-13 15:12:31 +05:30
2022-08-27 11:52:29 +05:30
it 'returns no matches for an empty string' do
expect ( described_class . search ( '' ) ) . to be_empty
2017-08-17 22:00:37 +05:30
end
2022-08-13 15:12:31 +05:30
2022-08-27 11:52:29 +05:30
it 'returns no matches for nil' do
expect ( described_class . search ( nil ) ) . to be_empty
end
2017-08-17 22:00:37 +05:30
end
2022-03-02 08:16:31 +05:30
describe '.user_search_minimum_char_limit' do
it 'returns true' do
expect ( described_class . user_search_minimum_char_limit ) . to be ( true )
end
end
2016-11-03 12:29:30 +05:30
describe '.find_by_ssh_key_id' do
2019-12-21 20:55:43 +05:30
let_it_be ( :user ) { create ( :user ) }
let_it_be ( :key ) { create ( :key , user : user ) }
2016-11-03 12:29:30 +05:30
2019-12-21 20:55:43 +05:30
context 'using an existing SSH key ID' do
2016-11-03 12:29:30 +05:30
it 'returns the corresponding User' do
expect ( described_class . find_by_ssh_key_id ( key . id ) ) . to eq ( user )
end
end
2019-12-21 20:55:43 +05:30
it 'only performs a single query' do
key # Don't count the queries for creating the key and user
expect { described_class . find_by_ssh_key_id ( key . id ) }
. not_to exceed_query_limit ( 1 )
end
2016-11-03 12:29:30 +05:30
context 'using an invalid SSH key ID' do
it 'returns nil' do
expect ( described_class . find_by_ssh_key_id ( - 1 ) ) . to be_nil
end
end
end
2022-08-27 11:52:29 +05:30
shared_examples " find user by login " do
let_it_be ( :user ) { create ( :user ) }
let_it_be ( :invalid_login ) { " #{ user . username } -NOT-EXISTS " }
context 'when login is nil or empty' do
it 'returns nil' do
expect ( login_method ( nil ) ) . to be_nil
expect ( login_method ( '' ) ) . to be_nil
end
end
context 'when login is invalid' do
it 'returns nil' do
expect ( login_method ( invalid_login ) ) . to be_nil
end
end
context 'when login is username' do
it 'returns user' do
expect ( login_method ( user . username ) ) . to eq ( user )
expect ( login_method ( user . username . downcase ) ) . to eq ( user )
expect ( login_method ( user . username . upcase ) ) . to eq ( user )
end
end
context 'when login is email' do
it 'returns user' do
expect ( login_method ( user . email ) ) . to eq ( user )
expect ( login_method ( user . email . downcase ) ) . to eq ( user )
expect ( login_method ( user . email . upcase ) ) . to eq ( user )
end
end
end
2015-04-26 12:48:37 +05:30
describe '.by_login' do
2022-08-27 11:52:29 +05:30
it_behaves_like " find user by login " do
def login_method ( login )
described_class . by_login ( login ) . take
end
end
end
2015-04-26 12:48:37 +05:30
2022-08-27 11:52:29 +05:30
describe '.find_by_login' do
it_behaves_like " find user by login " do
def login_method ( login )
described_class . find_by_login ( login )
end
2014-09-02 18:07:02 +05:30
end
end
2017-08-17 22:00:37 +05:30
describe '.find_by_username' do
it 'returns nil if not found' do
expect ( described_class . find_by_username ( 'JohnDoe' ) ) . to be_nil
end
it 'is case-insensitive' do
user = create ( :user , username : 'JohnDoe' )
2018-03-17 18:26:18 +05:30
2017-08-17 22:00:37 +05:30
expect ( described_class . find_by_username ( 'JOHNDOE' ) ) . to eq user
end
end
2015-09-11 14:41:01 +05:30
describe '.find_by_username!' do
it 'raises RecordNotFound' do
2017-09-10 17:25:29 +05:30
expect { described_class . find_by_username! ( 'JohnDoe' ) }
. to raise_error ( ActiveRecord :: RecordNotFound )
2015-09-11 14:41:01 +05:30
end
it 'is case-insensitive' do
user = create ( :user , username : 'JohnDoe' )
2018-03-17 18:26:18 +05:30
2015-09-11 14:41:01 +05:30
expect ( described_class . find_by_username! ( 'JOHNDOE' ) ) . to eq user
end
end
2017-08-17 22:00:37 +05:30
describe '.find_by_full_path' do
2022-01-26 12:08:38 +05:30
let! ( :user ) { create ( :user , namespace : create ( :user_namespace ) ) }
2017-08-17 22:00:37 +05:30
2022-01-26 12:08:38 +05:30
context 'with a route matching the given path' do
let! ( :route ) { user . namespace . route }
2017-08-17 22:00:37 +05:30
2022-01-26 12:08:38 +05:30
it 'returns the user' do
expect ( described_class . find_by_full_path ( route . path ) ) . to eq ( user )
end
2017-08-17 22:00:37 +05:30
2022-01-26 12:08:38 +05:30
it 'is case-insensitive' do
expect ( described_class . find_by_full_path ( route . path . upcase ) ) . to eq ( user )
expect ( described_class . find_by_full_path ( route . path . downcase ) ) . to eq ( user )
2017-08-17 22:00:37 +05:30
end
2021-11-18 22:05:49 +05:30
context 'with a redirect route matching the given path' do
let! ( :redirect_route ) { user . namespace . redirect_routes . create! ( path : 'foo' ) }
context 'without the follow_redirects option' do
it 'returns nil' do
expect ( described_class . find_by_full_path ( redirect_route . path ) ) . to eq ( nil )
end
2017-08-17 22:00:37 +05:30
end
2021-11-18 22:05:49 +05:30
context 'with the follow_redirects option set to true' do
it 'returns the user' do
expect ( described_class . find_by_full_path ( redirect_route . path , follow_redirects : true ) ) . to eq ( user )
end
it 'is case-insensitive' do
expect ( described_class . find_by_full_path ( redirect_route . path . upcase , follow_redirects : true ) ) . to eq ( user )
expect ( described_class . find_by_full_path ( redirect_route . path . downcase , follow_redirects : true ) ) . to eq ( user )
end
2017-08-17 22:00:37 +05:30
end
end
2021-11-18 22:05:49 +05:30
context 'without a route or a redirect route matching the given path' do
context 'without the follow_redirects option' do
it 'returns nil' do
expect ( described_class . find_by_full_path ( 'unknown' ) ) . to eq ( nil )
end
2017-08-17 22:00:37 +05:30
end
2021-11-18 22:05:49 +05:30
context 'with the follow_redirects option set to true' do
it 'returns nil' do
expect ( described_class . find_by_full_path ( 'unknown' , follow_redirects : true ) ) . to eq ( nil )
end
2017-08-17 22:00:37 +05:30
end
end
2021-11-18 22:05:49 +05:30
context 'with a group route matching the given path' do
let! ( :group ) { create ( :group , path : 'group_path' ) }
2018-10-15 14:42:47 +05:30
2021-11-18 22:05:49 +05:30
context 'when the group namespace has an owner_id (legacy data)' do
before do
group . update! ( owner_id : user . id )
end
2017-08-17 22:00:37 +05:30
2021-11-18 22:05:49 +05:30
it 'returns nil' do
expect ( described_class . find_by_full_path ( 'group_path' ) ) . to eq ( nil )
end
2017-08-17 22:00:37 +05:30
end
2021-11-18 22:05:49 +05:30
context 'when the group namespace does not have an owner_id' do
it 'returns nil' do
expect ( described_class . find_by_full_path ( 'group_path' ) ) . to eq ( nil )
end
2017-08-17 22:00:37 +05:30
end
end
end
end
2014-09-02 18:07:02 +05:30
describe 'all_ssh_keys' do
2015-04-26 12:48:37 +05:30
it { is_expected . to have_many ( :keys ) . dependent ( :destroy ) }
2014-09-02 18:07:02 +05:30
2021-11-18 22:05:49 +05:30
it 'has all ssh keys' do
2014-09-02 18:07:02 +05:30
user = create :user
2022-08-13 15:12:31 +05:30
key = create :key_without_comment , user_id : user . id
2014-09-02 18:07:02 +05:30
2016-09-13 17:45:13 +05:30
expect ( user . all_ssh_keys ) . to include ( a_string_starting_with ( key . key ) )
2014-09-02 18:07:02 +05:30
end
end
2016-08-24 12:49:21 +05:30
describe '#avatar_type' do
2014-09-02 18:07:02 +05:30
let ( :user ) { create ( :user ) }
2017-08-17 22:00:37 +05:30
it 'is true if avatar is image' do
2014-09-02 18:07:02 +05:30
user . update_attribute ( :avatar , 'uploads/avatar.png' )
2018-03-17 18:26:18 +05:30
2015-04-26 12:48:37 +05:30
expect ( user . avatar_type ) . to be_truthy
2014-09-02 18:07:02 +05:30
end
2017-08-17 22:00:37 +05:30
it 'is false if avatar is html page' do
2014-09-02 18:07:02 +05:30
user . update_attribute ( :avatar , 'uploads/avatar.html' )
2021-06-08 01:23:25 +05:30
user . avatar_type
2018-03-17 18:26:18 +05:30
2021-06-08 01:23:25 +05:30
expect ( user . errors . added? ( :avatar , " file format is not supported. Please try one of the following supported formats: png, jpg, jpeg, gif, bmp, tiff, ico, webp " ) ) . to be true
2017-08-17 22:00:37 +05:30
end
end
describe '#avatar_url' do
let ( :user ) { create ( :user , :with_avatar ) }
context 'when avatar file is uploaded' do
2017-09-10 17:25:29 +05:30
it 'shows correct avatar url' do
2018-03-17 18:26:18 +05:30
expect ( user . avatar_url ) . to eq ( user . avatar . url )
expect ( user . avatar_url ( only_path : false ) ) . to eq ( [ Gitlab . config . gitlab . url , user . avatar . url ] . join )
end
end
end
2017-09-10 17:25:29 +05:30
2021-11-18 22:05:49 +05:30
describe '#clear_avatar_caches' do
2021-04-17 20:07:23 +05:30
let ( :user ) { create ( :user ) }
2021-11-18 22:05:49 +05:30
it 'clears the avatar cache when saving' do
2021-04-29 21:17:54 +05:30
allow ( user ) . to receive ( :avatar_changed? ) . and_return ( true )
2021-04-17 20:07:23 +05:30
2021-04-29 21:17:54 +05:30
expect ( Gitlab :: AvatarCache ) . to receive ( :delete_by_email ) . with ( * user . verified_emails )
2021-04-17 20:07:23 +05:30
2021-06-08 01:23:25 +05:30
user . update! ( avatar : fixture_file_upload ( 'spec/fixtures/dk.png' ) )
2021-04-17 20:07:23 +05:30
end
end
2018-11-08 19:23:39 +05:30
describe '#accept_pending_invitations!' do
let ( :user ) { create ( :user , email : 'user@email.com' ) }
2022-07-29 17:44:30 +05:30
let ( :confirmed_secondary_email ) { create ( :email , :confirmed , email : 'confirmedsecondary@example.com' , user : user ) }
let ( :unconfirmed_secondary_email ) { create ( :email , email : 'unconfirmedsecondary@example.com' , user : user ) }
2018-11-08 19:23:39 +05:30
let! ( :project_member_invite ) { create ( :project_member , :invited , invite_email : user . email ) }
let! ( :group_member_invite ) { create ( :group_member , :invited , invite_email : user . email ) }
2022-07-29 17:44:30 +05:30
2018-11-08 19:23:39 +05:30
let! ( :external_project_member_invite ) { create ( :project_member , :invited , invite_email : 'external@email.com' ) }
let! ( :external_group_member_invite ) { create ( :group_member , :invited , invite_email : 'external@email.com' ) }
2022-07-29 17:44:30 +05:30
let! ( :project_member_invite_via_confirmed_secondary_email ) { create ( :project_member , :invited , invite_email : confirmed_secondary_email . email ) }
let! ( :group_member_invite_via_confirmed_secondary_email ) { create ( :group_member , :invited , invite_email : confirmed_secondary_email . email ) }
let! ( :project_member_invite_via_unconfirmed_secondary_email ) { create ( :project_member , :invited , invite_email : unconfirmed_secondary_email . email ) }
let! ( :group_member_invite_via_unconfirmed_secondary_email ) { create ( :group_member , :invited , invite_email : unconfirmed_secondary_email . email ) }
2018-11-08 19:23:39 +05:30
it 'accepts all the user members pending invitations and returns the accepted_members' do
accepted_members = user . accept_pending_invitations!
2022-07-29 17:44:30 +05:30
expect ( accepted_members ) . to match_array (
[
project_member_invite ,
group_member_invite ,
project_member_invite_via_confirmed_secondary_email ,
group_member_invite_via_confirmed_secondary_email
]
)
2018-11-08 19:23:39 +05:30
expect ( group_member_invite . reload ) . not_to be_invite
expect ( project_member_invite . reload ) . not_to be_invite
2022-07-29 17:44:30 +05:30
2018-11-08 19:23:39 +05:30
expect ( external_project_member_invite . reload ) . to be_invite
expect ( external_group_member_invite . reload ) . to be_invite
2022-07-29 17:44:30 +05:30
expect ( project_member_invite_via_confirmed_secondary_email . reload ) . not_to be_invite
expect ( group_member_invite_via_confirmed_secondary_email . reload ) . not_to be_invite
expect ( project_member_invite_via_unconfirmed_secondary_email . reload ) . to be_invite
expect ( group_member_invite_via_unconfirmed_secondary_email . reload ) . to be_invite
2018-11-08 19:23:39 +05:30
end
end
2018-03-17 18:26:18 +05:30
describe '#all_emails' do
let ( :user ) { create ( :user ) }
2022-07-29 17:44:30 +05:30
let! ( :unconfirmed_secondary_email ) { create ( :email , user : user ) }
let! ( :confirmed_secondary_email ) { create ( :email , :confirmed , user : user ) }
it 'returns all emails' do
expect ( user . all_emails ) . to contain_exactly (
user . email ,
user . private_commit_email ,
confirmed_secondary_email . email
)
end
context 'when the primary email is confirmed' do
it 'includes the primary email' do
expect ( user . all_emails ) . to include ( user . email )
end
end
context 'when the primary email is unconfirmed' do
let! ( :user ) { create ( :user , :unconfirmed ) }
it 'includes the primary email' do
expect ( user . all_emails ) . to include ( user . email )
end
end
context 'when the primary email is temp email for oauth' do
let! ( :user ) { create ( :omniauth_user , :unconfirmed , email : 'temp-email-for-oauth-user@gitlab.localhost' ) }
it 'does not include the primary email' do
expect ( user . all_emails ) . not_to include ( user . email )
end
end
2020-04-08 14:13:33 +05:30
context 'when `include_private_email` is true' do
2022-07-29 17:44:30 +05:30
it 'includes the private commit email' do
expect ( user . all_emails ) . to include ( user . private_commit_email )
2020-04-08 14:13:33 +05:30
end
end
2017-09-10 17:25:29 +05:30
2020-04-08 14:13:33 +05:30
context 'when `include_private_email` is false' do
it 'does not include the private commit email' do
2022-07-29 17:44:30 +05:30
expect ( user . all_emails ( include_private_email : false ) ) . not_to include (
user . private_commit_email
2020-04-08 14:13:33 +05:30
)
end
2018-03-17 18:26:18 +05:30
end
2022-07-29 17:44:30 +05:30
context 'when the secondary email is confirmed' do
it 'includes the secondary email' do
expect ( user . all_emails ) . to include ( confirmed_secondary_email . email )
end
end
context 'when the secondary email is unconfirmed' do
it 'does not include the secondary email' do
expect ( user . all_emails ) . not_to include ( unconfirmed_secondary_email . email )
end
end
2018-03-17 18:26:18 +05:30
end
describe '#verified_emails' do
let ( :user ) { create ( :user ) }
it 'returns only confirmed emails' do
2020-06-23 00:09:42 +05:30
email_confirmed = create :email , user : user , confirmed_at : Time . current
2018-03-17 18:26:18 +05:30
create :email , user : user
2019-02-15 15:39:39 +05:30
expect ( user . verified_emails ) . to contain_exactly (
user . email ,
user . private_commit_email ,
email_confirmed . email
)
2018-03-17 18:26:18 +05:30
end
end
2020-05-30 21:06:31 +05:30
describe '#public_verified_emails' do
let ( :user ) { create ( :user ) }
it 'returns only confirmed public emails' do
email_confirmed = create :email , user : user , confirmed_at : Time . current
create :email , user : user
expect ( user . public_verified_emails ) . to contain_exactly (
user . email ,
email_confirmed . email
)
end
it 'returns confirmed public emails plus main user email when user is not confirmed' do
user = create ( :user , confirmed_at : nil )
email_confirmed = create :email , user : user , confirmed_at : Time . current
create :email , user : user
expect ( user . public_verified_emails ) . to contain_exactly (
user . email ,
email_confirmed . email
)
end
end
2018-03-17 18:26:18 +05:30
describe '#verified_email?' do
let ( :user ) { create ( :user ) }
it 'returns true when the email is verified/confirmed' do
2020-06-23 00:09:42 +05:30
email_confirmed = create :email , user : user , confirmed_at : Time . current
2018-03-17 18:26:18 +05:30
create :email , user : user
user . reload
expect ( user . verified_email? ( user . email ) ) . to be_truthy
expect ( user . verified_email? ( email_confirmed . email . titlecase ) ) . to be_truthy
end
2018-12-13 13:39:08 +05:30
it 'returns true when user is found through private commit email' do
expect ( user . verified_email? ( user . private_commit_email ) ) . to be_truthy
end
2019-02-15 15:39:39 +05:30
it 'returns true for an outdated private commit email' do
old_email = user . private_commit_email
user . update! ( username : 'changed-username' )
expect ( user . verified_email? ( old_email ) ) . to be_truthy
end
2018-03-17 18:26:18 +05:30
it 'returns false when the email is not verified/confirmed' do
email_unconfirmed = create :email , user : user
user . reload
expect ( user . verified_email? ( email_unconfirmed . email ) ) . to be_falsy
2014-09-02 18:07:02 +05:30
end
end
2021-02-22 17:27:13 +05:30
context 'crowd synchronized user' do
describe '#crowd_user?' do
it 'is true if provider is crowd' do
user = create ( :omniauth_user , provider : 'crowd' )
expect ( user . crowd_user? ) . to be_truthy
end
it 'is false for other providers' do
user = create ( :omniauth_user , provider : 'other-provider' )
expect ( user . crowd_user? ) . to be_falsey
end
it 'is false if no extern_uid is provided' do
user = create ( :omniauth_user , extern_uid : nil )
expect ( user . crowd_user? ) . to be_falsey
end
end
end
2016-08-24 12:49:21 +05:30
describe '#requires_ldap_check?' do
2017-09-10 17:25:29 +05:30
let ( :user ) { described_class . new }
2014-09-02 18:07:02 +05:30
it 'is false when LDAP is disabled' do
# Create a condition which would otherwise cause 'true' to be returned
2015-09-11 14:41:01 +05:30
allow ( user ) . to receive ( :ldap_user? ) . and_return ( true )
2014-09-02 18:07:02 +05:30
user . last_credential_check_at = nil
2018-03-17 18:26:18 +05:30
2015-04-26 12:48:37 +05:30
expect ( user . requires_ldap_check? ) . to be_falsey
2014-09-02 18:07:02 +05:30
end
context 'when LDAP is enabled' do
2015-09-11 14:41:01 +05:30
before do
allow ( Gitlab . config . ldap ) . to receive ( :enabled ) . and_return ( true )
end
2014-09-02 18:07:02 +05:30
it 'is false for non-LDAP users' do
2015-09-11 14:41:01 +05:30
allow ( user ) . to receive ( :ldap_user? ) . and_return ( false )
2018-03-17 18:26:18 +05:30
2015-04-26 12:48:37 +05:30
expect ( user . requires_ldap_check? ) . to be_falsey
2014-09-02 18:07:02 +05:30
end
context 'and when the user is an LDAP user' do
2015-09-11 14:41:01 +05:30
before do
allow ( user ) . to receive ( :ldap_user? ) . and_return ( true )
end
2014-09-02 18:07:02 +05:30
it 'is true when the user has never had an LDAP check before' do
user . last_credential_check_at = nil
2018-03-17 18:26:18 +05:30
2015-04-26 12:48:37 +05:30
expect ( user . requires_ldap_check? ) . to be_truthy
2014-09-02 18:07:02 +05:30
end
it 'is true when the last LDAP check happened over 1 hour ago' do
user . last_credential_check_at = 2 . hours . ago
2018-03-17 18:26:18 +05:30
2015-04-26 12:48:37 +05:30
expect ( user . requires_ldap_check? ) . to be_truthy
2014-09-02 18:07:02 +05:30
end
end
end
end
2016-01-19 16:12:03 +05:30
context 'ldap synchronized user' do
2016-08-24 12:49:21 +05:30
describe '#ldap_user?' do
2016-01-19 16:12:03 +05:30
it 'is true if provider name starts with ldap' do
user = create ( :omniauth_user , provider : 'ldapmain' )
2018-03-17 18:26:18 +05:30
2016-01-19 16:12:03 +05:30
expect ( user . ldap_user? ) . to be_truthy
end
2015-04-26 12:48:37 +05:30
2016-01-19 16:12:03 +05:30
it 'is false for other providers' do
user = create ( :omniauth_user , provider : 'other-provider' )
2018-03-17 18:26:18 +05:30
2016-01-19 16:12:03 +05:30
expect ( user . ldap_user? ) . to be_falsey
end
it 'is false if no extern_uid is provided' do
user = create ( :omniauth_user , extern_uid : nil )
2018-03-17 18:26:18 +05:30
2016-01-19 16:12:03 +05:30
expect ( user . ldap_user? ) . to be_falsey
end
2015-04-26 12:48:37 +05:30
end
2016-08-24 12:49:21 +05:30
describe '#ldap_identity' do
2016-01-19 16:12:03 +05:30
it 'returns ldap identity' do
2022-05-07 20:08:51 +05:30
user = create ( :omniauth_user , :ldap )
2018-03-17 18:26:18 +05:30
2016-01-19 16:12:03 +05:30
expect ( user . ldap_identity . provider ) . not_to be_empty
end
2015-04-26 12:48:37 +05:30
end
2021-09-30 23:02:18 +05:30
describe '#matches_identity?' do
it 'finds the identity when the DN is formatted differently' do
user = create ( :omniauth_user , provider : 'ldapmain' , extern_uid : 'uid=john smith,ou=people,dc=example,dc=com' )
expect ( user . matches_identity? ( 'ldapmain' , 'uid=John Smith, ou=People, dc=example, dc=com' ) ) . to eq ( true )
end
end
2016-01-19 16:12:03 +05:30
describe '#ldap_block' do
let ( :user ) { create ( :omniauth_user , provider : 'ldapmain' , name : 'John Smith' ) }
it 'blocks user flaging the action caming from ldap' do
user . ldap_block
2018-03-17 18:26:18 +05:30
2016-01-19 16:12:03 +05:30
expect ( user . blocked? ) . to be_truthy
expect ( user . ldap_blocked? ) . to be_truthy
end
2020-03-13 15:44:24 +05:30
context 'on a read-only instance' do
before do
allow ( Gitlab :: Database ) . to receive ( :read_only? ) . and_return ( true )
end
it 'does not block user' do
user . ldap_block
expect ( user . blocked? ) . to be_falsey
expect ( user . ldap_blocked? ) . to be_falsey
end
end
2015-04-26 12:48:37 +05:30
end
end
2014-09-02 18:07:02 +05:30
describe '#full_website_url' do
let ( :user ) { create ( :user ) }
it 'begins with http if website url omits it' do
user . website_url = 'test.com'
expect ( user . full_website_url ) . to eq 'http://test.com'
end
it 'begins with http if website url begins with http' do
user . website_url = 'http://test.com'
expect ( user . full_website_url ) . to eq 'http://test.com'
end
it 'begins with https if website url begins with https' do
user . website_url = 'https://test.com'
expect ( user . full_website_url ) . to eq 'https://test.com'
end
end
describe '#short_website_url' do
let ( :user ) { create ( :user ) }
it 'does not begin with http if website url omits it' do
user . website_url = 'test.com'
expect ( user . short_website_url ) . to eq 'test.com'
end
it 'does not begin with http if website url begins with http' do
user . website_url = 'http://test.com'
expect ( user . short_website_url ) . to eq 'test.com'
end
it 'does not begin with https if website url begins with https' do
user . website_url = 'https://test.com'
expect ( user . short_website_url ) . to eq 'test.com'
end
end
2017-09-10 17:25:29 +05:30
describe '#sanitize_attrs' do
2021-07-02 01:05:55 +05:30
let ( :user ) { build ( :user , name : 'test <& user' , skype : 'test&user' ) }
2017-09-10 17:25:29 +05:30
it 'encodes HTML entities in the Skype attribute' do
expect { user . sanitize_attrs } . to change { user . skype } . to ( 'test&user' )
end
it 'does not encode HTML entities in the name attribute' do
expect { user . sanitize_attrs } . not_to change { user . name }
end
2021-07-02 01:05:55 +05:30
it 'sanitizes attr from html tags' do
user = create ( :user , name : '<a href="//example.com">Test<a>' , twitter : '<a href="//evil.com">https://twitter.com<a>' )
expect ( user . name ) . to eq ( 'Test' )
expect ( user . twitter ) . to eq ( 'https://twitter.com' )
end
it 'sanitizes attr from js scripts' do
user = create ( :user , name : '<script>alert("Test")</script>' )
expect ( user . name ) . to eq ( " alert( \" Test \" ) " )
end
it 'sanitizes attr from iframe scripts' do
user = create ( :user , name : 'User"><iframe src=javascript:alert()><iframe>' )
expect ( user . name ) . to eq ( 'User">' )
end
2017-09-10 17:25:29 +05:30
end
2017-08-17 22:00:37 +05:30
describe '#starred?' do
it 'determines if user starred a project' do
2014-09-02 18:07:02 +05:30
user = create :user
2017-09-10 17:25:29 +05:30
project1 = create ( :project , :public )
project2 = create ( :project , :public )
2014-09-02 18:07:02 +05:30
2015-04-26 12:48:37 +05:30
expect ( user . starred? ( project1 ) ) . to be_falsey
expect ( user . starred? ( project2 ) ) . to be_falsey
2014-09-02 18:07:02 +05:30
star1 = UsersStarProject . create! ( project : project1 , user : user )
2018-03-17 18:26:18 +05:30
2015-04-26 12:48:37 +05:30
expect ( user . starred? ( project1 ) ) . to be_truthy
expect ( user . starred? ( project2 ) ) . to be_falsey
2014-09-02 18:07:02 +05:30
star2 = UsersStarProject . create! ( project : project2 , user : user )
2018-03-17 18:26:18 +05:30
2015-04-26 12:48:37 +05:30
expect ( user . starred? ( project1 ) ) . to be_truthy
expect ( user . starred? ( project2 ) ) . to be_truthy
2014-09-02 18:07:02 +05:30
2021-06-08 01:23:25 +05:30
star1 . destroy!
2018-03-17 18:26:18 +05:30
2015-04-26 12:48:37 +05:30
expect ( user . starred? ( project1 ) ) . to be_falsey
expect ( user . starred? ( project2 ) ) . to be_truthy
2014-09-02 18:07:02 +05:30
2021-06-08 01:23:25 +05:30
star2 . destroy!
2018-03-17 18:26:18 +05:30
2015-04-26 12:48:37 +05:30
expect ( user . starred? ( project1 ) ) . to be_falsey
expect ( user . starred? ( project2 ) ) . to be_falsey
2014-09-02 18:07:02 +05:30
end
end
2017-08-17 22:00:37 +05:30
describe '#toggle_star' do
it 'toggles stars' do
2014-09-02 18:07:02 +05:30
user = create :user
2017-09-10 17:25:29 +05:30
project = create ( :project , :public )
2014-09-02 18:07:02 +05:30
2022-10-11 01:57:18 +05:30
# starring
expect { user . toggle_star ( project ) }
. to change { user . starred? ( project ) } . from ( false ) . to ( true )
. and not_change { project . reload . updated_at }
2018-03-17 18:26:18 +05:30
2022-10-11 01:57:18 +05:30
# unstarring
expect { user . toggle_star ( project ) }
. to change { user . starred? ( project ) } . from ( true ) . to ( false )
. and not_change { project . reload . updated_at }
2015-04-26 12:48:37 +05:30
end
end
2021-03-11 19:13:27 +05:30
describe '#following?' do
it 'check if following another user' do
user = create :user
followee1 = create :user
expect ( user . follow ( followee1 ) ) . to be_truthy
expect ( user . following? ( followee1 ) ) . to be_truthy
expect ( user . unfollow ( followee1 ) ) . to be_truthy
expect ( user . following? ( followee1 ) ) . to be_falsey
end
end
2022-08-13 15:12:31 +05:30
describe '#followed_by?' do
it 'check if followed by another user' do
follower = create :user
followee = create :user
expect { follower . follow ( followee ) } . to change { followee . followed_by? ( follower ) } . from ( false ) . to ( true )
end
end
2021-03-11 19:13:27 +05:30
describe '#follow' do
it 'follow another user' do
user = create :user
followee1 = create :user
followee2 = create :user
expect ( user . followees ) . to be_empty
expect ( user . follow ( followee1 ) ) . to be_truthy
expect ( user . follow ( followee1 ) ) . to be_falsey
expect ( user . followees ) . to contain_exactly ( followee1 )
expect ( user . follow ( followee2 ) ) . to be_truthy
expect ( user . follow ( followee2 ) ) . to be_falsey
expect ( user . followees ) . to contain_exactly ( followee1 , followee2 )
end
it 'follow itself is not possible' do
user = create :user
expect ( user . followees ) . to be_empty
expect ( user . follow ( user ) ) . to be_falsey
expect ( user . followees ) . to be_empty
end
2022-11-25 23:54:43 +05:30
it 'does not follow if max followee limit is reached' do
stub_const ( 'Users::UserFollowUser::MAX_FOLLOWEE_LIMIT' , 2 )
user = create ( :user )
Users :: UserFollowUser :: MAX_FOLLOWEE_LIMIT . times { user . follow ( create ( :user ) ) }
followee = create ( :user )
user_follow_user = user . follow ( followee )
expect ( user_follow_user ) . not_to be_persisted
expected_message = format ( _ ( " You can't follow more than %{limit} users. To follow more users, unfollow some others. " ) , limit : Users :: UserFollowUser :: MAX_FOLLOWEE_LIMIT )
expect ( user_follow_user . errors . messages [ :base ] . first ) . to eq ( expected_message )
expect ( user . following? ( followee ) ) . to be_falsey
end
2021-03-11 19:13:27 +05:30
end
describe '#unfollow' do
it 'unfollow another user' do
user = create :user
followee1 = create :user
followee2 = create :user
expect ( user . followees ) . to be_empty
expect ( user . follow ( followee1 ) ) . to be_truthy
expect ( user . follow ( followee1 ) ) . to be_falsey
expect ( user . follow ( followee2 ) ) . to be_truthy
expect ( user . follow ( followee2 ) ) . to be_falsey
expect ( user . followees ) . to contain_exactly ( followee1 , followee2 )
expect ( user . unfollow ( followee1 ) ) . to be_truthy
expect ( user . unfollow ( followee1 ) ) . to be_falsey
expect ( user . followees ) . to contain_exactly ( followee2 )
expect ( user . unfollow ( followee2 ) ) . to be_truthy
expect ( user . unfollow ( followee2 ) ) . to be_falsey
expect ( user . followees ) . to be_empty
end
2022-11-25 23:54:43 +05:30
it 'unfollows when over followee limit' do
user = create ( :user )
followees = create_list ( :user , 4 )
followees . each { | f | expect ( user . follow ( f ) ) . to be_truthy }
stub_const ( 'Users::UserFollowUser::MAX_FOLLOWEE_LIMIT' , followees . length - 2 )
expect ( user . unfollow ( followees . first ) ) . to be_truthy
expect ( user . following? ( followees . first ) ) . to be_falsey
end
2021-03-11 19:13:27 +05:30
end
2021-11-11 11:23:49 +05:30
describe '#notification_email_or_default' do
2021-10-27 15:23:28 +05:30
let ( :email ) { 'gonzo@muppets.com' }
context 'when the column in the database is null' do
subject { create ( :user , email : email , notification_email : nil ) }
it 'defaults to the primary email' do
2021-11-11 11:23:49 +05:30
expect ( subject . notification_email ) . to be nil
expect ( subject . notification_email_or_default ) . to eq ( email )
2021-10-27 15:23:28 +05:30
end
end
end
2018-12-13 13:39:08 +05:30
describe '.find_by_private_commit_email' do
context 'with email' do
2020-03-13 15:44:24 +05:30
let_it_be ( :user ) { create ( :user ) }
2018-12-13 13:39:08 +05:30
it 'returns user through private commit email' do
expect ( described_class . find_by_private_commit_email ( user . private_commit_email ) ) . to eq ( user )
end
it 'returns nil when email other than private_commit_email is used' do
expect ( described_class . find_by_private_commit_email ( user . email ) ) . to be_nil
end
end
it 'returns nil when email is nil' do
expect ( described_class . find_by_private_commit_email ( nil ) ) . to be_nil
end
end
2018-05-09 12:01:36 +05:30
describe '#sort_by_attribute' do
2022-08-13 15:12:31 +05:30
let_it_be ( :user ) { create :user , created_at : Date . today , current_sign_in_at : Date . today , username : 'user0' }
let_it_be ( :user1 ) { create :user , created_at : Date . today - 1 , last_activity_on : Date . today - 1 , current_sign_in_at : Date . today - 1 , username : 'user1' }
let_it_be ( :user2 ) { create :user , created_at : Date . today - 2 , username : 'user2' }
let_it_be ( :user3 ) { create :user , created_at : Date . today - 3 , last_activity_on : Date . today , username : " user3 " }
2015-04-26 12:48:37 +05:30
2017-08-17 22:00:37 +05:30
context 'when sort by recent_sign_in' do
2018-05-09 12:01:36 +05:30
let ( :users ) { described_class . sort_by_attribute ( 'recent_sign_in' ) }
2018-03-17 18:26:18 +05:30
2022-08-13 15:12:31 +05:30
it 'sorts users by recent sign-in time with user that never signed in at the end' do
expect ( users ) . to eq ( [ user , user1 , user2 , user3 ] )
2017-08-17 22:00:37 +05:30
end
2015-04-26 12:48:37 +05:30
end
2017-08-17 22:00:37 +05:30
context 'when sort by oldest_sign_in' do
2018-05-09 12:01:36 +05:30
let ( :users ) { described_class . sort_by_attribute ( 'oldest_sign_in' ) }
2018-03-17 18:26:18 +05:30
2022-08-13 15:12:31 +05:30
it 'sorts users by the oldest sign-in time with users that never signed in at the end' do
expect ( users ) . to eq ( [ user1 , user , user2 , user3 ] )
2017-08-17 22:00:37 +05:30
end
2015-04-26 12:48:37 +05:30
end
2017-08-17 22:00:37 +05:30
it 'sorts users in descending order by their creation time' do
2022-08-13 15:12:31 +05:30
expect ( described_class . sort_by_attribute ( 'created_desc' ) ) . to eq ( [ user , user1 , user2 , user3 ] )
2015-04-26 12:48:37 +05:30
end
2017-08-17 22:00:37 +05:30
it 'sorts users in ascending order by their creation time' do
2022-08-13 15:12:31 +05:30
expect ( described_class . sort_by_attribute ( 'created_asc' ) ) . to eq ( [ user3 , user2 , user1 , user ] )
2015-04-26 12:48:37 +05:30
end
2017-08-17 22:00:37 +05:30
it 'sorts users by id in descending order when nil is passed' do
2022-08-13 15:12:31 +05:30
expect ( described_class . sort_by_attribute ( nil ) ) . to eq ( [ user3 , user2 , user1 , user ] )
end
it 'sorts user by latest activity descending, nulls last ordered by ascending id' do
expect ( described_class . sort_by_attribute ( 'last_activity_on_desc' ) ) . to eq ( [ user3 , user1 , user , user2 ] )
end
it 'sorts user by latest activity ascending, nulls first ordered by descending id' do
expect ( described_class . sort_by_attribute ( 'last_activity_on_asc' ) ) . to eq ( [ user2 , user , user1 , user3 ] )
2015-04-26 12:48:37 +05:30
end
end
2021-11-18 22:05:49 +05:30
describe '#last_active_at' do
2019-12-21 20:55:43 +05:30
let ( :last_activity_on ) { 5 . days . ago . to_date }
let ( :current_sign_in_at ) { 8 . days . ago }
context 'for a user that has `last_activity_on` set' do
let ( :user ) { create ( :user , last_activity_on : last_activity_on ) }
it 'returns `last_activity_on` with current time zone' do
expect ( user . last_active_at ) . to eq ( last_activity_on . to_time . in_time_zone )
end
end
context 'for a user that has `current_sign_in_at` set' do
let ( :user ) { create ( :user , current_sign_in_at : current_sign_in_at ) }
it 'returns `current_sign_in_at`' do
expect ( user . last_active_at ) . to eq ( current_sign_in_at )
end
end
context 'for a user that has both `current_sign_in_at` & ``last_activity_on`` set' do
let ( :user ) { create ( :user , current_sign_in_at : current_sign_in_at , last_activity_on : last_activity_on ) }
it 'returns the latest among `current_sign_in_at` & `last_activity_on`' do
latest_event = [ current_sign_in_at , last_activity_on . to_time . in_time_zone ] . max
expect ( user . last_active_at ) . to eq ( latest_event )
end
end
context 'for a user that does not have both `current_sign_in_at` & `last_activity_on` set' do
let ( :user ) { create ( :user , current_sign_in_at : nil , last_activity_on : nil ) }
it 'returns nil' do
expect ( user . last_active_at ) . to eq ( nil )
end
end
end
2021-11-18 22:05:49 +05:30
describe '#can_be_deactivated?' do
2019-12-21 20:55:43 +05:30
let ( :activity ) { { } }
let ( :user ) { create ( :user , name : 'John Smith' , ** activity ) }
2022-10-11 01:57:18 +05:30
let ( :day_within_minium_inactive_days_threshold ) { Gitlab :: CurrentSettings . deactivate_dormant_users_period . pred . days . ago }
let ( :day_outside_minium_inactive_days_threshold ) { Gitlab :: CurrentSettings . deactivate_dormant_users_period . next . days . ago }
2019-12-21 20:55:43 +05:30
shared_examples 'not eligible for deactivation' do
it 'returns false' do
expect ( user . can_be_deactivated? ) . to be_falsey
end
end
shared_examples 'eligible for deactivation' do
it 'returns true' do
expect ( user . can_be_deactivated? ) . to be_truthy
end
end
2021-11-18 22:05:49 +05:30
context 'a user who is not active' do
2019-12-21 20:55:43 +05:30
before do
user . block
end
it_behaves_like 'not eligible for deactivation'
end
context 'a user who has activity within the specified minimum inactive days' do
let ( :activity ) { { last_activity_on : day_within_minium_inactive_days_threshold } }
it_behaves_like 'not eligible for deactivation'
end
context 'a user who has signed in within the specified minimum inactive days' do
let ( :activity ) { { current_sign_in_at : day_within_minium_inactive_days_threshold } }
it_behaves_like 'not eligible for deactivation'
end
context 'a user who has no activity within the specified minimum inactive days' do
let ( :activity ) { { last_activity_on : day_outside_minium_inactive_days_threshold } }
it_behaves_like 'eligible for deactivation'
end
context 'a user who has not signed in within the specified minimum inactive days' do
let ( :activity ) { { current_sign_in_at : day_outside_minium_inactive_days_threshold } }
it_behaves_like 'eligible for deactivation'
end
2021-01-03 14:25:43 +05:30
context 'a user who is internal' do
it 'returns false' do
internal_user = create ( :user , :bot )
expect ( internal_user . can_be_deactivated? ) . to be_falsey
end
end
2019-12-21 20:55:43 +05:30
end
2021-11-18 22:05:49 +05:30
describe '#contributed_projects' do
2015-04-26 12:48:37 +05:30
subject { create ( :user ) }
2019-12-21 20:55:43 +05:30
2017-09-10 17:25:29 +05:30
let! ( :project1 ) { create ( :project ) }
2018-03-17 18:26:18 +05:30
let! ( :project2 ) { fork_project ( project3 ) }
2017-09-10 17:25:29 +05:30
let! ( :project3 ) { create ( :project ) }
2022-04-04 11:22:00 +05:30
let! ( :project_aimed_for_deletion ) { create ( :project , marked_for_deletion_at : 2 . days . ago , pending_delete : false ) }
2015-04-26 12:48:37 +05:30
let! ( :merge_request ) { create ( :merge_request , source_project : project2 , target_project : project3 , author : subject ) }
2017-09-10 17:25:29 +05:30
let! ( :push_event ) { create ( :push_event , project : project1 , author : subject ) }
2017-08-17 22:00:37 +05:30
let! ( :merge_event ) { create ( :event , :created , project : project3 , target : merge_request , author : subject ) }
2022-04-04 11:22:00 +05:30
let! ( :merge_event_2 ) { create ( :event , :created , project : project_aimed_for_deletion , target : merge_request , author : subject ) }
2015-04-26 12:48:37 +05:30
before do
2018-11-18 11:00:15 +05:30
project1 . add_maintainer ( subject )
project2 . add_maintainer ( subject )
2022-04-04 11:22:00 +05:30
project_aimed_for_deletion . add_maintainer ( subject )
2015-04-26 12:48:37 +05:30
end
2021-11-18 22:05:49 +05:30
it 'includes IDs for projects the user has pushed to' do
2015-11-26 14:37:03 +05:30
expect ( subject . contributed_projects ) . to include ( project1 )
2015-04-26 12:48:37 +05:30
end
2021-11-18 22:05:49 +05:30
it 'includes IDs for projects the user has had merge requests merged into' do
2015-11-26 14:37:03 +05:30
expect ( subject . contributed_projects ) . to include ( project3 )
2015-04-26 12:48:37 +05:30
end
it " doesn't include IDs for unrelated projects " do
2015-11-26 14:37:03 +05:30
expect ( subject . contributed_projects ) . not_to include ( project2 )
2014-09-02 18:07:02 +05:30
end
2022-04-04 11:22:00 +05:30
it " doesn't include projects aimed for deletion " do
expect ( subject . contributed_projects ) . not_to include ( project_aimed_for_deletion )
end
2014-09-02 18:07:02 +05:30
end
2015-09-11 14:41:01 +05:30
2018-03-17 18:26:18 +05:30
describe '#fork_of' do
let ( :user ) { create ( :user ) }
it " returns a user's fork of a project " do
project = create ( :project , :public )
user_fork = fork_project ( project , user , namespace : user . namespace )
expect ( user . fork_of ( project ) ) . to eq ( user_fork )
end
it 'returns nil if the project does not have a fork network' do
project = create ( :project )
expect ( user . fork_of ( project ) ) . to be_nil
end
end
2016-08-24 12:49:21 +05:30
describe '#can_be_removed?' do
2015-09-11 14:41:01 +05:30
subject { create ( :user ) }
context 'no owned groups' do
it { expect ( subject . can_be_removed? ) . to be_truthy }
end
context 'has owned groups' do
before do
group = create ( :group )
group . add_owner ( subject )
end
it { expect ( subject . can_be_removed? ) . to be_falsey }
end
end
2015-09-25 12:07:36 +05:30
2021-02-22 17:27:13 +05:30
describe '#solo_owned_groups' do
let_it_be_with_refind ( :user ) { create ( :user ) }
subject ( :solo_owned_groups ) { user . solo_owned_groups }
context 'no owned groups' do
it { is_expected . to be_empty }
end
context 'has owned groups' do
2022-07-16 23:28:13 +05:30
let ( :group ) { create ( :group ) }
2021-02-22 17:27:13 +05:30
before do
group . add_owner ( user )
end
context 'not solo owner' do
let_it_be ( :user2 ) { create ( :user ) }
2022-07-16 23:28:13 +05:30
context 'with another direct owner' do
before do
group . add_owner ( user2 )
end
it { is_expected . to be_empty }
2021-02-22 17:27:13 +05:30
end
2022-07-16 23:28:13 +05:30
context 'with an inherited owner' do
let_it_be ( :group ) { create ( :group , :nested ) }
before do
group . parent . add_owner ( user2 )
end
it { is_expected . to be_empty }
end
2021-02-22 17:27:13 +05:30
end
context 'solo owner' do
it { is_expected . to include ( group ) }
it 'avoids N+1 queries' do
fresh_user = User . find ( user . id )
control_count = ActiveRecord :: QueryRecorder . new do
fresh_user . solo_owned_groups
end . count
create ( :group ) . add_owner ( user )
expect { solo_owned_groups } . not_to exceed_query_limit ( control_count )
end
end
end
end
describe '#can_remove_self?' do
let ( :user ) { create ( :user ) }
it 'returns true' do
expect ( user . can_remove_self? ) . to eq true
end
end
2021-11-18 22:05:49 +05:30
describe '#recent_push' do
2018-03-17 18:26:18 +05:30
let ( :user ) { build ( :user ) }
let ( :project ) { build ( :project ) }
let ( :event ) { build ( :push_event ) }
2015-09-25 12:07:36 +05:30
2018-03-17 18:26:18 +05:30
it 'returns the last push event for the user' do
expect_any_instance_of ( Users :: LastPushEventService )
. to receive ( :last_event_for_user )
. and_return ( event )
2015-09-25 12:07:36 +05:30
2018-03-17 18:26:18 +05:30
expect ( user . recent_push ) . to eq ( event )
2015-09-25 12:07:36 +05:30
end
2016-09-13 17:45:13 +05:30
2018-03-17 18:26:18 +05:30
it 'returns the last push event for a project when one is given' do
expect_any_instance_of ( Users :: LastPushEventService )
. to receive ( :last_event_for_project )
. and_return ( event )
2016-09-13 17:45:13 +05:30
2018-03-17 18:26:18 +05:30
expect ( user . recent_push ( project ) ) . to eq ( event )
2016-09-13 17:45:13 +05:30
end
2015-09-25 12:07:36 +05:30
end
2015-11-26 14:37:03 +05:30
describe '#authorized_groups' do
let! ( :user ) { create ( :user ) }
let! ( :private_group ) { create ( :group ) }
2018-03-27 19:54:05 +05:30
let! ( :child_group ) { create ( :group , parent : private_group ) }
let! ( :project_group ) { create ( :group ) }
let! ( :project ) { create ( :project , group : project_group ) }
2015-11-26 14:37:03 +05:30
before do
2022-08-13 15:12:31 +05:30
private_group . add_member ( user , Gitlab :: Access :: MAINTAINER )
2018-11-18 11:00:15 +05:30
project . add_maintainer ( user )
2015-11-26 14:37:03 +05:30
end
subject { user . authorized_groups }
2018-03-27 19:54:05 +05:30
it { is_expected . to contain_exactly private_group , project_group }
2021-01-29 00:20:46 +05:30
context 'with shared memberships' do
let! ( :shared_group ) { create ( :group ) }
let! ( :other_group ) { create ( :group ) }
before do
create ( :group_group_link , shared_group : shared_group , shared_with_group : private_group )
create ( :group_group_link , shared_group : private_group , shared_with_group : other_group )
end
2021-04-17 20:07:23 +05:30
it { is_expected . to include shared_group }
it { is_expected . not_to include other_group }
2021-01-29 00:20:46 +05:30
end
2018-03-27 19:54:05 +05:30
end
describe '#membership_groups' do
2021-11-11 11:23:49 +05:30
let_it_be ( :user ) { create ( :user ) }
2018-03-27 19:54:05 +05:30
2021-11-11 11:23:49 +05:30
let_it_be ( :parent_group ) do
create ( :group ) . tap do | g |
2022-08-13 15:12:31 +05:30
g . add_member ( user , Gitlab :: Access :: MAINTAINER )
2021-11-11 11:23:49 +05:30
end
2018-03-27 19:54:05 +05:30
end
2021-11-11 11:23:49 +05:30
let_it_be ( :child_group ) { create ( :group , parent : parent_group ) }
let_it_be ( :other_group ) { create ( :group ) }
2018-03-27 19:54:05 +05:30
subject { user . membership_groups }
2022-01-26 12:08:38 +05:30
specify { is_expected . to contain_exactly ( parent_group , child_group ) }
2015-11-26 14:37:03 +05:30
end
2018-03-17 18:26:18 +05:30
describe '#authorizations_for_projects' do
let! ( :user ) { create ( :user ) }
2020-03-13 15:44:24 +05:30
2018-03-17 18:26:18 +05:30
subject { Project . where ( " EXISTS (?) " , user . authorizations_for_projects ) }
it 'includes projects that belong to a user, but no other projects' do
owned = create ( :project , :private , namespace : user . namespace )
2018-11-18 11:00:15 +05:30
member = create ( :project , :private ) . tap { | p | p . add_maintainer ( user ) }
2018-03-17 18:26:18 +05:30
other = create ( :project )
expect ( subject ) . to include ( owned )
expect ( subject ) . to include ( member )
expect ( subject ) . not_to include ( other )
end
it 'includes projects a user has access to, but no other projects' do
other_user = create ( :user )
accessible = create ( :project , :private , namespace : other_user . namespace ) do | project |
project . add_developer ( user )
end
other = create ( :project )
expect ( subject ) . to include ( accessible )
expect ( subject ) . not_to include ( other )
end
2019-02-15 15:39:39 +05:30
context 'with min_access_level' do
let! ( :user ) { create ( :user ) }
2022-05-07 20:08:51 +05:30
let! ( :project ) { create ( :project , :private , group : create ( :group ) ) }
2019-02-15 15:39:39 +05:30
before do
project . add_developer ( user )
end
subject { Project . where ( " EXISTS (?) " , user . authorizations_for_projects ( min_access_level : min_access_level ) ) }
context 'when developer access' do
let ( :min_access_level ) { Gitlab :: Access :: DEVELOPER }
it 'includes projects a user has access to' do
expect ( subject ) . to include ( project )
end
end
context 'when owner access' do
let ( :min_access_level ) { Gitlab :: Access :: OWNER }
it 'does not include projects with higher access level' do
expect ( subject ) . not_to include ( project )
end
end
end
2018-03-17 18:26:18 +05:30
end
describe '#authorized_projects' , :delete do
2016-08-24 12:49:21 +05:30
context 'with a minimum access level' do
it 'includes projects for which the user is an owner' do
user = create ( :user )
2017-09-10 17:25:29 +05:30
project = create ( :project , :private , namespace : user . namespace )
2015-11-26 14:37:03 +05:30
2016-08-24 12:49:21 +05:30
expect ( user . authorized_projects ( Gitlab :: Access :: REPORTER ) )
. to contain_exactly ( project )
end
2018-11-18 11:00:15 +05:30
it 'includes projects for which the user is a maintainer' do
2016-08-24 12:49:21 +05:30
user = create ( :user )
2017-09-10 17:25:29 +05:30
project = create ( :project , :private )
2015-11-26 14:37:03 +05:30
2018-11-18 11:00:15 +05:30
project . add_maintainer ( user )
2015-11-26 14:37:03 +05:30
2016-08-24 12:49:21 +05:30
expect ( user . authorized_projects ( Gitlab :: Access :: REPORTER ) )
. to contain_exactly ( project )
end
end
2017-08-17 22:00:37 +05:30
it " includes user's personal projects " do
user = create ( :user )
2017-09-10 17:25:29 +05:30
project = create ( :project , :private , namespace : user . namespace )
2017-08-17 22:00:37 +05:30
expect ( user . authorized_projects ) . to include ( project )
end
2021-11-18 22:05:49 +05:30
it 'includes personal projects user has been given access to' do
2017-08-17 22:00:37 +05:30
user1 = create ( :user )
user2 = create ( :user )
2017-09-10 17:25:29 +05:30
project = create ( :project , :private , namespace : user1 . namespace )
2017-08-17 22:00:37 +05:30
2018-03-17 18:26:18 +05:30
project . add_developer ( user2 )
2017-08-17 22:00:37 +05:30
expect ( user2 . authorized_projects ) . to include ( project )
end
2021-11-18 22:05:49 +05:30
it 'includes projects of groups user has been added to' do
2017-08-17 22:00:37 +05:30
group = create ( :group )
2017-09-10 17:25:29 +05:30
project = create ( :project , group : group )
2017-08-17 22:00:37 +05:30
user = create ( :user )
group . add_developer ( user )
expect ( user . authorized_projects ) . to include ( project )
end
2021-11-18 22:05:49 +05:30
it 'does not include projects of groups user has been removed from' , :sidekiq_inline do
2017-08-17 22:00:37 +05:30
group = create ( :group )
2017-09-10 17:25:29 +05:30
project = create ( :project , group : group )
2017-08-17 22:00:37 +05:30
user = create ( :user )
member = group . add_developer ( user )
2018-03-17 18:26:18 +05:30
2017-08-17 22:00:37 +05:30
expect ( user . authorized_projects ) . to include ( project )
2021-06-08 01:23:25 +05:30
member . destroy!
2018-03-17 18:26:18 +05:30
2017-08-17 22:00:37 +05:30
expect ( user . authorized_projects ) . not_to include ( project )
end
it " includes projects shared with user's group " do
user = create ( :user )
2017-09-10 17:25:29 +05:30
project = create ( :project , :private )
2020-06-23 00:09:42 +05:30
group = create ( :group ) do | group |
group . add_reporter ( user )
end
create ( :project_group_link , group : group , project : project )
2017-08-17 22:00:37 +05:30
expect ( user . authorized_projects ) . to include ( project )
end
2021-11-18 22:05:49 +05:30
it 'does not include destroyed projects user had access to' do
2017-08-17 22:00:37 +05:30
user1 = create ( :user )
user2 = create ( :user )
2017-09-10 17:25:29 +05:30
project = create ( :project , :private , namespace : user1 . namespace )
2017-08-17 22:00:37 +05:30
2018-03-17 18:26:18 +05:30
project . add_developer ( user2 )
2017-08-17 22:00:37 +05:30
expect ( user2 . authorized_projects ) . to include ( project )
2021-06-08 01:23:25 +05:30
project . destroy!
2018-03-17 18:26:18 +05:30
2017-08-17 22:00:37 +05:30
expect ( user2 . authorized_projects ) . not_to include ( project )
end
2021-11-18 22:05:49 +05:30
it 'does not include projects of destroyed groups user had access to' do
2017-08-17 22:00:37 +05:30
group = create ( :group )
2017-09-10 17:25:29 +05:30
project = create ( :project , namespace : group )
2017-08-17 22:00:37 +05:30
user = create ( :user )
group . add_developer ( user )
2018-03-17 18:26:18 +05:30
2017-08-17 22:00:37 +05:30
expect ( user . authorized_projects ) . to include ( project )
2021-06-08 01:23:25 +05:30
group . destroy!
2018-03-17 18:26:18 +05:30
2017-08-17 22:00:37 +05:30
expect ( user . authorized_projects ) . not_to include ( project )
end
2015-11-26 14:37:03 +05:30
end
2016-06-02 11:05:42 +05:30
2016-09-13 17:45:13 +05:30
describe '#projects_where_can_admin_issues' do
let ( :user ) { create ( :user ) }
it 'includes projects for which the user access level is above or equal to reporter' do
2017-09-10 17:25:29 +05:30
reporter_project = create ( :project ) { | p | p . add_reporter ( user ) }
developer_project = create ( :project ) { | p | p . add_developer ( user ) }
2018-11-18 11:00:15 +05:30
maintainer_project = create ( :project ) { | p | p . add_maintainer ( user ) }
2016-09-13 17:45:13 +05:30
2018-11-18 11:00:15 +05:30
expect ( user . projects_where_can_admin_issues . to_a ) . to match_array ( [ maintainer_project , developer_project , reporter_project ] )
expect ( user . can? ( :admin_issue , maintainer_project ) ) . to eq ( true )
2016-09-13 17:45:13 +05:30
expect ( user . can? ( :admin_issue , developer_project ) ) . to eq ( true )
expect ( user . can? ( :admin_issue , reporter_project ) ) . to eq ( true )
end
it 'does not include for which the user access level is below reporter' do
2017-09-10 17:25:29 +05:30
project = create ( :project )
guest_project = create ( :project ) { | p | p . add_guest ( user ) }
2016-09-13 17:45:13 +05:30
expect ( user . projects_where_can_admin_issues . to_a ) . to be_empty
expect ( user . can? ( :admin_issue , guest_project ) ) . to eq ( false )
expect ( user . can? ( :admin_issue , project ) ) . to eq ( false )
end
it 'does not include archived projects' do
2017-09-10 17:25:29 +05:30
project = create ( :project , :archived )
2016-09-13 17:45:13 +05:30
expect ( user . projects_where_can_admin_issues . to_a ) . to be_empty
expect ( user . can? ( :admin_issue , project ) ) . to eq ( false )
end
it 'does not include projects for which issues are disabled' do
2017-09-10 17:25:29 +05:30
project = create ( :project , :issues_disabled )
2016-09-13 17:45:13 +05:30
expect ( user . projects_where_can_admin_issues . to_a ) . to be_empty
expect ( user . can? ( :admin_issue , project ) ) . to eq ( false )
end
end
2022-07-01 11:34:44 +05:30
describe '#authorized_project_mirrors' do
it 'returns project mirrors where the user has access equal to or above the given level' do
guest_project = create ( :project )
reporter_project = create ( :project )
maintainer_project = create ( :project )
guest_group = create ( :group )
reporter_group = create ( :group )
maintainer_group = create ( :group )
_guest_group_project = create ( :project , group : guest_group )
reporter_group_project = create ( :project , group : reporter_group )
maintainer_group_project = create ( :project , group : maintainer_group )
user = create ( :user )
guest_project . add_guest ( user )
reporter_project . add_reporter ( user )
maintainer_project . add_maintainer ( user )
guest_group . add_guest ( user )
reporter_group . add_reporter ( user )
maintainer_group . add_maintainer ( user )
project_mirrors = user . authorized_project_mirrors ( Gitlab :: Access :: REPORTER )
expect ( project_mirrors . pluck ( :project_id ) ) . to contain_exactly (
reporter_group_project . id ,
maintainer_group_project . id ,
reporter_project . id ,
maintainer_project . id
)
end
end
2022-03-02 08:16:31 +05:30
shared_context '#ci_owned_runners' do
2016-06-16 23:09:34 +05:30
let ( :user ) { create ( :user ) }
2020-04-22 19:07:51 +05:30
shared_examples :nested_groups_owner do
context 'when the user is the owner of a multi-level group' do
before do
set_permissions_for_users
end
it 'loads all the runners in the tree of groups' do
expect ( user . ci_owned_runners ) . to contain_exactly ( runner , group_runner )
end
2021-11-11 11:23:49 +05:30
it 'returns true for owns_runner?' do
expect ( user . owns_runner? ( runner ) ) . to eq ( true )
expect ( user . owns_runner? ( group_runner ) ) . to eq ( true )
end
2018-11-08 19:23:39 +05:30
end
2016-06-16 23:09:34 +05:30
end
2020-04-22 19:07:51 +05:30
shared_examples :group_owner do
context 'when the user is the owner of a one level group' do
before do
group . add_owner ( user )
end
2016-06-16 23:09:34 +05:30
2020-04-22 19:07:51 +05:30
it 'loads the runners in the group' do
expect ( user . ci_owned_runners ) . to contain_exactly ( group_runner )
end
2021-11-11 11:23:49 +05:30
it 'returns true for owns_runner?' do
expect ( user . owns_runner? ( group_runner ) ) . to eq ( true )
end
2016-06-16 23:09:34 +05:30
end
end
2020-04-22 19:07:51 +05:30
shared_examples :project_owner do
context 'when the user is the owner of a project' do
it 'loads the runner belonging to the project' do
expect ( user . ci_owned_runners ) . to contain_exactly ( runner )
2018-11-08 19:23:39 +05:30
end
2021-11-11 11:23:49 +05:30
it 'returns true for owns_runner?' do
expect ( user . owns_runner? ( runner ) ) . to eq ( true )
end
2018-11-08 19:23:39 +05:30
end
2020-04-22 19:07:51 +05:30
end
2018-11-08 19:23:39 +05:30
2020-04-22 19:07:51 +05:30
shared_examples :project_member do
context 'when the user is a maintainer' do
before do
add_user ( :maintainer )
end
it 'loads the runners of the project' do
expect ( user . ci_owned_runners ) . to contain_exactly ( project_runner )
end
2021-11-11 11:23:49 +05:30
it 'returns true for owns_runner?' do
expect ( user . owns_runner? ( project_runner ) ) . to eq ( true )
end
2018-11-08 19:23:39 +05:30
end
2020-04-22 19:07:51 +05:30
context 'when the user is a developer' do
before do
add_user ( :developer )
end
2018-11-08 19:23:39 +05:30
2020-04-22 19:07:51 +05:30
it 'does not load any runner' do
expect ( user . ci_owned_runners ) . to be_empty
2018-11-08 19:23:39 +05:30
end
2021-11-11 11:23:49 +05:30
it 'returns false for owns_runner?' do
expect ( user . owns_runner? ( project_runner ) ) . to eq ( false )
end
2018-11-08 19:23:39 +05:30
end
2016-06-16 23:09:34 +05:30
2020-04-22 19:07:51 +05:30
context 'when the user is a reporter' do
before do
add_user ( :reporter )
end
it 'does not load any runner' do
expect ( user . ci_owned_runners ) . to be_empty
end
2021-11-11 11:23:49 +05:30
it 'returns false for owns_runner?' do
expect ( user . owns_runner? ( project_runner ) ) . to eq ( false )
end
2020-04-22 19:07:51 +05:30
end
context 'when the user is a guest' do
before do
add_user ( :guest )
end
it 'does not load any runner' do
expect ( user . ci_owned_runners ) . to be_empty
end
2021-11-11 11:23:49 +05:30
it 'returns false for owns_runner?' do
expect ( user . owns_runner? ( project_runner ) ) . to eq ( false )
end
2016-06-16 23:09:34 +05:30
end
end
2020-04-22 19:07:51 +05:30
shared_examples :group_member do
2018-11-18 11:00:15 +05:30
context 'when the user is a maintainer' do
2016-06-16 23:09:34 +05:30
before do
2018-11-18 11:00:15 +05:30
add_user ( :maintainer )
2016-06-16 23:09:34 +05:30
end
2020-04-22 19:07:51 +05:30
it 'does not load the runners of the group' do
2020-01-03 18:37:03 +05:30
expect ( user . ci_owned_runners ) . to be_empty
2016-06-16 23:09:34 +05:30
end
2021-11-11 11:23:49 +05:30
it 'returns false for owns_runner?' do
expect ( user . owns_runner? ( runner ) ) . to eq ( false )
end
2016-06-16 23:09:34 +05:30
end
context 'when the user is a developer' do
before do
2018-03-17 18:26:18 +05:30
add_user ( :developer )
2016-06-16 23:09:34 +05:30
end
2020-04-22 19:07:51 +05:30
it 'does not load any runner' do
2018-11-08 19:23:39 +05:30
expect ( user . ci_owned_runners ) . to be_empty
2016-06-16 23:09:34 +05:30
end
2021-11-11 11:23:49 +05:30
it 'returns false for owns_runner?' do
expect ( user . owns_runner? ( runner ) ) . to eq ( false )
end
2016-06-16 23:09:34 +05:30
end
2020-04-22 19:07:51 +05:30
context 'when the user is a reporter' do
2020-01-03 18:37:03 +05:30
before do
2020-04-22 19:07:51 +05:30
add_user ( :reporter )
2020-01-03 18:37:03 +05:30
end
2020-04-22 19:07:51 +05:30
it 'does not load any runner' do
expect ( user . ci_owned_runners ) . to be_empty
2020-01-03 18:37:03 +05:30
end
2021-11-11 11:23:49 +05:30
it 'returns false for owns_runner?' do
expect ( user . owns_runner? ( runner ) ) . to eq ( false )
end
2020-01-03 18:37:03 +05:30
end
2020-04-22 19:07:51 +05:30
context 'when the user is a guest' do
before do
add_user ( :guest )
end
it 'does not load any runner' do
expect ( user . ci_owned_runners ) . to be_empty
end
2021-11-11 11:23:49 +05:30
it 'returns false for owns_runner?' do
expect ( user . owns_runner? ( runner ) ) . to eq ( false )
end
2020-04-22 19:07:51 +05:30
end
2020-01-03 18:37:03 +05:30
end
2020-04-22 19:07:51 +05:30
context 'without any projects nor groups' do
it 'does not load any runner' do
expect ( user . ci_owned_runners ) . to be_empty
end
2021-11-11 11:23:49 +05:30
it 'returns false for owns_runner?' do
expect ( user . owns_runner? ( create ( :ci_runner ) ) ) . to eq ( false )
end
2020-04-22 19:07:51 +05:30
end
context 'with runner in a personal project' do
2021-11-18 22:05:49 +05:30
let! ( :namespace ) { create ( :user_namespace , owner : user ) }
2020-04-22 19:07:51 +05:30
let! ( :project ) { create ( :project , namespace : namespace ) }
let! ( :runner ) { create ( :ci_runner , :project , projects : [ project ] ) }
it_behaves_like :project_owner
end
context 'with group runner in a non owned group' do
let! ( :group ) { create ( :group ) }
let! ( :runner ) { create ( :ci_runner , :group , groups : [ group ] ) }
2018-11-08 19:23:39 +05:30
def add_user ( access )
2022-08-13 15:12:31 +05:30
group . add_member ( user , access )
2018-11-08 19:23:39 +05:30
end
2020-01-03 18:37:03 +05:30
it_behaves_like :group_member
2018-11-08 19:23:39 +05:30
end
2020-04-22 19:07:51 +05:30
context 'with group runner in an owned group' do
let! ( :group ) { create ( :group ) }
let! ( :group_runner ) { create ( :ci_runner , :group , groups : [ group ] ) }
it_behaves_like :group_owner
end
context 'with group runner in an owned group and group runner in a different owner subgroup' do
let! ( :group ) { create ( :group ) }
2018-11-08 19:23:39 +05:30
let! ( :runner ) { create ( :ci_runner , :group , groups : [ group ] ) }
2020-04-22 19:07:51 +05:30
let! ( :subgroup ) { create ( :group , parent : group ) }
let! ( :group_runner ) { create ( :ci_runner , :group , groups : [ subgroup ] ) }
let! ( :another_user ) { create ( :user ) }
def set_permissions_for_users
group . add_owner ( user )
subgroup . add_owner ( another_user )
end
it_behaves_like :nested_groups_owner
end
context 'with personal project runner in an an owned group and a group runner in that same group' do
2018-11-08 19:23:39 +05:30
let! ( :group ) { create ( :group ) }
2020-04-22 19:07:51 +05:30
let! ( :group_runner ) { create ( :ci_runner , :group , groups : [ group ] ) }
let! ( :project ) { create ( :project , group : group ) }
let! ( :runner ) { create ( :ci_runner , :project , projects : [ project ] ) }
2016-06-16 23:09:34 +05:30
2020-04-22 19:07:51 +05:30
def set_permissions_for_users
group . add_owner ( user )
2016-06-16 23:09:34 +05:30
end
2020-04-22 19:07:51 +05:30
it_behaves_like :nested_groups_owner
2016-06-16 23:09:34 +05:30
end
2020-04-22 19:07:51 +05:30
context 'with personal project runner in an owned group and a group runner in a subgroup' do
let! ( :group ) { create ( :group ) }
let! ( :subgroup ) { create ( :group , parent : group ) }
let! ( :group_runner ) { create ( :ci_runner , :group , groups : [ subgroup ] ) }
let! ( :project ) { create ( :project , group : group ) }
let! ( :runner ) { create ( :ci_runner , :project , projects : [ project ] ) }
def set_permissions_for_users
group . add_owner ( user )
end
it_behaves_like :nested_groups_owner
end
context 'with personal project runner in an owned group in an owned namespace and a group runner in that group' do
2021-11-18 22:05:49 +05:30
let! ( :namespace ) { create ( :user_namespace , owner : user ) }
2020-04-22 19:07:51 +05:30
let! ( :group ) { create ( :group ) }
let! ( :group_runner ) { create ( :ci_runner , :group , groups : [ group ] ) }
let! ( :project ) { create ( :project , namespace : namespace , group : group ) }
let! ( :runner ) { create ( :ci_runner , :project , projects : [ project ] ) }
def set_permissions_for_users
group . add_owner ( user )
end
it_behaves_like :nested_groups_owner
end
context 'with personal project runner in an owned namespace, an owned group, a subgroup and a group runner in that subgroup' do
2021-11-18 22:05:49 +05:30
let! ( :namespace ) { create ( :user_namespace , owner : user ) }
2020-04-22 19:07:51 +05:30
let! ( :group ) { create ( :group ) }
let! ( :subgroup ) { create ( :group , parent : group ) }
let! ( :group_runner ) { create ( :ci_runner , :group , groups : [ subgroup ] ) }
let! ( :project ) { create ( :project , namespace : namespace , group : group ) }
let! ( :runner ) { create ( :ci_runner , :project , projects : [ project ] ) }
def set_permissions_for_users
group . add_owner ( user )
end
it_behaves_like :nested_groups_owner
end
context 'with a project runner that belong to projects that belong to a not owned group' do
let! ( :group ) { create ( :group ) }
let! ( :project ) { create ( :project , group : group ) }
let! ( :project_runner ) { create ( :ci_runner , :project , projects : [ project ] ) }
2016-06-16 23:09:34 +05:30
def add_user ( access )
2022-08-13 15:12:31 +05:30
project . add_member ( user , access )
2016-06-16 23:09:34 +05:30
end
2020-04-22 19:07:51 +05:30
it_behaves_like :project_member
2016-06-16 23:09:34 +05:30
end
2018-10-15 14:42:47 +05:30
2020-04-22 19:07:51 +05:30
context 'with project runners that belong to projects that do not belong to any group' do
let! ( :project ) { create ( :project ) }
let! ( :runner ) { create ( :ci_runner , :project , projects : [ project ] ) }
it 'does not load any runner' do
expect ( user . ci_owned_runners ) . to be_empty
end
end
context 'with a group runner that belongs to a subgroup of a group owned by another user' do
let! ( :group ) { create ( :group ) }
let! ( :subgroup ) { create ( :group , parent : group ) }
let! ( :runner ) { create ( :ci_runner , :group , groups : [ subgroup ] ) }
let! ( :another_user ) { create ( :user ) }
2018-10-15 14:42:47 +05:30
def add_user ( access )
2022-08-13 15:12:31 +05:30
subgroup . add_member ( user , access )
group . add_member ( another_user , :owner )
2018-10-15 14:42:47 +05:30
end
2020-01-03 18:37:03 +05:30
it_behaves_like :group_member
2018-10-15 14:42:47 +05:30
end
2016-06-16 23:09:34 +05:30
end
2022-06-21 17:19:12 +05:30
describe '#ci_owned_runners' do
it_behaves_like '#ci_owned_runners'
2022-03-02 08:16:31 +05:30
2022-06-21 17:19:12 +05:30
context 'when FF use_traversal_ids is disabled fallbacks to inefficient implementation' do
before do
stub_feature_flags ( use_traversal_ids : false )
end
2022-04-04 11:22:00 +05:30
2022-06-21 17:19:12 +05:30
it_behaves_like '#ci_owned_runners'
2022-03-02 08:16:31 +05:30
end
end
2017-08-17 22:00:37 +05:30
describe '#projects_with_reporter_access_limited_to' do
2017-09-10 17:25:29 +05:30
let ( :project1 ) { create ( :project ) }
let ( :project2 ) { create ( :project ) }
2017-08-17 22:00:37 +05:30
let ( :user ) { create ( :user ) }
before do
2018-03-17 18:26:18 +05:30
project1 . add_reporter ( user )
project2 . add_guest ( user )
2017-08-17 22:00:37 +05:30
end
it 'returns the projects when using a single project ID' do
projects = user . projects_with_reporter_access_limited_to ( project1 . id )
expect ( projects ) . to eq ( [ project1 ] )
end
it 'returns the projects when using an Array of project IDs' do
projects = user . projects_with_reporter_access_limited_to ( [ project1 . id ] )
expect ( projects ) . to eq ( [ project1 ] )
end
it 'returns the projects when using an ActiveRecord relation' do
2017-09-10 17:25:29 +05:30
projects = user
. projects_with_reporter_access_limited_to ( Project . select ( :id ) )
2017-08-17 22:00:37 +05:30
expect ( projects ) . to eq ( [ project1 ] )
end
it 'does not return projects you do not have reporter access to' do
projects = user . projects_with_reporter_access_limited_to ( project2 . id )
expect ( projects ) . to be_empty
end
end
2017-09-10 17:25:29 +05:30
describe '#all_expanded_groups' do
# foo/bar would also match foo/barbaz instead of just foo/bar and foo/bar/baz
2017-08-17 22:00:37 +05:30
let! ( :user ) { create ( :user ) }
2017-09-10 17:25:29 +05:30
# group
# _______ (foo) _______
# | |
# | |
# nested_group_1 nested_group_2
# (bar) (barbaz)
# | |
# | |
# nested_group_1_1 nested_group_2_1
# (baz) (baz)
#
let! ( :group ) { create :group }
let! ( :nested_group_1 ) { create :group , parent : group , name : 'bar' }
let! ( :nested_group_1_1 ) { create :group , parent : nested_group_1 , name : 'baz' }
let! ( :nested_group_2 ) { create :group , parent : group , name : 'barbaz' }
let! ( :nested_group_2_1 ) { create :group , parent : nested_group_2 , name : 'baz' }
subject { user . all_expanded_groups }
2017-08-17 22:00:37 +05:30
2017-09-10 17:25:29 +05:30
context 'user is not a member of any group' do
it 'returns an empty array' do
is_expected . to eq ( [ ] )
end
2017-08-17 22:00:37 +05:30
end
2017-09-10 17:25:29 +05:30
context 'user is member of all groups' do
before do
2019-02-15 15:39:39 +05:30
group . add_reporter ( user )
nested_group_1 . add_developer ( user )
nested_group_1_1 . add_maintainer ( user )
nested_group_2 . add_developer ( user )
nested_group_2_1 . add_maintainer ( user )
2017-09-10 17:25:29 +05:30
end
2017-08-17 22:00:37 +05:30
2017-09-10 17:25:29 +05:30
it 'returns all groups' do
is_expected . to match_array [
group ,
nested_group_1 , nested_group_1_1 ,
nested_group_2 , nested_group_2_1
]
end
end
2017-08-17 22:00:37 +05:30
2017-09-10 17:25:29 +05:30
context 'user is member of the top group' do
before do
group . add_owner ( user )
end
2017-08-17 22:00:37 +05:30
2019-10-12 21:52:04 +05:30
it 'returns all groups' do
is_expected . to match_array [
group ,
nested_group_1 , nested_group_1_1 ,
nested_group_2 , nested_group_2_1
]
2017-09-10 17:25:29 +05:30
end
end
2017-08-17 22:00:37 +05:30
2019-10-12 21:52:04 +05:30
context 'user is member of the first child (internal node), branch 1' do
2017-09-10 17:25:29 +05:30
before do
nested_group_1 . add_owner ( user )
end
2017-08-17 22:00:37 +05:30
2017-09-10 17:25:29 +05:30
it 'returns the groups in the hierarchy' do
is_expected . to match_array [
group ,
nested_group_1 , nested_group_1_1
]
end
end
2019-10-12 21:52:04 +05:30
context 'user is member of the first child (internal node), branch 2' do
2017-09-10 17:25:29 +05:30
before do
nested_group_2 . add_owner ( user )
end
2017-08-17 22:00:37 +05:30
2017-09-10 17:25:29 +05:30
it 'returns the groups in the hierarchy' do
is_expected . to match_array [
group ,
nested_group_2 , nested_group_2_1
]
end
2017-08-17 22:00:37 +05:30
end
2019-10-12 21:52:04 +05:30
context 'user is member of the last child (leaf node)' do
2017-09-10 17:25:29 +05:30
before do
nested_group_1_1 . add_owner ( user )
end
it 'returns the groups in the hierarchy' do
is_expected . to match_array [
group ,
nested_group_1 , nested_group_1_1
]
end
end
2021-10-27 15:23:28 +05:30
context 'when the user is not saved' do
let ( :user ) { build ( :user ) }
it 'returns empty when there are no groups or ancestor groups for the user' do
is_expected . to eq ( [ ] )
end
end
2017-08-17 22:00:37 +05:30
end
2018-03-17 18:26:18 +05:30
describe '#refresh_authorized_projects' , :clean_gitlab_redis_shared_state do
2017-09-10 17:25:29 +05:30
let ( :project1 ) { create ( :project ) }
let ( :project2 ) { create ( :project ) }
2017-08-17 22:00:37 +05:30
let ( :user ) { create ( :user ) }
before do
2018-03-17 18:26:18 +05:30
project1 . add_reporter ( user )
project2 . add_guest ( user )
2017-08-17 22:00:37 +05:30
user . project_authorizations . delete_all
user . refresh_authorized_projects
end
it 'refreshes the list of authorized projects' do
expect ( user . project_authorizations . count ) . to eq ( 2 )
end
it 'stores the correct access levels' do
expect ( user . project_authorizations . where ( access_level : Gitlab :: Access :: GUEST ) . exists? ) . to eq ( true )
expect ( user . project_authorizations . where ( access_level : Gitlab :: Access :: REPORTER ) . exists? ) . to eq ( true )
end
end
describe '#access_level=' do
let ( :user ) { build ( :user ) }
it 'does nothing for an invalid access level' do
user . access_level = :invalid_access_level
expect ( user . access_level ) . to eq ( :regular )
expect ( user . admin ) . to be false
end
it " assigns the 'admin' access level " do
user . access_level = :admin
expect ( user . access_level ) . to eq ( :admin )
expect ( user . admin ) . to be true
end
it " doesn't clear existing access levels when an invalid access level is passed in " do
user . access_level = :admin
user . access_level = :invalid_access_level
expect ( user . access_level ) . to eq ( :admin )
expect ( user . admin ) . to be true
end
2021-11-18 22:05:49 +05:30
it 'accepts string values in addition to symbols' do
2017-08-17 22:00:37 +05:30
user . access_level = 'admin'
expect ( user . access_level ) . to eq ( :admin )
expect ( user . admin ) . to be true
end
end
2020-03-13 15:44:24 +05:30
describe '#can_read_all_resources?' , :request_store do
2017-09-10 17:25:29 +05:30
it 'returns false for regular user' do
2020-03-13 15:44:24 +05:30
user = build_stubbed ( :user )
2017-09-10 17:25:29 +05:30
2020-01-01 13:55:28 +05:30
expect ( user . can_read_all_resources? ) . to be_falsy
2017-09-10 17:25:29 +05:30
end
2019-12-26 22:10:19 +05:30
context 'for admin user' do
include_context 'custom session'
2017-09-10 17:25:29 +05:30
2020-03-13 15:44:24 +05:30
let ( :user ) { build_stubbed ( :user , :admin ) }
2019-12-26 22:10:19 +05:30
context 'when admin mode is disabled' do
it 'returns false' do
2020-01-01 13:55:28 +05:30
expect ( user . can_read_all_resources? ) . to be_falsy
2019-12-26 22:10:19 +05:30
end
end
context 'when admin mode is enabled' do
before do
2020-01-01 13:55:28 +05:30
Gitlab :: Auth :: CurrentUserMode . new ( user ) . request_admin_mode!
2019-12-26 22:10:19 +05:30
Gitlab :: Auth :: CurrentUserMode . new ( user ) . enable_admin_mode! ( password : user . password )
end
it 'returns true' do
2020-01-01 13:55:28 +05:30
expect ( user . can_read_all_resources? ) . to be_truthy
2019-12-26 22:10:19 +05:30
end
end
2017-09-10 17:25:29 +05:30
end
end
2021-04-17 20:07:23 +05:30
describe '#can_admin_all_resources?' , :request_store do
it 'returns false for regular user' do
user = build_stubbed ( :user )
expect ( user . can_admin_all_resources? ) . to be_falsy
end
context 'for admin user' do
include_context 'custom session'
let ( :user ) { build_stubbed ( :user , :admin ) }
context 'when admin mode is disabled' do
it 'returns false' do
expect ( user . can_admin_all_resources? ) . to be_falsy
end
end
context 'when admin mode is enabled' do
before do
Gitlab :: Auth :: CurrentUserMode . new ( user ) . request_admin_mode!
Gitlab :: Auth :: CurrentUserMode . new ( user ) . enable_admin_mode! ( password : user . password )
end
it 'returns true' do
expect ( user . can_admin_all_resources? ) . to be_truthy
end
end
end
end
2017-08-17 22:00:37 +05:30
describe '.ghost' do
it " creates a ghost user if one isn't already present " do
2017-09-10 17:25:29 +05:30
ghost = described_class . ghost
2017-08-17 22:00:37 +05:30
expect ( ghost ) . to be_ghost
expect ( ghost ) . to be_persisted
2018-05-09 12:01:36 +05:30
expect ( ghost . namespace ) . not_to be_nil
expect ( ghost . namespace ) . to be_persisted
2020-04-22 19:07:51 +05:30
expect ( ghost . user_type ) . to eq 'ghost'
2017-08-17 22:00:37 +05:30
end
2021-11-18 22:05:49 +05:30
it 'does not create a second ghost user if one is already present' do
2017-08-17 22:00:37 +05:30
expect do
2017-09-10 17:25:29 +05:30
described_class . ghost
described_class . ghost
end . to change { described_class . count } . by ( 1 )
expect ( described_class . ghost ) . to eq ( described_class . ghost )
2017-08-17 22:00:37 +05:30
end
context " when a regular user exists with the username 'ghost' " do
2021-11-18 22:05:49 +05:30
it 'creates a ghost user with a non-conflicting username' do
2017-08-17 22:00:37 +05:30
create ( :user , username : 'ghost' )
2017-09-10 17:25:29 +05:30
ghost = described_class . ghost
2017-08-17 22:00:37 +05:30
expect ( ghost ) . to be_persisted
expect ( ghost . username ) . to eq ( 'ghost1' )
end
end
context " when a regular user exists with the email 'ghost@example.com' " do
2021-11-18 22:05:49 +05:30
it 'creates a ghost user with a non-conflicting email' do
2017-08-17 22:00:37 +05:30
create ( :user , email : 'ghost@example.com' )
2017-09-10 17:25:29 +05:30
ghost = described_class . ghost
2017-08-17 22:00:37 +05:30
expect ( ghost ) . to be_persisted
expect ( ghost . email ) . to eq ( 'ghost1@example.com' )
end
end
2021-01-29 00:20:46 +05:30
context 'when a domain allowlist is in place' do
2017-08-17 22:00:37 +05:30
before do
2021-01-29 00:20:46 +05:30
stub_application_setting ( domain_allowlist : [ 'gitlab.com' ] )
2017-08-17 22:00:37 +05:30
end
it 'creates a ghost user' do
2017-09-10 17:25:29 +05:30
expect ( described_class . ghost ) . to be_persisted
2017-08-17 22:00:37 +05:30
end
end
end
describe '#update_two_factor_requirement' do
let ( :user ) { create :user }
context 'with 2FA requirement on groups' do
let ( :group1 ) { create :group , require_two_factor_authentication : true , two_factor_grace_period : 23 }
let ( :group2 ) { create :group , require_two_factor_authentication : true , two_factor_grace_period : 32 }
before do
2022-08-13 15:12:31 +05:30
group1 . add_member ( user , GroupMember :: OWNER )
group2 . add_member ( user , GroupMember :: OWNER )
2017-08-17 22:00:37 +05:30
user . update_two_factor_requirement
end
it 'requires 2FA' do
expect ( user . require_two_factor_authentication_from_group ) . to be true
end
it 'uses the shortest grace period' do
expect ( user . two_factor_grace_period ) . to be 23
end
end
2019-10-12 21:52:04 +05:30
context 'with 2FA requirement from expanded groups' do
2017-08-17 22:00:37 +05:30
let! ( :group1 ) { create :group , require_two_factor_authentication : true }
2019-09-04 21:01:54 +05:30
let! ( :group1a ) { create :group , parent : group1 }
2017-08-17 22:00:37 +05:30
before do
2022-08-13 15:12:31 +05:30
group1a . add_member ( user , GroupMember :: OWNER )
2017-08-17 22:00:37 +05:30
user . update_two_factor_requirement
end
it 'requires 2FA' do
expect ( user . require_two_factor_authentication_from_group ) . to be true
end
end
2019-10-12 21:52:04 +05:30
context 'with 2FA requirement on nested child group' do
2017-08-17 22:00:37 +05:30
let! ( :group1 ) { create :group , require_two_factor_authentication : false }
let! ( :group1a ) { create :group , require_two_factor_authentication : true , parent : group1 }
before do
2022-08-13 15:12:31 +05:30
group1 . add_member ( user , GroupMember :: OWNER )
2017-08-17 22:00:37 +05:30
user . update_two_factor_requirement
end
it 'requires 2FA' do
expect ( user . require_two_factor_authentication_from_group ) . to be true
end
end
2019-09-04 21:01:54 +05:30
context " with 2FA requirement from shared project's group " do
let! ( :group1 ) { create :group , require_two_factor_authentication : true }
let! ( :group2 ) { create :group }
let ( :shared_project ) { create ( :project , namespace : group1 ) }
before do
shared_project . project_group_links . create! (
group : group2 ,
group_access : ProjectGroupLink . default_access
)
2022-08-13 15:12:31 +05:30
group2 . add_member ( user , GroupMember :: OWNER )
2019-09-04 21:01:54 +05:30
end
it 'does not require 2FA' do
user . update_two_factor_requirement
expect ( user . require_two_factor_authentication_from_group ) . to be false
end
end
2017-08-17 22:00:37 +05:30
context 'without 2FA requirement on groups' do
let ( :group ) { create :group }
before do
2022-08-13 15:12:31 +05:30
group . add_member ( user , GroupMember :: OWNER )
2017-08-17 22:00:37 +05:30
user . update_two_factor_requirement
end
it 'does not require 2FA' do
expect ( user . require_two_factor_authentication_from_group ) . to be false
end
it 'falls back to the default grace period' do
expect ( user . two_factor_grace_period ) . to be 48
end
end
2021-10-27 15:23:28 +05:30
context 'when the user is not saved' do
let ( :user ) { build ( :user ) }
it 'does not raise an ActiveRecord::StatementInvalid statement exception' do
expect { user . update_two_factor_requirement } . not_to raise_error
end
end
2017-08-17 22:00:37 +05:30
end
2020-09-03 11:15:55 +05:30
describe '#source_groups_of_two_factor_authentication_requirement' do
let_it_be ( :group_not_requiring_2FA ) { create :group }
2021-09-30 23:02:18 +05:30
2020-09-03 11:15:55 +05:30
let ( :user ) { create :user }
before do
2022-08-13 15:12:31 +05:30
group . add_member ( user , GroupMember :: OWNER )
group_not_requiring_2FA . add_member ( user , GroupMember :: OWNER )
2020-09-03 11:15:55 +05:30
end
context 'when user is direct member of group requiring 2FA' do
let_it_be ( :group ) { create :group , require_two_factor_authentication : true }
it 'returns group requiring 2FA' do
expect ( user . source_groups_of_two_factor_authentication_requirement ) . to contain_exactly ( group )
end
end
context 'when user is member of group which parent requires 2FA' do
let_it_be ( :parent_group ) { create :group , require_two_factor_authentication : true }
let_it_be ( :group ) { create :group , parent : parent_group }
it 'returns group requiring 2FA' do
expect ( user . source_groups_of_two_factor_authentication_requirement ) . to contain_exactly ( group )
end
end
context 'when user is member of group which child requires 2FA' do
let_it_be ( :group ) { create :group }
let_it_be ( :child_group ) { create :group , require_two_factor_authentication : true , parent : group }
it 'returns group requiring 2FA' do
expect ( user . source_groups_of_two_factor_authentication_requirement ) . to contain_exactly ( group )
end
end
end
2020-03-13 15:44:24 +05:30
describe '.active' do
2017-08-17 22:00:37 +05:30
before do
2017-09-10 17:25:29 +05:30
described_class . ghost
2017-08-17 22:00:37 +05:30
create ( :user , name : 'user' , state : 'active' )
create ( :user , name : 'user' , state : 'blocked' )
end
it 'only counts active and non internal users' do
2017-09-10 17:25:29 +05:30
expect ( described_class . active . count ) . to eq ( 1 )
2017-08-17 22:00:37 +05:30
end
end
describe 'preferred language' do
it 'is English by default' do
user = create ( :user )
expect ( user . preferred_language ) . to eq ( 'en' )
end
end
2020-03-13 15:44:24 +05:30
describe '#invalidate_issue_cache_counts' do
2021-09-04 01:27:46 +05:30
let ( :user ) { build_stubbed ( :user ) }
2021-06-08 01:23:25 +05:30
2021-09-04 01:27:46 +05:30
it 'invalidates cache for issue counter' do
cache_mock = double
2021-06-08 01:23:25 +05:30
2021-09-04 01:27:46 +05:30
expect ( cache_mock ) . to receive ( :delete ) . with ( [ 'users' , user . id , 'assigned_open_issues_count' ] )
2021-06-08 01:23:25 +05:30
2021-09-04 01:27:46 +05:30
allow ( Rails ) . to receive ( :cache ) . and_return ( cache_mock )
2021-06-08 01:23:25 +05:30
2021-09-04 01:27:46 +05:30
user . invalidate_issue_cache_counts
2017-08-17 22:00:37 +05:30
end
end
2020-03-13 15:44:24 +05:30
describe '#invalidate_merge_request_cache_counts' do
2017-08-17 22:00:37 +05:30
let ( :user ) { build_stubbed ( :user ) }
it 'invalidates cache for Merge Request counter' do
cache_mock = double
expect ( cache_mock ) . to receive ( :delete ) . with ( [ 'users' , user . id , 'assigned_open_merge_requests_count' ] )
2021-03-08 18:12:59 +05:30
expect ( cache_mock ) . to receive ( :delete ) . with ( [ 'users' , user . id , 'review_requested_open_merge_requests_count' ] )
2017-08-17 22:00:37 +05:30
allow ( Rails ) . to receive ( :cache ) . and_return ( cache_mock )
user . invalidate_merge_request_cache_counts
end
end
2017-09-10 17:25:29 +05:30
2020-03-13 15:44:24 +05:30
describe '#invalidate_personal_projects_count' do
2018-05-09 12:01:36 +05:30
let ( :user ) { build_stubbed ( :user ) }
it 'invalidates cache for personal projects counter' do
cache_mock = double
expect ( cache_mock ) . to receive ( :delete ) . with ( [ 'users' , user . id , 'personal_projects_count' ] )
allow ( Rails ) . to receive ( :cache ) . and_return ( cache_mock )
user . invalidate_personal_projects_count
end
end
2018-03-17 18:26:18 +05:30
describe '#allow_password_authentication_for_web?' do
2017-09-10 17:25:29 +05:30
context 'regular user' do
let ( :user ) { build ( :user ) }
2018-03-17 18:26:18 +05:30
it 'returns true when password authentication is enabled for the web interface' do
expect ( user . allow_password_authentication_for_web? ) . to be_truthy
2017-09-10 17:25:29 +05:30
end
2018-03-17 18:26:18 +05:30
it 'returns false when password authentication is disabled for the web interface' do
stub_application_setting ( password_authentication_enabled_for_web : false )
2017-09-10 17:25:29 +05:30
2018-03-17 18:26:18 +05:30
expect ( user . allow_password_authentication_for_web? ) . to be_falsey
2017-09-10 17:25:29 +05:30
end
end
it 'returns false for ldap user' do
user = create ( :omniauth_user , provider : 'ldapmain' )
2018-03-17 18:26:18 +05:30
expect ( user . allow_password_authentication_for_web? ) . to be_falsey
end
end
describe '#allow_password_authentication_for_git?' do
context 'regular user' do
let ( :user ) { build ( :user ) }
it 'returns true when password authentication is enabled for Git' do
expect ( user . allow_password_authentication_for_git? ) . to be_truthy
end
it 'returns false when password authentication is disabled Git' do
stub_application_setting ( password_authentication_enabled_for_git : false )
expect ( user . allow_password_authentication_for_git? ) . to be_falsey
end
end
it 'returns false for ldap user' do
user = create ( :omniauth_user , provider : 'ldapmain' )
expect ( user . allow_password_authentication_for_git? ) . to be_falsey
2017-09-10 17:25:29 +05:30
end
end
2018-12-05 23:21:45 +05:30
describe '#assigned_open_merge_requests_count' do
it 'returns number of open merge requests from non-archived projects' do
user = create ( :user )
project = create ( :project , :public )
archived_project = create ( :project , :public , :archived )
2019-07-31 22:56:46 +05:30
create ( :merge_request , source_project : project , author : user , assignees : [ user ] )
create ( :merge_request , :closed , source_project : project , author : user , assignees : [ user ] )
create ( :merge_request , source_project : archived_project , author : user , assignees : [ user ] )
2018-12-05 23:21:45 +05:30
expect ( user . assigned_open_merge_requests_count ( force : true ) ) . to eq 1
end
end
2021-03-08 18:12:59 +05:30
describe '#review_requested_open_merge_requests_count' do
it 'returns number of open merge requests from non-archived projects' do
user = create ( :user )
project = create ( :project , :public )
archived_project = create ( :project , :public , :archived )
create ( :merge_request , source_project : project , author : user , reviewers : [ user ] )
create ( :merge_request , :closed , source_project : project , author : user , reviewers : [ user ] )
create ( :merge_request , source_project : archived_project , author : user , reviewers : [ user ] )
expect ( user . review_requested_open_merge_requests_count ( force : true ) ) . to eq 1
end
end
2018-12-05 23:21:45 +05:30
describe '#assigned_open_issues_count' do
it 'returns number of open issues from non-archived projects' do
user = create ( :user )
project = create ( :project , :public )
archived_project = create ( :project , :public , :archived )
create ( :issue , project : project , author : user , assignees : [ user ] )
create ( :issue , :closed , project : project , author : user , assignees : [ user ] )
create ( :issue , project : archived_project , author : user , assignees : [ user ] )
expect ( user . assigned_open_issues_count ( force : true ) ) . to eq 1
end
end
2017-09-10 17:25:29 +05:30
describe '#personal_projects_count' do
it 'returns the number of personal projects using a single query' do
user = build ( :user )
projects = double ( :projects , count : 1 )
2018-05-09 12:01:36 +05:30
expect ( user ) . to receive ( :personal_projects ) . and_return ( projects )
2017-09-10 17:25:29 +05:30
2018-05-09 12:01:36 +05:30
expect ( user . personal_projects_count ) . to eq ( 1 )
2017-09-10 17:25:29 +05:30
end
end
describe '#projects_limit_left' do
it 'returns the number of projects that can be created by the user' do
user = build ( :user )
allow ( user ) . to receive ( :projects_limit ) . and_return ( 10 )
allow ( user ) . to receive ( :personal_projects_count ) . and_return ( 5 )
expect ( user . projects_limit_left ) . to eq ( 5 )
end
end
describe '#ensure_namespace_correct' do
context 'for a new user' do
let ( :user ) { build ( :user ) }
it 'creates the namespace' do
expect ( user . namespace ) . to be_nil
2018-03-17 18:26:18 +05:30
2017-09-10 17:25:29 +05:30
user . save!
2018-03-17 18:26:18 +05:30
2017-09-10 17:25:29 +05:30
expect ( user . namespace ) . not_to be_nil
2021-11-18 22:05:49 +05:30
expect ( user . namespace ) . to be_kind_of ( Namespaces :: UserNamespace )
2017-09-10 17:25:29 +05:30
end
2020-07-28 23:09:34 +05:30
it 'creates the namespace setting' do
user . save!
expect ( user . namespace . namespace_settings ) . to be_persisted
end
2017-09-10 17:25:29 +05:30
end
context 'for an existing user' do
let ( :username ) { 'foo' }
let ( :user ) { create ( :user , username : username ) }
context 'when the user is updated' do
2019-09-30 21:07:59 +05:30
context 'when the username or name is changed' do
2017-09-10 17:25:29 +05:30
let ( :new_username ) { 'bar' }
it 'changes the namespace (just to compare to when username is not changed)' do
expect do
2021-01-03 14:25:43 +05:30
travel_to ( 1 . second . from_now ) do
2018-11-18 11:00:15 +05:30
user . update! ( username : new_username )
end
2017-09-10 17:25:29 +05:30
end . to change { user . namespace . updated_at }
end
2019-09-30 21:07:59 +05:30
it 'updates the namespace path when the username was changed' do
2018-11-18 11:00:15 +05:30
user . update! ( username : new_username )
2018-03-17 18:26:18 +05:30
2019-09-30 21:07:59 +05:30
expect ( user . namespace . path ) . to eq ( new_username )
2017-09-10 17:25:29 +05:30
end
2019-09-30 21:07:59 +05:30
it 'updates the namespace name if the name was changed' do
user . update! ( name : 'New name' )
2018-03-17 18:26:18 +05:30
2019-09-30 21:07:59 +05:30
expect ( user . namespace . name ) . to eq ( 'New name' )
end
it 'updates nested routes for the namespace if the name was changed' do
project = create ( :project , namespace : user . namespace )
user . update! ( name : 'New name' )
expect ( project . route . reload . name ) . to include ( 'New name' )
2017-09-10 17:25:29 +05:30
end
context 'when there is a validation error (namespace name taken) while updating namespace' do
2018-03-17 18:26:18 +05:30
let! ( :conflicting_namespace ) { create ( :group , path : new_username ) }
2017-09-10 17:25:29 +05:30
it 'causes the user save to fail' do
2018-11-18 11:00:15 +05:30
expect ( user . update ( username : new_username ) ) . to be_falsey
2020-01-01 13:55:28 +05:30
expect ( user . namespace . errors . messages [ :path ] . first ) . to eq ( _ ( 'has already been taken' ) )
2017-09-10 17:25:29 +05:30
end
it 'adds the namespace errors to the user' do
2021-06-08 01:23:25 +05:30
user . username = new_username
2018-03-17 18:26:18 +05:30
2021-06-08 01:23:25 +05:30
expect ( user ) . to be_invalid
expect ( user . errors [ :base ] ) . to include ( 'A user, alias, or group already exists with that username.' )
2017-09-10 17:25:29 +05:30
end
end
end
context 'when the username is not changed' do
it 'does not change the namespace' do
expect do
2018-11-18 11:00:15 +05:30
user . update! ( email : 'asdf@asdf.com' )
2017-09-10 17:25:29 +05:30
end . not_to change { user . namespace . updated_at }
end
end
end
end
end
2018-03-17 18:26:18 +05:30
2022-11-25 23:54:43 +05:30
describe '#ensure_user_detail_assigned' do
let ( :user ) { build ( :user ) }
context 'when no user detail field has been changed' do
before do
allow ( UserDetail )
. to receive ( :user_fields_changed? )
. and_return ( false )
end
it 'does not assign user details before save' do
expect ( user . user_detail )
. not_to receive ( :assign_changed_fields_from_user )
user . save!
end
end
context 'when a user detail field has been changed' do
before do
allow ( UserDetail )
. to receive ( :user_fields_changed? )
. and_return ( true )
end
it 'assigns user details before save' do
expect ( user . user_detail )
. to receive ( :assign_changed_fields_from_user )
. and_call_original
user . save!
end
end
end
2018-03-17 18:26:18 +05:30
describe '#username_changed_hook' do
context 'for a new user' do
let ( :user ) { build ( :user ) }
it 'does not trigger system hook' do
expect ( user ) . not_to receive ( :system_hook_service )
user . save!
end
end
context 'for an existing user' do
let ( :user ) { create ( :user , username : 'old-username' ) }
context 'when the username is changed' do
let ( :new_username ) { 'very-new-name' }
it 'triggers the rename system hook' do
system_hook_service = SystemHooksService . new
expect ( system_hook_service ) . to receive ( :execute_hooks_for ) . with ( user , :rename )
expect ( user ) . to receive ( :system_hook_service ) . and_return ( system_hook_service )
2018-11-18 11:00:15 +05:30
user . update! ( username : new_username )
2018-03-17 18:26:18 +05:30
end
end
context 'when the username is not changed' do
it 'does not trigger system hook' do
expect ( user ) . not_to receive ( :system_hook_service )
2018-11-18 11:00:15 +05:30
user . update! ( email : 'asdf@asdf.com' )
2018-03-17 18:26:18 +05:30
end
end
end
end
2019-09-04 21:01:54 +05:30
describe '#will_save_change_to_login?' do
let ( :user ) { create ( :user , username : 'old-username' , email : 'old-email@example.org' ) }
let ( :new_username ) { 'new-name' }
let ( :new_email ) { 'new-email@example.org' }
subject { user . will_save_change_to_login? }
context 'when the username is changed' do
before do
user . username = new_username
end
it { is_expected . to be true }
end
context 'when the email is changed' do
before do
user . email = new_email
end
it { is_expected . to be true }
end
context 'when both email and username are changed' do
before do
user . username = new_username
user . email = new_email
end
it { is_expected . to be true }
end
2021-11-18 22:05:49 +05:30
context " when email and username aren't changed " do
2019-09-04 21:01:54 +05:30
before do
user . name = 'new_name'
end
it { is_expected . to be_falsy }
end
end
2018-03-17 18:26:18 +05:30
describe '#sync_attribute?' do
let ( :user ) { described_class . new }
context 'oauth user' do
it 'returns true if name can be synced' do
stub_omniauth_setting ( sync_profile_attributes : %w( name location ) )
expect ( user . sync_attribute? ( :name ) ) . to be_truthy
end
it 'returns true if email can be synced' do
stub_omniauth_setting ( sync_profile_attributes : %w( name email ) )
expect ( user . sync_attribute? ( :email ) ) . to be_truthy
end
it 'returns true if location can be synced' do
stub_omniauth_setting ( sync_profile_attributes : %w( location email ) )
expect ( user . sync_attribute? ( :email ) ) . to be_truthy
end
it 'returns false if name can not be synced' do
stub_omniauth_setting ( sync_profile_attributes : %w( location email ) )
expect ( user . sync_attribute? ( :name ) ) . to be_falsey
end
it 'returns false if email can not be synced' do
2020-04-22 19:07:51 +05:30
stub_omniauth_setting ( sync_profile_attributes : %w( location name ) )
2018-03-17 18:26:18 +05:30
2020-04-22 19:07:51 +05:30
expect ( user . sync_attribute? ( :email ) ) . to be_falsey
2018-03-17 18:26:18 +05:30
end
it 'returns false if location can not be synced' do
2020-04-22 19:07:51 +05:30
stub_omniauth_setting ( sync_profile_attributes : %w( name email ) )
2018-03-17 18:26:18 +05:30
2020-04-22 19:07:51 +05:30
expect ( user . sync_attribute? ( :location ) ) . to be_falsey
2018-03-17 18:26:18 +05:30
end
it 'returns true for all syncable attributes if all syncable attributes can be synced' do
stub_omniauth_setting ( sync_profile_attributes : true )
expect ( user . sync_attribute? ( :name ) ) . to be_truthy
expect ( user . sync_attribute? ( :email ) ) . to be_truthy
expect ( user . sync_attribute? ( :location ) ) . to be_truthy
end
it 'returns false for all syncable attributes but email if no syncable attributes are declared' do
expect ( user . sync_attribute? ( :name ) ) . to be_falsey
expect ( user . sync_attribute? ( :email ) ) . to be_truthy
expect ( user . sync_attribute? ( :location ) ) . to be_falsey
end
end
context 'ldap user' do
it 'returns true for email if ldap user' do
allow ( user ) . to receive ( :ldap_user? ) . and_return ( true )
expect ( user . sync_attribute? ( :name ) ) . to be_falsey
expect ( user . sync_attribute? ( :email ) ) . to be_truthy
expect ( user . sync_attribute? ( :location ) ) . to be_falsey
end
it 'returns true for email and location if ldap user and location declared as syncable' do
allow ( user ) . to receive ( :ldap_user? ) . and_return ( true )
stub_omniauth_setting ( sync_profile_attributes : %w( location ) )
expect ( user . sync_attribute? ( :name ) ) . to be_falsey
expect ( user . sync_attribute? ( :email ) ) . to be_truthy
expect ( user . sync_attribute? ( :location ) ) . to be_truthy
end
end
end
describe '#confirm_deletion_with_password?' do
where (
password_automatically_set : [ true , false ] ,
ldap_user : [ true , false ] ,
password_authentication_disabled : [ true , false ]
)
with_them do
let! ( :user ) { create ( :user , password_automatically_set : password_automatically_set ) }
let! ( :identity ) { create ( :identity , user : user ) if ldap_user }
# Only confirm deletion with password if all inputs are false
let ( :expected ) { ! ( password_automatically_set || ldap_user || password_authentication_disabled ) }
before do
stub_application_setting ( password_authentication_enabled_for_web : ! password_authentication_disabled )
stub_application_setting ( password_authentication_enabled_for_git : ! password_authentication_disabled )
end
it 'returns false unless all inputs are true' do
expect ( user . confirm_deletion_with_password? ) . to eq ( expected )
end
end
end
describe '#delete_async' do
let ( :user ) { create ( :user ) }
let ( :deleted_by ) { create ( :user ) }
it 'blocks the user then schedules them for deletion if a hard delete is specified' do
2022-07-16 23:28:13 +05:30
expect ( DeleteUserWorker ) . to receive ( :perform_async ) . with ( deleted_by . id , user . id , { hard_delete : true } )
2018-03-17 18:26:18 +05:30
user . delete_async ( deleted_by : deleted_by , params : { hard_delete : true } )
expect ( user ) . to be_blocked
end
it 'schedules user for deletion without blocking them' do
expect ( DeleteUserWorker ) . to receive ( :perform_async ) . with ( deleted_by . id , user . id , { } )
user . delete_async ( deleted_by : deleted_by )
expect ( user ) . not_to be_blocked
end
end
describe '#max_member_access_for_project_ids' do
shared_examples 'max member access for projects' do
let ( :user ) { create ( :user ) }
let ( :group ) { create ( :group ) }
let ( :owner_project ) { create ( :project , group : group ) }
2018-11-18 11:00:15 +05:30
let ( :maintainer_project ) { create ( :project ) }
2018-03-17 18:26:18 +05:30
let ( :reporter_project ) { create ( :project ) }
let ( :developer_project ) { create ( :project ) }
let ( :guest_project ) { create ( :project ) }
let ( :no_access_project ) { create ( :project ) }
let ( :projects ) do
2018-11-18 11:00:15 +05:30
[ owner_project , maintainer_project , reporter_project , developer_project , guest_project , no_access_project ] . map ( & :id )
2018-03-17 18:26:18 +05:30
end
let ( :expected ) do
{
owner_project . id = > Gitlab :: Access :: OWNER ,
2018-11-18 11:00:15 +05:30
maintainer_project . id = > Gitlab :: Access :: MAINTAINER ,
2018-03-17 18:26:18 +05:30
reporter_project . id = > Gitlab :: Access :: REPORTER ,
developer_project . id = > Gitlab :: Access :: DEVELOPER ,
guest_project . id = > Gitlab :: Access :: GUEST ,
no_access_project . id = > Gitlab :: Access :: NO_ACCESS
}
end
before do
create ( :group_member , user : user , group : group )
2018-11-18 11:00:15 +05:30
maintainer_project . add_maintainer ( user )
2018-03-17 18:26:18 +05:30
reporter_project . add_reporter ( user )
developer_project . add_developer ( user )
guest_project . add_guest ( user )
end
it 'returns correct roles for different projects' do
expect ( user . max_member_access_for_project_ids ( projects ) ) . to eq ( expected )
end
end
context 'with RequestStore enabled' , :request_store do
include_examples 'max member access for projects'
def access_levels ( projects )
user . max_member_access_for_project_ids ( projects )
end
it 'does not perform extra queries when asked for projects who have already been found' do
access_levels ( projects )
expect { access_levels ( projects ) } . not_to exceed_query_limit ( 0 )
expect ( access_levels ( projects ) ) . to eq ( expected )
end
it 'only requests the extra projects when uncached projects are passed' do
2018-11-18 11:00:15 +05:30
second_maintainer_project = create ( :project )
2018-03-17 18:26:18 +05:30
second_developer_project = create ( :project )
2018-11-18 11:00:15 +05:30
second_maintainer_project . add_maintainer ( user )
2018-03-17 18:26:18 +05:30
second_developer_project . add_developer ( user )
2018-11-18 11:00:15 +05:30
all_projects = projects + [ second_maintainer_project . id , second_developer_project . id ]
2018-03-17 18:26:18 +05:30
2018-11-18 11:00:15 +05:30
expected_all = expected . merge ( second_maintainer_project . id = > Gitlab :: Access :: MAINTAINER ,
2018-03-17 18:26:18 +05:30
second_developer_project . id = > Gitlab :: Access :: DEVELOPER )
access_levels ( projects )
queries = ActiveRecord :: QueryRecorder . new { access_levels ( all_projects ) }
expect ( queries . count ) . to eq ( 1 )
2018-11-18 11:00:15 +05:30
expect ( queries . log_message ) . to match ( / \ W( #{ second_maintainer_project . id } , #{ second_developer_project . id } ) \ W / )
2018-03-17 18:26:18 +05:30
expect ( access_levels ( all_projects ) ) . to eq ( expected_all )
end
end
context 'with RequestStore disabled' do
include_examples 'max member access for projects'
end
end
describe '#max_member_access_for_group_ids' do
shared_examples 'max member access for groups' do
let ( :user ) { create ( :user ) }
let ( :owner_group ) { create ( :group ) }
2018-11-18 11:00:15 +05:30
let ( :maintainer_group ) { create ( :group ) }
2018-03-17 18:26:18 +05:30
let ( :reporter_group ) { create ( :group ) }
let ( :developer_group ) { create ( :group ) }
let ( :guest_group ) { create ( :group ) }
let ( :no_access_group ) { create ( :group ) }
let ( :groups ) do
2018-11-18 11:00:15 +05:30
[ owner_group , maintainer_group , reporter_group , developer_group , guest_group , no_access_group ] . map ( & :id )
2018-03-17 18:26:18 +05:30
end
let ( :expected ) do
{
owner_group . id = > Gitlab :: Access :: OWNER ,
2018-11-18 11:00:15 +05:30
maintainer_group . id = > Gitlab :: Access :: MAINTAINER ,
2018-03-17 18:26:18 +05:30
reporter_group . id = > Gitlab :: Access :: REPORTER ,
developer_group . id = > Gitlab :: Access :: DEVELOPER ,
guest_group . id = > Gitlab :: Access :: GUEST ,
no_access_group . id = > Gitlab :: Access :: NO_ACCESS
}
end
before do
owner_group . add_owner ( user )
2018-11-18 11:00:15 +05:30
maintainer_group . add_maintainer ( user )
2018-03-17 18:26:18 +05:30
reporter_group . add_reporter ( user )
developer_group . add_developer ( user )
guest_group . add_guest ( user )
end
it 'returns correct roles for different groups' do
expect ( user . max_member_access_for_group_ids ( groups ) ) . to eq ( expected )
end
end
context 'with RequestStore enabled' , :request_store do
include_examples 'max member access for groups'
def access_levels ( groups )
user . max_member_access_for_group_ids ( groups )
end
it 'does not perform extra queries when asked for groups who have already been found' do
access_levels ( groups )
expect { access_levels ( groups ) } . not_to exceed_query_limit ( 0 )
expect ( access_levels ( groups ) ) . to eq ( expected )
end
it 'only requests the extra groups when uncached groups are passed' do
2018-11-18 11:00:15 +05:30
second_maintainer_group = create ( :group )
2018-03-17 18:26:18 +05:30
second_developer_group = create ( :group )
2018-11-18 11:00:15 +05:30
second_maintainer_group . add_maintainer ( user )
2018-03-17 18:26:18 +05:30
second_developer_group . add_developer ( user )
2018-11-18 11:00:15 +05:30
all_groups = groups + [ second_maintainer_group . id , second_developer_group . id ]
2018-03-17 18:26:18 +05:30
2018-11-18 11:00:15 +05:30
expected_all = expected . merge ( second_maintainer_group . id = > Gitlab :: Access :: MAINTAINER ,
2018-03-17 18:26:18 +05:30
second_developer_group . id = > Gitlab :: Access :: DEVELOPER )
access_levels ( groups )
queries = ActiveRecord :: QueryRecorder . new { access_levels ( all_groups ) }
expect ( queries . count ) . to eq ( 1 )
2018-11-18 11:00:15 +05:30
expect ( queries . log_message ) . to match ( / \ W( #{ second_maintainer_group . id } , #{ second_developer_group . id } ) \ W / )
2018-03-17 18:26:18 +05:30
expect ( access_levels ( all_groups ) ) . to eq ( expected_all )
end
end
context 'with RequestStore disabled' do
include_examples 'max member access for groups'
end
end
2018-05-09 12:01:36 +05:30
context 'changing a username' do
let ( :user ) { create ( :user , username : 'foo' ) }
2018-03-17 18:26:18 +05:30
2018-05-09 12:01:36 +05:30
it 'creates a redirect route' do
expect { user . update! ( username : 'bar' ) }
. to change { RedirectRoute . where ( path : 'foo' ) . count } . by ( 1 )
2018-03-17 18:26:18 +05:30
end
2018-05-09 12:01:36 +05:30
it 'deletes the redirect when a user with the old username was created' do
user . update! ( username : 'bar' )
expect { create ( :user , username : 'foo' ) }
. to change { RedirectRoute . where ( path : 'foo' ) . count } . by ( - 1 )
2018-03-17 18:26:18 +05:30
end
end
2018-10-15 14:42:47 +05:30
describe '#required_terms_not_accepted?' do
let ( :user ) { build ( :user ) }
2021-01-03 14:25:43 +05:30
let ( :project_bot ) { create ( :user , :project_bot ) }
2020-03-13 15:44:24 +05:30
2018-10-15 14:42:47 +05:30
subject { user . required_terms_not_accepted? }
2021-11-18 22:05:49 +05:30
context 'when terms are not enforced' do
2021-01-03 14:25:43 +05:30
it { is_expected . to be_falsey }
2018-10-15 14:42:47 +05:30
end
2021-11-18 22:05:49 +05:30
context 'when terms are enforced' do
2018-10-15 14:42:47 +05:30
before do
enforce_terms
end
2021-11-18 22:05:49 +05:30
it 'is not accepted by the user' do
2021-01-03 14:25:43 +05:30
expect ( subject ) . to be_truthy
end
2018-10-15 14:42:47 +05:30
2021-11-18 22:05:49 +05:30
it 'is accepted by the user' do
2021-01-03 14:25:43 +05:30
accept_terms ( user )
expect ( subject ) . to be_falsey
2018-10-15 14:42:47 +05:30
end
2021-11-18 22:05:49 +05:30
it 'auto accepts the term for project bots' do
2021-01-03 14:25:43 +05:30
expect ( project_bot . required_terms_not_accepted? ) . to be_falsey
end
2018-10-15 14:42:47 +05:30
end
end
2018-11-08 19:23:39 +05:30
describe '#increment_failed_attempts!' do
subject ( :user ) { create ( :user , failed_attempts : 0 ) }
it 'logs failed sign-in attempts' do
expect { user . increment_failed_attempts! } . to change ( user , :failed_attempts ) . from ( 0 ) . to ( 1 )
end
it 'does not log failed sign-in attempts when in a GitLab read-only instance' do
allow ( Gitlab :: Database ) . to receive ( :read_only? ) { true }
expect { user . increment_failed_attempts! } . not_to change ( user , :failed_attempts )
end
end
2018-11-20 20:47:30 +05:30
describe '#requires_usage_stats_consent?' do
2019-09-30 21:07:59 +05:30
let ( :user ) { create ( :user , :admin , created_at : 8 . days . ago ) }
2018-11-20 20:47:30 +05:30
before do
allow ( user ) . to receive ( :has_current_license? ) . and_return false
end
context 'in single-user environment' do
it 'requires user consent after one week' do
2020-05-24 23:13:21 +05:30
create ( :user , :ghost )
2018-11-20 20:47:30 +05:30
expect ( user . requires_usage_stats_consent? ) . to be true
end
it 'requires user consent after one week if there is another ghost user' do
expect ( user . requires_usage_stats_consent? ) . to be true
end
it 'does not require consent in the first week' do
user . created_at = 6 . days . ago
expect ( user . requires_usage_stats_consent? ) . to be false
end
it 'does not require consent if usage stats were set by this user' do
2019-09-30 21:07:59 +05:30
create ( :application_setting , usage_stats_set_by_user_id : user . id )
2018-11-20 20:47:30 +05:30
expect ( user . requires_usage_stats_consent? ) . to be false
end
end
context 'in multi-user environment' do
before do
create ( :user )
end
it 'does not require consent' do
expect ( user . requires_usage_stats_consent? ) . to be false
end
end
end
2018-11-08 19:23:39 +05:30
context 'with uploads' do
2019-02-15 15:39:39 +05:30
it_behaves_like 'model with uploads' , false do
2018-11-08 19:23:39 +05:30
let ( :model_object ) { create ( :user , :with_avatar ) }
let ( :upload_attribute ) { :avatar }
let ( :uploader_class ) { AttachmentUploader }
end
end
2018-11-20 20:47:30 +05:30
describe '.union_with_user' do
context 'when no user ID is provided' do
it 'returns the input relation' do
user = create ( :user )
expect ( described_class . union_with_user ) . to eq ( [ user ] )
end
end
context 'when a user ID is provided' do
it 'includes the user object in the returned relation' do
user1 = create ( :user )
user2 = create ( :user )
users = described_class . where ( id : user1 . id ) . union_with_user ( user2 . id )
expect ( users ) . to include ( user1 )
expect ( users ) . to include ( user2 )
end
it 'does not re-apply any WHERE conditions on the outer query' do
relation = described_class . where ( id : 1 ) . union_with_user ( 2 )
expect ( relation . arel . where_sql ) . to be_nil
end
end
end
describe '.optionally_search' do
context 'using nil as the argument' do
it 'returns the current relation' do
user = create ( :user )
expect ( described_class . optionally_search ) . to eq ( [ user ] )
end
end
context 'using an empty String as the argument' do
it 'returns the current relation' do
user = create ( :user )
expect ( described_class . optionally_search ( '' ) ) . to eq ( [ user ] )
end
end
context 'using a non-empty String' do
it 'returns users matching the search query' do
user1 = create ( :user )
create ( :user )
expect ( described_class . optionally_search ( user1 . name ) ) . to eq ( [ user1 ] )
end
end
end
describe '.where_not_in' do
context 'without an argument' do
it 'returns the current relation' do
user = create ( :user )
expect ( described_class . where_not_in ) . to eq ( [ user ] )
end
end
context 'using a list of user IDs' do
it 'excludes the users from the returned relation' do
user1 = create ( :user )
user2 = create ( :user )
expect ( described_class . where_not_in ( [ user2 . id ] ) ) . to eq ( [ user1 ] )
end
end
end
describe '.reorder_by_name' do
it 'reorders the input relation' do
user1 = create ( :user , name : 'A' )
user2 = create ( :user , name : 'B' )
expect ( described_class . reorder_by_name ) . to eq ( [ user1 , user2 ] )
end
end
2019-10-12 21:52:04 +05:30
2019-12-21 20:55:43 +05:30
describe '#notification_settings_for' do
let ( :user ) { create ( :user ) }
let ( :source ) { nil }
subject { user . notification_settings_for ( source ) }
context 'when source is nil' do
it 'returns a blank global notification settings object' do
expect ( subject . source ) . to eq ( nil )
expect ( subject . notification_email ) . to eq ( nil )
expect ( subject . level ) . to eq ( 'global' )
end
end
context 'when source is a Group' do
let ( :group ) { create ( :group ) }
subject { user . notification_settings_for ( group , inherit : true ) }
context 'when group has no existing notification settings' do
context 'when group has no ancestors' do
it 'will be a default Global notification setting' do
expect ( subject . notification_email ) . to eq ( nil )
expect ( subject . level ) . to eq ( 'global' )
end
end
context 'when group has ancestors' do
context 'when an ancestor has a level other than Global' do
let ( :ancestor ) { create ( :group ) }
let ( :group ) { create ( :group , parent : ancestor ) }
2020-05-30 21:06:31 +05:30
let ( :email ) { create ( :email , :confirmed , email : 'ancestor@example.com' , user : user ) }
2019-12-21 20:55:43 +05:30
before do
2020-05-30 21:06:31 +05:30
create ( :notification_setting , user : user , source : ancestor , level : 'participating' , notification_email : email . email )
2019-12-21 20:55:43 +05:30
end
it 'has the same level set' do
expect ( subject . level ) . to eq ( 'participating' )
end
it 'has the same email set' do
expect ( subject . notification_email ) . to eq ( 'ancestor@example.com' )
end
context 'when inherit is false' do
subject { user . notification_settings_for ( group ) }
it 'does not inherit settings' do
expect ( subject . notification_email ) . to eq ( nil )
expect ( subject . level ) . to eq ( 'global' )
end
end
end
context 'when an ancestor has a Global level but has an email set' do
let ( :grand_ancestor ) { create ( :group ) }
let ( :ancestor ) { create ( :group , parent : grand_ancestor ) }
let ( :group ) { create ( :group , parent : ancestor ) }
2020-05-30 21:06:31 +05:30
let ( :ancestor_email ) { create ( :email , :confirmed , email : 'ancestor@example.com' , user : user ) }
let ( :grand_email ) { create ( :email , :confirmed , email : 'grand@example.com' , user : user ) }
2019-12-21 20:55:43 +05:30
before do
2020-05-30 21:06:31 +05:30
create ( :notification_setting , user : user , source : grand_ancestor , level : 'participating' , notification_email : grand_email . email )
create ( :notification_setting , user : user , source : ancestor , level : 'global' , notification_email : ancestor_email . email )
2019-12-21 20:55:43 +05:30
end
it 'has the same email set' do
expect ( subject . level ) . to eq ( 'global' )
expect ( subject . notification_email ) . to eq ( 'ancestor@example.com' )
end
end
end
end
end
end
2020-11-24 15:15:51 +05:30
describe '#notification_settings_for_groups' do
let_it_be ( :user ) { create ( :user ) }
let_it_be ( :groups ) { create_list ( :group , 2 ) }
subject { user . notification_settings_for_groups ( arg ) }
before do
groups . each do | group |
group . add_maintainer ( user )
end
end
shared_examples_for 'notification_settings_for_groups method' do
it 'returns NotificationSetting objects for provided groups' , :aggregate_failures do
expect ( subject . count ) . to eq ( groups . count )
expect ( subject . map ( & :source_id ) ) . to match_array ( groups . map ( & :id ) )
end
end
context 'when given an ActiveRecord relationship' do
let_it_be ( :arg ) { Group . where ( id : groups . map ( & :id ) ) }
it_behaves_like 'notification_settings_for_groups method'
it 'uses #select to maintain lazy querying behavior' do
expect ( arg ) . to receive ( :select ) . and_call_original
subject
end
end
context 'when given an Array of Groups' do
let_it_be ( :arg ) { groups }
it_behaves_like 'notification_settings_for_groups method'
end
end
2019-10-12 21:52:04 +05:30
describe '#notification_email_for' do
let ( :user ) { create ( :user ) }
let ( :group ) { create ( :group ) }
subject { user . notification_email_for ( group ) }
context 'when group is nil' do
let ( :group ) { nil }
it 'returns global notification email' do
2021-11-11 11:23:49 +05:30
is_expected . to eq ( user . notification_email_or_default )
2019-10-12 21:52:04 +05:30
end
end
context 'when group has no notification email set' do
it 'returns global notification email' do
create ( :notification_setting , user : user , source : group , notification_email : '' )
2021-11-11 11:23:49 +05:30
is_expected . to eq ( user . notification_email_or_default )
2019-10-12 21:52:04 +05:30
end
end
context 'when group has notification email set' do
it 'returns group notification email' do
group_notification_email = 'user+group@example.com'
2020-05-30 21:06:31 +05:30
create ( :email , :confirmed , user : user , email : group_notification_email )
2019-10-12 21:52:04 +05:30
create ( :notification_setting , user : user , source : group , notification_email : group_notification_email )
is_expected . to eq ( group_notification_email )
end
end
end
2019-12-21 20:55:43 +05:30
2022-08-13 15:12:31 +05:30
describe '#authenticatable_salt' do
let ( :user ) { create ( :user ) }
subject ( :authenticatable_salt ) { user . authenticatable_salt }
it 'uses password_salt' do
expect ( authenticatable_salt ) . to eq ( user . password_salt )
end
context 'when the encrypted_password is an unknown type' do
let ( :encrypted_password ) { '$argon2i$v=19$m=512,t=4,p=2$eM+ZMyYkpDRGaI3xXmuNcQ$c5DeJg3eb5dskVt1mDdxfw' }
before do
user . update_attribute ( :encrypted_password , encrypted_password )
end
it 'returns the first 30 characters of the encrypted_password' do
expect ( authenticatable_salt ) . to eq ( encrypted_password [ 0 , 29 ] )
end
end
context 'when pbkdf2_password_encryption is disabled' do
before do
stub_feature_flags ( pbkdf2_password_encryption : false )
end
it 'returns the first 30 characters of the encrypted_password' do
expect ( authenticatable_salt ) . to eq ( user . encrypted_password [ 0 , 29 ] )
end
end
end
def compare_pbkdf2_password ( user , password )
Devise :: Pbkdf2Encryptable :: Encryptors :: Pbkdf2Sha512 . compare ( user . encrypted_password , password )
end
2022-04-01 21:47:47 +05:30
describe '#valid_password?' do
2022-08-13 15:12:31 +05:30
subject ( :validate_password ) { user . valid_password? ( password ) }
2022-04-01 21:47:47 +05:30
context 'user with password not in disallowed list' do
let ( :user ) { create ( :user ) }
let ( :password ) { user . password }
it { is_expected . to be_truthy }
context 'using a wrong password' do
let ( :password ) { 'WRONG PASSWORD' }
it { is_expected . to be_falsey }
end
2022-08-13 15:12:31 +05:30
context 'when pbkdf2_sha512_encryption is disabled and the user password is pbkdf2+sha512' do
it 'does not validate correctly' do
user # Create the user while the feature is enabled
stub_feature_flags ( pbkdf2_password_encryption : false )
expect ( validate_password ) . to be_falsey
end
end
2022-04-01 21:47:47 +05:30
end
context 'user with disallowed password' do
let ( :user ) { create ( :user , :disallowed_password ) }
let ( :password ) { user . password }
it { is_expected . to be_falsey }
context 'using a wrong password' do
let ( :password ) { 'WRONG PASSWORD' }
it { is_expected . to be_falsey }
end
end
2022-08-13 15:12:31 +05:30
context 'user with a bcrypt password hash' do
2022-08-27 11:52:29 +05:30
# Manually set a 'known' encrypted password
let ( :password ) { User . random_password }
let ( :encrypted_password ) { Devise :: Encryptor . digest ( User , password ) }
2022-08-13 15:12:31 +05:30
let ( :user ) { create ( :user , encrypted_password : encrypted_password ) }
shared_examples 'not re-encrypting with PBKDF2' do
it 'does not re-encrypt with PBKDF2' do
validate_password
expect ( user . reload . encrypted_password ) . to eq ( encrypted_password )
end
end
context 'using the wrong password' do
2022-08-27 11:52:29 +05:30
# password 'WRONG PASSWORD' will not match the bcrypt hash
2022-08-13 15:12:31 +05:30
let ( :password ) { 'WRONG PASSWORD' }
2022-08-27 11:52:29 +05:30
let ( :encrypted_password ) { Devise :: Encryptor . digest ( User , User . random_password ) }
2022-08-13 15:12:31 +05:30
it { is_expected . to be_falsey }
2022-08-27 11:52:29 +05:30
2022-08-13 15:12:31 +05:30
it_behaves_like 'not re-encrypting with PBKDF2'
context 'when pbkdf2_password_encryption is disabled' do
before do
stub_feature_flags ( pbkdf2_password_encryption : false )
end
it { is_expected . to be_falsey }
2022-08-27 11:52:29 +05:30
2022-08-13 15:12:31 +05:30
it_behaves_like 'not re-encrypting with PBKDF2'
end
end
context 'using the correct password' do
it { is_expected . to be_truthy }
it 'validates the password and re-encrypts with PBKDF2' do
validate_password
current_encrypted_password = user . reload . encrypted_password
expect ( compare_pbkdf2_password ( user , password ) ) . to eq ( true )
expect { :: BCrypt :: Password . new ( current_encrypted_password ) }
. to raise_error ( :: BCrypt :: Errors :: InvalidHash )
end
context 'when pbkdf2_password_encryption is disabled' do
before do
stub_feature_flags ( pbkdf2_password_encryption : false )
end
it { is_expected . to be_truthy }
2022-08-27 11:52:29 +05:30
2022-08-13 15:12:31 +05:30
it_behaves_like 'not re-encrypting with PBKDF2'
end
context 'when pbkdf2_password_encryption_write is disabled' do
before do
stub_feature_flags ( pbkdf2_password_encryption_write : false )
end
it { is_expected . to be_truthy }
2022-08-27 11:52:29 +05:30
2022-08-13 15:12:31 +05:30
it_behaves_like 'not re-encrypting with PBKDF2'
end
end
end
context 'user with password hash that is neither PBKDF2 nor BCrypt' do
2022-08-27 11:52:29 +05:30
# Manually calculated User.random_password
let ( :password ) { " gg_w215TmVXGWSt7RJKXwYTVz886f6SDM3zvzztaJf2mX9ttUE8gRkNJSbWyWRLqxz4LFzxBekPe75ydDcGauE9wqg-acKMRT-WpSYjTm1Rdx-tnssE7CQByJcnxwWNH " }
# Created with https://argon2.online/ using 'aaaaaaaa' as the salt
let ( :encrypted_password ) { " $argon2i$v=19$m=512,t=4,p=2$YWFhYWFhYWE$PvJscKO5XRlevcgRReUg6w " }
let ( :user ) { create ( :user , encrypted_password : encrypted_password ) }
2022-08-13 15:12:31 +05:30
it { is_expected . to be_falsey }
context 'when pbkdf2_password_encryption is disabled' do
before do
stub_feature_flags ( pbkdf2_password_encryption : false )
end
it { is_expected . to be_falsey }
end
end
2022-11-25 23:54:43 +05:30
context 'user with autogenerated_password' do
let ( :user ) { build_stubbed ( :user , password_automatically_set : true ) }
let ( :password ) { user . password }
it { is_expected . to be_falsey }
end
end
describe '#generate_otp_backup_codes!' do
let ( :user ) { create ( :user ) }
context 'with FIPS mode' , :fips_mode do
it 'attempts to use #generate_otp_backup_codes_pbkdf2!' do
expect ( user ) . to receive ( :generate_otp_backup_codes_pbkdf2! ) . and_call_original
user . generate_otp_backup_codes!
end
end
context 'outside FIPS mode' do
it 'does not attempt to use #generate_otp_backup_codes_pbkdf2!' do
expect ( user ) . not_to receive ( :generate_otp_backup_codes_pbkdf2! )
user . generate_otp_backup_codes!
end
end
end
describe '#invalidate_otp_backup_code!' do
let ( :user ) { create ( :user ) }
context 'with FIPS mode' , :fips_mode do
context 'with a PBKDF2-encrypted password' do
let ( :encrypted_password ) { '$pbkdf2-sha512$20000$boHGAw0hEyI$DBA67J7zNZebyzLtLk2X9wRDbmj1LNKVGnZLYyz6PGrIDGIl45fl/BPH0y1TPZnV90A20i.fD9C3G9Bp8jzzOA' }
it 'attempts to use #invalidate_otp_backup_code_pdkdf2!' do
expect ( user ) . to receive ( :otp_backup_codes ) . at_least ( :once ) . and_return ( [ encrypted_password ] )
expect ( user ) . to receive ( :invalidate_otp_backup_code_pdkdf2! ) . and_return ( true )
user . invalidate_otp_backup_code! ( user . password )
end
end
it 'does not attempt to use #invalidate_otp_backup_code_pdkdf2!' do
expect ( user ) . not_to receive ( :invalidate_otp_backup_code_pdkdf2! )
user . invalidate_otp_backup_code! ( user . password )
end
end
context 'outside FIPS mode' do
it 'does not attempt to use #invalidate_otp_backup_code_pdkdf2!' do
expect ( user ) . not_to receive ( :invalidate_otp_backup_code_pdkdf2! )
user . invalidate_otp_backup_code! ( user . password )
end
end
2022-08-13 15:12:31 +05:30
end
# These entire test section can be removed once the :pbkdf2_password_encryption feature flag is removed.
describe '#password=' do
let ( :user ) { create ( :user ) }
2022-08-27 11:52:29 +05:30
let ( :password ) { User . random_password }
2022-08-13 15:12:31 +05:30
def compare_bcrypt_password ( user , password )
Devise :: Encryptor . compare ( User , user . encrypted_password , password )
end
context 'when pbkdf2_password_encryption is enabled' do
it 'calls PBKDF2 digest and not the default Devise encryptor' do
expect ( Devise :: Pbkdf2Encryptable :: Encryptors :: Pbkdf2Sha512 ) . to receive ( :digest ) . at_least ( :once ) . and_call_original
expect ( Devise :: Encryptor ) . not_to receive ( :digest )
user . password = password
end
it 'saves the password in PBKDF2 format' do
user . password = password
user . save!
expect ( compare_pbkdf2_password ( user , password ) ) . to eq ( true )
expect { compare_bcrypt_password ( user , password ) } . to raise_error ( :: BCrypt :: Errors :: InvalidHash )
end
context 'when pbkdf2_password_encryption_write is disabled' do
before do
stub_feature_flags ( pbkdf2_password_encryption_write : false )
end
it 'calls default Devise encryptor and not the PBKDF2 encryptor' do
expect ( Devise :: Encryptor ) . to receive ( :digest ) . at_least ( :once ) . and_call_original
expect ( Devise :: Pbkdf2Encryptable :: Encryptors :: Pbkdf2Sha512 ) . not_to receive ( :digest )
user . password = password
end
end
end
context 'when pbkdf2_password_encryption is disabled' do
before do
stub_feature_flags ( pbkdf2_password_encryption : false )
end
it 'calls default Devise encryptor and not the PBKDF2 encryptor' do
expect ( Devise :: Encryptor ) . to receive ( :digest ) . at_least ( :once ) . and_call_original
expect ( Devise :: Pbkdf2Encryptable :: Encryptors :: Pbkdf2Sha512 ) . not_to receive ( :digest )
user . password = password
end
it 'saves the password in BCrypt format' do
user . password = password
user . save!
expect { compare_pbkdf2_password ( user , password ) } . to raise_error Devise :: Pbkdf2Encryptable :: Encryptors :: InvalidHash
expect ( compare_bcrypt_password ( user , password ) ) . to eq ( true )
end
end
end
describe '#password_strategy' do
let ( :user ) { create ( :user , encrypted_password : encrypted_password ) }
context 'with a PBKDF2+SHA512 encrypted password' do
let ( :encrypted_password ) { '$pbkdf2-sha512$20000$boHGAw0hEyI$DBA67J7zNZebyzLtLk2X9wRDbmj1LNKVGnZLYyz6PGrIDGIl45fl/BPH0y1TPZnV90A20i.fD9C3G9Bp8jzzOA' }
it 'extracts the correct strategy' , :aggregate_failures do
expect ( user . password_strategy ) . to eq ( :pbkdf2_sha512 )
end
end
context 'with a BCrypt encrypted password' do
let ( :encrypted_password ) { '$2a$10$xLTxCKOa75IU4RQGqqOrTuZOgZdJEzfSzjG6ZSEi/C31TB/yLZYpi' }
it 'extracts the correct strategy' , :aggregate_failures do
expect ( user . password_strategy ) . to eq ( :bcrypt )
end
end
context 'with an unknown encrypted password' do
let ( :encrypted_password ) { '$pbkdf2-sha256$6400$.6UI/S.nXIk8jcbdHx3Fhg$98jZicV16ODfEsEZeYPGHU3kbrUrvUEXOPimVSQDD44' }
it 'returns unknown strategy' do
expect ( user . password_strategy ) . to eq ( :unknown )
end
end
2022-04-01 21:47:47 +05:30
end
2019-12-21 20:55:43 +05:30
describe '#password_expired?' do
let ( :user ) { build ( :user , password_expires_at : password_expires_at ) }
subject { user . password_expired? }
context 'when password_expires_at is not set' do
let ( :password_expires_at ) { }
it 'returns false' do
is_expected . to be_falsey
end
end
context 'when password_expires_at is in the past' do
let ( :password_expires_at ) { 1 . minute . ago }
it 'returns true' do
is_expected . to be_truthy
end
end
context 'when password_expires_at is in the future' do
let ( :password_expires_at ) { 1 . minute . from_now }
it 'returns false' do
is_expected . to be_falsey
end
end
end
2020-03-13 15:44:24 +05:30
2021-07-02 01:05:55 +05:30
describe '#password_expired_if_applicable?' do
let ( :user ) { build ( :user , password_expires_at : password_expires_at ) }
subject { user . password_expired_if_applicable? }
2021-09-30 23:02:18 +05:30
shared_examples 'password expired not applicable' do
2021-07-02 01:05:55 +05:30
context 'when password_expires_at is not set' do
let ( :password_expires_at ) { }
it 'returns false' do
is_expected . to be_falsey
end
end
context 'when password_expires_at is in the past' do
let ( :password_expires_at ) { 1 . minute . ago }
2021-09-30 23:02:18 +05:30
it 'returns false' do
is_expected . to be_falsey
2021-07-02 01:05:55 +05:30
end
end
context 'when password_expires_at is in the future' do
let ( :password_expires_at ) { 1 . minute . from_now }
it 'returns false' do
is_expected . to be_falsey
end
end
end
2021-09-30 23:02:18 +05:30
context 'with a regular user' do
2021-07-02 01:05:55 +05:30
context 'when password_expires_at is not set' do
let ( :password_expires_at ) { }
it 'returns false' do
is_expected . to be_falsey
end
end
context 'when password_expires_at is in the past' do
let ( :password_expires_at ) { 1 . minute . ago }
2021-09-30 23:02:18 +05:30
it 'returns true' do
is_expected . to be_truthy
2021-07-02 01:05:55 +05:30
end
end
context 'when password_expires_at is in the future' do
let ( :password_expires_at ) { 1 . minute . from_now }
it 'returns false' do
is_expected . to be_falsey
end
end
end
2021-09-30 23:02:18 +05:30
context 'when user is a bot' do
before do
allow ( user ) . to receive ( :bot? ) . and_return ( true )
end
it_behaves_like 'password expired not applicable'
end
context 'when password_automatically_set is true' do
2022-08-27 11:52:29 +05:30
let ( :user ) { create ( :omniauth_user , provider : 'ldap' ) }
2021-09-30 23:02:18 +05:30
it_behaves_like 'password expired not applicable'
end
context 'when allow_password_authentication is false' do
before do
allow ( user ) . to receive ( :allow_password_authentication? ) . and_return ( false )
end
it_behaves_like 'password expired not applicable'
end
2021-07-02 01:05:55 +05:30
end
2022-03-02 08:16:31 +05:30
describe '#can_log_in_with_non_expired_password?' do
let ( :user ) { build ( :user ) }
subject { user . can_log_in_with_non_expired_password? }
context 'when user can log in' do
it 'returns true' do
is_expected . to be_truthy
end
context 'when user with expired password' do
before do
user . password_expires_at = 2 . minutes . ago
end
it 'returns false' do
is_expected . to be_falsey
end
context 'when password expiration is not applicable' do
context 'when ldap user' do
let ( :user ) { build ( :omniauth_user , provider : 'ldap' ) }
it 'returns true' do
is_expected . to be_truthy
end
end
end
end
end
context 'when user cannot log in' do
context 'when user is blocked' do
let ( :user ) { build ( :user , :blocked ) }
it 'returns false' do
is_expected . to be_falsey
end
end
end
end
2020-03-13 15:44:24 +05:30
describe '#read_only_attribute?' do
context 'when synced attributes metadata is present' do
it 'delegates to synced_attributes_metadata' do
subject . build_user_synced_attributes_metadata
expect ( subject . build_user_synced_attributes_metadata )
. to receive ( :read_only? ) . with ( :email ) . and_return ( 'return-value' )
expect ( subject . read_only_attribute? ( :email ) ) . to eq ( 'return-value' )
end
end
2020-04-22 19:07:51 +05:30
context 'when synced attributes metadata is not present' do
2020-03-13 15:44:24 +05:30
it 'is false for any attribute' do
expect ( subject . read_only_attribute? ( :email ) ) . to be_falsey
end
end
end
2020-05-24 23:13:21 +05:30
describe '.active_without_ghosts' do
let_it_be ( :user1 ) { create ( :user , :external ) }
let_it_be ( :user2 ) { create ( :user , state : 'blocked' ) }
let_it_be ( :user3 ) { create ( :user , :ghost ) }
let_it_be ( :user4 ) { create ( :user , user_type : :support_bot ) }
let_it_be ( :user5 ) { create ( :user , state : 'blocked' , user_type : :support_bot ) }
2021-09-04 01:27:46 +05:30
let_it_be ( :user6 ) { create ( :user , user_type : :automation_bot ) }
2020-03-13 15:44:24 +05:30
2020-05-24 23:13:21 +05:30
it 'returns all active users including active bots but ghost users' do
2021-09-04 01:27:46 +05:30
expect ( described_class . active_without_ghosts ) . to match_array ( [ user1 , user4 , user6 ] )
2020-03-13 15:44:24 +05:30
end
end
describe '#dismissed_callout?' do
2021-11-11 11:23:49 +05:30
let_it_be ( :user , refind : true ) { create ( :user ) }
2022-01-26 12:08:38 +05:30
let_it_be ( :feature_name ) { Users :: Callout . feature_names . each_key . first }
2020-03-13 15:44:24 +05:30
context 'when no callout dismissal record exists' do
it 'returns false when no ignore_dismissal_earlier_than provided' do
expect ( user . dismissed_callout? ( feature_name : feature_name ) ) . to eq false
end
end
context 'when dismissed callout exists' do
2021-11-11 11:23:49 +05:30
before_all do
2022-01-26 12:08:38 +05:30
create ( :callout , user : user , feature_name : feature_name , dismissed_at : 4 . months . ago )
2020-03-13 15:44:24 +05:30
end
it 'returns true when no ignore_dismissal_earlier_than provided' do
expect ( user . dismissed_callout? ( feature_name : feature_name ) ) . to eq true
end
it 'returns true when ignore_dismissal_earlier_than is earlier than dismissed_at' do
expect ( user . dismissed_callout? ( feature_name : feature_name , ignore_dismissal_earlier_than : 6 . months . ago ) ) . to eq true
end
it 'returns false when ignore_dismissal_earlier_than is later than dismissed_at' do
expect ( user . dismissed_callout? ( feature_name : feature_name , ignore_dismissal_earlier_than : 3 . months . ago ) ) . to eq false
end
end
end
2021-11-11 11:23:49 +05:30
describe '#find_or_initialize_callout' do
let_it_be ( :user , refind : true ) { create ( :user ) }
2022-01-26 12:08:38 +05:30
let_it_be ( :feature_name ) { Users :: Callout . feature_names . each_key . first }
2021-11-11 11:23:49 +05:30
subject ( :find_or_initialize_callout ) { user . find_or_initialize_callout ( feature_name ) }
context 'when callout exists' do
2022-01-26 12:08:38 +05:30
let! ( :callout ) { create ( :callout , user : user , feature_name : feature_name ) }
2021-11-11 11:23:49 +05:30
it 'returns existing callout' do
expect ( find_or_initialize_callout ) . to eq ( callout )
end
end
context 'when callout does not exist' do
context 'when feature name is valid' do
it 'initializes a new callout' do
2022-01-26 12:08:38 +05:30
expect ( find_or_initialize_callout ) . to be_a_new ( Users :: Callout )
2021-11-11 11:23:49 +05:30
end
it 'is valid' do
expect ( find_or_initialize_callout ) . to be_valid
end
end
context 'when feature name is not valid' do
let ( :feature_name ) { 'notvalid' }
it 'initializes a new callout' do
2022-01-26 12:08:38 +05:30
expect ( find_or_initialize_callout ) . to be_a_new ( Users :: Callout )
2021-11-11 11:23:49 +05:30
end
it 'is not valid' do
expect ( find_or_initialize_callout ) . not_to be_valid
end
end
end
end
describe '#dismissed_callout_for_group?' do
let_it_be ( :user , refind : true ) { create ( :user ) }
let_it_be ( :group ) { create ( :group ) }
let_it_be ( :feature_name ) { Users :: GroupCallout . feature_names . each_key . first }
context 'when no callout dismissal record exists' do
it 'returns false when no ignore_dismissal_earlier_than provided' do
expect ( user . dismissed_callout_for_group? ( feature_name : feature_name , group : group ) ) . to eq false
end
end
context 'when dismissed callout exists' do
before_all do
create ( :group_callout ,
user : user ,
group_id : group . id ,
feature_name : feature_name ,
dismissed_at : 4 . months . ago )
end
it 'returns true when no ignore_dismissal_earlier_than provided' do
expect ( user . dismissed_callout_for_group? ( feature_name : feature_name , group : group ) ) . to eq true
end
it 'returns true when ignore_dismissal_earlier_than is earlier than dismissed_at' do
expect ( user . dismissed_callout_for_group? ( feature_name : feature_name , group : group , ignore_dismissal_earlier_than : 6 . months . ago ) ) . to eq true
end
it 'returns false when ignore_dismissal_earlier_than is later than dismissed_at' do
expect ( user . dismissed_callout_for_group? ( feature_name : feature_name , group : group , ignore_dismissal_earlier_than : 3 . months . ago ) ) . to eq false
end
end
end
2022-08-27 11:52:29 +05:30
describe '#dismissed_callout_for_project?' do
let_it_be ( :user , refind : true ) { create ( :user ) }
let_it_be ( :project ) { create ( :project ) }
let_it_be ( :feature_name ) { Users :: ProjectCallout . feature_names . each_key . first }
context 'when no callout dismissal record exists' do
it 'returns false when no ignore_dismissal_earlier_than provided' do
expect ( user . dismissed_callout_for_project? ( feature_name : feature_name , project : project ) ) . to eq false
end
end
context 'when dismissed callout exists' do
before_all do
create ( :project_callout ,
user : user ,
project_id : project . id ,
feature_name : feature_name ,
dismissed_at : 4 . months . ago )
end
it 'returns true when no ignore_dismissal_earlier_than provided' do
expect ( user . dismissed_callout_for_project? ( feature_name : feature_name , project : project ) ) . to eq true
end
it 'returns true when ignore_dismissal_earlier_than is earlier than dismissed_at' do
expect ( user . dismissed_callout_for_project? ( feature_name : feature_name , project : project , ignore_dismissal_earlier_than : 6 . months . ago ) ) . to eq true
end
it 'returns false when ignore_dismissal_earlier_than is later than dismissed_at' do
expect ( user . dismissed_callout_for_project? ( feature_name : feature_name , project : project , ignore_dismissal_earlier_than : 3 . months . ago ) ) . to eq false
end
end
end
2021-11-11 11:23:49 +05:30
describe '#find_or_initialize_group_callout' do
let_it_be ( :user , refind : true ) { create ( :user ) }
let_it_be ( :group ) { create ( :group ) }
let_it_be ( :feature_name ) { Users :: GroupCallout . feature_names . each_key . first }
subject ( :callout_with_source ) do
user . find_or_initialize_group_callout ( feature_name , group . id )
end
context 'when callout exists' do
let! ( :callout ) do
create ( :group_callout , user : user , feature_name : feature_name , group_id : group . id )
end
it 'returns existing callout' do
expect ( callout_with_source ) . to eq ( callout )
end
end
context 'when callout does not exist' do
context 'when feature name is valid' do
it 'initializes a new callout' do
expect ( callout_with_source ) . to be_a_new ( Users :: GroupCallout )
end
it 'is valid' do
expect ( callout_with_source ) . to be_valid
end
end
context 'when feature name is not valid' do
let ( :feature_name ) { 'notvalid' }
it 'initializes a new callout' do
expect ( callout_with_source ) . to be_a_new ( Users :: GroupCallout )
end
it 'is not valid' do
expect ( callout_with_source ) . not_to be_valid
end
end
end
end
2022-08-27 11:52:29 +05:30
describe '#find_or_initialize_project_callout' do
let_it_be ( :user , refind : true ) { create ( :user ) }
let_it_be ( :project ) { create ( :project ) }
let_it_be ( :feature_name ) { Users :: ProjectCallout . feature_names . each_key . first }
subject ( :callout_with_source ) do
user . find_or_initialize_project_callout ( feature_name , project . id )
end
context 'when callout exists' do
let! ( :callout ) do
create ( :project_callout , user : user , feature_name : feature_name , project_id : project . id )
end
it 'returns existing callout' do
expect ( callout_with_source ) . to eq ( callout )
end
end
context 'when callout does not exist' do
context 'when feature name is valid' do
it 'initializes a new callout' do
expect ( callout_with_source ) . to be_a_new ( Users :: ProjectCallout )
end
it 'is valid' do
expect ( callout_with_source ) . to be_valid
end
end
context 'when feature name is not valid' do
let ( :feature_name ) { 'notvalid' }
it 'initializes a new callout' do
expect ( callout_with_source ) . to be_a_new ( Users :: ProjectCallout )
end
it 'is not valid' do
expect ( callout_with_source ) . not_to be_valid
end
end
end
end
2020-03-13 15:44:24 +05:30
describe '#hook_attrs' do
2021-10-29 20:43:33 +05:30
let ( :user ) { create ( :user ) }
let ( :user_attributes ) do
{
2021-03-08 18:12:59 +05:30
id : user . id ,
2020-03-13 15:44:24 +05:30
name : user . name ,
username : user . username ,
2021-10-29 20:43:33 +05:30
avatar_url : user . avatar_url ( only_path : false )
2020-03-13 15:44:24 +05:30
}
2021-10-29 20:43:33 +05:30
end
context 'with a public email' do
it 'includes id, name, username, avatar_url, and email' do
user . public_email = " hello@hello.com "
user_attributes [ :email ] = user . public_email
expect ( user . hook_attrs ) . to eq ( user_attributes )
end
end
context 'without a public email' do
it " does not include email if user's email is private " do
user_attributes [ :email ] = " [REDACTED] "
expect ( user . hook_attrs ) . to eq ( user_attributes )
end
2020-03-13 15:44:24 +05:30
end
end
2020-04-08 14:13:33 +05:30
2022-10-02 17:18:49 +05:30
describe '#webhook_email' do
let ( :user ) { build ( :user , public_email : nil ) }
context 'when public email is present' do
before do
user . public_email = " hello@hello.com "
end
it 'returns public email' do
expect ( user . webhook_email ) . to eq ( user . public_email )
end
end
context 'when public email is nil' do
it 'returns [REDACTED]' do
expect ( user . webhook_email ) . to eq ( _ ( '[REDACTED]' ) )
end
end
end
2021-06-08 01:23:25 +05:30
describe 'user credit card validation' do
context 'when user is initialized' do
let ( :user ) { build ( :user ) }
it { expect ( user . credit_card_validation ) . not_to be_present }
end
context 'when create user without credit card validation' do
let ( :user ) { create ( :user ) }
it { expect ( user . credit_card_validation ) . not_to be_present }
end
context 'when user credit card validation exists' do
let ( :user ) { create ( :user , :with_credit_card_validation ) }
it { expect ( user . credit_card_validation ) . to be_persisted }
end
end
2020-04-08 14:13:33 +05:30
describe 'user detail' do
context 'when user is initialized' do
let ( :user ) { build ( :user ) }
it { expect ( user . user_detail ) . to be_present }
it { expect ( user . user_detail ) . not_to be_persisted }
end
context 'when user detail exists' do
let ( :user ) { create ( :user , job_title : 'Engineer' ) }
it { expect ( user . user_detail ) . to be_persisted }
end
end
2020-04-22 19:07:51 +05:30
describe '#current_highest_access_level' do
let_it_be ( :user ) { create ( :user ) }
context 'when no memberships exist' do
it 'returns nil' do
expect ( user . current_highest_access_level ) . to be_nil
end
end
context 'when memberships exist' do
it 'returns the highest access level for non requested memberships' do
create ( :group_member , :reporter , user_id : user . id )
create ( :project_member , :guest , user_id : user . id )
create ( :project_member , :maintainer , user_id : user . id , requested_at : Time . current )
expect ( user . current_highest_access_level ) . to eq ( Gitlab :: Access :: REPORTER )
end
end
end
context 'when after_commit :update_highest_role' do
describe 'create user' do
subject { create ( :user ) }
it 'schedules a job in the future' , :aggregate_failures , :clean_gitlab_redis_shared_state do
allow_next_instance_of ( Gitlab :: ExclusiveLease ) do | instance |
allow ( instance ) . to receive ( :try_obtain ) . and_return ( 'uuid' )
end
expect ( UpdateHighestRoleWorker ) . to receive ( :perform_in ) . and_call_original
expect { subject } . to change ( UpdateHighestRoleWorker . jobs , :size ) . by ( 1 )
end
end
context 'when user already exists' do
let! ( :user ) { create ( :user ) }
let ( :user_id ) { user . id }
describe 'update user' do
using RSpec :: Parameterized :: TableSyntax
where ( :attributes ) do
[
{ state : 'blocked' } ,
2020-05-24 23:13:21 +05:30
{ user_type : :ghost } ,
2020-07-28 23:09:34 +05:30
{ user_type : :alert_bot } ,
2021-01-03 14:25:43 +05:30
{ user_type : :support_bot } ,
2021-09-04 01:27:46 +05:30
{ user_type : :security_bot } ,
{ user_type : :automation_bot }
2020-04-22 19:07:51 +05:30
]
end
with_them do
context 'when state was changed' do
2021-06-08 01:23:25 +05:30
subject { user . update! ( attributes ) }
2020-04-22 19:07:51 +05:30
include_examples 'update highest role with exclusive lease'
end
end
context 'when state was not changed' do
2021-06-08 01:23:25 +05:30
subject { user . update! ( email : 'newmail@example.com' ) }
2020-04-22 19:07:51 +05:30
include_examples 'does not update the highest role'
end
end
describe 'destroy user' do
2021-06-08 01:23:25 +05:30
subject { user . destroy! }
2020-04-22 19:07:51 +05:30
include_examples 'does not update the highest role'
end
end
end
describe '#active_for_authentication?' do
2021-12-11 22:18:48 +05:30
subject ( :active_for_authentication? ) { user . active_for_authentication? }
2020-04-22 19:07:51 +05:30
let ( :user ) { create ( :user ) }
context 'when user is blocked' do
before do
user . block
end
it { is_expected . to be false }
2021-12-11 22:18:48 +05:30
it 'does not check if LDAP is allowed' do
stub_ldap_setting ( enabled : true )
expect ( Gitlab :: Auth :: Ldap :: Access ) . not_to receive ( :allowed? )
active_for_authentication?
end
2020-04-22 19:07:51 +05:30
end
context 'when user is a ghost user' do
before do
2021-06-08 01:23:25 +05:30
user . update! ( user_type : :ghost )
2020-04-22 19:07:51 +05:30
end
it { is_expected . to be false }
end
2021-12-11 22:18:48 +05:30
context 'when user is ldap_blocked' do
before do
user . ldap_block
end
it 'rechecks if LDAP is allowed when LDAP is enabled' do
stub_ldap_setting ( enabled : true )
expect ( Gitlab :: Auth :: Ldap :: Access ) . to receive ( :allowed? )
active_for_authentication?
end
it 'does not check if LDAP is allowed when LDAP is not enabled' do
stub_ldap_setting ( enabled : false )
expect ( Gitlab :: Auth :: Ldap :: Access ) . not_to receive ( :allowed? )
active_for_authentication?
end
end
2020-04-22 19:07:51 +05:30
context 'based on user type' do
using RSpec :: Parameterized :: TableSyntax
where ( :user_type , :expected_result ) do
'human' | true
'alert_bot' | false
2020-07-28 23:09:34 +05:30
'support_bot' | false
2021-01-03 14:25:43 +05:30
'security_bot' | false
2021-09-04 01:27:46 +05:30
'automation_bot' | false
2020-04-22 19:07:51 +05:30
end
with_them do
before do
2021-06-08 01:23:25 +05:30
user . update! ( user_type : user_type )
2020-04-22 19:07:51 +05:30
end
it { is_expected . to be expected_result }
end
end
end
describe '#inactive_message' do
subject { user . inactive_message }
let ( :user ) { create ( :user ) }
context 'when user is blocked' do
before do
user . block
end
2021-01-03 14:25:43 +05:30
it { is_expected . to eq :blocked }
2020-04-22 19:07:51 +05:30
end
context 'when user is an internal user' do
before do
2021-06-08 01:23:25 +05:30
user . update! ( user_type : :ghost )
2020-04-22 19:07:51 +05:30
end
2021-01-03 14:25:43 +05:30
it { is_expected . to be :forbidden }
2020-04-22 19:07:51 +05:30
end
context 'when user is locked' do
before do
user . lock_access!
end
it { is_expected . to be :locked }
end
2021-01-03 14:25:43 +05:30
context 'when user is blocked pending approval' do
before do
user . block_pending_approval!
end
it { is_expected . to be :blocked_pending_approval }
end
2020-04-22 19:07:51 +05:30
end
describe '#password_required?' do
let_it_be ( :user ) { create ( :user ) }
shared_examples 'does not require password to be present' do
it { expect ( user ) . not_to validate_presence_of ( :password ) }
it { expect ( user ) . not_to validate_presence_of ( :password_confirmation ) }
end
context 'when user is an internal user' do
before do
2021-06-08 01:23:25 +05:30
user . update! ( user_type : 'alert_bot' )
2020-04-22 19:07:51 +05:30
end
it_behaves_like 'does not require password to be present'
end
context 'when user is a project bot user' do
before do
2021-06-08 01:23:25 +05:30
user . update! ( user_type : 'project_bot' )
2020-04-22 19:07:51 +05:30
end
it_behaves_like 'does not require password to be present'
end
2020-04-08 14:13:33 +05:30
end
2020-05-24 23:13:21 +05:30
2021-04-17 20:07:23 +05:30
describe 'can_trigger_notifications?' do
context 'when user is not confirmed' do
let_it_be ( :user ) { create ( :user , :unconfirmed ) }
it 'returns false' do
expect ( user . can_trigger_notifications? ) . to be ( false )
end
end
context 'when user is blocked' do
let_it_be ( :user ) { create ( :user , :blocked ) }
it 'returns false' do
expect ( user . can_trigger_notifications? ) . to be ( false )
end
end
context 'when user is a ghost' do
let_it_be ( :user ) { create ( :user , :ghost ) }
it 'returns false' do
expect ( user . can_trigger_notifications? ) . to be ( false )
end
end
context 'when user is confirmed and neither blocked or a ghost' do
let_it_be ( :user ) { create ( :user ) }
it 'returns true' do
expect ( user . can_trigger_notifications? ) . to be ( true )
end
end
end
2020-07-28 23:09:34 +05:30
context 'bot users' do
shared_examples 'bot users' do | bot_type |
it 'creates the user if it does not exist' do
expect do
described_class . public_send ( bot_type )
end . to change { User . where ( user_type : bot_type ) . count } . by ( 1 )
end
it 'creates a route for the namespace of the created user' do
bot_user = described_class . public_send ( bot_type )
expect ( bot_user . namespace . route ) . to be_present
end
it 'does not create a new user if it already exists' do
described_class . public_send ( bot_type )
expect do
described_class . public_send ( bot_type )
end . not_to change { User . count }
end
2020-05-24 23:13:21 +05:30
end
2020-07-28 23:09:34 +05:30
shared_examples 'bot user avatars' do | bot_type , avatar_filename |
it 'sets the custom avatar for the created bot' do
bot_user = described_class . public_send ( bot_type )
2020-05-24 23:13:21 +05:30
2020-07-28 23:09:34 +05:30
expect ( bot_user . avatar . url ) . to be_present
expect ( bot_user . avatar . filename ) . to eq ( avatar_filename )
end
2020-05-24 23:13:21 +05:30
end
2020-07-28 23:09:34 +05:30
it_behaves_like 'bot users' , :alert_bot
it_behaves_like 'bot users' , :support_bot
it_behaves_like 'bot users' , :migration_bot
2021-01-03 14:25:43 +05:30
it_behaves_like 'bot users' , :security_bot
2020-07-28 23:09:34 +05:30
it_behaves_like 'bot users' , :ghost
2021-09-04 01:27:46 +05:30
it_behaves_like 'bot users' , :automation_bot
2020-07-28 23:09:34 +05:30
it_behaves_like 'bot user avatars' , :alert_bot , 'alert-bot.png'
it_behaves_like 'bot user avatars' , :support_bot , 'support-bot.png'
2021-01-03 14:25:43 +05:30
it_behaves_like 'bot user avatars' , :security_bot , 'security-bot.png'
2021-09-04 01:27:46 +05:30
it_behaves_like 'bot user avatars' , :automation_bot , 'support-bot.png'
2021-04-29 21:17:54 +05:30
context 'when bot is the support_bot' do
subject { described_class . support_bot }
it { is_expected . to be_confirmed }
end
2020-05-24 23:13:21 +05:30
end
2021-04-17 20:07:23 +05:30
describe '#confirmation_required_on_sign_in?' do
subject { user . confirmation_required_on_sign_in? }
context 'when user is confirmed' do
2021-12-11 22:18:48 +05:30
let ( :user ) { create ( :user ) }
2021-04-17 20:07:23 +05:30
it 'is falsey' do
expect ( user . confirmed? ) . to be_truthy
expect ( subject ) . to be_falsey
end
end
context 'when user is not confirmed' do
let_it_be ( :user ) { build_stubbed ( :user , :unconfirmed , confirmation_sent_at : Time . current ) }
it 'is truthy when soft_email_confirmation feature is disabled' do
stub_feature_flags ( soft_email_confirmation : false )
expect ( subject ) . to be_truthy
end
context 'when soft_email_confirmation feature is enabled' do
before do
stub_feature_flags ( soft_email_confirmation : true )
end
it 'is falsey when confirmation period is valid' do
expect ( subject ) . to be_falsey
end
it 'is truthy when confirmation period is expired' do
travel_to ( User . allow_unconfirmed_access_for . from_now + 1 . day ) do
expect ( subject ) . to be_truthy
end
end
context 'when user has no confirmation email sent' do
let ( :user ) { build ( :user , :unconfirmed , confirmation_sent_at : nil ) }
it 'is truthy' do
expect ( subject ) . to be_truthy
end
end
end
end
end
2021-06-08 01:23:25 +05:30
describe '.dormant' do
it 'returns dormant users' do
freeze_time do
2022-10-11 01:57:18 +05:30
not_that_long_ago = ( Gitlab :: CurrentSettings . deactivate_dormant_users_period - 1 ) . days . ago . to_date
too_long_ago = Gitlab :: CurrentSettings . deactivate_dormant_users_period . days . ago . to_date
2021-06-08 01:23:25 +05:30
create ( :user , :deactivated , last_activity_on : too_long_ago )
User :: INTERNAL_USER_TYPES . map do | user_type |
create ( :user , state : :active , user_type : user_type , last_activity_on : too_long_ago )
end
create ( :user , last_activity_on : not_that_long_ago )
dormant_user = create ( :user , last_activity_on : too_long_ago )
expect ( described_class . dormant ) . to contain_exactly ( dormant_user )
end
end
end
describe '.with_no_activity' do
it 'returns users with no activity' do
freeze_time do
2022-10-11 01:57:18 +05:30
active_not_that_long_ago = ( Gitlab :: CurrentSettings . deactivate_dormant_users_period - 1 ) . days . ago . to_date
active_too_long_ago = Gitlab :: CurrentSettings . deactivate_dormant_users_period . days . ago . to_date
2022-07-23 23:45:48 +05:30
created_recently = ( described_class :: MINIMUM_DAYS_CREATED - 1 ) . days . ago . to_date
created_not_recently = described_class :: MINIMUM_DAYS_CREATED . days . ago . to_date
2021-06-08 01:23:25 +05:30
create ( :user , :deactivated , last_activity_on : nil )
User :: INTERNAL_USER_TYPES . map do | user_type |
create ( :user , state : :active , user_type : user_type , last_activity_on : nil )
end
2022-07-23 23:45:48 +05:30
create ( :user , last_activity_on : active_not_that_long_ago )
create ( :user , last_activity_on : active_too_long_ago )
create ( :user , last_activity_on : nil , created_at : created_recently )
2021-06-08 01:23:25 +05:30
2022-07-23 23:45:48 +05:30
old_enough_user_with_no_activity = create ( :user , last_activity_on : nil , created_at : created_not_recently )
2021-06-08 01:23:25 +05:30
2022-07-23 23:45:48 +05:30
expect ( described_class . with_no_activity ) . to contain_exactly ( old_enough_user_with_no_activity )
2021-06-08 01:23:25 +05:30
end
end
end
2021-09-30 23:02:18 +05:30
describe '.by_provider_and_extern_uid' do
it 'calls Identity model scope to ensure case-insensitive query' , :aggregate_failures do
expected_user = create ( :user )
create ( :identity , extern_uid : 'some-other-name-id' , provider : :github )
create ( :identity , extern_uid : 'my_github_id' , provider : :gitlab )
create ( :identity )
create ( :identity , user : expected_user , extern_uid : 'my_github_id' , provider : :github )
expect ( Identity ) . to receive ( :with_extern_uid ) . and_call_original
expect ( described_class . by_provider_and_extern_uid ( :github , 'my_github_id' ) ) . to match_array ( [ expected_user ] )
end
end
2021-11-11 11:23:49 +05:30
describe '#unset_secondary_emails_matching_deleted_email!' do
let ( :deleted_email ) { 'kermit@muppets.com' }
subject { build ( :user , commit_email : commit_email ) }
context 'when no secondary email matches the deleted email' do
let ( :commit_email ) { 'fozzie@muppets.com' }
it 'does nothing' do
expect ( subject ) . not_to receive ( :save )
subject . unset_secondary_emails_matching_deleted_email! ( deleted_email )
expect ( subject . commit_email ) . to eq commit_email
end
end
context 'when a secondary email matches the deleted_email' do
let ( :commit_email ) { deleted_email }
it 'un-sets the secondary email' do
expect ( subject ) . to receive ( :save )
subject . unset_secondary_emails_matching_deleted_email! ( deleted_email )
expect ( subject . commit_email ) . to be nil
end
end
end
describe '#groups_with_developer_maintainer_project_access' do
let_it_be ( :user ) { create ( :user ) }
let_it_be ( :group1 ) { create ( :group ) }
let_it_be ( :developer_group1 ) do
create ( :group ) . tap do | g |
g . add_developer ( user )
end
end
let_it_be ( :developer_group2 ) do
create ( :group , project_creation_level : :: Gitlab :: Access :: DEVELOPER_MAINTAINER_PROJECT_ACCESS ) . tap do | g |
g . add_developer ( user )
end
end
let_it_be ( :guest_group1 ) do
create ( :group , project_creation_level : :: Gitlab :: Access :: DEVELOPER_MAINTAINER_PROJECT_ACCESS ) . tap do | g |
g . add_guest ( user )
end
end
let_it_be ( :developer_group1 ) do
create ( :group , project_creation_level : :: Gitlab :: Access :: DEVELOPER_MAINTAINER_PROJECT_ACCESS ) . tap do | g |
g . add_maintainer ( user )
end
end
subject { user . send ( :groups_with_developer_maintainer_project_access ) }
2022-01-26 12:08:38 +05:30
specify { is_expected . to contain_exactly ( developer_group2 ) }
2021-11-11 11:23:49 +05:30
end
2021-11-18 22:05:49 +05:30
2022-03-02 08:16:31 +05:30
describe '.get_ids_by_ids_or_usernames' do
2021-11-18 22:05:49 +05:30
let ( :user_name ) { 'user_name' }
let! ( :user ) { create ( :user , username : user_name ) }
let ( :user_id ) { user . id }
it 'returns the id of each record matching username' do
2022-03-02 08:16:31 +05:30
expect ( described_class . get_ids_by_ids_or_usernames ( nil , [ user_name ] ) ) . to match_array ( [ user_id ] )
end
it 'returns the id of each record matching user id' do
expect ( described_class . get_ids_by_ids_or_usernames ( [ user_id ] , nil ) ) . to match_array ( [ user_id ] )
end
it 'return the id for all records matching either user id or user name' do
new_user_id = create ( :user ) . id
expect ( described_class . get_ids_by_ids_or_usernames ( [ new_user_id ] , [ user_name ] ) ) . to match_array ( [ user_id , new_user_id ] )
end
end
describe '.by_ids_or_usernames' do
let ( :user_name ) { 'user_name' }
let! ( :user ) { create ( :user , username : user_name ) }
let ( :user_id ) { user . id }
it 'returns matching records based on username' do
expect ( described_class . by_ids_or_usernames ( nil , [ user_name ] ) ) . to match_array ( [ user ] )
end
it 'returns matching records based on id' do
expect ( described_class . by_ids_or_usernames ( [ user_id ] , nil ) ) . to match_array ( [ user ] )
end
it 'returns matching records based on both username and id' do
new_user = create ( :user )
expect ( described_class . by_ids_or_usernames ( [ new_user . id ] , [ user_name ] ) ) . to match_array ( [ user , new_user ] )
2021-11-18 22:05:49 +05:30
end
end
2021-12-11 22:18:48 +05:30
2022-06-21 17:19:12 +05:30
describe '.without_forbidden_states' do
let_it_be ( :normal_user ) { create ( :user , username : 'johndoe' ) }
let_it_be ( :admin_user ) { create ( :user , :admin , username : 'iamadmin' ) }
let_it_be ( :blocked_user ) { create ( :user , :blocked , username : 'notsorandom' ) }
let_it_be ( :banned_user ) { create ( :user , :banned , username : 'iambanned' ) }
let_it_be ( :external_user ) { create ( :user , :external ) }
let_it_be ( :unconfirmed_user ) { create ( :user , confirmed_at : nil ) }
let_it_be ( :omniauth_user ) { create ( :omniauth_user , provider : 'twitter' , extern_uid : '123456' ) }
let_it_be ( :internal_user ) { User . alert_bot . tap { | u | u . confirm } }
it 'does not return blocked or banned users' do
2022-11-25 23:54:43 +05:30
expect ( described_class . without_forbidden_states ) . to match_array (
[
normal_user , admin_user , external_user , unconfirmed_user , omniauth_user , internal_user
] )
2022-06-21 17:19:12 +05:30
end
end
2021-12-11 22:18:48 +05:30
describe 'user_project' do
it 'returns users project matched by username and public visibility' do
user = create ( :user )
public_project = create ( :project , :public , path : user . username , namespace : user . namespace )
create ( :project , namespace : user . namespace )
expect ( user . user_project ) . to eq ( public_project )
end
end
describe 'user_readme' do
it 'returns readme from user project' do
user = create ( :user )
create ( :project , :repository , :public , path : user . username , namespace : user . namespace )
expect ( user . user_readme . name ) . to eq ( 'README.md' )
expect ( user . user_readme . data ) . to include ( 'testme' )
end
it 'returns nil if project is private' do
user = create ( :user )
create ( :project , :repository , :private , path : user . username , namespace : user . namespace )
expect ( user . user_readme ) . to be ( nil )
end
end
2022-01-26 12:08:38 +05:30
it_behaves_like 'it has loose foreign keys' do
let ( :factory_name ) { :user }
end
2022-07-16 23:28:13 +05:30
2022-08-27 11:52:29 +05:30
describe 'user age' do
let ( :user ) { create ( :user , created_at : Date . yesterday ) }
it 'returns age in days' do
expect ( user . account_age_in_days ) . to be ( 1 )
end
end
2014-09-02 18:07:02 +05:30
end