users_spec.rb 60.5 KB
Newer Older
Nihad Abbasov's avatar
Nihad Abbasov committed
1 2
require 'spec_helper'

3 4
describe API::Users do
  let(:user)  { create(:user) }
5
  let(:admin) { create(:admin) }
6
  let(:key) { create(:key, user: user) }
7
  let(:gpg_key) { create(:gpg_key, user: user) }
8
  let(:email) { create(:email, user: user) }
9
  let(:omniauth_user) { create(:omniauth_user) }
10 11
  let(:ldap_user) { create(:omniauth_user, provider: 'ldapmain') }
  let(:ldap_blocked_user) { create(:omniauth_user, provider: 'ldapmain', state: 'ldap_blocked') }
12
  let(:not_existing_user_id) { (User.maximum('id') || 0 ) + 10 }
13
  let(:not_existing_pat_id) { (PersonalAccessToken.maximum('id') || 0 ) + 10 }
Nihad Abbasov's avatar
Nihad Abbasov committed
14

15
  describe 'GET /users' do
16
    context "when unauthenticated" do
17
      it "returns authorization error when the `username` parameter is not passed" do
18
        get api("/users")
19

20
        expect(response).to have_gitlab_http_status(403)
21 22 23 24 25
      end

      it "returns the user when a valid `username` parameter is passed" do
        get api("/users"), username: user.username

26
        expect(response).to match_response_schema('public_api/v4/user/basics')
27 28 29 30 31 32 33 34
        expect(json_response.size).to eq(1)
        expect(json_response[0]['id']).to eq(user.id)
        expect(json_response[0]['username']).to eq(user.username)
      end

      it "returns an empty response when an invalid `username` parameter is passed" do
        get api("/users"), username: 'invalid'

35
        expect(response).to have_gitlab_http_status(200)
36 37
        expect(json_response).to be_an Array
        expect(json_response.size).to eq(0)
38
      end
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56

      context "when public level is restricted" do
        before do
          stub_application_setting(restricted_visibility_levels: [Gitlab::VisibilityLevel::PUBLIC])
        end

        it "returns authorization error when the `username` parameter refers to an inaccessible user" do
          get api("/users"), username: user.username

          expect(response).to have_gitlab_http_status(403)
        end

        it "returns authorization error when the `username` parameter is not passed" do
          get api("/users")

          expect(response).to have_gitlab_http_status(403)
        end
      end
Nihad Abbasov's avatar
Nihad Abbasov committed
57 58
    end

59
    context "when authenticated" do
60
      # These specs are written just in case API authentication is not required anymore
Felipe Artur's avatar
Felipe Artur committed
61 62 63 64 65
      context "when public level is restricted" do
        before do
          stub_application_setting(restricted_visibility_levels: [Gitlab::VisibilityLevel::PUBLIC])
        end

66
        context 'when authenticate as a regular user' do
67
          it "renders 200" do
68 69
            get api("/users", user)

70
            expect(response).to match_response_schema('public_api/v4/user/basics')
71
          end
Felipe Artur's avatar
Felipe Artur committed
72 73
        end

74 75 76 77
        context 'when authenticate as an admin' do
          it "renders 200" do
            get api("/users", admin)

78
            expect(response).to match_response_schema('public_api/v4/user/basics')
79
          end
Felipe Artur's avatar
Felipe Artur committed
80 81 82
        end
      end

83
      it "returns an array of users" do
Robert Speicher's avatar
Robert Speicher committed
84
        get api("/users", user)
85

86
        expect(response).to match_response_schema('public_api/v4/user/basics')
87
        expect(response).to include_pagination_headers
Marin Jankovski's avatar
Marin Jankovski committed
88
        username = user.username
89 90 91
        expect(json_response.detect do |user|
          user['username'] == username
        end['username']).to eq(username)
Nihad Abbasov's avatar
Nihad Abbasov committed
92
      end
93

94 95 96 97 98 99
      it "returns an array of blocked users" do
        ldap_blocked_user
        create(:user, state: 'blocked')

        get api("/users?blocked=true", user)

100
        expect(response).to match_response_schema('public_api/v4/user/basics')
101
        expect(response).to include_pagination_headers
102 103 104
        expect(json_response).to all(include('state' => /(blocked|ldap_blocked)/))
      end

105
      it "returns one user" do
106
        get api("/users?username=#{omniauth_user.username}", user)
107

108
        expect(response).to match_response_schema('public_api/v4/user/basics')
109
        expect(response).to include_pagination_headers
110 111
        expect(json_response.first['username']).to eq(omniauth_user.username)
      end
112 113 114 115

      it "returns a 403 when non-admin user searches by external UID" do
        get api("/users?extern_uid=#{omniauth_user.identities.first.extern_uid}&provider=#{omniauth_user.identities.first.provider}", user)

116
        expect(response).to have_gitlab_http_status(403)
117
      end
118 119 120 121

      it 'does not reveal the `is_admin` flag of the user' do
        get api('/users', user)

122
        expect(response).to match_response_schema('public_api/v4/user/basics')
123 124
        expect(json_response.first.keys).not_to include 'is_admin'
      end
Nihad Abbasov's avatar
Nihad Abbasov committed
125
    end
126 127

    context "when admin" do
128 129
      context 'when sudo is defined' do
        it 'does not return 500' do
Douwe Maan's avatar
Douwe Maan committed
130 131
          admin_personal_access_token = create(:personal_access_token, user: admin, scopes: [:sudo])
          get api("/users?sudo=#{user.id}", admin, personal_access_token: admin_personal_access_token)
132

133
          expect(response).to have_gitlab_http_status(:success)
134 135 136
        end
      end

137
      it "returns an array of users" do
138
        get api("/users", admin)
139

140
        expect(response).to match_response_schema('public_api/v4/user/admins')
141
        expect(response).to include_pagination_headers
142
      end
143 144 145 146 147 148

      it "returns an array of external users" do
        create(:user, external: true)

        get api("/users?external=true", admin)

149
        expect(response).to match_response_schema('public_api/v4/user/admins')
150
        expect(response).to include_pagination_headers
151 152
        expect(json_response).to all(include('external' => true))
      end
153 154 155 156

      it "returns one user by external UID" do
        get api("/users?extern_uid=#{omniauth_user.identities.first.extern_uid}&provider=#{omniauth_user.identities.first.provider}", admin)

157
        expect(response).to match_response_schema('public_api/v4/user/admins')
158 159 160 161 162 163 164
        expect(json_response.size).to eq(1)
        expect(json_response.first['username']).to eq(omniauth_user.username)
      end

      it "returns 400 error if provider with no extern_uid" do
        get api("/users?extern_uid=#{omniauth_user.identities.first.extern_uid}", admin)

165
        expect(response).to have_gitlab_http_status(400)
166 167 168 169 170
      end

      it "returns 400 error if provider with no extern_uid" do
        get api("/users?provider=#{omniauth_user.identities.first.provider}", admin)

171
        expect(response).to have_gitlab_http_status(400)
172
      end
173

James Lopez's avatar
James Lopez committed
174
      it "returns a user created before a specific date" do
James Lopez's avatar
James Lopez committed
175
        user = create(:user, created_at: Date.new(2000, 1, 1))
176 177 178

        get api("/users?created_before=2000-01-02T00:00:00.060Z", admin)

179
        expect(response).to match_response_schema('public_api/v4/user/admins')
180 181 182 183 184
        expect(json_response.size).to eq(1)
        expect(json_response.first['username']).to eq(user.username)
      end

      it "returns no users created before a specific date" do
James Lopez's avatar
James Lopez committed
185
        create(:user, created_at: Date.new(2001, 1, 1))
186 187 188

        get api("/users?created_before=2000-01-02T00:00:00.060Z", admin)

189
        expect(response).to match_response_schema('public_api/v4/user/admins')
190 191 192 193
        expect(json_response.size).to eq(0)
      end

      it "returns users created before and after a specific date" do
James Lopez's avatar
James Lopez committed
194
        user = create(:user, created_at: Date.new(2001, 1, 1))
195 196 197

        get api("/users?created_before=2001-01-02T00:00:00.060Z&created_after=1999-01-02T00:00:00.060", admin)

198
        expect(response).to match_response_schema('public_api/v4/user/admins')
199 200 201
        expect(json_response.size).to eq(1)
        expect(json_response.first['username']).to eq(user.username)
      end
202 203 204 205 206 207 208 209 210 211 212 213 214

      it 'returns the correct order when sorted by id' do
        admin
        user

        get api('/users', admin), { order_by: 'id', sort: 'asc' }

        expect(response).to match_response_schema('public_api/v4/user/admins')
        expect(json_response.size).to eq(2)
        expect(json_response.first['id']).to eq(admin.id)
        expect(json_response.last['id']).to eq(user.id)
      end

215 216 217 218 219 220 221 222 223 224 225 226
      it 'returns users with 2fa enabled' do
        admin
        user
        user_with_2fa = create(:user, :two_factor_via_otp)

        get api('/users', admin), { two_factor: 'enabled' }

        expect(response).to match_response_schema('public_api/v4/user/admins')
        expect(json_response.size).to eq(1)
        expect(json_response.first['id']).to eq(user_with_2fa.id)
      end

