user_spec.rb 12.5 KB
Newer Older
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
1 2
require 'spec_helper'

Douwe Maan's avatar
Douwe Maan committed
3
describe Gitlab::OAuth::User, lib: true do
4 5 6 7
  let(:oauth_user) { Gitlab::OAuth::User.new(auth_hash) }
  let(:gl_user) { oauth_user.gl_user }
  let(:uid) { 'my-uid' }
  let(:provider) { 'my-provider' }
8
  let(:auth_hash) { OmniAuth::AuthHash.new(uid: uid, provider: provider, info: info_hash) }
9 10
  let(:info_hash) do
    {
11
      nickname: '-john+gitlab-ETC%.git@gmail.com',
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
12 13
      name: 'John',
      email: 'john@mail.com'
14
    }
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
15
  end
16
  let(:ldap_user) { Gitlab::LDAP::Person.new(Net::LDAP::Entry.new, 'ldapmain') }
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
17

18
  describe '#persisted?' do
19
    let!(:existing_user) { create(:omniauth_user, extern_uid: 'my-uid', provider: 'my-provider') }
20 21

    it "finds an existing user based on uid and provider (facebook)" do
22
      expect( oauth_user.persisted? ).to be_truthy
23 24
    end

25
    it 'returns false if user is not found in database' do
26
      allow(auth_hash).to receive(:uid).and_return('non-existing')
27
      expect( oauth_user.persisted? ).to be_falsey
28 29 30
    end
  end

31
  describe '#save' do
32 33 34 35 36 37 38 39
    def stub_omniauth_config(messages)
      allow(Gitlab.config.omniauth).to receive_messages(messages)
    end

    def stub_ldap_config(messages)
      allow(Gitlab::LDAP::Config).to receive_messages(messages)
    end

40
    let(:provider) { 'twitter' }
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
41

42
    describe 'signup' do
43 44 45 46 47 48 49 50 51
      it 'marks user as having password_automatically_set' do
        stub_omniauth_config(allow_single_sign_on: ['twitter'], external_providers: ['twitter'])

        oauth_user.save

        expect(gl_user).to be_persisted
        expect(gl_user).to be_password_automatically_set
      end

52 53
      shared_examples 'to verify compliance with allow_single_sign_on' do
        context 'provider is marked as external' do
54
          it 'marks user as external' do
55 56 57 58 59 60 61 62
            stub_omniauth_config(allow_single_sign_on: ['twitter'], external_providers: ['twitter'])
            oauth_user.save
            expect(gl_user).to be_valid
            expect(gl_user.external).to be_truthy
          end
        end

        context 'provider was external, now has been removed' do
63
          it 'does not mark external user as internal' do
64 65 66 67
            create(:omniauth_user, extern_uid: 'my-uid', provider: 'twitter', external: true)
            stub_omniauth_config(allow_single_sign_on: ['twitter'], external_providers: ['facebook'])
            oauth_user.save
            expect(gl_user).to be_valid
68 69 70 71 72 73
            expect(gl_user.external).to be_truthy
          end
        end

        context 'provider is not external' do
          context 'when adding a new OAuth identity' do
74
            it 'does not promote an external user to internal' do
75 76 77 78 79 80 81
              user = create(:user, email: 'john@mail.com', external: true)
              user.identities.create(provider: provider, extern_uid: uid)

              oauth_user.save
              expect(gl_user).to be_valid
              expect(gl_user.external).to be_truthy
            end
82 83 84 85
          end
        end

        context 'with new allow_single_sign_on enabled syntax' do
86
          before { stub_omniauth_config(allow_single_sign_on: ['twitter']) }
87

88 89
          it "creates a user from Omniauth" do
            oauth_user.save
90

91 92 93 94 95 96 97
            expect(gl_user).to be_valid
            identity = gl_user.identities.first
            expect(identity.extern_uid).to eql uid
            expect(identity.provider).to eql 'twitter'
          end
        end

98 99 100 101 102 103 104 105 106 107 108 109 110
        context "with old allow_single_sign_on enabled syntax" do
          before { stub_omniauth_config(allow_single_sign_on: true) }

          it "creates a user from Omniauth" do
            oauth_user.save

            expect(gl_user).to be_valid
            identity = gl_user.identities.first
            expect(identity.extern_uid).to eql uid
            expect(identity.provider).to eql 'twitter'
          end
        end

111
        context 'with new allow_single_sign_on disabled syntax' do
112
          before { stub_omniauth_config(allow_single_sign_on: []) }
