2019-10-12 21:52:04 +05:30
# frozen_string_literal: true
2015-04-26 12:48:37 +05:30
require 'spec_helper'
2020-07-28 23:09:34 +05:30
RSpec . describe Gitlab :: Auth :: OAuth :: User do
2018-05-09 12:01:36 +05:30
include LdapHelpers
2017-09-10 17:25:29 +05:30
let ( :oauth_user ) { described_class . new ( auth_hash ) }
2022-06-21 17:19:12 +05:30
let ( :oauth_user_2 ) { described_class . new ( auth_hash_2 ) }
2015-04-26 12:48:37 +05:30
let ( :gl_user ) { oauth_user . gl_user }
2022-06-21 17:19:12 +05:30
let ( :gl_user_2 ) { oauth_user_2 . gl_user }
2015-04-26 12:48:37 +05:30
let ( :uid ) { 'my-uid' }
2022-06-21 17:19:12 +05:30
let ( :uid_2 ) { 'my-uid-2' }
2018-03-17 18:26:18 +05:30
let ( :dn ) { 'uid=user1,ou=people,dc=example' }
2015-04-26 12:48:37 +05:30
let ( :provider ) { 'my-provider' }
2015-09-25 12:07:36 +05:30
let ( :auth_hash ) { OmniAuth :: AuthHash . new ( uid : uid , provider : provider , info : info_hash ) }
2022-06-21 17:19:12 +05:30
let ( :auth_hash_2 ) { OmniAuth :: AuthHash . new ( uid : uid_2 , provider : provider , info : info_hash ) }
2015-04-26 12:48:37 +05:30
let ( :info_hash ) do
{
nickname : '-john+gitlab-ETC%.git@gmail.com' ,
name : 'John' ,
2018-03-17 18:26:18 +05:30
email : 'john@mail.com' ,
address : {
locality : 'locality' ,
country : 'country'
}
2015-04-26 12:48:37 +05:30
}
end
2020-10-24 23:57:45 +05:30
2020-04-08 14:13:33 +05:30
let ( :ldap_user ) { Gitlab :: Auth :: Ldap :: Person . new ( Net :: LDAP :: Entry . new , 'ldapmain' ) }
2022-06-21 17:19:12 +05:30
let ( :ldap_user_2 ) { Gitlab :: Auth :: Ldap :: Person . new ( Net :: LDAP :: Entry . new , 'ldapmain' ) }
2015-04-26 12:48:37 +05:30
2021-02-22 17:27:13 +05:30
describe '.find_by_uid_and_provider' do
let ( :dn ) { 'CN=John Åström, CN=Users, DC=Example, DC=com' }
it 'retrieves the correct user' do
special_info = {
name : 'John Åström' ,
email : 'john@example.com' ,
nickname : 'jastrom'
}
special_hash = OmniAuth :: AuthHash . new ( uid : dn , provider : 'ldapmain' , info : special_info )
special_chars_user = described_class . new ( special_hash )
user = special_chars_user . save
expect ( described_class . find_by_uid_and_provider ( dn , 'ldapmain' ) ) . to eq user
end
end
2016-06-02 11:05:42 +05:30
describe '#persisted?' do
2015-04-26 12:48:37 +05:30
let! ( :existing_user ) { create ( :omniauth_user , extern_uid : 'my-uid' , provider : 'my-provider' ) }
it " finds an existing user based on uid and provider (facebook) " do
2022-06-21 17:19:12 +05:30
expect ( oauth_user . persisted? ) . to be_truthy
2015-04-26 12:48:37 +05:30
end
2016-06-02 11:05:42 +05:30
it 'returns false if user is not found in database' do
2015-09-11 14:41:01 +05:30
allow ( auth_hash ) . to receive ( :uid ) . and_return ( 'non-existing' )
2022-06-21 17:19:12 +05:30
expect ( oauth_user . persisted? ) . to be_falsey
2015-04-26 12:48:37 +05:30
end
end
2017-09-10 17:25:29 +05:30
def stub_omniauth_config ( messages )
allow ( Gitlab . config . omniauth ) . to receive_messages ( messages )
end
2015-09-11 14:41:01 +05:30
2017-09-10 17:25:29 +05:30
describe '#save' do
2015-04-26 12:48:37 +05:30
let ( :provider ) { 'twitter' }
2018-03-17 18:26:18 +05:30
describe 'when account exists on server' do
it 'does not mark the user as external' do
create ( :omniauth_user , extern_uid : 'my-uid' , provider : provider )
stub_omniauth_config ( allow_single_sign_on : [ provider ] , external_providers : [ provider ] )
2022-04-04 11:22:00 +05:30
oauth_user . save # rubocop:disable Rails/SaveBang
2018-03-17 18:26:18 +05:30
expect ( gl_user ) . to be_valid
expect ( gl_user . external ) . to be_falsey
end
end
2015-04-26 12:48:37 +05:30
describe 'signup' do
2017-08-17 22:00:37 +05:30
context 'when signup is disabled' do
before do
stub_application_setting signup_enabled : false
2022-06-21 17:19:12 +05:30
stub_omniauth_config ( allow_single_sign_on : [ provider ] )
2017-08-17 22:00:37 +05:30
end
it 'creates the user' do
2022-04-04 11:22:00 +05:30
oauth_user . save # rubocop:disable Rails/SaveBang
2017-08-17 22:00:37 +05:30
expect ( gl_user ) . to be_persisted
end
2022-06-21 17:19:12 +05:30
it 'does not repeat the default user password' do
oauth_user . save # rubocop:disable Rails/SaveBang
oauth_user_2 . save # rubocop:disable Rails/SaveBang
expect ( gl_user . password ) . not_to eq ( gl_user_2 . password )
end
it 'has the password length within specified range' do
oauth_user . save # rubocop:disable Rails/SaveBang
expect ( gl_user . password . length ) . to be_between ( Devise . password_length . min , Devise . password_length . max )
end
2017-08-17 22:00:37 +05:30
end
context 'when user confirmation email is enabled' do
before do
2023-03-04 22:38:38 +05:30
stub_application_setting_enum ( 'email_confirmation_setting' , 'hard' )
2017-08-17 22:00:37 +05:30
end
it 'creates and confirms the user anyway' do
2018-03-17 18:26:18 +05:30
stub_omniauth_config ( allow_single_sign_on : [ provider ] )
2017-08-17 22:00:37 +05:30
2022-04-04 11:22:00 +05:30
oauth_user . save # rubocop:disable Rails/SaveBang
2017-08-17 22:00:37 +05:30
expect ( gl_user ) . to be_persisted
expect ( gl_user ) . to be_confirmed
end
end
2020-03-13 15:44:24 +05:30
context 'when the current minimum password length is different from the default minimum password length' do
before do
stub_application_setting minimum_password_length : 21
end
it 'creates the user' do
stub_omniauth_config ( allow_single_sign_on : [ provider ] )
2022-04-04 11:22:00 +05:30
oauth_user . save # rubocop:disable Rails/SaveBang
2020-03-13 15:44:24 +05:30
expect ( gl_user ) . to be_persisted
end
end
2017-08-17 22:00:37 +05:30
it 'marks user as having password_automatically_set' do
2018-03-17 18:26:18 +05:30
stub_omniauth_config ( allow_single_sign_on : [ provider ] , external_providers : [ provider ] )
2017-08-17 22:00:37 +05:30
2022-04-04 11:22:00 +05:30
oauth_user . save # rubocop:disable Rails/SaveBang
2017-08-17 22:00:37 +05:30
expect ( gl_user ) . to be_persisted
expect ( gl_user ) . to be_password_automatically_set
end
2016-06-02 11:05:42 +05:30
shared_examples 'to verify compliance with allow_single_sign_on' do
context 'provider is marked as external' do
2016-09-13 17:45:13 +05:30
it 'marks user as external' do
2018-03-17 18:26:18 +05:30
stub_omniauth_config ( allow_single_sign_on : [ provider ] , external_providers : [ provider ] )
2022-04-04 11:22:00 +05:30
oauth_user . save # rubocop:disable Rails/SaveBang
2016-06-02 11:05:42 +05:30
expect ( gl_user ) . to be_valid
expect ( gl_user . external ) . to be_truthy
end
end
context 'provider was external, now has been removed' do
2016-09-13 17:45:13 +05:30
it 'does not mark external user as internal' do
2018-03-17 18:26:18 +05:30
create ( :omniauth_user , extern_uid : 'my-uid' , provider : provider , external : true )
stub_omniauth_config ( allow_single_sign_on : [ provider ] , external_providers : [ 'facebook' ] )
2022-04-04 11:22:00 +05:30
oauth_user . save # rubocop:disable Rails/SaveBang
2016-06-02 11:05:42 +05:30
expect ( gl_user ) . to be_valid
2016-08-24 12:49:21 +05:30
expect ( gl_user . external ) . to be_truthy
end
end
context 'provider is not external' do
context 'when adding a new OAuth identity' do
2016-09-13 17:45:13 +05:30
it 'does not promote an external user to internal' do
2016-08-24 12:49:21 +05:30
user = create ( :user , email : 'john@mail.com' , external : true )
2022-04-04 11:22:00 +05:30
user . identities . create! ( provider : provider , extern_uid : uid )
2016-08-24 12:49:21 +05:30
2022-04-04 11:22:00 +05:30
oauth_user . save # rubocop:disable Rails/SaveBang
2016-08-24 12:49:21 +05:30
expect ( gl_user ) . to be_valid
expect ( gl_user . external ) . to be_truthy
end
2016-06-02 11:05:42 +05:30
end
end
context 'with new allow_single_sign_on enabled syntax' do
2017-09-10 17:25:29 +05:30
before do
2018-03-17 18:26:18 +05:30
stub_omniauth_config ( allow_single_sign_on : [ provider ] )
2017-09-10 17:25:29 +05:30
end
2016-04-02 18:10:28 +05:30
it " creates a user from Omniauth " do
2022-04-04 11:22:00 +05:30
oauth_user . save # rubocop:disable Rails/SaveBang
2016-04-02 18:10:28 +05:30
expect ( gl_user ) . to be_valid
identity = gl_user . identities . first
expect ( identity . extern_uid ) . to eql uid
2018-03-17 18:26:18 +05:30
expect ( identity . provider ) . to eql provider
2016-04-02 18:10:28 +05:30
end
end
context " with old allow_single_sign_on enabled syntax " do
2017-09-10 17:25:29 +05:30
before do
stub_omniauth_config ( allow_single_sign_on : true )
end
2015-04-26 12:48:37 +05:30
2015-09-11 14:41:01 +05:30
it " creates a user from Omniauth " do
2022-04-04 11:22:00 +05:30
oauth_user . save # rubocop:disable Rails/SaveBang
2015-09-11 14:41:01 +05:30
expect ( gl_user ) . to be_valid
identity = gl_user . identities . first
expect ( identity . extern_uid ) . to eql uid
2018-03-17 18:26:18 +05:30
expect ( identity . provider ) . to eql provider
2015-09-11 14:41:01 +05:30
end
end
2015-04-26 12:48:37 +05:30
2016-06-02 11:05:42 +05:30
context 'with new allow_single_sign_on disabled syntax' do
2017-09-10 17:25:29 +05:30
before do
stub_omniauth_config ( allow_single_sign_on : [ ] )
end
2016-06-02 11:05:42 +05:30
it 'throws an error' do
2022-04-04 11:22:00 +05:30
expect { oauth_user . save } . to raise_error StandardError # rubocop:disable Rails/SaveBang
2016-04-02 18:10:28 +05:30
end
end
2016-06-02 11:05:42 +05:30
context 'with old allow_single_sign_on disabled (Default)' do
2017-09-10 17:25:29 +05:30
before do
stub_omniauth_config ( allow_single_sign_on : false )
end
2016-06-02 11:05:42 +05:30
it 'throws an error' do
2022-04-04 11:22:00 +05:30
expect { oauth_user . save } . to raise_error StandardError # rubocop:disable Rails/SaveBang
2015-09-11 14:41:01 +05:30
end
2015-04-26 12:48:37 +05:30
end
end
2020-10-24 23:57:45 +05:30
context " with auto_link_user disabled (default) " do
before do
stub_omniauth_config ( auto_link_user : false )
end
include_examples " to verify compliance with allow_single_sign_on "
end
2020-11-24 15:15:51 +05:30
context " with auto_link_user enabled for a different provider " do
before do
stub_omniauth_config ( auto_link_user : [ 'saml' ] )
end
context " and a current GitLab user with a matching email " do
let! ( :existing_user ) { create ( :user , email : 'john@mail.com' , username : 'john' ) }
it " adds the OmniAuth identity to the GitLab user account " do
2022-04-04 11:22:00 +05:30
oauth_user . save # rubocop:disable Rails/SaveBang
2020-11-24 15:15:51 +05:30
expect ( gl_user ) . not_to be_valid
end
end
context " and no current GitLab user with a matching email " do
include_examples " to verify compliance with allow_single_sign_on "
end
end
context " with auto_link_user enabled for the correct provider " do
before do
stub_omniauth_config ( auto_link_user : [ 'twitter' ] )
end
context " and a current GitLab user with a matching email " do
let! ( :existing_user ) { create ( :user , email : 'john@mail.com' , username : 'john' ) }
it " adds the OmniAuth identity to the GitLab user account " do
2022-04-04 11:22:00 +05:30
oauth_user . save # rubocop:disable Rails/SaveBang
2020-11-24 15:15:51 +05:30
expect ( gl_user ) . to be_valid
expect ( gl_user . username ) . to eql 'john'
expect ( gl_user . email ) . to eql 'john@mail.com'
expect ( gl_user . identities . length ) . to be 1
identities_as_hash = gl_user . identities . map { | id | { provider : id . provider , extern_uid : id . extern_uid } }
expect ( identities_as_hash ) . to match_array (
[
{ provider : 'twitter' , extern_uid : uid }
]
)
end
end
context " and no current GitLab user with a matching email " do
include_examples " to verify compliance with allow_single_sign_on "
end
end
context " with auto_link_user enabled for all providers " do
2020-10-24 23:57:45 +05:30
before do
stub_omniauth_config ( auto_link_user : true )
end
context " and a current GitLab user with a matching email " do
let! ( :existing_user ) { create ( :user , email : 'john@mail.com' , username : 'john' ) }
it " adds the OmniAuth identity to the GitLab user account " do
2022-04-04 11:22:00 +05:30
oauth_user . save # rubocop:disable Rails/SaveBang
2020-10-24 23:57:45 +05:30
expect ( gl_user ) . to be_valid
expect ( gl_user . username ) . to eql 'john'
expect ( gl_user . email ) . to eql 'john@mail.com'
expect ( gl_user . identities . length ) . to be 1
identities_as_hash = gl_user . identities . map { | id | { provider : id . provider , extern_uid : id . extern_uid } }
expect ( identities_as_hash ) . to match_array (
[
{ provider : 'twitter' , extern_uid : uid }
]
)
end
end
context " and no current GitLab user with a matching email " do
include_examples " to verify compliance with allow_single_sign_on "
end
end
2015-09-11 14:41:01 +05:30
context " with auto_link_ldap_user disabled (default) " do
2017-09-10 17:25:29 +05:30
before do
stub_omniauth_config ( auto_link_ldap_user : false )
end
2015-09-11 14:41:01 +05:30
include_examples " to verify compliance with allow_single_sign_on "
end
context " with auto_link_ldap_user enabled " do
2017-09-10 17:25:29 +05:30
before do
stub_omniauth_config ( auto_link_ldap_user : true )
end
2015-09-11 14:41:01 +05:30
context " and no LDAP provider defined " do
2017-09-10 17:25:29 +05:30
before do
stub_ldap_config ( providers : [ ] )
end
2015-09-11 14:41:01 +05:30
include_examples " to verify compliance with allow_single_sign_on "
end
context " and at least one LDAP provider is defined " do
2017-09-10 17:25:29 +05:30
before do
stub_ldap_config ( providers : %w( ldapmain ) )
end
2015-09-11 14:41:01 +05:30
context " and a corresponding LDAP person " do
before do
allow ( ldap_user ) . to receive ( :uid ) { uid }
allow ( ldap_user ) . to receive ( :username ) { uid }
2019-07-07 11:18:12 +05:30
allow ( ldap_user ) . to receive ( :name ) { 'John Doe' }
2016-08-24 12:49:21 +05:30
allow ( ldap_user ) . to receive ( :email ) { [ 'johndoe@example.com' , 'john2@example.com' ] }
2018-03-17 18:26:18 +05:30
allow ( ldap_user ) . to receive ( :dn ) { dn }
2022-06-21 17:19:12 +05:30
allow ( ldap_user_2 ) . to receive ( :uid ) { uid_2 }
allow ( ldap_user_2 ) . to receive ( :username ) { uid_2 }
allow ( ldap_user_2 ) . to receive ( :name ) { 'Beck Potter' }
allow ( ldap_user_2 ) . to receive ( :email ) { [ 'beckpotter@example.com' , 'beck2@example.com' ] }
allow ( ldap_user_2 ) . to receive ( :dn ) { dn }
2015-09-11 14:41:01 +05:30
end
context " and no account for the LDAP user " do
2020-10-24 23:57:45 +05:30
context 'when the LDAP user is found by UID' do
before do
allow ( Gitlab :: Auth :: Ldap :: Person ) . to receive ( :find_by_uid ) . and_return ( ldap_user )
2016-11-24 13:41:30 +05:30
2022-04-04 11:22:00 +05:30
oauth_user . save # rubocop:disable Rails/SaveBang
2020-10-24 23:57:45 +05:30
end
2015-09-11 14:41:01 +05:30
2022-06-21 17:19:12 +05:30
it 'does not repeat the default user password' do
allow ( Gitlab :: Auth :: Ldap :: Person ) . to receive ( :find_by_uid ) . and_return ( ldap_user_2 )
oauth_user_2 . save # rubocop:disable Rails/SaveBang
expect ( gl_user . password ) . not_to eq ( gl_user_2 . password )
end
2020-10-24 23:57:45 +05:30
it " creates a user with dual LDAP and omniauth identities " do
expect ( gl_user ) . to be_valid
expect ( gl_user . username ) . to eql uid
expect ( gl_user . name ) . to eql 'John Doe'
expect ( gl_user . email ) . to eql 'johndoe@example.com'
expect ( gl_user . identities . length ) . to be 2
identities_as_hash = gl_user . identities . map { | id | { provider : id . provider , extern_uid : id . extern_uid } }
expect ( identities_as_hash ) . to match_array (
[
{ provider : 'ldapmain' , extern_uid : dn } ,
{ provider : 'twitter' , extern_uid : uid }
]
)
end
2018-03-17 18:26:18 +05:30
2020-10-24 23:57:45 +05:30
it " has name and email set as synced " do
expect ( gl_user . user_synced_attributes_metadata . name_synced ) . to be_truthy
expect ( gl_user . user_synced_attributes_metadata . email_synced ) . to be_truthy
end
2018-03-17 18:26:18 +05:30
2020-10-24 23:57:45 +05:30
it " has name and email set as read-only " do
expect ( gl_user . read_only_attribute? ( :name ) ) . to be_truthy
expect ( gl_user . read_only_attribute? ( :email ) ) . to be_truthy
end
it " has synced attributes provider set to ldapmain " do
expect ( gl_user . user_synced_attributes_metadata . provider ) . to eql 'ldapmain'
end
2018-03-17 18:26:18 +05:30
end
2020-10-24 23:57:45 +05:30
context 'when the LDAP user is found by email address' do
before do
allow ( Gitlab :: Auth :: Ldap :: Person ) . to receive ( :find_by_uid ) . and_return ( nil )
allow ( Gitlab :: Auth :: Ldap :: Person ) . to receive ( :find_by_email ) . with ( uid , any_args ) . and_return ( nil )
allow ( Gitlab :: Auth :: Ldap :: Person ) . to receive ( :find_by_email ) . with ( info_hash [ :email ] , any_args ) . and_return ( ldap_user )
2022-04-04 11:22:00 +05:30
oauth_user . save # rubocop:disable Rails/SaveBang
2020-10-24 23:57:45 +05:30
end
it 'creates the LDAP identity' do
identities_as_hash = gl_user . identities . map { | id | { provider : id . provider , extern_uid : id . extern_uid } }
expect ( identities_as_hash ) . to include ( { provider : 'ldapmain' , extern_uid : dn } )
end
2018-03-17 18:26:18 +05:30
end
2015-09-11 14:41:01 +05:30
end
context " and LDAP user has an account already " do
2019-07-07 11:18:12 +05:30
let! ( :existing_user ) { create ( :omniauth_user , name : 'John Doe' , email : 'john@example.com' , extern_uid : dn , provider : 'ldapmain' , username : 'john' ) }
2020-01-01 13:55:28 +05:30
2015-09-11 14:41:01 +05:30
it " adds the omniauth identity to the LDAP account " do
2020-04-08 14:13:33 +05:30
allow ( Gitlab :: Auth :: Ldap :: Person ) . to receive ( :find_by_uid ) . and_return ( ldap_user )
2016-11-24 13:41:30 +05:30
2022-04-04 11:22:00 +05:30
oauth_user . save # rubocop:disable Rails/SaveBang
2015-09-11 14:41:01 +05:30
expect ( gl_user ) . to be_valid
expect ( gl_user . username ) . to eql 'john'
2019-07-07 11:18:12 +05:30
expect ( gl_user . name ) . to eql 'John Doe'
2015-09-11 14:41:01 +05:30
expect ( gl_user . email ) . to eql 'john@example.com'
2017-08-17 22:00:37 +05:30
expect ( gl_user . identities . length ) . to be 2
2015-09-11 14:41:01 +05:30
identities_as_hash = gl_user . identities . map { | id | { provider : id . provider , extern_uid : id . extern_uid } }
expect ( identities_as_hash ) . to match_array (
2017-08-17 22:00:37 +05:30
[
2018-03-17 18:26:18 +05:30
{ provider : 'ldapmain' , extern_uid : dn } ,
2015-09-11 14:41:01 +05:30
{ provider : 'twitter' , extern_uid : uid }
2017-08-17 22:00:37 +05:30
]
)
2015-09-11 14:41:01 +05:30
end
end
2016-11-24 13:41:30 +05:30
context 'when an LDAP person is not found by uid' do
2018-05-09 12:01:36 +05:30
it 'tries to find an LDAP person by email and adds the omniauth identity to the user' do
2020-04-08 14:13:33 +05:30
allow ( Gitlab :: Auth :: Ldap :: Person ) . to receive ( :find_by_uid ) . and_return ( nil )
allow ( Gitlab :: Auth :: Ldap :: Person ) . to receive ( :find_by_email ) . and_return ( ldap_user )
2018-05-09 12:01:36 +05:30
2022-04-04 11:22:00 +05:30
oauth_user . save # rubocop:disable Rails/SaveBang
2018-05-09 12:01:36 +05:30
identities_as_hash = gl_user . identities . map { | id | { provider : id . provider , extern_uid : id . extern_uid } }
expect ( identities_as_hash ) . to match_array ( result_identities ( dn , uid ) )
end
context 'when also not found by email' do
it 'tries to find an LDAP person by DN and adds the omniauth identity to the user' do
2020-04-08 14:13:33 +05:30
allow ( Gitlab :: Auth :: Ldap :: Person ) . to receive ( :find_by_uid ) . and_return ( nil )
allow ( Gitlab :: Auth :: Ldap :: Person ) . to receive ( :find_by_email ) . and_return ( nil )
allow ( Gitlab :: Auth :: Ldap :: Person ) . to receive ( :find_by_dn ) . and_return ( ldap_user )
2018-05-09 12:01:36 +05:30
2022-04-04 11:22:00 +05:30
oauth_user . save # rubocop:disable Rails/SaveBang
2018-05-09 12:01:36 +05:30
identities_as_hash = gl_user . identities . map { | id | { provider : id . provider , extern_uid : id . extern_uid } }
expect ( identities_as_hash ) . to match_array ( result_identities ( dn , uid ) )
end
end
end
2016-11-24 13:41:30 +05:30
2018-05-09 12:01:36 +05:30
def result_identities ( dn , uid )
[
{ provider : 'ldapmain' , extern_uid : dn } ,
{ provider : 'twitter' , extern_uid : uid }
]
end
context 'when there is an LDAP connection error' do
before do
raise_ldap_connection_error
end
it 'does not save the identity' do
2022-04-04 11:22:00 +05:30
oauth_user . save # rubocop:disable Rails/SaveBang
2016-11-24 13:41:30 +05:30
identities_as_hash = gl_user . identities . map { | id | { provider : id . provider , extern_uid : id . extern_uid } }
2018-05-09 12:01:36 +05:30
expect ( identities_as_hash ) . to match_array ( [ { provider : 'twitter' , extern_uid : uid } ] )
2016-11-24 13:41:30 +05:30
end
end
2015-09-11 14:41:01 +05:30
end
2018-03-17 18:26:18 +05:30
context 'and a corresponding LDAP person with a non-default username' do
before do
allow ( ldap_user ) . to receive ( :uid ) { uid }
allow ( ldap_user ) . to receive ( :username ) { 'johndoe@example.com' }
allow ( ldap_user ) . to receive ( :email ) { %w( johndoe@example.com john2@example.com ) }
allow ( ldap_user ) . to receive ( :dn ) { dn }
end
context 'and no account for the LDAP user' do
it 'creates a user favoring the LDAP username and strips email domain' do
2020-04-08 14:13:33 +05:30
allow ( Gitlab :: Auth :: Ldap :: Person ) . to receive ( :find_by_uid ) . and_return ( ldap_user )
2018-03-17 18:26:18 +05:30
2022-04-04 11:22:00 +05:30
oauth_user . save # rubocop:disable Rails/SaveBang
2018-03-17 18:26:18 +05:30
expect ( gl_user ) . to be_valid
expect ( gl_user . username ) . to eql 'johndoe'
end
end
end
2015-09-11 14:41:01 +05:30
context " and no corresponding LDAP person " do
2017-09-10 17:25:29 +05:30
before do
2020-04-08 14:13:33 +05:30
allow ( Gitlab :: Auth :: Ldap :: Person ) . to receive ( :find_by_uid ) . and_return ( nil )
2017-09-10 17:25:29 +05:30
end
2015-09-11 14:41:01 +05:30
include_examples " to verify compliance with allow_single_sign_on "
end
2015-04-26 12:48:37 +05:30
end
end
2020-10-24 23:57:45 +05:30
context " with both auto_link_user and auto_link_ldap_user enabled " do
before do
2020-11-24 15:15:51 +05:30
stub_omniauth_config ( auto_link_user : [ 'twitter' ] , auto_link_ldap_user : true )
2020-10-24 23:57:45 +05:30
end
context " and at least one LDAP provider is defined " do
before do
stub_ldap_config ( providers : %w( ldapmain ) )
end
context " and a corresponding LDAP person " do
before do
allow ( ldap_user ) . to receive_messages (
uid : uid ,
username : uid ,
name : 'John Doe' ,
email : [ 'john@mail.com' ] ,
dn : dn
)
end
context " and no account for the LDAP user " do
before do
allow ( Gitlab :: Auth :: Ldap :: Person ) . to receive ( :find_by_uid ) . and_return ( ldap_user )
2022-04-04 11:22:00 +05:30
oauth_user . save # rubocop:disable Rails/SaveBang
2020-10-24 23:57:45 +05:30
end
it " creates a user with dual LDAP and omniauth identities " do
expect ( gl_user ) . to be_valid
expect ( gl_user . username ) . to eql uid
expect ( gl_user . name ) . to eql 'John Doe'
expect ( gl_user . email ) . to eql 'john@mail.com'
expect ( gl_user . identities . length ) . to be 2
identities_as_hash = gl_user . identities . map { | id | { provider : id . provider , extern_uid : id . extern_uid } }
expect ( identities_as_hash ) . to match_array (
[
{ provider : 'ldapmain' , extern_uid : dn } ,
{ provider : 'twitter' , extern_uid : uid }
]
)
end
it " has name and email set as synced " do
expect ( gl_user . user_synced_attributes_metadata . name_synced ) . to be_truthy
expect ( gl_user . user_synced_attributes_metadata . email_synced ) . to be_truthy
end
it " has name and email set as read-only " do
expect ( gl_user . read_only_attribute? ( :name ) ) . to be_truthy
expect ( gl_user . read_only_attribute? ( :email ) ) . to be_truthy
end
it " has synced attributes provider set to ldapmain " do
expect ( gl_user . user_synced_attributes_metadata . provider ) . to eql 'ldapmain'
end
end
context " and LDAP user has an account already " do
let! ( :existing_user ) { create ( :omniauth_user , name : 'John Doe' , email : 'john@mail.com' , extern_uid : dn , provider : 'ldapmain' , username : 'john' ) }
it " adds the omniauth identity to the LDAP account " do
allow ( Gitlab :: Auth :: Ldap :: Person ) . to receive ( :find_by_uid ) . and_return ( ldap_user )
2022-04-04 11:22:00 +05:30
oauth_user . save # rubocop:disable Rails/SaveBang
2020-10-24 23:57:45 +05:30
expect ( gl_user ) . to be_valid
expect ( gl_user . username ) . to eql 'john'
expect ( gl_user . name ) . to eql 'John Doe'
expect ( gl_user . email ) . to eql 'john@mail.com'
expect ( gl_user . identities . length ) . to be 2
identities_as_hash = gl_user . identities . map { | id | { provider : id . provider , extern_uid : id . extern_uid } }
expect ( identities_as_hash ) . to match_array (
[
{ provider : 'ldapmain' , extern_uid : dn } ,
{ provider : 'twitter' , extern_uid : uid }
]
)
end
end
end
end
end
2015-04-26 12:48:37 +05:30
end
describe 'blocking' do
let ( :provider ) { 'twitter' }
2017-09-10 17:25:29 +05:30
before do
stub_omniauth_config ( allow_single_sign_on : [ 'twitter' ] )
end
2015-04-26 12:48:37 +05:30
2022-05-07 20:08:51 +05:30
shared_examples 'being blocked on creation' do
context 'when blocking on creation' do
it 'creates a blocked user' do
oauth_user . save # rubocop:disable Rails/SaveBang
expect ( gl_user ) . to be_valid
expect ( gl_user ) . to be_blocked
2017-09-10 17:25:29 +05:30
end
2015-04-26 12:48:37 +05:30
2022-05-07 20:08:51 +05:30
context 'when a sign up user cap has been set up but has not been reached yet' do
it 'still creates a blocked user' do
stub_application_setting ( new_user_signups_cap : 999 )
oauth_user . save # rubocop:disable Rails/SaveBang
expect ( gl_user ) . to be_valid
expect ( gl_user ) . to be_blocked
end
end
end
end
shared_examples 'not being blocked on creation' do
context 'when not blocking on creation' do
it 'creates a non-blocked user' do
2022-04-04 11:22:00 +05:30
oauth_user . save # rubocop:disable Rails/SaveBang
2015-04-26 12:48:37 +05:30
expect ( gl_user ) . to be_valid
expect ( gl_user ) . not_to be_blocked
end
end
2022-05-07 20:08:51 +05:30
end
context 'signup with SAML' do
let ( :provider ) { 'saml' }
2022-06-21 17:19:12 +05:30
let ( :block_auto_created_users ) { false }
2022-05-07 20:08:51 +05:30
before do
stub_omniauth_config ( {
allow_single_sign_on : [ 'saml' ] ,
auto_link_saml_user : true ,
block_auto_created_users : block_auto_created_users
} )
end
it_behaves_like 'being blocked on creation' do
let ( :block_auto_created_users ) { true }
end
it_behaves_like 'not being blocked on creation' do
let ( :block_auto_created_users ) { false }
end
2022-06-21 17:19:12 +05:30
it 'does not repeat the default user password' do
oauth_user . save # rubocop:disable Rails/SaveBang
oauth_user_2 . save # rubocop:disable Rails/SaveBang
expect ( gl_user . password ) . not_to eq ( gl_user_2 . password )
end
2022-05-07 20:08:51 +05:30
end
2015-04-26 12:48:37 +05:30
2022-05-07 20:08:51 +05:30
context 'signup with omniauth only' do
it_behaves_like 'being blocked on creation' do
2017-09-10 17:25:29 +05:30
before do
stub_omniauth_config ( block_auto_created_users : true )
end
2022-05-07 20:08:51 +05:30
end
2015-04-26 12:48:37 +05:30
2022-05-07 20:08:51 +05:30
it_behaves_like 'not being blocked on creation' do
before do
stub_omniauth_config ( block_auto_created_users : false )
2015-04-26 12:48:37 +05:30
end
end
end
2015-09-11 14:41:01 +05:30
context 'signup with linked omniauth and LDAP account' do
before do
stub_omniauth_config ( auto_link_ldap_user : true )
2022-08-27 11:52:29 +05:30
stub_ldap_setting ( enabled : true )
2015-09-11 14:41:01 +05:30
allow ( ldap_user ) . to receive ( :uid ) { uid }
allow ( ldap_user ) . to receive ( :username ) { uid }
2016-08-24 12:49:21 +05:30
allow ( ldap_user ) . to receive ( :email ) { [ 'johndoe@example.com' , 'john2@example.com' ] }
2018-03-17 18:26:18 +05:30
allow ( ldap_user ) . to receive ( :dn ) { dn }
2020-04-08 14:13:33 +05:30
allow ( Gitlab :: Auth :: Ldap :: Person ) . to receive ( :find_by_uid ) . and_return ( ldap_user )
2015-09-11 14:41:01 +05:30
end
context " and no account for the LDAP user " do
2022-05-07 20:08:51 +05:30
it_behaves_like 'being blocked on creation' do
2017-09-10 17:25:29 +05:30
before do
2020-04-08 14:13:33 +05:30
allow_next_instance_of ( Gitlab :: Auth :: Ldap :: Config ) do | instance |
2022-05-07 20:08:51 +05:30
allow ( instance ) . to receive_messages ( block_auto_created_users : true )
2020-01-01 13:55:28 +05:30
end
2017-09-10 17:25:29 +05:30
end
2015-09-11 14:41:01 +05:30
end
2022-05-07 20:08:51 +05:30
it_behaves_like 'not being blocked on creation' do
2017-09-10 17:25:29 +05:30
before do
2020-04-08 14:13:33 +05:30
allow_next_instance_of ( Gitlab :: Auth :: Ldap :: Config ) do | instance |
2022-05-07 20:08:51 +05:30
allow ( instance ) . to receive_messages ( block_auto_created_users : false )
2020-01-01 13:55:28 +05:30
end
2017-09-10 17:25:29 +05:30
end
2015-09-11 14:41:01 +05:30
end
end
context 'and LDAP user has an account already' do
2018-03-17 18:26:18 +05:30
let! ( :existing_user ) { create ( :omniauth_user , email : 'john@example.com' , extern_uid : dn , provider : 'ldapmain' , username : 'john' ) }
2015-09-11 14:41:01 +05:30
2022-05-07 20:08:51 +05:30
it_behaves_like 'not being blocked on creation' do
2017-09-10 17:25:29 +05:30
before do
2020-04-08 14:13:33 +05:30
allow_next_instance_of ( Gitlab :: Auth :: Ldap :: Config ) do | instance |
2020-01-01 13:55:28 +05:30
allow ( instance ) . to receive_messages ( block_auto_created_users : false )
end
2017-09-10 17:25:29 +05:30
end
2015-09-11 14:41:01 +05:30
end
2022-05-07 20:08:51 +05:30
it_behaves_like 'not being blocked on creation' do
2017-09-10 17:25:29 +05:30
before do
2020-04-08 14:13:33 +05:30
allow_next_instance_of ( Gitlab :: Auth :: Ldap :: Config ) do | instance |
2020-01-01 13:55:28 +05:30
allow ( instance ) . to receive_messages ( block_auto_created_users : true )
end
2017-09-10 17:25:29 +05:30
end
2015-09-11 14:41:01 +05:30
end
end
end
2015-04-26 12:48:37 +05:30
context 'sign-in' do
before do
2022-04-04 11:22:00 +05:30
oauth_user . save # rubocop:disable Rails/SaveBang
2015-04-26 12:48:37 +05:30
oauth_user . gl_user . activate
end
2022-05-07 20:08:51 +05:30
it_behaves_like 'not being blocked on creation' do
2017-09-10 17:25:29 +05:30
before do
stub_omniauth_config ( block_auto_created_users : false )
end
2015-04-26 12:48:37 +05:30
end
2022-05-07 20:08:51 +05:30
it_behaves_like 'not being blocked on creation' do
2017-09-10 17:25:29 +05:30
before do
stub_omniauth_config ( block_auto_created_users : true )
end
2015-09-11 14:41:01 +05:30
end
2022-05-07 20:08:51 +05:30
it_behaves_like 'not being blocked on creation' do
2017-09-10 17:25:29 +05:30
before do
2020-04-08 14:13:33 +05:30
allow_next_instance_of ( Gitlab :: Auth :: Ldap :: Config ) do | instance |
2020-01-01 13:55:28 +05:30
allow ( instance ) . to receive_messages ( block_auto_created_users : false )
end
2017-09-10 17:25:29 +05:30
end
2015-09-11 14:41:01 +05:30
end
2022-05-07 20:08:51 +05:30
it_behaves_like 'not being blocked on creation' do
2017-09-10 17:25:29 +05:30
before do
2020-04-08 14:13:33 +05:30
allow_next_instance_of ( Gitlab :: Auth :: Ldap :: Config ) do | instance |
2020-01-01 13:55:28 +05:30
allow ( instance ) . to receive_messages ( block_auto_created_users : true )
end
2017-09-10 17:25:29 +05:30
end
2015-04-26 12:48:37 +05:30
end
end
end
end
2017-09-10 17:25:29 +05:30
2019-02-15 15:39:39 +05:30
describe 'ensure backwards compatibility with sync email from provider option' do
2017-09-10 17:25:29 +05:30
let! ( :existing_user ) { create ( :omniauth_user , extern_uid : 'my-uid' , provider : 'my-provider' ) }
before do
stub_omniauth_config ( sync_email_from_provider : 'my-provider' )
2018-03-17 18:26:18 +05:30
stub_omniauth_config ( sync_profile_from_provider : [ 'my-provider' ] )
2017-09-10 17:25:29 +05:30
end
context " when provider sets an email " do
it " updates the user email " do
expect ( gl_user . email ) . to eq ( info_hash [ :email ] )
end
2018-03-17 18:26:18 +05:30
it " has email set as synced " do
expect ( gl_user . user_synced_attributes_metadata . email_synced ) . to be_truthy
2017-09-10 17:25:29 +05:30
end
2018-03-17 18:26:18 +05:30
it " has email set as read-only " do
expect ( gl_user . read_only_attribute? ( :email ) ) . to be_truthy
end
it " has synced attributes provider set to my-provider " do
expect ( gl_user . user_synced_attributes_metadata . provider ) . to eql 'my-provider'
2017-09-10 17:25:29 +05:30
end
end
context " when provider doesn't set an email " do
before do
info_hash . delete ( :email )
end
it " does not update the user email " do
expect ( gl_user . email ) . not_to eq ( info_hash [ :email ] )
end
2018-03-17 18:26:18 +05:30
it " has email set as not synced " do
expect ( gl_user . user_synced_attributes_metadata . email_synced ) . to be_falsey
end
it " does not have email set as read-only " do
expect ( gl_user . read_only_attribute? ( :email ) ) . to be_falsey
2017-09-10 17:25:29 +05:30
end
end
end
describe 'generating username' do
context 'when no collision with existing user' do
it 'generates the username with no counter' do
expect ( gl_user . username ) . to eq ( 'johngitlab-ETC' )
end
end
context 'when collision with existing user' do
it 'generates the username with a counter' do
2022-04-04 11:22:00 +05:30
oauth_user . save # rubocop:disable Rails/SaveBang
2017-09-10 17:25:29 +05:30
oauth_user2 = described_class . new ( OmniAuth :: AuthHash . new ( uid : 'my-uid2' , provider : provider , info : { nickname : 'johngitlab-ETC@othermail.com' , email : 'john@othermail.com' } ) )
expect ( oauth_user2 . gl_user . username ) . to eq ( 'johngitlab-ETC1' )
end
end
context 'when username is a reserved word' do
let ( :info_hash ) do
{
nickname : 'admin@othermail.com' ,
email : 'admin@othermail.com'
}
end
2018-03-17 18:26:18 +05:30
2017-09-10 17:25:29 +05:30
it 'generates the username with a counter' do
expect ( gl_user . username ) . to eq ( 'admin1' )
end
end
end
2018-03-17 18:26:18 +05:30
describe 'updating email with sync profile' do
let! ( :existing_user ) { create ( :omniauth_user , extern_uid : 'my-uid' , provider : 'my-provider' ) }
before do
stub_omniauth_config ( sync_profile_from_provider : [ 'my-provider' ] )
stub_omniauth_config ( sync_profile_attributes : true )
end
context " when provider sets an email " do
it " updates the user email " do
expect ( gl_user . email ) . to eq ( info_hash [ :email ] )
end
it " has email set as synced " do
expect ( gl_user . user_synced_attributes_metadata . email_synced ) . to be ( true )
end
it " has email set as read-only " do
expect ( gl_user . read_only_attribute? ( :email ) ) . to be_truthy
end
it " has synced attributes provider set to my-provider " do
expect ( gl_user . user_synced_attributes_metadata . provider ) . to eql 'my-provider'
end
end
context " when provider doesn't set an email " do
before do
info_hash . delete ( :email )
end
it " does not update the user email " do
expect ( gl_user . email ) . not_to eq ( info_hash [ :email ] )
end
it " has email set as not synced " do
expect ( gl_user . user_synced_attributes_metadata . email_synced ) . to be_falsey
end
it " does not have email set as read-only " do
expect ( gl_user . read_only_attribute? ( :email ) ) . to be_falsey
end
end
end
describe 'updating name' do
let! ( :existing_user ) { create ( :omniauth_user , extern_uid : 'my-uid' , provider : 'my-provider' ) }
before do
stub_omniauth_setting ( sync_profile_from_provider : [ 'my-provider' ] )
stub_omniauth_setting ( sync_profile_attributes : true )
end
context " when provider sets a name " do
it " updates the user name " do
expect ( gl_user . name ) . to eq ( info_hash [ :name ] )
end
end
context " when provider doesn't set a name " do
before do
info_hash . delete ( :name )
end
it " does not update the user name " do
expect ( gl_user . name ) . not_to eq ( info_hash [ :name ] )
expect ( gl_user . user_synced_attributes_metadata . name_synced ) . to be ( false )
end
end
end
describe 'updating location' do
let! ( :existing_user ) { create ( :omniauth_user , extern_uid : 'my-uid' , provider : 'my-provider' ) }
before do
stub_omniauth_setting ( sync_profile_from_provider : [ 'my-provider' ] )
stub_omniauth_setting ( sync_profile_attributes : true )
end
context " when provider sets a location " do
it " updates the user location " do
expect ( gl_user . location ) . to eq ( info_hash [ :address ] [ :locality ] + ', ' + info_hash [ :address ] [ :country ] )
expect ( gl_user . user_synced_attributes_metadata . location_synced ) . to be ( true )
end
end
context " when provider doesn't set a location " do
before do
info_hash [ :address ] . delete ( :country )
info_hash [ :address ] . delete ( :locality )
end
it " does not update the user location " do
expect ( gl_user . location ) . to be_nil
expect ( gl_user . user_synced_attributes_metadata . location_synced ) . to be ( false )
end
end
end
describe 'updating user info' do
let! ( :existing_user ) { create ( :omniauth_user , extern_uid : 'my-uid' , provider : 'my-provider' ) }
context " update all info " do
before do
stub_omniauth_setting ( sync_profile_from_provider : [ 'my-provider' ] )
stub_omniauth_setting ( sync_profile_attributes : true )
end
it " updates the user email " do
expect ( gl_user . email ) . to eq ( info_hash [ :email ] )
expect ( gl_user . user_synced_attributes_metadata . email_synced ) . to be ( true )
end
it " updates the user name " do
expect ( gl_user . name ) . to eq ( info_hash [ :name ] )
expect ( gl_user . user_synced_attributes_metadata . name_synced ) . to be ( true )
end
it " updates the user location " do
expect ( gl_user . location ) . to eq ( info_hash [ :address ] [ :locality ] + ', ' + info_hash [ :address ] [ :country ] )
expect ( gl_user . user_synced_attributes_metadata . location_synced ) . to be ( true )
end
it " sets my-provider as the attributes provider " do
expect ( gl_user . user_synced_attributes_metadata . provider ) . to eql ( 'my-provider' )
end
end
context " update only requested info " do
before do
stub_omniauth_setting ( sync_profile_from_provider : [ 'my-provider' ] )
stub_omniauth_setting ( sync_profile_attributes : %w( name location ) )
end
it " updates the user name " do
expect ( gl_user . name ) . to eq ( info_hash [ :name ] )
expect ( gl_user . user_synced_attributes_metadata . name_synced ) . to be ( true )
end
it " updates the user location " do
expect ( gl_user . location ) . to eq ( info_hash [ :address ] [ :locality ] + ', ' + info_hash [ :address ] [ :country ] )
expect ( gl_user . user_synced_attributes_metadata . location_synced ) . to be ( true )
end
it " does not update the user email " do
expect ( gl_user . user_synced_attributes_metadata . email_synced ) . to be ( false )
end
end
context " update default_scope " do
before do
stub_omniauth_setting ( sync_profile_from_provider : [ 'my-provider' ] )
end
it " updates the user email " do
expect ( gl_user . email ) . to eq ( info_hash [ :email ] )
expect ( gl_user . user_synced_attributes_metadata . email_synced ) . to be ( true )
end
end
context " update no info when profile sync is nil " do
it " does not have sync_attribute " do
expect ( gl_user . user_synced_attributes_metadata ) . to be ( nil )
end
it " does not update the user email " do
expect ( gl_user . email ) . not_to eq ( info_hash [ :email ] )
end
it " does not update the user name " do
expect ( gl_user . name ) . not_to eq ( info_hash [ :name ] )
end
it " does not update the user location " do
expect ( gl_user . location ) . not_to eq ( info_hash [ :address ] [ :country ] )
end
it 'does not create associated user synced attributes metadata' do
expect ( gl_user . user_synced_attributes_metadata ) . to be_nil
end
end
end
2021-04-17 20:07:23 +05:30
context 'when gl_user is nil' do
# We can't use `allow_next_instance_of` here because the stubbed method is called inside `initialize`.
# When the class calls `gl_user` during `initialize`, the `nil` value is overwritten and we do not see expected results from the spec.
# So we use `allow_any_instance_of` to preserve the `nil` value to test the behavior when `gl_user` is nil.
# rubocop:disable RSpec/AnyInstanceOf
before do
allow_any_instance_of ( described_class ) . to receive ( :gl_user ) { nil }
allow_any_instance_of ( described_class ) . to receive ( :sync_profile_from_provider? ) { true } # to make the code flow proceed until gl_user.build_user_synced_attributes_metadata is called
end
# rubocop:enable RSpec/AnyInstanceOf
it 'does not raise NoMethodError' do
expect { oauth_user } . not_to raise_error
end
end
2020-10-24 23:57:45 +05:30
describe '._uid_and_provider' do
2018-03-17 18:26:18 +05:30
let! ( :existing_user ) { create ( :omniauth_user , extern_uid : 'my-uid' , provider : 'my-provider' ) }
it 'normalizes extern_uid' do
allow ( oauth_user . auth_hash ) . to receive ( :uid ) . and_return ( 'MY-UID' )
expect ( oauth_user . find_user ) . to eql gl_user
end
end
2018-05-09 12:01:36 +05:30
describe '#find_ldap_person' do
context 'when LDAP connection fails' do
before do
raise_ldap_connection_error
end
it 'returns nil' do
2020-04-08 14:13:33 +05:30
adapter = Gitlab :: Auth :: Ldap :: Adapter . new ( 'ldapmain' )
2018-05-09 12:01:36 +05:30
hash = OmniAuth :: AuthHash . new ( uid : 'whatever' , provider : 'ldapmain' )
expect ( oauth_user . send ( :find_ldap_person , hash , adapter ) ) . to be_nil
end
end
end
2018-11-08 19:23:39 +05:30
2019-12-04 20:38:33 +05:30
describe " # bypass_two_factor? " do
it " when with allow_bypass_two_factor disabled (Default) " do
stub_omniauth_config ( allow_bypass_two_factor : false )
expect ( oauth_user . bypass_two_factor? ) . to be_falsey
end
it " when with allow_bypass_two_factor enabled " do
stub_omniauth_config ( allow_bypass_two_factor : true )
expect ( oauth_user . bypass_two_factor? ) . to be_truthy
end
it " when provider in allow_bypass_two_factor array " do
stub_omniauth_config ( allow_bypass_two_factor : [ provider ] )
expect ( oauth_user . bypass_two_factor? ) . to be_truthy
end
2018-11-08 19:23:39 +05:30
2019-12-04 20:38:33 +05:30
it " when provider not in allow_bypass_two_factor array " do
stub_omniauth_config ( allow_bypass_two_factor : [ " foo " ] )
expect ( oauth_user . bypass_two_factor? ) . to be_falsey
2018-11-08 19:23:39 +05:30
end
end
2022-05-07 20:08:51 +05:30
describe '#protocol_name' do
it 'is OAuth' do
expect ( oauth_user . protocol_name ) . to eq ( 'OAuth' )
end
end
2015-04-26 12:48:37 +05:30
end