227 228 229 230 231
      it 'returns 400 when provided incorrect sort params' do
        get api('/users', admin), { order_by: 'magic', sort: 'asc' }

        expect(response).to have_gitlab_http_status(400)
      end
232
    end
Nihad Abbasov's avatar
Nihad Abbasov committed
233 234 235
  end

  describe "GET /users/:id" do
236
    it "returns a user by id" do
Robert Speicher's avatar
Robert Speicher committed
237
      get api("/users/#{user.id}", user)
238

239
      expect(response).to match_response_schema('public_api/v4/user/basic')
240
      expect(json_response['username']).to eq(user.username)
Nihad Abbasov's avatar
Nihad Abbasov committed
241 242
    end

243 244 245
    it "does not return the user's `is_admin` flag" do
      get api("/users/#{user.id}", user)

246 247
      expect(response).to match_response_schema('public_api/v4/user/basic')
      expect(json_response.keys).not_to include 'is_admin'
248 249
    end

250 251 252 253
    context 'when authenticated as admin' do
      it 'includes the `is_admin` field' do
        get api("/users/#{user.id}", admin)

254
        expect(response).to match_response_schema('public_api/v4/user/admin')
255 256 257 258
        expect(json_response['is_admin']).to be(false)
      end
    end

259 260 261 262
    context 'for an anonymous user' do
      it "returns a user by id" do
        get api("/users/#{user.id}")

263
        expect(response).to match_response_schema('public_api/v4/user/basic')
264 265 266 267 268 269 270 271 272
        expect(json_response['username']).to eq(user.username)
      end

      it "returns a 404 if the target user is present but inaccessible" do
        allow(Ability).to receive(:allowed?).and_call_original
        allow(Ability).to receive(:allowed?).with(nil, :read_user, user).and_return(false)

        get api("/users/#{user.id}")

273
        expect(response).to have_gitlab_http_status(404)
274
      end
275
    end
276

277
    it "returns a 404 error if user id not found" do
278
      get api("/users/9999", user)
279

280
      expect(response).to have_gitlab_http_status(404)
Robert Schilling's avatar
Robert Schilling committed
281
      expect(json_response['message']).to eq('404 User Not Found')
282
    end
283

284
    it "returns a 404 for invalid ID" do
285
      get api("/users/1ASDF", user)
286

287
      expect(response).to have_gitlab_http_status(404)
288
    end
289 290 291
  end

  describe "POST /users" do
292 293 294
    before do
      admin
    end
295

296
    it "creates user" do
297
      expect do
298
        post api("/users", admin), attributes_for(:user, projects_limit: 3)
299
      end.to change { User.count }.by(1)
300 301
    end

302
    it "creates user with correct attributes" do
303
      post api('/users', admin), attributes_for(:user, admin: true, can_create_group: true)
304
      expect(response).to have_gitlab_http_status(201)
305 306
      user_id = json_response['id']
      new_user = User.find(user_id)
307 308 309
      expect(new_user).not_to eq(nil)
      expect(new_user.admin).to eq(true)
      expect(new_user.can_create_group).to eq(true)
310 311
    end

312 313 314 315 316 317
    it "creates user with optional attributes" do
      optional_attributes = { confirm: true }
      attributes = attributes_for(:user).merge(optional_attributes)

      post api('/users', admin), attributes

318
      expect(response).to have_gitlab_http_status(201)
319 320
    end

321
    it "creates non-admin user" do
322
      post api('/users', admin), attributes_for(:user, admin: false, can_create_group: false)
323
      expect(response).to have_gitlab_http_status(201)
324 325
      user_id = json_response['id']
      new_user = User.find(user_id)
326 327 328
      expect(new_user).not_to eq(nil)
      expect(new_user.admin).to eq(false)
      expect(new_user.can_create_group).to eq(false)
329 330
    end

331
    it "creates non-admin users by default" do
332
      post api('/users', admin), attributes_for(:user)
333
      expect(response).to have_gitlab_http_status(201)
334 335
      user_id = json_response['id']
      new_user = User.find(user_id)
336 337
      expect(new_user).not_to eq(nil)
      expect(new_user.admin).to eq(false)
338 339
    end

340
    it "returns 201 Created on success" do
341
      post api("/users", admin), attributes_for(:user, projects_limit: 3)
342
      expect(response).to have_gitlab_http_status(201)
343 344
    end

Zeger-Jan van de Weg's avatar
Zeger-Jan van de Weg committed
345 346
    it 'creates non-external users by default' do
      post api("/users", admin), attributes_for(:user)
347
      expect(response).to have_gitlab_http_status(201)
Zeger-Jan van de Weg's avatar
Zeger-Jan van de Weg committed
348 349 350 351 352 353 354

      user_id = json_response['id']
      new_user = User.find(user_id)
      expect(new_user).not_to eq nil
      expect(new_user.external).to be_falsy
    end

355
    it 'allows an external user to be created' do
Zeger-Jan van de Weg's avatar
Zeger-Jan van de Weg committed
356
      post api("/users", admin), attributes_for(:user, external: true)
357
      expect(response).to have_gitlab_http_status(201)
Zeger-Jan van de Weg's avatar
Zeger-Jan van de Weg committed
358 359 360 361 362 363 364

      user_id = json_response['id']
      new_user = User.find(user_id)
      expect(new_user).not_to eq nil
      expect(new_user.external).to be_truthy
    end

365 366 367
    it "creates user with reset password" do
      post api('/users', admin), attributes_for(:user, reset_password: true).except(:password)

368
      expect(response).to have_gitlab_http_status(201)
369 370 371 372 373 374 375 376

      user_id = json_response['id']
      new_user = User.find(user_id)

      expect(new_user).not_to eq(nil)
      expect(new_user.recently_sent_password_reset?).to eq(true)
    end

377
    it "does not create user with invalid email" do
378
      post api('/users', admin),
379 380 381
           email: 'invalid email',
           password: 'password',
           name: 'test'
382
      expect(response).to have_gitlab_http_status(400)
383 384
    end

385
    it 'returns 400 error if name not given' do
386
      post api('/users', admin), attributes_for(:user).except(:name)
387
      expect(response).to have_gitlab_http_status(400)
388 389
    end

390
    it 'returns 400 error if password not given' do
391
      post api('/users', admin), attributes_for(:user).except(:password)
392
      expect(response).to have_gitlab_http_status(400)
393 394
    end

395
    it 'returns 400 error if email not given' do
396
      post api('/users', admin), attributes_for(:user).except(:email)
397
      expect(response).to have_gitlab_http_status(400)
398 399
    end

400
    it 'returns 400 error if username not given' do
401
      post api('/users', admin), attributes_for(:user).except(:username)
402
      expect(response).to have_gitlab_http_status(400)
403 404
    end

405
    it 'returns 400 error if user does not validate' do
406
      post api('/users', admin),
407 408 409 410 411 412
           password: 'pass',
           email: 'test@example.com',
           username: 'test!',
           name: 'test',
           bio: 'g' * 256,
           projects_limit: -1
413
      expect(response).to have_gitlab_http_status(400)
414 415 416 417 418 419 420 421
      expect(json_response['message']['password'])
        .to eq(['is too short (minimum is 8 characters)'])
      expect(json_response['message']['bio'])
        .to eq(['is too long (maximum is 255 characters)'])
      expect(json_response['message']['projects_limit'])
        .to eq(['must be greater than or equal to 0'])
      expect(json_response['message']['username'])
        .to eq([Gitlab::PathRegex.namespace_format_message])
422 423
    end

424
    it "is not available for non admin users" do
425
      post api("/users", user), attributes_for(:user)
426
      expect(response).to have_gitlab_http_status(403)
427
    end
428

429 430 431
    context 'with existing user' do
      before do
        post api('/users', admin),
432 433 434 435
             email: 'test@example.com',
             password: 'password',
             username: 'test',
             name: 'foo'
436
      end
437

438
      it 'returns 409 conflict error if user with same email exists' do
439
        expect do
440
          post api('/users', admin),
441 442 443 444
               name: 'foo',
               email: 'test@example.com',
               password: 'password',
               username: 'foo'
445
        end.to change { User.count }.by(0)
446
        expect(response).to have_gitlab_http_status(409)
447
        expect(json_response['message']).to eq('Email has already been taken')
448 449
      end

450
      it 'returns 409 conflict error if same username exists' do
451 452
        expect do
          post api('/users', admin),
453 454 455 456
               name: 'foo',
               email: 'foo@example.com',
               password: 'password',
               username: 'test'
457
        end.to change { User.count }.by(0)
458
        expect(response).to have_gitlab_http_status(409)
459
        expect(json_response['message']).to eq('Username has already been taken')
460
      end
461 462 463 464

      it 'creates user with new identity' do
        post api("/users", admin), attributes_for(:user, provider: 'github', extern_uid: '67890')

465
        expect(response).to have_gitlab_http_status(201)
466 467 468
        expect(json_response['identities'].first['extern_uid']).to eq('67890')
        expect(json_response['identities'].first['provider']).to eq('github')
      end
469
    end
470 471 472 473 474 475 476 477

    context "scopes" do
      let(:user) { admin }
      let(:path) { '/users' }
      let(:api_call) { method(:api) }

      include_examples 'does not allow the "read_user" scope'
    end
478 479
  end