113
          it 'throws an error' do
114 115
            expect{ oauth_user.save }.to raise_error StandardError
          end
116
        end
117

118
        context 'with old allow_single_sign_on disabled (Default)' do
119
          before { stub_omniauth_config(allow_single_sign_on: false) }
120
          it 'throws an error' do
121 122 123
            expect{ oauth_user.save }.to raise_error StandardError
          end
        end
124
      end
125

126
      context "with auto_link_ldap_user disabled (default)" do
127
        before { stub_omniauth_config(auto_link_ldap_user: false) }
128 129 130 131
        include_examples "to verify compliance with allow_single_sign_on"
      end

      context "with auto_link_ldap_user enabled" do
132 133
        before { stub_omniauth_config(auto_link_ldap_user: true) }

134
        context "and no LDAP provider defined" do
135 136
          before { stub_ldap_config(providers: []) }

137 138
          include_examples "to verify compliance with allow_single_sign_on"
        end
139

140
        context "and at least one LDAP provider is defined" do
141
          before { stub_ldap_config(providers: %w(ldapmain)) }
142 143 144

          context "and a corresponding LDAP person" do
            before do
145 146
              allow(ldap_user).to receive(:uid) { uid }
              allow(ldap_user).to receive(:username) { uid }
147
              allow(ldap_user).to receive(:email) { ['johndoe@example.com', 'john2@example.com'] }
148
              allow(ldap_user).to receive(:dn) { 'uid=user1,ou=People,dc=example' }
149
            end
150

151 152
            context "and no account for the LDAP user" do
              it "creates a user with dual LDAP and omniauth identities" do
153 154
                allow(Gitlab::LDAP::Person).to receive(:find_by_uid).and_return(ldap_user)

155
                oauth_user.save
156

157 158 159
                expect(gl_user).to be_valid
                expect(gl_user.username).to eql uid
                expect(gl_user.email).to eql 'johndoe@example.com'
160
                expect(gl_user.identities.length).to be 2
161 162
                identities_as_hash = gl_user.identities.map { |id| { provider: id.provider, extern_uid: id.extern_uid } }
                expect(identities_as_hash).to match_array(
163 164 165 166 167
                  [
                    { provider: 'ldapmain', extern_uid: 'uid=user1,ou=People,dc=example' },
                    { provider: 'twitter', extern_uid: uid }
                  ]
                )
168 169
              end
            end
170

171 172 173
            context "and LDAP user has an account already" do
              let!(:existing_user) { create(:omniauth_user, email: 'john@example.com', extern_uid: 'uid=user1,ou=People,dc=example', provider: 'ldapmain', username: 'john') }
              it "adds the omniauth identity to the LDAP account" do
174 175
                allow(Gitlab::LDAP::Person).to receive(:find_by_uid).and_return(ldap_user)

176
                oauth_user.save
177

178 179 180
                expect(gl_user).to be_valid
                expect(gl_user.username).to eql 'john'
                expect(gl_user.email).to eql 'john@example.com'
181
                expect(gl_user.identities.length).to be 2
182 183
                identities_as_hash = gl_user.identities.map { |id| { provider: id.provider, extern_uid: id.extern_uid } }
                expect(identities_as_hash).to match_array(
184 185 186 187 188
                  [
                    { provider: 'ldapmain', extern_uid: 'uid=user1,ou=People,dc=example' },
                    { provider: 'twitter', extern_uid: uid }
                  ]
                )
189
              end
190
            end
191 192 193 194 195 196 197 198 199

            context 'when an LDAP person is not found by uid' do
              it 'tries to find an LDAP person by DN and adds the omniauth identity to the user' do
                allow(Gitlab::LDAP::Person).to receive(:find_by_uid).and_return(nil)
                allow(Gitlab::LDAP::Person).to receive(:find_by_dn).and_return(ldap_user)

                oauth_user.save

                identities_as_hash = gl_user.identities.map { |id| { provider: id.provider, extern_uid: id.extern_uid } }
200 201
                expect(identities_as_hash)
                  .to match_array(
202 203 204 205 206 207 208
                    [
                      { provider: 'ldapmain', extern_uid: 'uid=user1,ou=People,dc=example' },
                      { provider: 'twitter', extern_uid: uid }
                    ]
                  )
              end
            end
209
          end
210

211 212
          context "and no corresponding LDAP person" do
            before { allow(Gitlab::LDAP::Person).to receive(:find_by_uid).and_return(nil) }
213

214 215
            include_examples "to verify compliance with allow_single_sign_on"
          end