Marin Jankovski's avatar
Marin Jankovski committed
480
  describe "GET /users/sign_up" do
481
    it "redirects to sign in page" do
482
      get "/users/sign_up"
483
      expect(response).to have_gitlab_http_status(302)
484
      expect(response).to redirect_to(new_user_session_path)
Marin Jankovski's avatar
Marin Jankovski committed
485 486 487
    end
  end

488
  describe "PUT /users/:id" do
489 490
    let!(:admin_user) { create(:admin) }

491 492 493
    before do
      admin
    end
494

495
    it "updates user with new bio" do
496
      put api("/users/#{user.id}", admin), { bio: 'new test bio' }
497

498
      expect(response).to have_gitlab_http_status(200)
499 500
      expect(json_response['bio']).to eq('new test bio')
      expect(user.reload.bio).to eq('new test bio')
501 502
    end

503
    it "updates user with new password and forces reset on next login" do
504 505
      put api("/users/#{user.id}", admin), password: '12345678'

506
      expect(response).to have_gitlab_http_status(200)
507
      expect(user.reload.password_expires_at).to be <= Time.now
508 509
    end

510 511
    it "updates user with organization" do
      put api("/users/#{user.id}", admin), { organization: 'GitLab' }
512

513
      expect(response).to have_gitlab_http_status(200)
514 515 516 517
      expect(json_response['organization']).to eq('GitLab')
      expect(user.reload.organization).to eq('GitLab')
    end

518 519 520 521 522 523
    it 'updates user with avatar' do
      put api("/users/#{user.id}", admin), { avatar: fixture_file_upload(Rails.root + 'spec/fixtures/banana_sample.gif', 'image/gif') }

      user.reload

      expect(user.avatar).to be_present
524
      expect(response).to have_gitlab_http_status(200)
525 526 527
      expect(json_response['avatar_url']).to include(user.avatar_path)
    end

528
    it 'updates user with his own email' do
529
      put api("/users/#{user.id}", admin), email: user.email
530

531
      expect(response).to have_gitlab_http_status(200)
532 533
      expect(json_response['email']).to eq(user.email)
      expect(user.reload.email).to eq(user.email)
534 535
    end

James Lopez's avatar
James Lopez committed
536 537
    it 'updates user with a new email' do
      put api("/users/#{user.id}", admin), email: 'new@email.com'
538

539
      expect(response).to have_gitlab_http_status(200)
James Lopez's avatar
James Lopez committed
540 541 542
      expect(user.reload.notification_email).to eq('new@email.com')
    end

Daniel Juarez's avatar
Daniel Juarez committed
543 544 545 546 547 548 549 550
    it 'skips reconfirmation when requested' do
      put api("/users/#{user.id}", admin), { skip_reconfirmation: true }

      user.reload

      expect(user.confirmed_at).to be_present
    end

551
    it 'updates user with his own username' do
552
      put api("/users/#{user.id}", admin), username: user.username
553

554
      expect(response).to have_gitlab_http_status(200)
555 556
      expect(json_response['username']).to eq(user.username)
      expect(user.reload.username).to eq(user.username)
557 558
    end

559
    it "updates user's existing identity" do
560
      put api("/users/#{omniauth_user.id}", admin), provider: 'ldapmain', extern_uid: '654321'
561

562
      expect(response).to have_gitlab_http_status(200)
563 564 565
      expect(omniauth_user.reload.identities.first.extern_uid).to eq('654321')
    end

566
    it 'updates user with new identity' do
567
      put api("/users/#{user.id}", admin), provider: 'github', extern_uid: 'john'
568

569
      expect(response).to have_gitlab_http_status(200)
570
      expect(user.reload.identities.first.extern_uid).to eq('john')
571 572 573
      expect(user.reload.identities.first.provider).to eq('github')
    end

574
    it "updates admin status" do
575
      put api("/users/#{user.id}", admin), { admin: true }
576

577
      expect(response).to have_gitlab_http_status(200)
578
      expect(user.reload.admin).to eq(true)
579 580
    end

581
    it "updates external status" do
582
      put api("/users/#{user.id}", admin), { external: true }
583

584 585 586 587 588
      expect(response.status).to eq 200
      expect(json_response['external']).to eq(true)
      expect(user.reload.external?).to be_truthy
    end

589
    it "does not update admin status" do
590
      put api("/users/#{admin_user.id}", admin), { can_create_group: false }
591

592
      expect(response).to have_gitlab_http_status(200)
593 594
      expect(admin_user.reload.admin).to eq(true)
      expect(admin_user.can_create_group).to eq(false)
595 596
    end

597
    it "does not allow invalid update" do
598
      put api("/users/#{user.id}", admin), { email: 'invalid email' }
599

600
      expect(response).to have_gitlab_http_status(400)
601
      expect(user.reload.email).not_to eq('invalid email')
602 603
    end

604 605 606 607 608 609
    context 'when the current user is not an admin' do
      it "is not available" do
        expect do
          put api("/users/#{user.id}", user), attributes_for(:user)
        end.not_to change { user.reload.attributes }

610
        expect(response).to have_gitlab_http_status(403)
611
      end
612 613
    end

614
    it "returns 404 for non-existing user" do
615
      put api("/users/999999", admin), { bio: 'update should fail' }
616

617
      expect(response).to have_gitlab_http_status(404)
Robert Schilling's avatar
Robert Schilling committed
618
      expect(json_response['message']).to eq('404 User Not Found')
619 620
    end

621
    it "returns a 404 if invalid ID" do
622 623
      put api("/users/ASDF", admin)

624
      expect(response).to have_gitlab_http_status(404)
625 626
    end

627
    it 'returns 400 error if user does not validate' do
628
      put api("/users/#{user.id}", admin),
629 630 631 632 633 634
          password: 'pass',
          email: 'test@example.com',
          username: 'test!',
          name: 'test',
          bio: 'g' * 256,
          projects_limit: -1
635
      expect(response).to have_gitlab_http_status(400)
636 637 638 639 640 641 642 643
      expect(json_response['message']['password'])
        .to eq(['is too short (minimum is 8 characters)'])
      expect(json_response['message']['bio'])
        .to eq(['is too long (maximum is 255 characters)'])
      expect(json_response['message']['projects_limit'])
        .to eq(['must be greater than or equal to 0'])
      expect(json_response['message']['username'])
        .to eq([Gitlab::PathRegex.namespace_format_message])
644
    end
645

Robert Schilling's avatar
Robert Schilling committed
646 647 648
    it 'returns 400 if provider is missing for identity update' do
      put api("/users/#{omniauth_user.id}", admin), extern_uid: '654321'

649
      expect(response).to have_gitlab_http_status(400)
Robert Schilling's avatar
Robert Schilling committed
650 651 652 653 654
    end

    it 'returns 400 if external UID is missing for identity update' do
      put api("/users/#{omniauth_user.id}", admin), provider: 'ldap'

655
      expect(response).to have_gitlab_http_status(400)
Robert Schilling's avatar
Robert Schilling committed
656 657
    end

658
    context "with existing user" do
659
      before do
660 661
        post api("/users", admin), { email: 'test@example.com', password: 'password', username: 'test', name: 'test' }
        post api("/users", admin), { email: 'foo@bar.com', password: 'password', username: 'john', name: 'john' }
662
        @user = User.all.last
663
      end
664

665
      it 'returns 409 conflict error if email address exists' do
666
        put api("/users/#{@user.id}", admin), email: 'test@example.com'
667

668
        expect(response).to have_gitlab_http_status(409)
669
        expect(@user.reload.email).to eq(@user.email)
670 671
      end

672
      it 'returns 409 conflict error if username taken' do
673 674
        @user_id = User.all.last.id
        put api("/users/#{@user.id}", admin), username: 'test'
675

676
        expect(response).to have_gitlab_http_status(409)
677
        expect(@user.reload.username).to eq(@user.username)
678
      end
679
    end
680 681
  end

Angus MacArthur's avatar
Angus MacArthur committed
682
  describe "POST /users/:id/keys" do
683 684 685
    before do
      admin
    end
Angus MacArthur's avatar
Angus MacArthur committed
686

687
    it "does not create invalid ssh key" do
Angus MacArthur's avatar
Angus MacArthur committed
688
      post api("/users/#{user.id}/keys", admin), { title: "invalid key" }
Robert Schilling's avatar
Robert Schilling committed
689

690
      expect(response).to have_gitlab_http_status(400)
Robert Schilling's avatar
Robert Schilling committed
691
      expect(json_response['error']).to eq('key is missing')
692 693
    end

694
    it 'does not create key without title' do
695
      post api("/users/#{user.id}/keys", admin), key: 'some key'
Robert Schilling's avatar
Robert Schilling committed
696

697
      expect(response).to have_gitlab_http_status(400)
Robert Schilling's avatar
Robert Schilling committed
698
      expect(json_response['error']).to eq('title is missing')
Angus MacArthur's avatar
Angus MacArthur committed
699 700
    end

701
    it "creates ssh key" do
Angus MacArthur's avatar
Angus MacArthur committed
702
      key_attrs = attributes_for :key
703
      expect do
Angus MacArthur's avatar
Angus MacArthur committed
704
        post api("/users/#{user.id}/keys", admin), key_attrs
705
      end.to change { user.keys.count }.by(1)
Angus MacArthur's avatar
Angus MacArthur committed
706
    end
707

708
    it "returns 400 for invalid ID" do
Connor Shea's avatar
Connor Shea committed
709
      post api("/users/999999/keys", admin)
710
      expect(response).to have_gitlab_http_status(400)
711
    end
Angus MacArthur's avatar
Angus MacArthur committed
712 713
  end

Robert Schilling's avatar
Robert Schilling committed
714
  describe 'GET /user/:id/keys' do
715 716 717
    before do
      admin
    end
718 719

    context 'when unauthenticated' do
720
      it 'returns authentication error' do
721
        get api("/users/#{user.id}/keys")
722
        expect(response).to have_gitlab_http_status(401)
723 724 725 726
      end
    end

    context 'when authenticated' do
727
      it 'returns 404 for non-existing user' do
728
        get api('/users/999999/keys', admin)
729
        expect(response).to have_gitlab_http_status(404)
730
        expect(json_response['message']).to eq('404 User Not Found')
731 732
      end

733
      it 'returns array of ssh keys' do
734 735
        user.keys << key
        user.save
736

737
        get api("/users/#{user.id}/keys", admin)
738

739
        expect(response).to have_gitlab_http_status(200)
740
        expect(response).to include_pagination_headers
741 742
        expect(json_response).to be_an Array
        expect(json_response.first['title']).to eq(key.title)
743 744 745 746
      end
    end
  end

Robert Schilling's avatar
Robert Schilling committed
747
  describe 'DELETE /user/:id/keys/:key_id' do
748 749 750
    before do
      admin
    end
751 752

    context 'when unauthenticated' do
753
      it 'returns authentication error' do
754
        delete api("/users/#{user.id}/keys/42")
755
        expect(response).to have_gitlab_http_status(401)
756 757 758 759
      end
    end

    context 'when authenticated' do
760
      it 'deletes existing key' do
761 762
        user.keys << key
        user.save
763

764
        expect do
765
          delete api("/users/#{user.id}/keys/#{key.id}", admin)
766

767
          expect(response).to have_gitlab_http_status(204)
768
        end.to change { user.keys.count }.by(-1)
769 770
      end

771 772 773 774
      it_behaves_like '412 response' do
        let(:request) { api("/users/#{user.id}/keys/#{key.id}", admin) }
      end

775
      it 'returns 404 error if user not found' do
776 777 778
        user.keys << key
        user.save
        delete api("/users/999999/keys/#{key.id}", admin)
779
        expect(response).to have_gitlab_http_status(404)
780
        expect(json_response['message']).to eq('404 User Not Found')
781 782
      end

783
      it 'returns 404 error if key not foud' do
784
        delete api("/users/#{user.id}/keys/42", admin)
785
        expect(response).to have_gitlab_http_status(404)
786
        expect(json_response['message']).to eq('404 Key Not Found')
787 788 789 790
      end
    end
  end

791 792 793 794 795 796 797 798
  describe 'POST /users/:id/keys' do
    before do
      admin
    end

    it 'does not create invalid GPG key' do
      post api("/users/#{user.id}/gpg_keys", admin)

799
      expect(response).to have_gitlab_http_status(400)
800 801 802 803 804 805 806 807
      expect(json_response['error']).to eq('key is missing')
    end

    it 'creates GPG key' do
      key_attrs = attributes_for :gpg_key
      expect do
        post api("/users/#{user.id}/gpg_keys", admin), key_attrs

808
        expect(response).to have_gitlab_http_status(201)
809 810 811 812 813 814
      end.to change { user.gpg_keys.count }.by(1)
    end

    it 'returns 400 for invalid ID' do
      post api('/users/999999/gpg_keys', admin)

815
      expect(response).to have_gitlab_http_status(400)
816 817 818 819 820 821 822 823 824 825 826 827
    end
  end

  describe 'GET /user/:id/gpg_keys' do
    before do
      admin
    end

    context 'when unauthenticated' do
      it 'returns authentication error' do
        get api("/users/#{user.id}/gpg_keys")

828
        expect(response).to have_gitlab_http_status(401)
829 830 831 832 833 834 835
      end
    end

    context 'when authenticated' do
      it 'returns 404 for non-existing user' do
        get api('/users/999999/gpg_keys', admin)

836
        expect(response).to have_gitlab_http_status(404)
837 838 839 840 841 842
        expect(json_response['message']).to eq('404 User Not Found')
      end

      it 'returns 404 error if key not foud' do
        delete api("/users/#{user.id}/gpg_keys/42", admin)

843
        expect(response).to have_gitlab_http_status(404)
844 845 846 847 848 849 850 851 852
        expect(json_response['message']).to eq('404 GPG Key Not Found')
      end

      it 'returns array of GPG keys' do
        user.gpg_keys << gpg_key
        user.save

        get api("/users/#{user.id}/gpg_keys", admin)

853
        expect(response).to have_gitlab_http_status(200)
854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869
        expect(response).to include_pagination_headers
        expect(json_response).to be_an Array
        expect(json_response.first['key']).to eq(gpg_key.key)
      end
    end
  end

  describe 'DELETE /user/:id/gpg_keys/:key_id' do
    before do
      admin
    end

    context 'when unauthenticated' do
      it 'returns authentication error' do
        delete api("/users/#{user.id}/keys/42")

870
        expect(response).to have_gitlab_http_status(401)
871 872 873 874 875 876 877 878 879 880 881
      end
    end

    context 'when authenticated' do
      it 'deletes existing key' do
        user.gpg_keys << gpg_key
        user.save

        expect do
          delete api("/users/#{user.id}/gpg_keys/#{gpg_key.id}", admin)

882
          expect(response).to have_gitlab_http_status(204)
883 884 885 886 887 888 889 890 891
        end.to change { user.gpg_keys.count }.by(-1)
      end

      it 'returns 404 error if user not found' do
        user.keys << key
        user.save

        delete api("/users/999999/gpg_keys/#{gpg_key.id}", admin)

892
        expect(response).to have_gitlab_http_status(404)
893 894 895 896 897 898
        expect(json_response['message']).to eq('404 User Not Found')
      end

      it 'returns 404 error if key not foud' do
        delete api("/users/#{user.id}/gpg_keys/42", admin)

899
        expect(response).to have_gitlab_http_status(404)
900 901 902 903 904 905 906 907 908 909 910 911 912 913
        expect(json_response['message']).to eq('404 GPG Key Not Found')
      end
    end
  end

  describe 'POST /user/:id/gpg_keys/:key_id/revoke' do
    before do
      admin
    end

    context 'when unauthenticated' do
      it 'returns authentication error' do
        post api("/users/#{user.id}/gpg_keys/42/revoke")

914
        expect(response).to have_gitlab_http_status(401)
915 916 917 918 919 920 921 922 923 924 925
      end
    end

    context 'when authenticated' do
      it 'revokes existing key' do
        user.gpg_keys << gpg_key
        user.save

        expect do
          post api("/users/#{user.id}/gpg_keys/#{gpg_key.id}/revoke", admin)

926
          expect(response).to have_gitlab_http_status(:accepted)
927 928 929 930 931 932 933 934 935
        end.to change { user.gpg_keys.count }.by(-1)
      end

      it 'returns 404 error if user not found' do
        user.gpg_keys << gpg_key
        user.save

        post api("/users/999999/gpg_keys/#{gpg_key.id}/revoke", admin)

936
        expect(response).to have_gitlab_http_status(404)
937 938 939 940 941 942
        expect(json_response['message']).to eq('404 User Not Found')
      end

      it 'returns 404 error if key not foud' do
        post api("/users/#{user.id}/gpg_keys/42/revoke", admin)

943
        expect(response).to have_gitlab_http_status(404)
944 945 946 947 948
        expect(json_response['message']).to eq('404 GPG Key Not Found')
      end
    end
  end

949
  describe "POST /users/:id/emails" do
950 951 952
    before do
      admin
    end
953

954
    it "does not create invalid email" do
Douwe Maan's avatar
Douwe Maan committed
955
      post api("/users/#{user.id}/emails", admin), {}
Robert Schilling's avatar
Robert Schilling committed
956

957
      expect(response).to have_gitlab_http_status(400)
Robert Schilling's avatar
Robert Schilling committed
958
      expect(json_response['error']).to eq('email is missing')
959 960
    end

961
    it "creates email" do
962 963 964
      email_attrs = attributes_for :email
      expect do
        post api("/users/#{user.id}/emails", admin), email_attrs
965
      end.to change { user.emails.count }.by(1)
966
    end
967

968
    it "returns a 400 for invalid ID" do
Connor Shea's avatar
Connor Shea committed
969
      post api("/users/999999/emails", admin)
970

971
      expect(response).to have_gitlab_http_status(400)
972
    end
973 974
  end

Robert Schilling's avatar
Robert Schilling committed
975
  describe 'GET /user/:id/emails' do
976 977 978
    before do
      admin
    end
979 980

    context 'when unauthenticated' do
981
      it 'returns authentication error' do
982
        get api("/users/#{user.id}/emails")
983
        expect(response).to have_gitlab_http_status(401)
984 985 986 987
      end
    end

    context 'when authenticated' do
988
      it 'returns 404 for non-existing user' do
989
        get api('/users/999999/emails', admin)