216
        end
217
      end
218
    end
219

220 221
    describe 'blocking' do
      let(:provider) { 'twitter' }
222
      before { stub_omniauth_config(allow_single_sign_on: ['twitter']) }
223

224
      context 'signup with omniauth only' do
225
        context 'dont block on create' do
226
          before { stub_omniauth_config(block_auto_created_users: false) }
227 228 229

          it do
            oauth_user.save
230 231
            expect(gl_user).to be_valid
            expect(gl_user).not_to be_blocked
232 233 234 235
          end
        end

        context 'block on create' do
236
          before { stub_omniauth_config(block_auto_created_users: true) }
237 238 239

          it do
            oauth_user.save
240 241
            expect(gl_user).to be_valid
            expect(gl_user).to be_blocked
242 243 244 245
          end
        end
      end

246 247
      context 'signup with linked omniauth and LDAP account' do
        before do
248 249 250
          stub_omniauth_config(auto_link_ldap_user: true)
          allow(ldap_user).to receive(:uid) { uid }
          allow(ldap_user).to receive(:username) { uid }
251
          allow(ldap_user).to receive(:email) { ['johndoe@example.com', 'john2@example.com'] }
252
          allow(ldap_user).to receive(:dn) { 'uid=user1,ou=People,dc=example' }
253 254 255 256 257
          allow(oauth_user).to receive(:ldap_person).and_return(ldap_user)
        end

        context "and no account for the LDAP user" do
          context 'dont block on create (LDAP)' do
258
            before { allow_any_instance_of(Gitlab::LDAP::Config).to receive_messages(block_auto_created_users: false) }
259 260 261 262 263 264 265 266 267

            it do
              oauth_user.save
              expect(gl_user).to be_valid
              expect(gl_user).not_to be_blocked
            end
          end

          context 'block on create (LDAP)' do
268
            before { allow_any_instance_of(Gitlab::LDAP::Config).to receive_messages(block_auto_created_users: true) }
269 270 271 272 273 274 275 276 277 278 279 280 281

            it do
              oauth_user.save
              expect(gl_user).to be_valid
              expect(gl_user).to be_blocked
            end
          end
        end

        context 'and LDAP user has an account already' do
          let!(:existing_user) { create(:omniauth_user, email: 'john@example.com', extern_uid: 'uid=user1,ou=People,dc=example', provider: 'ldapmain', username: 'john') }

          context 'dont block on create (LDAP)' do
282
            before { allow_any_instance_of(Gitlab::LDAP::Config).to receive_messages(block_auto_created_users: false) }
283 284 285 286 287 288 289 290 291

            it do
              oauth_user.save
              expect(gl_user).to be_valid
              expect(gl_user).not_to be_blocked
            end
          end

          context 'block on create (LDAP)' do
292
            before { allow_any_instance_of(Gitlab::LDAP::Config).to receive_messages(block_auto_created_users: true) }
293 294 295 296 297 298 299 300 301 302

            it do
              oauth_user.save
              expect(gl_user).to be_valid
              expect(gl_user).not_to be_blocked
            end
          end
        end
      end

303 304 305 306 307 308 309
      context 'sign-in' do
        before do
          oauth_user.save
          oauth_user.gl_user.activate
        end

        context 'dont block on create' do
310
          before { stub_omniauth_config(block_auto_created_users: false) }
311 312 313

          it do
            oauth_user.save
314 315
            expect(gl_user).to be_valid
            expect(gl_user).not_to be_blocked
316 317 318 319
          end
        end

        context 'block on create' do
320
          before { stub_omniauth_config(block_auto_created_users: true) }
321 322 323

          it do
            oauth_user.save
324 325
            expect(gl_user).to be_valid
            expect(gl_user).not_to be_blocked
326 327
          end
        end
328 329

        context 'dont block on create (LDAP)' do
330
          before { allow_any_instance_of(Gitlab::LDAP::Config).to receive_messages(block_auto_created_users: false) }
331 332 333 334 335 336 337 338 339

          it do
            oauth_user.save
            expect(gl_user).to be_valid
            expect(gl_user).not_to be_blocked
          end
        end

        context 'block on create (LDAP)' do
340
          before { allow_any_instance_of(Gitlab::LDAP::Config).to receive_messages(block_auto_created_users: true) }
341 342 343 344 345 346 347

          it do
            oauth_user.save
            expect(gl_user).to be_valid
            expect(gl_user).not_to be_blocked
          end
        end
348 349
      end
    end
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
350 351
  end
end