990
        expect(response).to have_gitlab_http_status(404)
991 992 993
        expect(json_response['message']).to eq('404 User Not Found')
      end

994
      it 'returns array of emails' do
995 996
        user.emails << email
        user.save
997

998
        get api("/users/#{user.id}/emails", admin)
999

1000
        expect(response).to have_gitlab_http_status(200)
1001
        expect(response).to include_pagination_headers
1002 1003 1004
        expect(json_response).to be_an Array
        expect(json_response.first['email']).to eq(email.email)
      end
1005

1006
      it "returns a 404 for invalid ID" do
1007
        get api("/users/ASDF/emails", admin)
1008

1009
        expect(response).to have_gitlab_http_status(404)
1010
      end
1011 1012 1013
    end
  end

Robert Schilling's avatar
Robert Schilling committed
1014
  describe 'DELETE /user/:id/emails/:email_id' do
1015 1016 1017
    before do
      admin
    end
1018 1019

    context 'when unauthenticated' do
1020
      it 'returns authentication error' do
1021
        delete api("/users/#{user.id}/emails/42")
1022
        expect(response).to have_gitlab_http_status(401)
1023 1024 1025 1026
      end
    end

    context 'when authenticated' do
1027
      it 'deletes existing email' do
1028 1029
        user.emails << email
        user.save
1030

1031 1032
        expect do
          delete api("/users/#{user.id}/emails/#{email.id}", admin)
1033

1034
          expect(response).to have_gitlab_http_status(204)
1035 1036 1037
        end.to change { user.emails.count }.by(-1)
      end

1038 1039 1040 1041
      it_behaves_like '412 response' do
        let(:request) { api("/users/#{user.id}/emails/#{email.id}", admin) }
      end

1042
      it 'returns 404 error if user not found' do
1043 1044 1045
        user.emails << email
        user.save
        delete api("/users/999999/emails/#{email.id}", admin)
1046
        expect(response).to have_gitlab_http_status(404)
1047 1048 1049
        expect(json_response['message']).to eq('404 User Not Found')
      end

1050
      it 'returns 404 error if email not foud' do
1051
        delete api("/users/#{user.id}/emails/42", admin)
1052
        expect(response).to have_gitlab_http_status(404)
1053 1054
        expect(json_response['message']).to eq('404 Email Not Found')
      end
1055

1056
      it "returns a 404 for invalid ID" do
1057 1058
        delete api("/users/ASDF/emails/bar", admin)

1059
        expect(response).to have_gitlab_http_status(404)
1060
      end
1061 1062 1063
    end
  end

1064
  describe "DELETE /users/:id" do
1065
    let!(:namespace) { user.namespace }
1066
    let!(:issue) { create(:issue, author: user) }
1067 1068 1069 1070

    before do
      admin
    end
1071

1072
    it "deletes user" do
Stan Hu's avatar
Stan Hu committed
1073
      Sidekiq::Testing.inline! { delete api("/users/#{user.id}", admin) }
1074

1075
      expect(response).to have_gitlab_http_status(204)
1076
      expect { User.find(user.id) }.to raise_error ActiveRecord::RecordNotFound
1077
      expect { Namespace.find(namespace.id) }.to raise_error ActiveRecord::RecordNotFound
1078 1079
    end

1080 1081 1082 1083
    it_behaves_like '412 response' do
      let(:request) { api("/users/#{user.id}", admin) }
    end

1084
    it "does not delete for unauthenticated user" do
Stan Hu's avatar
Stan Hu committed
1085
      Sidekiq::Testing.inline! { delete api("/users/#{user.id}") }
1086
      expect(response).to have_gitlab_http_status(401)
1087 1088
    end

1089
    it "is not available for non admin users" do
Stan Hu's avatar
Stan Hu committed
1090
      Sidekiq::Testing.inline! { delete api("/users/#{user.id}", user) }
1091
      expect(response).to have_gitlab_http_status(403)
1092 1093
    end

1094
    it "returns 404 for non-existing user" do
Stan Hu's avatar
Stan Hu committed
1095
      Sidekiq::Testing.inline! { delete api("/users/999999", admin) }
1096
      expect(response).to have_gitlab_http_status(404)
1097
      expect(json_response['message']).to eq('404 User Not Found')
1098
    end
1099

1100
    it "returns a 404 for invalid ID" do
Stan Hu's avatar
Stan Hu committed
1101
      Sidekiq::Testing.inline! { delete api("/users/ASDF", admin) }
1102

1103
      expect(response).to have_gitlab_http_status(404)
1104
    end
1105 1106 1107 1108 1109

    context "hard delete disabled" do
      it "moves contributions to the ghost user" do
        Sidekiq::Testing.inline! { delete api("/users/#{user.id}", admin) }

1110
        expect(response).to have_gitlab_http_status(204)
1111 1112 1113 1114 1115 1116 1117 1118 1119
        expect(issue.reload).to be_persisted
        expect(issue.author.ghost?).to be_truthy
      end
    end

    context "hard delete enabled" do
      it "removes contributions" do
        Sidekiq::Testing.inline! { delete api("/users/#{user.id}?hard_delete=true", admin) }

1120
        expect(response).to have_gitlab_http_status(204)
1121 1122 1123
        expect(Issue.exists?(issue.id)).to be_falsy
      end
    end
1124 1125
  end

Nihad Abbasov's avatar
Nihad Abbasov committed
1126
  describe "GET /user" do
1127
    let(:personal_access_token) { create(:personal_access_token, user: user).token }
1128 1129 1130 1131

    context 'with regular user' do
      context 'with personal access token' do
        it 'returns 403 without private token when sudo is defined' do
1132
          get api("/user?private_token=#{personal_access_token}&sudo=123")
1133

1134
          expect(response).to have_gitlab_http_status(403)
1135 1136 1137 1138 1139 1140
        end
      end

      it 'returns current user without private token when sudo not defined' do
        get api("/user", user)

1141
        expect(response).to have_gitlab_http_status(200)
1142
        expect(response).to match_response_schema('public_api/v4/user/public')
1143
        expect(json_response['id']).to eq(user.id)
1144
      end
Timothy Andrew's avatar
Timothy Andrew committed
1145 1146 1147 1148 1149 1150 1151

      context "scopes" do
        let(:path) { "/user" }
        let(:api_call) { method(:api) }

        include_examples 'allows the "read_user" scope'
      end
Nihad Abbasov's avatar
Nihad Abbasov committed
1152
    end
1153

1154
    context 'with admin' do
1155
      let(:admin_personal_access_token) { create(:personal_access_token, user: admin).token }
1156 1157 1158

      context 'with personal access token' do
        it 'returns 403 without private token when sudo defined' do
1159
          get api("/user?private_token=#{admin_personal_access_token}&sudo=#{user.id}")
1160

1161
          expect(response).to have_gitlab_http_status(403)
1162 1163
        end

1164
        it 'returns initial current user without private token but with is_admin when sudo not defined' do
1165
          get api("/user?private_token=#{admin_personal_access_token}")
1166

1167
          expect(response).to have_gitlab_http_status(200)
1168
          expect(response).to match_response_schema('public_api/v4/user/admin')
1169
          expect(json_response['id']).to eq(admin.id)
1170 1171 1172 1173 1174 1175 1176 1177
        end
      end
    end

    context 'with unauthenticated user' do
      it "returns 401 error if user is unauthenticated" do
        get api("/user")

1178
        expect(response).to have_gitlab_http_status(401)
1179
      end
1180
    end
Nihad Abbasov's avatar
Nihad Abbasov committed
1181
  end
1182 1183 1184

  describe "GET /user/keys" do
    context "when unauthenticated" do
1185
      it "returns authentication error" do
1186
        get api("/user/keys")
1187
        expect(response).to have_gitlab_http_status(401)
1188 1189
      end
    end
Nihad Abbasov's avatar
Nihad Abbasov committed
1190

1191
    context "when authenticated" do
1192
      it "returns array of ssh keys" do
1193 1194
        user.keys << key
        user.save
1195

1196
        get api("/user/keys", user)
1197

1198
        expect(response).to have_gitlab_http_status(200)
1199
        expect(response).to include_pagination_headers
1200 1201
        expect(json_response).to be_an Array
        expect(json_response.first["title"]).to eq(key.title)
1202
      end
Timothy Andrew's avatar
Timothy Andrew committed
1203 1204 1205 1206 1207 1208 1209

      context "scopes" do
        let(:path) { "/user/keys" }
        let(:api_call) { method(:api) }

        include_examples 'allows the "read_user" scope'
      end
1210 1211 1212
    end
  end

Robert Schilling's avatar
Robert Schilling committed
1213
  describe "GET /user/keys/:key_id" do
1214
    it "returns single key" do
1215 1216 1217
      user.keys << key
      user.save
      get api("/user/keys/#{key.id}", user)
1218
      expect(response).to have_gitlab_http_status(200)
1219
      expect(json_response["title"]).to eq(key.title)
1220
    end
Nihad Abbasov's avatar
Nihad Abbasov committed
1221

1222
    it "returns 404 Not Found within invalid ID" do
1223
      get api("/user/keys/42", user)
1224

1225
      expect(response).to have_gitlab_http_status(404)
Robert Schilling's avatar
Robert Schilling committed
1226
      expect(json_response['message']).to eq('404 Key Not Found')
1227 1228
    end

1229
    it "returns 404 error if admin accesses user's ssh key" do
1230 1231 1232 1233
      user.keys << key
      user.save
      admin
      get api("/user/keys/#{key.id}", admin)
1234
      expect(response).to have_gitlab_http_status(404)
Robert Schilling's avatar
Robert Schilling committed
1235
      expect(json_response['message']).to eq('404 Key Not Found')
1236
    end
1237

1238
    it "returns 404 for invalid ID" do
1239
      get api("/users/keys/ASDF", admin)
1240

1241
      expect(response).to have_gitlab_http_status(404)
1242
    end
Timothy Andrew's avatar
Timothy Andrew committed
1243 1244 1245 1246 1247 1248 1249

    context "scopes" do
      let(:path) { "/user/keys/#{key.id}" }
      let(:api_call) { method(:api) }

      include_examples 'allows the "read_user" scope'
    end
1250
  end
Nihad Abbasov's avatar
Nihad Abbasov committed
1251

1252
  describe "POST /user/keys" do
1253
    it "creates ssh key" do
1254
      key_attrs = attributes_for :key
1255
      expect do
1256
        post api("/user/keys", user), key_attrs
1257
      end.to change { user.keys.count }.by(1)
1258
      expect(response).to have_gitlab_http_status(201)
1259 1260
    end

1261
    it "returns a 401 error if unauthorized" do
1262
      post api("/user/keys"), title: 'some title', key: 'some key'
1263
      expect(response).to have_gitlab_http_status(401)
1264 1265
    end

1266
    it "does not create ssh key without key" do
1267
      post api("/user/keys", user), title: 'title'
Robert Schilling's avatar
Robert Schilling committed
1268

1269
      expect(response).to have_gitlab_http_status(400)
Robert Schilling's avatar
Robert Schilling committed
1270
      expect(json_response['error']).to eq('key is missing')
1271 1272
    end

1273
    it 'does not create ssh key without title' do
1274
      post api('/user/keys', user), key: 'some key'
Robert Schilling's avatar
Robert Schilling committed
1275

1276
      expect(response).to have_gitlab_http_status(400)
Robert Schilling's avatar
Robert Schilling committed
1277
      expect(json_response['error']).to eq('title is missing')
1278 1279
    end

1280
    it "does not create ssh key without title" do
1281
      post api("/user/keys", user), key: "somekey"
1282
      expect(response).to have_gitlab_http_status(400)
1283 1284 1285
    end
  end

Robert Schilling's avatar
Robert Schilling committed
1286
  describe "DELETE /user/keys/:key_id" do
1287
    it "deletes existed key" do
1288 1289
      user.keys << key
      user.save
1290

1291
      expect do
1292
        delete api("/user/keys/#{key.id}", user)
1293

1294
        expect(response).to have_gitlab_http_status(204)
1295
      end.to change { user.keys.count}.by(-1)
1296
    end
Nihad Abbasov's avatar
Nihad Abbasov committed
1297

1298 1299 1300 1301
    it_behaves_like '412 response' do
      let(:request) { api("/user/keys/#{key.id}", user) }
    end

Robert Schilling's avatar
Robert Schilling committed
1302
    it "returns 404 if key ID not found" do
1303
      delete api("/user/keys/42", user)
Robert Schilling's avatar
Robert Schilling committed
1304

1305
      expect(response).to have_gitlab_http_status(404)
Robert Schilling's avatar
Robert Schilling committed
1306
      expect(json_response['message']).to eq('404 Key Not Found')
1307 1308
    end

1309
    it "returns 401 error if unauthorized" do
1310 1311 1312
      user.keys << key
      user.save
      delete api("/user/keys/#{key.id}")
1313
      expect(response).to have_gitlab_http_status(401)
1314
    end
1315

1316
    it "returns a 404 for invalid ID" do
1317 1318
      delete api("/users/keys/ASDF", admin)

1319
      expect(response).to have_gitlab_http_status(404)
1320
    end
1321
  end
1322

1323 1324 1325 1326 1327
  describe 'GET /user/gpg_keys' do
    context 'when unauthenticated' do
      it 'returns authentication error' do
        get api('/user/gpg_keys')

1328
        expect(response).to have_gitlab_http_status(401)
1329 1330 1331 1332 1333 1334 1335 1336 1337 1338
      end
    end

    context 'when authenticated' do
      it 'returns array of GPG keys' do
        user.gpg_keys << gpg_key
        user.save

        get api('/user/gpg_keys', user)

1339
        expect(response).to have_gitlab_http_status(200)
1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360
        expect(response).to include_pagination_headers
        expect(json_response).to be_an Array
        expect(json_response.first['key']).to eq(gpg_key.key)
      end

      context 'scopes' do
        let(:path) { '/user/gpg_keys' }
        let(:api_call) { method(:api) }

        include_examples 'allows the "read_user" scope'
      end
    end
  end

  describe 'GET /user/gpg_keys/:key_id' do
    it 'returns a single key' do
      user.gpg_keys << gpg_key
      user.save

      get api("/user/gpg_keys/#{gpg_key.id}", user)

1361
      expect(response).to have_gitlab_http_status(200)
1362 1363 1364 1365 1366 1367
      expect(json_response['key']).to eq(gpg_key.key)
    end

    it 'returns 404 Not Found within invalid ID' do
      get api('/user/gpg_keys/42', user)

1368
      expect(response).to have_gitlab_http_status(404)
1369 1370 1371 1372 1373 1374 1375 1376 1377
      expect(json_response['message']).to eq('404 GPG Key Not Found')
    end

    it "returns 404 error if admin accesses user's GPG key" do
      user.gpg_keys << gpg_key
      user.save

      get api("/user/gpg_keys/#{gpg_key.id}", admin)

1378
      expect(response).to have_gitlab_http_status(404)
1379 1380 1381 1382 1383 1384
      expect(json_response['message']).to eq('404 GPG Key Not Found')
    end

    it 'returns 404 for invalid ID' do
      get api('/users/gpg_keys/ASDF', admin)

1385
      expect(response).to have_gitlab_http_status(404)
1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401
    end

    context 'scopes' do
      let(:path) { "/user/gpg_keys/#{gpg_key.id}" }
      let(:api_call) { method(:api) }

      include_examples 'allows the "read_user" scope'
    end
  end

  describe 'POST /user/gpg_keys' do
    it 'creates a GPG key' do
      key_attrs = attributes_for :gpg_key
      expect do
        post api('/user/gpg_keys', user), key_attrs

1402
        expect(response).to have_gitlab_http_status(201)
1403 1404 1405 1406 1407 1408
      end.to change { user.gpg_keys.count }.by(1)
    end

    it 'returns a 401 error if unauthorized' do
      post api('/user/gpg_keys'), key: 'some key'

1409
      expect(response).to have_gitlab_http_status(401)
1410 1411 1412 1413 1414
    end

    it 'does not create GPG key without key' do
      post api('/user/gpg_keys', user)

1415
      expect(response).to have_gitlab_http_status(400)
1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427
      expect(json_response['error']).to eq('key is missing')
    end
  end

  describe 'POST /user/gpg_keys/:key_id/revoke' do
    it 'revokes existing GPG key' do
      user.gpg_keys << gpg_key
      user.save

      expect do
        post api("/user/gpg_keys/#{gpg_key.id}/revoke", user)

1428
        expect(response).to have_gitlab_http_status(:accepted)
1429 1430 1431 1432 1433 1434
      end.to change { user.gpg_keys.count}.by(-1)
    end

    it 'returns 404 if key ID not found' do
      post api('/user/gpg_keys/42/revoke', user)

1435
      expect(response).to have_gitlab_http_status(404)
1436 1437 1438 1439 1440 1441 1442 1443 1444
      expect(json_response['message']).to eq('404 GPG Key Not Found')
    end

    it 'returns 401 error if unauthorized' do
      user.gpg_keys << gpg_key
      user.save

      post api("/user/gpg_keys/#{gpg_key.id}/revoke")

1445
      expect(response).to have_gitlab_http_status(401)
1446 1447 1448 1449 1450
    end

    it 'returns a 404 for invalid ID' do
      post api('/users/gpg_keys/ASDF/revoke', admin)

1451
      expect(response).to have_gitlab_http_status(404)
1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462
    end
  end

  describe 'DELETE /user/gpg_keys/:key_id' do
    it 'deletes existing GPG key' do
      user.gpg_keys << gpg_key
      user.save

      expect do
        delete api("/user/gpg_keys/#{gpg_key.id}", user)

1463
        expect(response).to have_gitlab_http_status(204)
1464 1465 1466 1467 1468 1469
      end.to change { user.gpg_keys.count}.by(-1)
    end

    it 'returns 404 if key ID not found' do
      delete api('/user/gpg_keys/42', user)

1470
      expect(response).to have_gitlab_http_status(404)
1471 1472 1473 1474 1475 1476 1477 1478 1479
      expect(json_response['message']).to eq('404 GPG Key Not Found')
    end

    it 'returns 401 error if unauthorized' do
      user.gpg_keys << gpg_key
      user.save

      delete api("/user/gpg_keys/#{gpg_key.id}")

1480
      expect(response).to have_gitlab_http_status(401)
1481 1482 1483 1484 1485
    end

    it 'returns a 404 for invalid ID' do
      delete api('/users/gpg_keys/ASDF', admin)

1486
      expect(response).to have_gitlab_http_status(404)
1487 1488 1489
    end
  end

1490 1491
  describe "GET /user/emails" do
    context "when unauthenticated" do
1492
      it "returns authentication error" do
1493
        get api("/user/emails")
1494
        expect(response).to have_gitlab_http_status(401)
1495 1496 1497 1498
      end
    end

    context "when authenticated" do
1499
      it "returns array of emails" do
1500 1501
        user.emails << email
        user.save
1502

1503
        get api("/user/emails", user)
1504

1505
        expect(response).to have_gitlab_http_status(200)
1506
        expect(response).to include_pagination_headers
1507 1508 1509
        expect(json_response).to be_an Array
        expect(json_response.first["email"]).to eq(email.email)
      end
Timothy Andrew's avatar
Timothy Andrew committed
1510 1511 1512 1513 1514 1515 1516

      context "scopes" do
        let(:path) { "/user/emails" }
        let(:api_call) { method(:api) }

        include_examples 'allows the "read_user" scope'
      end
1517 1518 1519
    end
  end

Robert Schilling's avatar
Robert Schilling committed
1520
  describe "GET /user/emails/:email_id" do
1521
    it "returns single email" do
1522 1523 1524
      user.emails << email
      user.save
      get api("/user/emails/#{email.id}", user)
1525
      expect(response).to have_gitlab_http_status(200)
1526 1527 1528
      expect(json_response["email"]).to eq(email.email)
    end

1529
    it "returns 404 Not Found within invalid ID" do
1530
      get api("/user/emails/42", user)
1531
      expect(response).to have_gitlab_http_status(404)
Robert Schilling's avatar
Robert Schilling committed
1532
      expect(json_response['message']).to eq('404 Email Not Found')
1533 1534
    end

1535
    it "returns 404 error if admin accesses user's email" do
1536 1537 1538 1539
      user.emails << email
      user.save
      admin
      get api("/user/emails/#{email.id}", admin)
1540
      expect(response).to have_gitlab_http_status(404)
Robert Schilling's avatar
Robert Schilling committed
1541
      expect(json_response['message']).to eq('404 Email Not Found')
1542
    end
1543

1544
    it "returns 404 for invalid ID" do
1545
      get api("/users/emails/ASDF", admin)
1546

1547
      expect(response).to have_gitlab_http_status(404)
1548
    end
Timothy Andrew's avatar
Timothy Andrew committed
1549 1550 1551 1552 1553 1554 1555

    context "scopes" do
      let(:path) { "/user/emails/#{email.id}" }
      let(:api_call) { method(:api) }

      include_examples 'allows the "read_user" scope'
    end
1556 1557 1558
  end

  describe "POST /user/emails" do
1559
    it "creates email" do
1560 1561 1562
      email_attrs = attributes_for :email
      expect do
        post api("/user/emails", user), email_attrs
1563
      end.to change { user.emails.count }.by(1)
1564
      expect(response).to have_gitlab_http_status(201)
1565 1566
    end

1567
    it "returns a 401 error if unauthorized" do
1568
      post api("/user/emails"), email: 'some email'
1569
      expect(response).to have_gitlab_http_status(401)
1570 1571
    end

1572
    it "does not create email with invalid email" do
1573
      post api("/user/emails", user), {}
Robert Schilling's avatar
Robert Schilling committed
1574

1575
      expect(response).to have_gitlab_http_status(400)
Robert Schilling's avatar
Robert Schilling committed
1576
      expect(json_response['error']).to eq('email is missing')
1577 1578 1579
    end
  end

Robert Schilling's avatar
Robert Schilling committed
1580
  describe "DELETE /user/emails/:email_id" do
1581
    it "deletes existed email" do
1582 1583
      user.emails << email
      user.save
1584

1585 1586
      expect do
        delete api("/user/emails/#{email.id}", user)
1587

1588
        expect(response).to have_gitlab_http_status(204)
1589
      end.to change { user.emails.count}.by(-1)
1590 1591
    end

1592 1593 1594 1595
    it_behaves_like '412 response' do
      let(:request) { api("/user/emails/#{email.id}", user) }
    end

Robert Schilling's avatar
Robert Schilling committed
1596
    it "returns 404 if email ID not found" do
1597
      delete api("/user/emails/42", user)
Robert Schilling's avatar
Robert Schilling committed
1598

1599
      expect(response).to have_gitlab_http_status(404)
Robert Schilling's avatar
Robert Schilling committed
1600
      expect(json_response['message']).to eq('404 Email Not Found')
1601 1602
    end

1603
    it "returns 401 error if unauthorized" do
1604 1605 1606
      user.emails << email
      user.save
      delete api("/user/emails/#{email.id}")
1607
      expect(response).to have_gitlab_http_status(401)
1608
    end
1609

Robert Schilling's avatar
Robert Schilling committed
1610 1611
    it "returns 400 for invalid ID" do
      delete api("/user/emails/ASDF", admin)
1612

1613
      expect(response).to have_gitlab_http_status(400)
1614
    end
1615 1616
  end

1617
  describe 'POST /users/:id/block' do
1618 1619 1620 1621
    before do
      admin
    end

1622
    it 'blocks existing user' do
1623
      post api("/users/#{user.id}/block", admin)
1624
      expect(response).to have_gitlab_http_status(201)
1625 1626 1627
      expect(user.reload.state).to eq('blocked')
    end

1628
    it 'does not re-block ldap blocked users' do
1629
      post api("/users/#{ldap_blocked_user.id}/block", admin)
1630
      expect(response).to have_gitlab_http_status(403)
1631 1632 1633
      expect(ldap_blocked_user.reload.state).to eq('ldap_blocked')
    end

1634
    it 'does not be available for non admin users' do
1635
      post api("/users/#{user.id}/block", user)
1636
      expect(response).to have_gitlab_http_status(403)
1637 1638 1639
      expect(user.reload.state).to eq('active')
    end

1640
    it 'returns a 404 error if user id not found' do
1641
      post api('/users/9999/block', admin)
1642
      expect(response).to have_gitlab_http_status(404)
1643 1644 1645 1646
      expect(json_response['message']).to eq('404 User Not Found')
    end
  end

1647
  describe 'POST /users/:id/unblock' do
1648
    let(:blocked_user)  { create(:user, state: 'blocked') }
1649 1650 1651 1652

    before do
      admin
    end
1653

1654
    it 'unblocks existing user' do
1655
      post api("/users/#{user.id}/unblock", admin)
1656
      expect(response).to have_gitlab_http_status(201)
1657 1658 1659
      expect(user.reload.state).to eq('active')
    end

1660
    it 'unblocks a blocked user' do
1661
      post api("/users/#{blocked_user.id}/unblock", admin)
1662
      expect(response).to have_gitlab_http_status(201)
1663 1664 1665
      expect(blocked_user.reload.state).to eq('active')
    end

1666
    it 'does not unblock ldap blocked users' do
1667
      post api("/users/#{ldap_blocked_user.id}/unblock", admin)
1668
      expect(response).to have_gitlab_http_status(403)
1669
      expect(ldap_blocked_user.reload.state).to eq('ldap_blocked')
1670 1671
    end

1672
    it 'does not be available for non admin users' do
1673
      post api("/users/#{user.id}/unblock", user)
1674
      expect(response).to have_gitlab_http_status(403)
1675 1676 1677
      expect(user.reload.state).to eq('active')
    end

1678
    it 'returns a 404 error if user id not found' do
1679
      post api('/users/9999/block', admin)
1680
      expect(response).to have_gitlab_http_status(404)
1681 1682
      expect(json_response['message']).to eq('404 User Not Found')
    end
1683

1684
    it "returns a 404 for invalid ID" do
1685
      post api("/users/ASDF/block", admin)
1686

1687
      expect(response).to have_gitlab_http_status(404)
1688
    end
1689
  end
1690

1691
  context "user activities", :clean_gitlab_redis_shared_state do
1692 1693 1694 1695 1696 1697 1698
    let!(:old_active_user) { create(:user, last_activity_on: Time.utc(2000, 1, 1)) }
    let!(:newly_active_user) { create(:user, last_activity_on: 2.days.ago.midday) }

    context 'last activity as normal user' do
      it 'has no permission' do
        get api("/user/activities", user)

1699
        expect(response).to have_gitlab_http_status(403)
1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733
      end
    end

    context 'as admin' do
      it 'returns the activities from the last 6 months' do
        get api("/user/activities", admin)

        expect(response).to include_pagination_headers
        expect(json_response.size).to eq(1)

        activity = json_response.last

        expect(activity['username']).to eq(newly_active_user.username)
        expect(activity['last_activity_on']).to eq(2.days.ago.to_date.to_s)
        expect(activity['last_activity_at']).to eq(2.days.ago.to_date.to_s)
      end

      context 'passing a :from parameter' do
        it 'returns the activities from the given date' do
          get api("/user/activities?from=2000-1-1", admin)

          expect(response).to include_pagination_headers
          expect(json_response.size).to eq(2)

          activity = json_response.first

          expect(activity['username']).to eq(old_active_user.username)
          expect(activity['last_activity_on']).to eq(Time.utc(2000, 1, 1).to_date.to_s)
          expect(activity['last_activity_at']).to eq(Time.utc(2000, 1, 1).to_date.to_s)
        end
      end
    end
  end

1734
  describe 'GET /users/:user_id/impersonation_tokens' do
1735
    let!(:active_personal_access_token) { create(:personal_access_token, user: user) }
1736 1737 1738 1739
    let!(:revoked_personal_access_token) { create(:personal_access_token, :revoked, user: user) }
    let!(:expired_personal_access_token) { create(:personal_access_token, :expired, user: user) }
    let!(:impersonation_token) { create(:personal_access_token, :impersonation, user: user) }
    let!(:revoked_impersonation_token) { create(:personal_access_token, :impersonation, :revoked, user: user) }
1740 1741

    it 'returns a 404 error if user not found' do
1742
      get api("/users/#{not_existing_user_id}/impersonation_tokens", admin)
1743

1744
      expect(response).to have_gitlab_http_status(404)
1745 1746 1747 1748
      expect(json_response['message']).to eq('404 User Not Found')
    end

    it 'returns a 403 error when authenticated as normal user' do
1749
      get api("/users/#{not_existing_user_id}/impersonation_tokens", user)
1750

1751
      expect(response).to have_gitlab_http_status(403)
1752 1753 1754
      expect(json_response['message']).to eq('403 Forbidden')
    end

1755 1756
    it 'returns an array of all impersonated tokens' do
      get api("/users/#{user.id}/impersonation_tokens", admin)
1757

1758
      expect(response).to have_gitlab_http_status(200)
1759
      expect(response).to include_pagination_headers
1760
      expect(json_response).to be_an Array
1761
      expect(json_response.size).to eq(2)
1762 1763
    end

1764 1765
    it 'returns an array of active impersonation tokens if state active' do
      get api("/users/#{user.id}/impersonation_tokens?state=active", admin)
1766

1767
      expect(response).to have_gitlab_http_status(200)
1768
      expect(response).to include_pagination_headers
1769
      expect(json_response).to be_an Array
1770
      expect(json_response.size).to eq(1)
1771 1772 1773 1774
      expect(json_response).to all(include('active' => true))
    end

    it 'returns an array of inactive personal access tokens if active is set to false' do
1775
      get api("/users/#{user.id}/impersonation_tokens?state=inactive", admin)
1776

1777
      expect(response).to have_gitlab_http_status(200)
1778
      expect(json_response).to be_an Array
1779
      expect(json_response.size).to eq(1)
1780 1781 1782 1783
      expect(json_response).to all(include('active' => false))
    end
  end

1784
  describe 'POST /users/:user_id/impersonation_tokens' do
1785 1786
    let(:name) { 'my new pat' }
    let(:expires_at) { '2016-12-28' }
1787
    let(:scopes) { %w(api read_user) }
Simon Vocella's avatar
Simon Vocella committed
1788
    let(:impersonation) { true }
1789

1790 1791
    it 'returns validation error if impersonation token misses some attributes' do
      post api("/users/#{user.id}/impersonation_tokens", admin)
1792

1793
      expect(response).to have_gitlab_http_status(400)
1794 1795 1796 1797
      expect(json_response['error']).to eq('name is missing')
    end

    it 'returns a 404 error if user not found' do
1798
      post api("/users/#{not_existing_user_id}/impersonation_tokens", admin),
1799 1800 1801
        name: name,
        expires_at: expires_at

1802
      expect(response).to have_gitlab_http_status(404)
1803 1804 1805 1806
      expect(json_response['message']).to eq('404 User Not Found')
    end

    it 'returns a 403 error when authenticated as normal user' do
1807
      post api("/users/#{user.id}/impersonation_tokens", user),
1808 1809 1810
        name: name,
        expires_at: expires_at

1811
      expect(response).to have_gitlab_http_status(403)
1812 1813 1814
      expect(json_response['message']).to eq('403 Forbidden')
    end

1815 1816
    it 'creates a impersonation token' do
      post api("/users/#{user.id}/impersonation_tokens", admin),
1817 1818
        name: name,
        expires_at: expires_at,
Simon Vocella's avatar
Simon Vocella committed
1819 1820
        scopes: scopes,
        impersonation: impersonation
1821

1822
      expect(response).to have_gitlab_http_status(201)
1823 1824 1825 1826 1827
      expect(json_response['name']).to eq(name)
      expect(json_response['scopes']).to eq(scopes)
      expect(json_response['expires_at']).to eq(expires_at)
      expect(json_response['id']).to be_present
      expect(json_response['created_at']).to be_present
1828 1829
      expect(json_response['active']).to be_falsey
      expect(json_response['revoked']).to be_falsey
1830
      expect(json_response['token']).to be_present
Simon Vocella's avatar
Simon Vocella committed
1831
      expect(json_response['impersonation']).to eq(impersonation)
1832 1833 1834
    end
  end

1835 1836 1837
  describe 'GET /users/:user_id/impersonation_tokens/:impersonation_token_id' do
    let!(:personal_access_token) { create(:personal_access_token, user: user) }
    let!(:impersonation_token) { create(:personal_access_token, :impersonation, user: user) }
1838 1839

    it 'returns 404 error if user not found' do
1840
      get api("/users/#{not_existing_user_id}/impersonation_tokens/1", admin)
1841

1842
      expect(response).to have_gitlab_http_status(404)
1843 1844 1845
      expect(json_response['message']).to eq('404 User Not Found')
    end

1846 1847
    it 'returns a 404 error if impersonation token not found' do
      get api("/users/#{user.id}/impersonation_tokens/#{not_existing_pat_id}", admin)
1848

1849
      expect(response).to have_gitlab_http_status(404)
1850 1851 1852 1853 1854 1855
      expect(json_response['message']).to eq('404 Impersonation Token Not Found')
    end

    it 'returns a 404 error if token is not impersonation token' do
      get api("/users/#{user.id}/impersonation_tokens/#{personal_access_token.id}", admin)

1856
      expect(response).to have_gitlab_http_status(404)
1857
      expect(json_response['message']).to eq('404 Impersonation Token Not Found')
1858 1859 1860
    end

    it 'returns a 403 error when authenticated as normal user' do
1861
      get api("/users/#{user.id}/impersonation_tokens/#{impersonation_token.id}", user)
1862

1863
      expect(response).to have_gitlab_http_status(403)
1864 1865 1866 1867
      expect(json_response['message']).to eq('403 Forbidden')
    end

    it 'returns a personal access token' do
1868
      get api("/users/#{user.id}/impersonation_tokens/#{impersonation_token.id}", admin)
1869

1870
      expect(response).to have_gitlab_http_status(200)
1871
      expect(json_response['token']).to be_present
1872
      expect(json_response['impersonation']).to be_truthy
1873 1874 1875
    end
  end

1876 1877 1878
  describe 'DELETE /users/:user_id/impersonation_tokens/:impersonation_token_id' do
    let!(:personal_access_token) { create(:personal_access_token, user: user) }
    let!(:impersonation_token) { create(:personal_access_token, :impersonation, user: user) }
1879 1880

    it 'returns a 404 error if user not found' do
1881
      delete api("/users/#{not_existing_user_id}/impersonation_tokens/1", admin)
1882

1883
      expect(response).to have_gitlab_http_status(404)
1884 1885 1886
      expect(json_response['message']).to eq('404 User Not Found')
    end

1887 1888 1889
    it 'returns a 404 error if impersonation token not found' do
      delete api("/users/#{user.id}/impersonation_tokens/#{not_existing_pat_id}", admin)

1890
      expect(response).to have_gitlab_http_status(404)
1891 1892 1893 1894 1895
      expect(json_response['message']).to eq('404 Impersonation Token Not Found')
    end

    it 'returns a 404 error if token is not impersonation token' do
      delete api("/users/#{user.id}/impersonation_tokens/#{personal_access_token.id}", admin)
1896

1897
      expect(response).to have_gitlab_http_status(404)
1898
      expect(json_response['message']).to eq('404 Impersonation Token Not Found')
1899 1900 1901
    end

    it 'returns a 403 error when authenticated as normal user' do
1902
      delete api("/users/#{user.id}/impersonation_tokens/#{impersonation_token.id}", user)
1903

1904
      expect(response).to have_gitlab_http_status(403)
1905 1906 1907
      expect(json_response['message']).to eq('403 Forbidden')
    end

1908 1909 1910 1911
    it_behaves_like '412 response' do
      let(:request) { api("/users/#{user.id}/impersonation_tokens/#{impersonation_token.id}", admin) }
    end

1912 1913
    it 'revokes a impersonation token' do
      delete api("/users/#{user.id}/impersonation_tokens/#{impersonation_token.id}", admin)
1914

1915
      expect(response).to have_gitlab_http_status(204)
1916 1917
      expect(impersonation_token.revoked).to be_falsey
      expect(impersonation_token.reload.revoked).to be_truthy
1918 1919
    end
  end
1920

1921
  it_behaves_like 'custom attributes endpoints', 'users' do
1922
    let(:attributable) { user }
1923
    let(:other_attributable) { admin }
1924
  end
Nihad Abbasov's avatar
Nihad Abbasov committed
1925
end