1# frozen_string_literal: true 2 3require 'spec_helper' 4 5RSpec.describe User do 6 include ProjectForksHelper 7 include TermsHelper 8 include ExclusiveLeaseHelpers 9 include LdapHelpers 10 11 it_behaves_like 'having unique enum values' 12 13 describe 'modules' do 14 subject { described_class } 15 16 it { is_expected.to include_module(Gitlab::ConfigHelper) } 17 it { is_expected.to include_module(Referable) } 18 it { is_expected.to include_module(Sortable) } 19 it { is_expected.to include_module(TokenAuthenticatable) } 20 it { is_expected.to include_module(BlocksJsonSerialization) } 21 it { is_expected.to include_module(AsyncDeviseEmail) } 22 end 23 24 describe 'constants' do 25 it { expect(described_class::COUNT_CACHE_VALIDITY_PERIOD).to be_a(Integer) } 26 it { expect(described_class::MAX_USERNAME_LENGTH).to be_a(Integer) } 27 it { expect(described_class::MIN_USERNAME_LENGTH).to be_a(Integer) } 28 end 29 30 describe 'delegations' do 31 it { is_expected.to delegate_method(:path).to(:namespace).with_prefix } 32 33 it { is_expected.to delegate_method(:notes_filter_for).to(:user_preference) } 34 it { is_expected.to delegate_method(:set_notes_filter).to(:user_preference) } 35 36 it { is_expected.to delegate_method(:first_day_of_week).to(:user_preference) } 37 it { is_expected.to delegate_method(:first_day_of_week=).to(:user_preference).with_arguments(:args) } 38 39 it { is_expected.to delegate_method(:timezone).to(:user_preference) } 40 it { is_expected.to delegate_method(:timezone=).to(:user_preference).with_arguments(:args) } 41 42 it { is_expected.to delegate_method(:time_display_relative).to(:user_preference) } 43 it { is_expected.to delegate_method(:time_display_relative=).to(:user_preference).with_arguments(:args) } 44 45 it { is_expected.to delegate_method(:time_format_in_24h).to(:user_preference) } 46 it { is_expected.to delegate_method(:time_format_in_24h=).to(:user_preference).with_arguments(:args) } 47 48 it { is_expected.to delegate_method(:show_whitespace_in_diffs).to(:user_preference) } 49 it { is_expected.to delegate_method(:show_whitespace_in_diffs=).to(:user_preference).with_arguments(:args) } 50 51 it { is_expected.to delegate_method(:view_diffs_file_by_file).to(:user_preference) } 52 it { is_expected.to delegate_method(:view_diffs_file_by_file=).to(:user_preference).with_arguments(:args) } 53 54 it { is_expected.to delegate_method(:tab_width).to(:user_preference) } 55 it { is_expected.to delegate_method(:tab_width=).to(:user_preference).with_arguments(:args) } 56 57 it { is_expected.to delegate_method(:sourcegraph_enabled).to(:user_preference) } 58 it { is_expected.to delegate_method(:sourcegraph_enabled=).to(:user_preference).with_arguments(:args) } 59 60 it { is_expected.to delegate_method(:gitpod_enabled).to(:user_preference) } 61 it { is_expected.to delegate_method(:gitpod_enabled=).to(:user_preference).with_arguments(:args) } 62 63 it { is_expected.to delegate_method(:setup_for_company).to(:user_preference) } 64 it { is_expected.to delegate_method(:setup_for_company=).to(:user_preference).with_arguments(:args) } 65 66 it { is_expected.to delegate_method(:render_whitespace_in_code).to(:user_preference) } 67 it { is_expected.to delegate_method(:render_whitespace_in_code=).to(:user_preference).with_arguments(:args) } 68 69 it { is_expected.to delegate_method(:markdown_surround_selection).to(:user_preference) } 70 it { is_expected.to delegate_method(:markdown_surround_selection=).to(:user_preference).with_arguments(:args) } 71 72 it { is_expected.to delegate_method(:job_title).to(:user_detail).allow_nil } 73 it { is_expected.to delegate_method(:job_title=).to(:user_detail).with_arguments(:args).allow_nil } 74 75 it { is_expected.to delegate_method(:pronouns).to(:user_detail).allow_nil } 76 it { is_expected.to delegate_method(:pronouns=).to(:user_detail).with_arguments(:args).allow_nil } 77 78 it { is_expected.to delegate_method(:pronunciation).to(:user_detail).allow_nil } 79 it { is_expected.to delegate_method(:pronunciation=).to(:user_detail).with_arguments(:args).allow_nil } 80 81 it { is_expected.to delegate_method(:bio).to(:user_detail).allow_nil } 82 it { is_expected.to delegate_method(:bio=).to(:user_detail).with_arguments(:args).allow_nil } 83 84 it { is_expected.to delegate_method(:registration_objective).to(:user_detail).allow_nil } 85 it { is_expected.to delegate_method(:registration_objective=).to(:user_detail).with_arguments(:args).allow_nil } 86 end 87 88 describe 'associations' do 89 it { is_expected.to have_one(:namespace) } 90 it { is_expected.to have_one(:status) } 91 it { is_expected.to have_one(:user_detail) } 92 it { is_expected.to have_one(:atlassian_identity) } 93 it { is_expected.to have_one(:user_highest_role) } 94 it { is_expected.to have_one(:credit_card_validation) } 95 it { is_expected.to have_one(:banned_user) } 96 it { is_expected.to have_many(:snippets).dependent(:destroy) } 97 it { is_expected.to have_many(:members) } 98 it { is_expected.to have_many(:project_members) } 99 it { is_expected.to have_many(:group_members) } 100 it { is_expected.to have_many(:groups) } 101 it { is_expected.to have_many(:keys).dependent(:destroy) } 102 it { is_expected.to have_many(:expired_today_and_unnotified_keys) } 103 it { is_expected.to have_many(:deploy_keys).dependent(:nullify) } 104 it { is_expected.to have_many(:group_deploy_keys) } 105 it { is_expected.to have_many(:events).dependent(:delete_all) } 106 it { is_expected.to have_many(:issues).dependent(:destroy) } 107 it { is_expected.to have_many(:notes).dependent(:destroy) } 108 it { is_expected.to have_many(:merge_requests).dependent(:destroy) } 109 it { is_expected.to have_many(:identities).dependent(:destroy) } 110 it { is_expected.to have_many(:spam_logs).dependent(:destroy) } 111 it { is_expected.to have_many(:todos) } 112 it { is_expected.to have_many(:award_emoji).dependent(:destroy) } 113 it { is_expected.to have_many(:builds) } 114 it { is_expected.to have_many(:pipelines) } 115 it { is_expected.to have_many(:chat_names).dependent(:destroy) } 116 it { is_expected.to have_many(:uploads) } 117 it { is_expected.to have_many(:reported_abuse_reports).dependent(:destroy).class_name('AbuseReport') } 118 it { is_expected.to have_many(:custom_attributes).class_name('UserCustomAttribute') } 119 it { is_expected.to have_many(:releases).dependent(:nullify) } 120 it { is_expected.to have_many(:metrics_users_starred_dashboards).inverse_of(:user) } 121 it { is_expected.to have_many(:reviews).inverse_of(:author) } 122 it { is_expected.to have_many(:merge_request_assignees).inverse_of(:assignee) } 123 it { is_expected.to have_many(:merge_request_reviewers).inverse_of(:reviewer) } 124 it { is_expected.to have_many(:created_custom_emoji).inverse_of(:creator) } 125 it { is_expected.to have_many(:in_product_marketing_emails) } 126 it { is_expected.to have_many(:timelogs) } 127 it { is_expected.to have_many(:callouts).class_name('Users::Callout') } 128 it { is_expected.to have_many(:group_callouts).class_name('Users::GroupCallout') } 129 130 describe '#user_detail' do 131 it 'does not persist `user_detail` by default' do 132 expect(create(:user).user_detail).not_to be_persisted 133 end 134 135 it 'creates `user_detail` when `bio` is given' do 136 user = create(:user, bio: 'my bio') 137 138 expect(user.user_detail).to be_persisted 139 expect(user.user_detail.bio).to eq('my bio') 140 end 141 142 it 'delegates `bio` to `user_detail`' do 143 user = create(:user, bio: 'my bio') 144 145 expect(user.bio).to eq(user.user_detail.bio) 146 end 147 148 it 'delegates `pronouns` to `user_detail`' do 149 user = create(:user, pronouns: 'they/them') 150 151 expect(user.pronouns).to eq(user.user_detail.pronouns) 152 end 153 154 it 'delegates `pronunciation` to `user_detail`' do 155 user = create(:user, name: 'Example', pronunciation: 'uhg-zaam-pl') 156 157 expect(user.pronunciation).to eq(user.user_detail.pronunciation) 158 end 159 160 it 'creates `user_detail` when `bio` is first updated' do 161 user = create(:user) 162 163 expect { user.update!(bio: 'my bio') }.to change { user.user_detail.persisted? }.from(false).to(true) 164 end 165 end 166 167 describe '#abuse_report' do 168 let(:current_user) { create(:user) } 169 let(:other_user) { create(:user) } 170 171 it { is_expected.to have_one(:abuse_report) } 172 173 it 'refers to the abuse report whose user_id is the current user' do 174 abuse_report = create(:abuse_report, reporter: other_user, user: current_user) 175 176 expect(current_user.abuse_report).to eq(abuse_report) 177 end 178 179 it 'does not refer to the abuse report whose reporter_id is the current user' do 180 create(:abuse_report, reporter: current_user, user: other_user) 181 182 expect(current_user.abuse_report).to be_nil 183 end 184 185 it 'does not update the user_id of an abuse report when the user is updated' do 186 abuse_report = create(:abuse_report, reporter: current_user, user: other_user) 187 188 current_user.block 189 190 expect(abuse_report.reload.user).to eq(other_user) 191 end 192 end 193 194 describe '#group_members' do 195 it 'does not include group memberships for which user is a requester' do 196 user = create(:user) 197 group = create(:group, :public) 198 group.request_access(user) 199 200 expect(user.group_members).to be_empty 201 end 202 end 203 204 describe '#project_members' do 205 it 'does not include project memberships for which user is a requester' do 206 user = create(:user) 207 project = create(:project, :public) 208 project.request_access(user) 209 210 expect(user.project_members).to be_empty 211 end 212 end 213 end 214 215 describe 'Devise emails' do 216 let!(:user) { create(:user) } 217 218 describe 'behaviour' do 219 it 'sends emails asynchronously' do 220 expect do 221 user.update!(email: 'hello@hello.com') 222 end.to have_enqueued_job.on_queue('mailers').exactly(:twice) 223 end 224 end 225 226 context 'emails sent on changing password' do 227 context 'when password is updated' do 228 context 'default behaviour' do 229 it 'enqueues the `password changed` email' do 230 user.password = User.random_password 231 232 expect { user.save! }.to have_enqueued_mail(DeviseMailer, :password_change) 233 end 234 235 it 'does not enqueue the `admin changed your password` email' do 236 user.password = User.random_password 237 238 expect { user.save! }.not_to have_enqueued_mail(DeviseMailer, :password_change_by_admin) 239 end 240 end 241 242 context '`admin changed your password` email' do 243 it 'is enqueued only when explicitly allowed' do 244 user.password = User.random_password 245 user.send_only_admin_changed_your_password_notification! 246 247 expect { user.save! }.to have_enqueued_mail(DeviseMailer, :password_change_by_admin) 248 end 249 250 it '`password changed` email is not enqueued if it is explicitly allowed' do 251 user.password = User.random_password 252 user.send_only_admin_changed_your_password_notification! 253 254 expect { user.save! }.not_to have_enqueued_mail(DeviseMailer, :password_changed) 255 end 256 257 it 'is not enqueued if sending notifications on password updates is turned off as per Devise config' do 258 user.password = User.random_password 259 user.send_only_admin_changed_your_password_notification! 260 261 allow(Devise).to receive(:send_password_change_notification).and_return(false) 262 263 expect { user.save! }.not_to have_enqueued_mail(DeviseMailer, :password_change_by_admin) 264 end 265 end 266 end 267 268 context 'when password is not updated' do 269 it 'does not enqueue the `admin changed your password` email even if explicitly allowed' do 270 user.name = 'John' 271 user.send_only_admin_changed_your_password_notification! 272 273 expect { user.save! }.not_to have_enqueued_mail(DeviseMailer, :password_change_by_admin) 274 end 275 end 276 end 277 end 278 279 describe 'validations' do 280 describe 'password' do 281 let!(:user) { build_stubbed(:user) } 282 283 before do 284 allow(Devise).to receive(:password_length).and_return(8..128) 285 allow(described_class).to receive(:password_length).and_return(10..130) 286 end 287 288 context 'length' do 289 it { is_expected.to validate_length_of(:password).is_at_least(10).is_at_most(130) } 290 end 291 292 context 'length validator' do 293 context 'for a short password' do 294 before do 295 user.password = user.password_confirmation = 'abc' 296 end 297 298 it 'does not run the default Devise password length validation' do 299 expect(user).to be_invalid 300 expect(user.errors.full_messages.join).not_to include('is too short (minimum is 8 characters)') 301 end 302 303 it 'runs the custom password length validator' do 304 expect(user).to be_invalid 305 expect(user.errors.full_messages.join).to include('is too short (minimum is 10 characters)') 306 end 307 end 308 309 context 'for a long password' do 310 before do 311 user.password = user.password_confirmation = 'a' * 140 312 end 313 314 it 'does not run the default Devise password length validation' do 315 expect(user).to be_invalid 316 expect(user.errors.full_messages.join).not_to include('is too long (maximum is 128 characters)') 317 end 318 319 it 'runs the custom password length validator' do 320 expect(user).to be_invalid 321 expect(user.errors.full_messages.join).to include('is too long (maximum is 130 characters)') 322 end 323 end 324 end 325 end 326 327 describe 'name' do 328 it { is_expected.to validate_presence_of(:name) } 329 it { is_expected.to validate_length_of(:name).is_at_most(255) } 330 end 331 332 describe 'first name' do 333 it { is_expected.to validate_length_of(:first_name).is_at_most(127) } 334 end 335 336 describe 'last name' do 337 it { is_expected.to validate_length_of(:last_name).is_at_most(127) } 338 end 339 340 describe 'preferred_language' do 341 context 'when its value is nil in the database' do 342 let(:user) { build(:user, preferred_language: nil) } 343 344 it 'falls back to I18n.default_locale when empty in the database' do 345 expect(user.preferred_language).to eq I18n.default_locale.to_s 346 end 347 348 it 'falls back to english when I18n.default_locale is not an available language' do 349 I18n.default_locale = :kl 350 default_preferred_language = user.send(:default_preferred_language) 351 352 expect(user.preferred_language).to eq default_preferred_language 353 end 354 end 355 end 356 357 describe 'username' do 358 it 'validates presence' do 359 expect(subject).to validate_presence_of(:username) 360 end 361 362 it 'rejects denied names' do 363 user = build(:user, username: 'dashboard') 364 365 expect(user).not_to be_valid 366 expect(user.errors.messages[:username]).to eq ['dashboard is a reserved name'] 367 end 368 369 it 'allows child names' do 370 user = build(:user, username: 'avatar') 371 372 expect(user).to be_valid 373 end 374 375 it 'allows wildcard names' do 376 user = build(:user, username: 'blob') 377 378 expect(user).to be_valid 379 end 380 381 context 'when username is changed' do 382 let(:user) { build_stubbed(:user, username: 'old_path', namespace: build_stubbed(:user_namespace)) } 383 384 it 'validates move_dir is allowed for the namespace' do 385 expect(user.namespace).to receive(:any_project_has_container_registry_tags?).and_return(true) 386 user.username = 'new_path' 387 expect(user).to be_invalid 388 expect(user.errors.messages[:username].first).to eq(_('cannot be changed if a personal project has container registry tags.')) 389 end 390 end 391 392 context 'when the username is in use by another user' do 393 let(:username) { 'foo' } 394 let!(:other_user) { create(:user, username: username) } 395 396 it 'is invalid' do 397 user = build(:user, username: username) 398 399 expect(user).not_to be_valid 400 expect(user.errors.full_messages).to eq(['Username has already been taken']) 401 end 402 end 403 404 it 'validates format' do 405 Mime::EXTENSION_LOOKUP.keys.each do |type| 406 user = build(:user, username: "test.#{type}") 407 408 expect(user).not_to be_valid 409 expect(user.errors.full_messages).to include('Username ending with a reserved file extension is not allowed.') 410 expect(build(:user, username: "test#{type}")).to be_valid 411 end 412 end 413 414 it 'validates format on updated record' do 415 expect(create(:user).update(username: 'profile.html')).to be_falsey 416 end 417 end 418 419 it 'has a DB-level NOT NULL constraint on projects_limit' do 420 user = create(:user) 421 422 expect(user.persisted?).to eq(true) 423 424 expect do 425 user.update_columns(projects_limit: nil) 426 end.to raise_error(ActiveRecord::StatementInvalid) 427 end 428 429 it { is_expected.to validate_presence_of(:projects_limit) } 430 it { is_expected.to validate_numericality_of(:projects_limit) } 431 it { is_expected.to allow_value(0).for(:projects_limit) } 432 it { is_expected.not_to allow_value(-1).for(:projects_limit) } 433 it { is_expected.not_to allow_value(Gitlab::Database::MAX_INT_VALUE + 1).for(:projects_limit) } 434 435 it_behaves_like 'an object with email-formatted attributes', :email do 436 subject { build(:user) } 437 end 438 439 it_behaves_like 'an object with RFC3696 compliant email-formatted attributes', :public_email, :notification_email do 440 subject { create(:user).tap { |user| user.emails << build(:email, email: email_value, confirmed_at: Time.current) } } 441 end 442 443 describe '#commit_email_or_default' do 444 subject(:user) { create(:user) } 445 446 it 'defaults to the primary email' do 447 expect(user.email).to be_present 448 expect(user.commit_email_or_default).to eq(user.email) 449 end 450 451 it 'defaults to the primary email when the column in the database is null' do 452 user.update_column(:commit_email, nil) 453 454 found_user = described_class.find_by(id: user.id) 455 456 expect(found_user.commit_email_or_default).to eq(user.email) 457 end 458 459 it 'returns the private commit email when commit_email has _private' do 460 user.update_column(:commit_email, Gitlab::PrivateCommitEmail::TOKEN) 461 462 expect(user.commit_email_or_default).to eq(user.private_commit_email) 463 end 464 end 465 466 describe '#commit_email=' do 467 subject(:user) { create(:user) } 468 469 it 'can be set to a confirmed email' do 470 confirmed = create(:email, :confirmed, user: user) 471 user.commit_email = confirmed.email 472 473 expect(user).to be_valid 474 end 475 476 it 'can not be set to an unconfirmed email' do 477 unconfirmed = create(:email, user: user) 478 user.commit_email = unconfirmed.email 479 480 expect(user).not_to be_valid 481 end 482 483 it 'can not be set to a non-existent email' do 484 user.commit_email = 'non-existent-email@nonexistent.nonexistent' 485 486 expect(user).not_to be_valid 487 end 488 489 it 'can not be set to an invalid email, even if confirmed' do 490 confirmed = create(:email, :confirmed, :skip_validate, user: user, email: 'invalid') 491 user.commit_email = confirmed.email 492 493 expect(user).not_to be_valid 494 end 495 end 496 497 describe 'email' do 498 let(:expected_error) { _('is not allowed for sign-up. Check with your administrator.') } 499 500 context 'when no signup domains allowed' do 501 before do 502 stub_application_setting(domain_allowlist: []) 503 end 504 505 it 'accepts any email' do 506 user = build(:user, email: "info@example.com") 507 expect(user).to be_valid 508 end 509 end 510 511 context 'bad regex' do 512 before do 513 stub_application_setting(domain_allowlist: ['([a-zA-Z0-9]+)+\.com']) 514 end 515 516 it 'does not hang on evil input' do 517 user = build(:user, email: 'user@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!.com') 518 519 expect do 520 Timeout.timeout(2.seconds) { user.valid? } 521 end.not_to raise_error 522 end 523 end 524 525 context 'when a signup domain is allowed and subdomains are allowed' do 526 before do 527 stub_application_setting(domain_allowlist: ['example.com', '*.example.com']) 528 end 529 530 it 'accepts info@example.com' do 531 user = build(:user, email: "info@example.com") 532 expect(user).to be_valid 533 end 534 535 it 'accepts info@test.example.com' do 536 user = build(:user, email: "info@test.example.com") 537 expect(user).to be_valid 538 end 539 540 it 'rejects example@test.com' do 541 user = build(:user, email: "example@test.com") 542 expect(user).to be_invalid 543 expect(user.errors.messages[:email].first).to eq(expected_error) 544 end 545 end 546 547 context 'when a signup domain is allowed and subdomains are not allowed' do 548 before do 549 stub_application_setting(domain_allowlist: ['example.com']) 550 end 551 552 it 'accepts info@example.com' do 553 user = build(:user, email: "info@example.com") 554 expect(user).to be_valid 555 end 556 557 it 'rejects info@test.example.com' do 558 user = build(:user, email: "info@test.example.com") 559 expect(user).to be_invalid 560 expect(user.errors.messages[:email].first).to eq(expected_error) 561 end 562 563 it 'rejects example@test.com' do 564 user = build(:user, email: "example@test.com") 565 expect(user).to be_invalid 566 expect(user.errors.messages[:email].first).to eq(expected_error) 567 end 568 569 it 'accepts example@test.com when added by another user' do 570 user = build(:user, email: "example@test.com", created_by_id: 1) 571 expect(user).to be_valid 572 end 573 end 574 575 context 'domain denylist' do 576 before do 577 stub_application_setting(domain_denylist_enabled: true) 578 stub_application_setting(domain_denylist: ['example.com']) 579 end 580 581 context 'bad regex' do 582 before do 583 stub_application_setting(domain_denylist: ['([a-zA-Z0-9]+)+\.com']) 584 end 585 586 it 'does not hang on evil input' do 587 user = build(:user, email: 'user@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!.com') 588 589 expect do 590 Timeout.timeout(2.seconds) { user.valid? } 591 end.not_to raise_error 592 end 593 end 594 595 context 'when a signup domain is denied' do 596 it 'accepts info@test.com' do 597 user = build(:user, email: 'info@test.com') 598 expect(user).to be_valid 599 end 600 601 it 'rejects info@example.com' do 602 user = build(:user, email: 'info@example.com') 603 expect(user).not_to be_valid 604 expect(user.errors.messages[:email].first).to eq(expected_error) 605 end 606 607 it 'accepts info@example.com when added by another user' do 608 user = build(:user, email: 'info@example.com', created_by_id: 1) 609 expect(user).to be_valid 610 end 611 end 612 613 context 'when a signup domain is denied but a wildcard subdomain is allowed' do 614 before do 615 stub_application_setting(domain_denylist: ['test.example.com']) 616 stub_application_setting(domain_allowlist: ['*.example.com']) 617 end 618 619 it 'gives priority to allowlist and allow info@test.example.com' do 620 user = build(:user, email: 'info@test.example.com') 621 expect(user).to be_valid 622 end 623 end 624 625 context 'with both lists containing a domain' do 626 before do 627 stub_application_setting(domain_allowlist: ['test.com']) 628 end 629 630 it 'accepts info@test.com' do 631 user = build(:user, email: 'info@test.com') 632 expect(user).to be_valid 633 end 634 635 it 'rejects info@example.com' do 636 user = build(:user, email: 'info@example.com') 637 expect(user).not_to be_valid 638 expect(user.errors.messages[:email].first).to eq(expected_error) 639 end 640 end 641 end 642 643 context 'email restrictions' do 644 context 'when email restriction is disabled' do 645 before do 646 stub_application_setting(email_restrictions_enabled: false) 647 stub_application_setting(email_restrictions: '\+') 648 end 649 650 it 'does accept email address' do 651 user = build(:user, email: 'info+1@test.com') 652 653 expect(user).to be_valid 654 end 655 end 656 657 context 'when email restrictions is enabled' do 658 before do 659 stub_application_setting(email_restrictions_enabled: true) 660 stub_application_setting(email_restrictions: '([\+]|\b(\w*gitlab.com\w*)\b)') 661 end 662 663 it 'does not accept email address with + characters' do 664 user = build(:user, email: 'info+1@test.com') 665 666 expect(user).not_to be_valid 667 end 668 669 it 'does not accept email with a gitlab domain' do 670 user = build(:user, email: 'info@gitlab.com') 671 672 expect(user).not_to be_valid 673 end 674 675 it 'adds an error message when email is not accepted' do 676 user = build(:user, email: 'info@gitlab.com') 677 678 expect(user).not_to be_valid 679 expect(user.errors.messages[:email].first).to eq(expected_error) 680 end 681 682 it 'does accept a valid email address' do 683 user = build(:user, email: 'info@test.com') 684 685 expect(user).to be_valid 686 end 687 688 context 'when created_by_id is set' do 689 it 'does accept the email address' do 690 user = build(:user, email: 'info+1@test.com', created_by_id: 1) 691 692 expect(user).to be_valid 693 end 694 end 695 end 696 end 697 698 context 'when secondary email is same as primary' do 699 let(:user) { create(:user, email: 'user@example.com') } 700 701 it 'lets user change primary email without failing validations' do 702 user.commit_email = user.email 703 user.notification_email = user.email 704 user.public_email = user.email 705 user.save! 706 707 user.email = 'newemail@example.com' 708 user.confirm 709 710 expect(user).to be_valid 711 end 712 end 713 714 context 'when commit_email is changed to _private' do 715 it 'passes user validations' do 716 user = create(:user) 717 user.commit_email = '_private' 718 719 expect(user).to be_valid 720 end 721 end 722 end 723 end 724 725 describe 'scopes' do 726 context 'blocked users' do 727 let_it_be(:active_user) { create(:user) } 728 let_it_be(:blocked_user) { create(:user, :blocked) } 729 let_it_be(:ldap_blocked_user) { create(:omniauth_user, :ldap_blocked) } 730 let_it_be(:blocked_pending_approval_user) { create(:user, :blocked_pending_approval) } 731 let_it_be(:banned_user) { create(:user, :banned) } 732 733 describe '.blocked' do 734 subject { described_class.blocked } 735 736 it 'returns only blocked users' do 737 expect(subject).to include( 738 blocked_user, 739 ldap_blocked_user 740 ) 741 742 expect(subject).not_to include(active_user, blocked_pending_approval_user, banned_user) 743 end 744 end 745 746 describe '.blocked_pending_approval' do 747 subject { described_class.blocked_pending_approval } 748 749 it 'returns only pending approval users' do 750 expect(subject).to contain_exactly(blocked_pending_approval_user) 751 end 752 end 753 754 describe '.banned' do 755 subject { described_class.banned } 756 757 it 'returns only banned users' do 758 expect(subject).to contain_exactly(banned_user) 759 end 760 end 761 end 762 763 describe '.with_two_factor' do 764 it 'returns users with 2fa enabled via OTP' do 765 user_with_2fa = create(:user, :two_factor_via_otp) 766 user_without_2fa = create(:user) 767 users_with_two_factor = described_class.with_two_factor.pluck(:id) 768 769 expect(users_with_two_factor).to include(user_with_2fa.id) 770 expect(users_with_two_factor).not_to include(user_without_2fa.id) 771 end 772 773 shared_examples 'returns the right users' do |trait| 774 it 'returns users with 2fa enabled via hardware token' do 775 user_with_2fa = create(:user, trait) 776 user_without_2fa = create(:user) 777 users_with_two_factor = described_class.with_two_factor.pluck(:id) 778 779 expect(users_with_two_factor).to include(user_with_2fa.id) 780 expect(users_with_two_factor).not_to include(user_without_2fa.id) 781 end 782 783 it 'returns users with 2fa enabled via OTP and hardware token' do 784 user_with_2fa = create(:user, :two_factor_via_otp, trait) 785 user_without_2fa = create(:user) 786 users_with_two_factor = described_class.with_two_factor.pluck(:id) 787 788 expect(users_with_two_factor).to eq([user_with_2fa.id]) 789 expect(users_with_two_factor).not_to include(user_without_2fa.id) 790 end 791 792 it 'works with ORDER BY' do 793 user_with_2fa = create(:user, :two_factor_via_otp, trait) 794 795 expect(described_class 796 .with_two_factor 797 .reorder_by_name).to eq([user_with_2fa]) 798 end 799 end 800 801 describe 'and U2F' do 802 it_behaves_like "returns the right users", :two_factor_via_u2f 803 end 804 805 describe 'and WebAuthn' do 806 it_behaves_like "returns the right users", :two_factor_via_webauthn 807 end 808 end 809 810 describe '.without_two_factor' do 811 it 'excludes users with 2fa enabled via OTP' do 812 user_with_2fa = create(:user, :two_factor_via_otp) 813 user_without_2fa = create(:user) 814 users_without_two_factor = described_class.without_two_factor.pluck(:id) 815 816 expect(users_without_two_factor).to include(user_without_2fa.id) 817 expect(users_without_two_factor).not_to include(user_with_2fa.id) 818 end 819 820 describe 'and u2f' do 821 it 'excludes users with 2fa enabled via U2F' do 822 user_with_2fa = create(:user, :two_factor_via_u2f) 823 user_without_2fa = create(:user) 824 users_without_two_factor = described_class.without_two_factor.pluck(:id) 825 826 expect(users_without_two_factor).to include(user_without_2fa.id) 827 expect(users_without_two_factor).not_to include(user_with_2fa.id) 828 end 829 830 it 'excludes users with 2fa enabled via OTP and U2F' do 831 user_with_2fa = create(:user, :two_factor_via_otp, :two_factor_via_u2f) 832 user_without_2fa = create(:user) 833 users_without_two_factor = described_class.without_two_factor.pluck(:id) 834 835 expect(users_without_two_factor).to include(user_without_2fa.id) 836 expect(users_without_two_factor).not_to include(user_with_2fa.id) 837 end 838 end 839 840 describe 'and webauthn' do 841 it 'excludes users with 2fa enabled via WebAuthn' do 842 user_with_2fa = create(:user, :two_factor_via_webauthn) 843 user_without_2fa = create(:user) 844 users_without_two_factor = described_class.without_two_factor.pluck(:id) 845 846 expect(users_without_two_factor).to include(user_without_2fa.id) 847 expect(users_without_two_factor).not_to include(user_with_2fa.id) 848 end 849 850 it 'excludes users with 2fa enabled via OTP and WebAuthn' do 851 user_with_2fa = create(:user, :two_factor_via_otp, :two_factor_via_webauthn) 852 user_without_2fa = create(:user) 853 users_without_two_factor = described_class.without_two_factor.pluck(:id) 854 855 expect(users_without_two_factor).to include(user_without_2fa.id) 856 expect(users_without_two_factor).not_to include(user_with_2fa.id) 857 end 858 end 859 end 860 861 describe '.random_password' do 862 let(:random_password) { described_class.random_password } 863 864 before do 865 expect(User).to receive(:password_length).and_return(88..128) 866 end 867 868 context 'length' do 869 it 'conforms to the current password length settings' do 870 expect(random_password.length).to eq(128) 871 end 872 end 873 end 874 875 describe '.password_length' do 876 let(:password_length) { described_class.password_length } 877 878 it 'is expected to be a Range' do 879 expect(password_length).to be_a(Range) 880 end 881 882 context 'minimum value' do 883 before do 884 stub_application_setting(minimum_password_length: 101) 885 end 886 887 it 'is determined by the current value of `minimum_password_length` attribute of application_setting' do 888 expect(password_length.min).to eq(101) 889 end 890 end 891 892 context 'maximum value' do 893 it 'is determined by the current value of `Devise.password_length.max`' do 894 expect(password_length.max).to eq(Devise.password_length.max) 895 end 896 end 897 end 898 899 describe '.limit_to_todo_authors' do 900 context 'when filtering by todo authors' do 901 let(:user1) { create(:user) } 902 let(:user2) { create(:user) } 903 904 before do 905 create(:todo, user: user1, author: user1, state: :done) 906 create(:todo, user: user2, author: user2, state: :pending) 907 end 908 909 it 'only returns users that have authored todos' do 910 users = described_class.limit_to_todo_authors( 911 user: user2, 912 with_todos: true, 913 todo_state: :pending 914 ) 915 916 expect(users).to eq([user2]) 917 end 918 919 it 'ignores users that do not have a todo in the matching state' do 920 users = described_class.limit_to_todo_authors( 921 user: user1, 922 with_todos: true, 923 todo_state: :pending 924 ) 925 926 expect(users).to be_empty 927 end 928 end 929 930 context 'when not filtering by todo authors' do 931 it 'returns the input relation' do 932 user1 = create(:user) 933 user2 = create(:user) 934 rel = described_class.limit_to_todo_authors(user: user1) 935 936 expect(rel).to include(user1, user2) 937 end 938 end 939 940 context 'when no user is provided' do 941 it 'returns the input relation' do 942 user1 = create(:user) 943 user2 = create(:user) 944 rel = described_class.limit_to_todo_authors 945 946 expect(rel).to include(user1, user2) 947 end 948 end 949 end 950 951 describe '.by_username' do 952 it 'finds users regardless of the case passed' do 953 user = create(:user, username: 'CaMeLcAsEd') 954 user2 = create(:user, username: 'UPPERCASE') 955 956 expect(described_class.by_username(%w(CAMELCASED uppercase))) 957 .to contain_exactly(user, user2) 958 end 959 960 it 'finds a single user regardless of the case passed' do 961 user = create(:user, username: 'CaMeLcAsEd') 962 963 expect(described_class.by_username('CAMELCASED')) 964 .to contain_exactly(user) 965 end 966 end 967 968 describe '.with_expiring_and_not_notified_personal_access_tokens' do 969 let_it_be(:user1) { create(:user) } 970 let_it_be(:user2) { create(:user) } 971 let_it_be(:user3) { create(:user) } 972 973 let_it_be(:expired_token) { create(:personal_access_token, user: user1, expires_at: 2.days.ago) } 974 let_it_be(:revoked_token) { create(:personal_access_token, user: user1, revoked: true) } 975 let_it_be(:impersonation_token) { create(:personal_access_token, :impersonation, user: user1, expires_at: 2.days.from_now) } 976 let_it_be(:valid_token_and_notified) { create(:personal_access_token, user: user2, expires_at: 2.days.from_now, expire_notification_delivered: true) } 977 let_it_be(:valid_token1) { create(:personal_access_token, user: user2, expires_at: 2.days.from_now) } 978 let_it_be(:valid_token2) { create(:personal_access_token, user: user2, expires_at: 2.days.from_now) } 979 980 let(:users) { described_class.with_expiring_and_not_notified_personal_access_tokens(from) } 981 982 context 'in one day' do 983 let(:from) { 1.day.from_now } 984 985 it "doesn't include an user" do 986 expect(users).to be_empty 987 end 988 end 989 990 context 'in three days' do 991 let(:from) { 3.days.from_now } 992 993 it 'only includes user2' do 994 expect(users).to contain_exactly(user2) 995 end 996 end 997 end 998 999 describe '.with_personal_access_tokens_expired_today' do 1000 let_it_be(:user1) { create(:user) } 1001 let_it_be(:expired_today) { create(:personal_access_token, user: user1, expires_at: Date.current) } 1002 1003 let_it_be(:user2) { create(:user) } 1004 let_it_be(:revoked_token) { create(:personal_access_token, user: user2, expires_at: Date.current, revoked: true) } 1005 1006 let_it_be(:user3) { create(:user) } 1007 let_it_be(:impersonated_token) { create(:personal_access_token, user: user3, expires_at: Date.current, impersonation: true) } 1008 1009 let_it_be(:user4) { create(:user) } 1010 let_it_be(:already_notified) { create(:personal_access_token, user: user4, expires_at: Date.current, after_expiry_notification_delivered: true) } 1011 1012 it 'returns users whose token has expired today' do 1013 expect(described_class.with_personal_access_tokens_expired_today).to contain_exactly(user1) 1014 end 1015 end 1016 1017 context 'SSH key expiration scopes' do 1018 let_it_be(:user1) { create(:user) } 1019 let_it_be(:user2) { create(:user) } 1020 let_it_be(:expired_today_not_notified) { create(:key, expires_at: Time.current, user: user1) } 1021 let_it_be(:expired_today_already_notified) { create(:key, expires_at: Time.current, user: user2, expiry_notification_delivered_at: Time.current) } 1022 let_it_be(:expiring_soon_not_notified) { create(:key, expires_at: 2.days.from_now, user: user2) } 1023 let_it_be(:expiring_soon_notified) { create(:key, expires_at: 2.days.from_now, user: user1, before_expiry_notification_delivered_at: Time.current) } 1024 1025 describe '.with_ssh_key_expiring_soon' do 1026 it 'returns users whose keys will expire soon' do 1027 expect(described_class.with_ssh_key_expiring_soon).to contain_exactly(user2) 1028 end 1029 end 1030 end 1031 1032 describe '.active_without_ghosts' do 1033 let_it_be(:user1) { create(:user, :external) } 1034 let_it_be(:user2) { create(:user, state: 'blocked') } 1035 let_it_be(:user3) { create(:user, :ghost) } 1036 let_it_be(:user4) { create(:user) } 1037 1038 it 'returns all active users but ghost users' do 1039 expect(described_class.active_without_ghosts).to match_array([user1, user4]) 1040 end 1041 end 1042 1043 describe '.without_ghosts' do 1044 let_it_be(:user1) { create(:user, :external) } 1045 let_it_be(:user2) { create(:user, state: 'blocked') } 1046 let_it_be(:user3) { create(:user, :ghost) } 1047 1048 it 'returns users without ghosts users' do 1049 expect(described_class.without_ghosts).to match_array([user1, user2]) 1050 end 1051 end 1052 1053 describe '.by_id_and_login' do 1054 let_it_be(:user) { create(:user) } 1055 1056 it 'finds a user regardless of case' do 1057 expect(described_class.by_id_and_login(user.id, user.username.upcase)) 1058 .to contain_exactly(user) 1059 end 1060 1061 it 'finds a user when login is an email address regardless of case' do 1062 expect(described_class.by_id_and_login(user.id, user.email.upcase)) 1063 .to contain_exactly(user) 1064 end 1065 end 1066 1067 describe '.for_todos' do 1068 let_it_be(:user1) { create(:user) } 1069 let_it_be(:user2) { create(:user) } 1070 let_it_be(:issue) { create(:issue) } 1071 1072 let_it_be(:todo1) { create(:todo, target: issue, author: user1, user: user1) } 1073 let_it_be(:todo2) { create(:todo, target: issue, author: user1, user: user1) } 1074 let_it_be(:todo3) { create(:todo, target: issue, author: user2, user: user2) } 1075 1076 it 'returns users for the given todos' do 1077 expect(described_class.for_todos(issue.todos)) 1078 .to contain_exactly(user1, user2) 1079 end 1080 end 1081 end 1082 1083 context 'strip attributes' do 1084 context 'name' do 1085 let(:user) { User.new(name: ' John Smith ') } 1086 1087 it 'strips whitespaces on validation' do 1088 expect { user.valid? }.to change { user.name }.to('John Smith') 1089 end 1090 end 1091 end 1092 1093 describe 'Respond to' do 1094 it { is_expected.to respond_to(:admin?) } 1095 it { is_expected.to respond_to(:name) } 1096 it { is_expected.to respond_to(:external?) } 1097 end 1098 1099 describe 'before save hook' do 1100 describe '#default_private_profile_to_false' do 1101 let(:user) { create(:user, private_profile: true) } 1102 1103 it 'converts nil to false' do 1104 user.private_profile = nil 1105 user.save! 1106 1107 expect(user.private_profile).to eq false 1108 end 1109 end 1110 1111 context 'when saving an external user' do 1112 let(:user) { create(:user) } 1113 let(:external_user) { create(:user, external: true) } 1114 1115 it 'sets other properties as well' do 1116 expect(external_user.can_create_team).to be_falsey 1117 expect(external_user.can_create_group).to be_falsey 1118 expect(external_user.projects_limit).to be 0 1119 end 1120 end 1121 1122 describe '#check_for_verified_email' do 1123 let(:user) { create(:user) } 1124 let(:secondary) { create(:email, :confirmed, email: 'secondary@example.com', user: user) } 1125 1126 it 'allows a verified secondary email to be used as the primary without needing reconfirmation' do 1127 user.update!(email: secondary.email) 1128 user.reload 1129 expect(user.email).to eq secondary.email 1130 expect(user.unconfirmed_email).to eq nil 1131 expect(user.confirmed?).to be_truthy 1132 end 1133 end 1134 end 1135 1136 describe 'after commit hook' do 1137 describe 'when the primary email is updated' do 1138 before do 1139 @user = create(:user, email: 'primary@example.com').tap do |user| 1140 user.skip_reconfirmation! 1141 end 1142 @secondary = create :email, email: 'secondary@example.com', user: @user 1143 @user.reload 1144 end 1145 1146 it 'keeps old primary to secondary emails when secondary is a new email' do 1147 @user.update!(email: 'new_primary@example.com') 1148 @user.reload 1149 1150 expect(@user.emails.count).to eq 2 1151 expect(@user.emails.pluck(:email)).to match_array([@secondary.email, 'primary@example.com']) 1152 end 1153 1154 context 'when the first email was unconfirmed and the second email gets confirmed' do 1155 let(:user) { create(:user, :unconfirmed, email: 'should-be-unconfirmed@test.com') } 1156 1157 before do 1158 user.update!(email: 'should-be-confirmed@test.com') 1159 user.confirm 1160 end 1161 1162 it 'updates user.email' do 1163 expect(user.email).to eq('should-be-confirmed@test.com') 1164 end 1165 1166 it 'confirms user.email' do 1167 expect(user).to be_confirmed 1168 end 1169 1170 it 'does not add unconfirmed email to secondary' do 1171 expect(user.emails.map(&:email)).not_to include('should-be-unconfirmed@test.com') 1172 end 1173 1174 it 'has only one email association' do 1175 expect(user.emails.size).to eq(1) 1176 end 1177 end 1178 end 1179 1180 context 'when an existing email record is set as primary' do 1181 let(:user) { create(:user, email: 'confirmed@test.com') } 1182 1183 context 'when it is unconfirmed' do 1184 let(:originally_unconfirmed_email) { 'should-stay-unconfirmed@test.com' } 1185 1186 before do 1187 user.emails << create(:email, email: originally_unconfirmed_email, confirmed_at: nil) 1188 1189 user.update!(email: originally_unconfirmed_email) 1190 end 1191 1192 it 'keeps the user confirmed' do 1193 expect(user).to be_confirmed 1194 end 1195 1196 it 'keeps the original email' do 1197 expect(user.email).to eq('confirmed@test.com') 1198 end 1199 1200 context 'when the email gets confirmed' do 1201 before do 1202 user.confirm 1203 end 1204 1205 it 'keeps the user confirmed' do 1206 expect(user).to be_confirmed 1207 end 1208 1209 it 'updates the email' do 1210 expect(user.email).to eq(originally_unconfirmed_email) 1211 end 1212 end 1213 end 1214 1215 context 'when it is confirmed' do 1216 let!(:old_confirmed_email) { user.email } 1217 let(:confirmed_email) { 'already-confirmed@test.com' } 1218 1219 before do 1220 user.emails << create(:email, :confirmed, email: confirmed_email) 1221 1222 user.update!(email: confirmed_email) 1223 end 1224 1225 it 'keeps the user confirmed' do 1226 expect(user).to be_confirmed 1227 end 1228 1229 it 'updates the email' do 1230 expect(user.email).to eq(confirmed_email) 1231 end 1232 1233 it 'keeps the old email' do 1234 email = user.reload.emails.first 1235 1236 expect(email.email).to eq(old_confirmed_email) 1237 expect(email).to be_confirmed 1238 end 1239 end 1240 end 1241 1242 context 'when unconfirmed user deletes a confirmed additional email' do 1243 let(:user) { create(:user, :unconfirmed) } 1244 1245 before do 1246 user.emails << create(:email, :confirmed) 1247 end 1248 1249 it 'does not affect the confirmed status' do 1250 expect { user.emails.confirmed.destroy_all }.not_to change { user.confirmed? } # rubocop: disable Cop/DestroyAll 1251 end 1252 end 1253 1254 describe 'when changing email' do 1255 let(:user) { create(:user) } 1256 let(:new_email) { 'new-email@example.com' } 1257 1258 context 'if notification_email was nil' do 1259 it 'sets :unconfirmed_email' do 1260 expect do 1261 user.tap { |u| u.update!(email: new_email) }.reload 1262 end.to change(user, :unconfirmed_email).to(new_email) 1263 end 1264 1265 it 'does not change notification_email or notification_email_or_default before email is confirmed' do 1266 expect do 1267 user.tap { |u| u.update!(email: new_email) }.reload 1268 end.not_to change(user, :notification_email_or_default) 1269 1270 expect(user.notification_email).to be_nil 1271 end 1272 1273 it 'updates notification_email_or_default to the new email once confirmed' do 1274 user.update!(email: new_email) 1275 1276 expect do 1277 user.tap(&:confirm).reload 1278 end.to change(user, :notification_email_or_default).to eq(new_email) 1279 1280 expect(user.notification_email).to be_nil 1281 end 1282 end 1283 1284 context 'when notification_email is set to a secondary email' do 1285 let!(:email_attrs) { attributes_for(:email, :confirmed, user: user) } 1286 let(:secondary) { create(:email, :confirmed, email: 'secondary@example.com', user: user) } 1287 1288 before do 1289 user.emails.create!(email_attrs) 1290 user.tap { |u| u.update!(notification_email: email_attrs[:email]) }.reload 1291 end 1292 1293 it 'does not change notification_email to email before email is confirmed' do 1294 expect do 1295 user.tap { |u| u.update!(email: new_email) }.reload 1296 end.not_to change(user, :notification_email) 1297 end 1298 1299 it 'does not change notification_email to email once confirmed' do 1300 user.update!(email: new_email) 1301 1302 expect do 1303 user.tap(&:confirm).reload 1304 end.not_to change(user, :notification_email) 1305 end 1306 end 1307 end 1308 1309 describe '#update_invalid_gpg_signatures' do 1310 let(:user) do 1311 create(:user, email: 'tula.torphy@abshire.ca').tap do |user| 1312 user.skip_reconfirmation! 1313 end 1314 end 1315 1316 it 'does nothing when the name is updated' do 1317 expect(user).not_to receive(:update_invalid_gpg_signatures) 1318 user.update!(name: 'Bette') 1319 end 1320 1321 it 'synchronizes the gpg keys when the email is updated' do 1322 expect(user).to receive(:update_invalid_gpg_signatures).at_most(:twice) 1323 user.update!(email: 'shawnee.ritchie@denesik.com') 1324 end 1325 end 1326 end 1327 1328 describe 'name getters' do 1329 let(:user) { create(:user, name: 'Kane Martin William') } 1330 1331 it 'derives first name from full name, if not present' do 1332 expect(user.first_name).to eq('Kane') 1333 end 1334 1335 it 'derives last name from full name, if not present' do 1336 expect(user.last_name).to eq('Martin William') 1337 end 1338 end 1339 1340 describe '#highest_role' do 1341 let_it_be(:user) { create(:user) } 1342 1343 context 'when user_highest_role does not exist' do 1344 it 'returns NO_ACCESS' do 1345 expect(user.highest_role).to eq(Gitlab::Access::NO_ACCESS) 1346 end 1347 end 1348 1349 context 'when user_highest_role exists' do 1350 context 'stored highest access level is nil' do 1351 it 'returns Gitlab::Access::NO_ACCESS' do 1352 create(:user_highest_role, user: user) 1353 1354 expect(user.highest_role).to eq(Gitlab::Access::NO_ACCESS) 1355 end 1356 end 1357 1358 context 'stored highest access level present' do 1359 context 'with association :user_highest_role' do 1360 let(:another_user) { create(:user) } 1361 1362 before do 1363 create(:user_highest_role, :maintainer, user: user) 1364 create(:user_highest_role, :developer, user: another_user) 1365 end 1366 1367 it 'returns the correct highest role' do 1368 users = User.includes(:user_highest_role).where(id: [user.id, another_user.id]) 1369 1370 expect(users.collect { |u| [u.id, u.highest_role] }).to contain_exactly( 1371 [user.id, Gitlab::Access::MAINTAINER], 1372 [another_user.id, Gitlab::Access::DEVELOPER] 1373 ) 1374 end 1375 end 1376 end 1377 end 1378 end 1379 1380 describe '#credit_card_validated_at' do 1381 let_it_be(:user) { create(:user) } 1382 1383 context 'when credit_card_validation does not exist' do 1384 it 'returns nil' do 1385 expect(user.credit_card_validated_at).to be nil 1386 end 1387 end 1388 1389 context 'when credit_card_validation exists' do 1390 it 'returns the credit card validated time' do 1391 credit_card_validated_time = Time.current - 1.day 1392 1393 create(:credit_card_validation, credit_card_validated_at: credit_card_validated_time, user: user) 1394 1395 expect(user.credit_card_validated_at).to eq(credit_card_validated_time) 1396 end 1397 end 1398 end 1399 1400 describe '#update_tracked_fields!', :clean_gitlab_redis_shared_state do 1401 let(:request) { OpenStruct.new(remote_ip: "127.0.0.1") } 1402 let(:user) { create(:user) } 1403 1404 it 'writes trackable attributes' do 1405 expect do 1406 user.update_tracked_fields!(request) 1407 end.to change { user.reload.current_sign_in_at } 1408 end 1409 1410 it 'does not write trackable attributes when called a second time within the hour' do 1411 user.update_tracked_fields!(request) 1412 1413 expect do 1414 user.update_tracked_fields!(request) 1415 end.not_to change { user.reload.current_sign_in_at } 1416 end 1417 1418 it 'writes trackable attributes for a different user' do 1419 user2 = create(:user) 1420 1421 user.update_tracked_fields!(request) 1422 1423 expect do 1424 user2.update_tracked_fields!(request) 1425 end.to change { user2.reload.current_sign_in_at } 1426 end 1427 1428 it 'does not write if the DB is in read-only mode' do 1429 expect(Gitlab::Database).to receive(:read_only?).and_return(true) 1430 1431 expect do 1432 user.update_tracked_fields!(request) 1433 end.not_to change { user.reload.current_sign_in_at } 1434 end 1435 end 1436 1437 shared_context 'user keys' do 1438 let(:user) { create(:user) } 1439 let!(:key) { create(:key, user: user) } 1440 let!(:deploy_key) { create(:deploy_key, user: user) } 1441 end 1442 1443 describe '#keys' do 1444 include_context 'user keys' 1445 1446 context 'with key and deploy key stored' do 1447 it 'returns stored key, but not deploy_key' do 1448 expect(user.keys).to include key 1449 expect(user.keys).not_to include deploy_key 1450 end 1451 end 1452 end 1453 1454 describe '#accessible_deploy_keys' do 1455 let(:user) { create(:user) } 1456 let(:project) { create(:project) } 1457 let!(:private_deploy_keys_project) { create(:deploy_keys_project) } 1458 let!(:public_deploy_keys_project) { create(:deploy_keys_project) } 1459 let!(:accessible_deploy_keys_project) { create(:deploy_keys_project, project: project) } 1460 1461 before do 1462 public_deploy_keys_project.deploy_key.update!(public: true) 1463 project.add_developer(user) 1464 end 1465 1466 it 'user can only see deploy keys accessible to right projects' do 1467 expect(user.accessible_deploy_keys).to match_array([public_deploy_keys_project.deploy_key, 1468 accessible_deploy_keys_project.deploy_key]) 1469 end 1470 end 1471 1472 describe '#deploy_keys' do 1473 include_context 'user keys' 1474 1475 context 'with key and deploy key stored' do 1476 it 'returns stored deploy key, but not normal key' do 1477 expect(user.deploy_keys).to include deploy_key 1478 expect(user.deploy_keys).not_to include key 1479 end 1480 end 1481 end 1482 1483 describe '#confirm' do 1484 before do 1485 allow_any_instance_of(ApplicationSetting).to receive(:send_user_confirmation_email).and_return(true) 1486 end 1487 1488 let(:user) { create(:user, :unconfirmed, unconfirmed_email: 'test@gitlab.com') } 1489 1490 it 'returns unconfirmed' do 1491 expect(user.confirmed?).to be_falsey 1492 end 1493 1494 it 'confirms a user' do 1495 user.confirm 1496 expect(user.confirmed?).to be_truthy 1497 end 1498 1499 it 'adds the confirmed primary email to emails' do 1500 expect(user.emails.confirmed.map(&:email)).not_to include(user.email) 1501 1502 user.confirm 1503 1504 expect(user.emails.confirmed.map(&:email)).to include(user.email) 1505 end 1506 end 1507 1508 context 'if the user is created with confirmed_at set to a time' do 1509 let!(:user) { create(:user, email: 'test@gitlab.com', confirmed_at: Time.now.utc) } 1510 1511 it 'adds the confirmed primary email to emails upon creation' do 1512 expect(user.emails.confirmed.map(&:email)).to include(user.email) 1513 end 1514 end 1515 1516 describe '#to_reference' do 1517 let(:user) { create(:user) } 1518 1519 it 'returns a String reference to the object' do 1520 expect(user.to_reference).to eq "@#{user.username}" 1521 end 1522 end 1523 1524 describe '#generate_password' do 1525 it 'does not generate password by default' do 1526 user = create(:user, password: 'abcdefghe') 1527 1528 expect(user.password).to eq('abcdefghe') 1529 end 1530 end 1531 1532 describe 'ensure user preference' do 1533 it 'has user preference upon user initialization' do 1534 user = build(:user) 1535 1536 expect(user.user_preference).to be_present 1537 expect(user.user_preference).not_to be_persisted 1538 end 1539 end 1540 1541 describe 'ensure incoming email token' do 1542 it 'has incoming email token' do 1543 user = create(:user) 1544 1545 expect(user.incoming_email_token).not_to be_blank 1546 end 1547 1548 it 'uses SecureRandom to generate the incoming email token' do 1549 allow_next_instance_of(User) do |user| 1550 allow(user).to receive(:update_highest_role) 1551 end 1552 1553 allow_next_instance_of(Namespaces::UserNamespace) do |namespace| 1554 allow(namespace).to receive(:schedule_sync_event_worker) 1555 end 1556 1557 expect(SecureRandom).to receive(:hex).with(no_args).and_return('3b8ca303') 1558 1559 user = create(:user) 1560 1561 expect(user.incoming_email_token).to eql('gitlab') 1562 end 1563 end 1564 1565 describe '#ensure_user_rights_and_limits' do 1566 describe 'with external user' do 1567 let(:user) { create(:user, external: true) } 1568 1569 it 'receives callback when external changes' do 1570 expect(user).to receive(:ensure_user_rights_and_limits) 1571 1572 user.update!(external: false) 1573 end 1574 1575 it 'ensures correct rights and limits for user' do 1576 stub_config_setting(default_can_create_group: true) 1577 1578 expect { user.update!(external: false) }.to change { user.can_create_group }.to(true) 1579 .and change { user.projects_limit }.to(Gitlab::CurrentSettings.default_projects_limit) 1580 end 1581 end 1582 1583 describe 'without external user' do 1584 let(:user) { create(:user, external: false) } 1585 1586 it 'receives callback when external changes' do 1587 expect(user).to receive(:ensure_user_rights_and_limits) 1588 1589 user.update!(external: true) 1590 end 1591 1592 it 'ensures correct rights and limits for user' do 1593 expect { user.update!(external: true) }.to change { user.can_create_group }.to(false) 1594 .and change { user.projects_limit }.to(0) 1595 end 1596 end 1597 end 1598 1599 describe 'feed token' do 1600 it 'ensures a feed token on read' do 1601 user = create(:user, feed_token: nil) 1602 feed_token = user.feed_token 1603 1604 expect(feed_token).not_to be_blank 1605 expect(user.reload.feed_token).to eq feed_token 1606 end 1607 1608 it 'ensures no feed token when disabled' do 1609 allow(Gitlab::CurrentSettings).to receive(:disable_feed_token).and_return(true) 1610 1611 user = create(:user, feed_token: nil) 1612 feed_token = user.feed_token 1613 1614 expect(feed_token).to be_blank 1615 expect(user.reload.feed_token).to be_blank 1616 end 1617 end 1618 1619 describe 'static object token' do 1620 it 'ensures a static object token on read' do 1621 user = create(:user, static_object_token: nil) 1622 static_object_token = user.static_object_token 1623 1624 expect(static_object_token).not_to be_blank 1625 expect(user.reload.static_object_token).to eq static_object_token 1626 end 1627 end 1628 1629 describe 'enabled_static_object_token' do 1630 let_it_be(:static_object_token) { 'ilqx6jm1u945macft4eff0nw' } 1631 1632 it 'returns incoming email token when supported' do 1633 allow(Gitlab::CurrentSettings).to receive(:static_objects_external_storage_enabled?).and_return(true) 1634 1635 user = create(:user, static_object_token: static_object_token) 1636 1637 expect(user.enabled_static_object_token).to eq(static_object_token) 1638 end 1639 1640 it 'returns `nil` when not supported' do 1641 allow(Gitlab::CurrentSettings).to receive(:static_objects_external_storage_enabled?).and_return(false) 1642 1643 user = create(:user, static_object_token: static_object_token) 1644 1645 expect(user.enabled_static_object_token).to be_nil 1646 end 1647 end 1648 1649 describe 'enabled_incoming_email_token' do 1650 let_it_be(:incoming_email_token) { 'ilqx6jm1u945macft4eff0nw' } 1651 1652 it 'returns incoming email token when supported' do 1653 allow(Gitlab::IncomingEmail).to receive(:supports_issue_creation?).and_return(true) 1654 1655 user = create(:user, incoming_email_token: incoming_email_token) 1656 1657 expect(user.enabled_incoming_email_token).to eq(incoming_email_token) 1658 end 1659 1660 it 'returns `nil` when not supported' do 1661 allow(Gitlab::IncomingEmail).to receive(:supports_issue_creation?).and_return(false) 1662 1663 user = create(:user, incoming_email_token: incoming_email_token) 1664 1665 expect(user.enabled_incoming_email_token).to be_nil 1666 end 1667 end 1668 1669 describe '#recently_sent_password_reset?' do 1670 it 'is false when reset_password_sent_at is nil' do 1671 user = build_stubbed(:user, reset_password_sent_at: nil) 1672 1673 expect(user.recently_sent_password_reset?).to eq false 1674 end 1675 1676 it 'is false when sent more than one minute ago' do 1677 user = build_stubbed(:user, reset_password_sent_at: 5.minutes.ago) 1678 1679 expect(user.recently_sent_password_reset?).to eq false 1680 end 1681 1682 it 'is true when sent less than one minute ago' do 1683 user = build_stubbed(:user, reset_password_sent_at: Time.current) 1684 1685 expect(user.recently_sent_password_reset?).to eq true 1686 end 1687 end 1688 1689 describe '#disable_two_factor!' do 1690 it 'clears all 2FA-related fields' do 1691 user = create(:user, :two_factor) 1692 1693 expect(user).to be_two_factor_enabled 1694 expect(user.encrypted_otp_secret).not_to be_nil 1695 expect(user.otp_backup_codes).not_to be_nil 1696 expect(user.otp_grace_period_started_at).not_to be_nil 1697 1698 user.disable_two_factor! 1699 1700 expect(user).not_to be_two_factor_enabled 1701 expect(user.encrypted_otp_secret).to be_nil 1702 expect(user.encrypted_otp_secret_iv).to be_nil 1703 expect(user.encrypted_otp_secret_salt).to be_nil 1704 expect(user.otp_backup_codes).to be_nil 1705 expect(user.otp_grace_period_started_at).to be_nil 1706 end 1707 end 1708 1709 describe '#two_factor_otp_enabled?' do 1710 let_it_be(:user) { create(:user) } 1711 1712 context 'when 2FA is enabled by an MFA Device' do 1713 let(:user) { create(:user, :two_factor) } 1714 1715 it { expect(user.two_factor_otp_enabled?).to eq(true) } 1716 end 1717 1718 context 'FortiAuthenticator' do 1719 context 'when enabled via GitLab settings' do 1720 before do 1721 allow(::Gitlab.config.forti_authenticator).to receive(:enabled).and_return(true) 1722 end 1723 1724 context 'when feature is disabled for the user' do 1725 before do 1726 stub_feature_flags(forti_authenticator: false) 1727 end 1728 1729 it { expect(user.two_factor_otp_enabled?).to eq(false) } 1730 end 1731 1732 context 'when feature is enabled for the user' do 1733 before do 1734 stub_feature_flags(forti_authenticator: user) 1735 end 1736 1737 it { expect(user.two_factor_otp_enabled?).to eq(true) } 1738 end 1739 end 1740 1741 context 'when disabled via GitLab settings' do 1742 before do 1743 allow(::Gitlab.config.forti_authenticator).to receive(:enabled).and_return(false) 1744 end 1745 1746 it { expect(user.two_factor_otp_enabled?).to eq(false) } 1747 end 1748 end 1749 1750 context 'FortiTokenCloud' do 1751 context 'when enabled via GitLab settings' do 1752 before do 1753 allow(::Gitlab.config.forti_token_cloud).to receive(:enabled).and_return(true) 1754 end 1755 1756 context 'when feature is disabled for the user' do 1757 before do 1758 stub_feature_flags(forti_token_cloud: false) 1759 end 1760 1761 it { expect(user.two_factor_otp_enabled?).to eq(false) } 1762 end 1763 1764 context 'when feature is enabled for the user' do 1765 before do 1766 stub_feature_flags(forti_token_cloud: user) 1767 end 1768 1769 it { expect(user.two_factor_otp_enabled?).to eq(true) } 1770 end 1771 end 1772 1773 context 'when disabled via GitLab settings' do 1774 before do 1775 allow(::Gitlab.config.forti_token_cloud).to receive(:enabled).and_return(false) 1776 end 1777 1778 it { expect(user.two_factor_otp_enabled?).to eq(false) } 1779 end 1780 end 1781 end 1782 1783 context 'two_factor_u2f_enabled?' do 1784 let_it_be(:user) { create(:user, :two_factor) } 1785 1786 context 'when webauthn feature flag is enabled' do 1787 context 'user has no U2F registration' do 1788 it { expect(user.two_factor_u2f_enabled?).to eq(false) } 1789 end 1790 1791 context 'user has existing U2F registration' do 1792 it 'returns false' do 1793 device = U2F::FakeU2F.new(FFaker::BaconIpsum.characters(5)) 1794 create(:u2f_registration, name: 'my u2f device', 1795 user: user, 1796 certificate: Base64.strict_encode64(device.cert_raw), 1797 key_handle: U2F.urlsafe_encode64(device.key_handle_raw), 1798 public_key: Base64.strict_encode64(device.origin_public_key_raw)) 1799 1800 expect(user.two_factor_u2f_enabled?).to eq(false) 1801 end 1802 end 1803 end 1804 1805 context 'when webauthn feature flag is disabled' do 1806 before do 1807 stub_feature_flags(webauthn: false) 1808 end 1809 1810 context 'user has no U2F registration' do 1811 it { expect(user.two_factor_u2f_enabled?).to eq(false) } 1812 end 1813 1814 context 'user has existing U2F registration' do 1815 it 'returns true' do 1816 device = U2F::FakeU2F.new(FFaker::BaconIpsum.characters(5)) 1817 create(:u2f_registration, name: 'my u2f device', 1818 user: user, 1819 certificate: Base64.strict_encode64(device.cert_raw), 1820 key_handle: U2F.urlsafe_encode64(device.key_handle_raw), 1821 public_key: Base64.strict_encode64(device.origin_public_key_raw)) 1822 1823 expect(user.two_factor_u2f_enabled?).to eq(true) 1824 end 1825 end 1826 end 1827 end 1828 1829 describe 'projects' do 1830 before do 1831 @user = create(:user) 1832 1833 @project = create(:project, namespace: @user.namespace) 1834 @project_2 = create(:project, group: create(:group)) do |project| 1835 project.add_maintainer(@user) 1836 end 1837 @project_3 = create(:project, group: create(:group)) do |project| 1838 project.add_developer(@user) 1839 end 1840 end 1841 1842 it { expect(@user.authorized_projects).to include(@project) } 1843 it { expect(@user.authorized_projects).to include(@project_2) } 1844 it { expect(@user.authorized_projects).to include(@project_3) } 1845 it { expect(@user.owned_projects).to include(@project) } 1846 it { expect(@user.owned_projects).not_to include(@project_2) } 1847 it { expect(@user.owned_projects).not_to include(@project_3) } 1848 it { expect(@user.personal_projects).to include(@project) } 1849 it { expect(@user.personal_projects).not_to include(@project_2) } 1850 it { expect(@user.personal_projects).not_to include(@project_3) } 1851 end 1852 1853 describe 'groups' do 1854 let(:user) { create(:user) } 1855 let(:group) { create(:group) } 1856 1857 before do 1858 group.add_owner(user) 1859 end 1860 1861 it { expect(user.several_namespaces?).to be_truthy } 1862 it { expect(user.authorized_groups).to eq([group]) } 1863 it { expect(user.owned_groups).to eq([group]) } 1864 it { expect(user.namespaces).to contain_exactly(user.namespace, group) } 1865 it { expect(user.manageable_namespaces).to contain_exactly(user.namespace, group) } 1866 1867 context 'with owned groups only' do 1868 before do 1869 other_group = create(:group) 1870 other_group.add_developer(user) 1871 end 1872 1873 it { expect(user.namespaces(owned_only: true)).to contain_exactly(user.namespace, group) } 1874 end 1875 1876 context 'with child groups' do 1877 let!(:subgroup) { create(:group, parent: group) } 1878 1879 describe '#manageable_namespaces' do 1880 it 'includes all the namespaces the user can manage' do 1881 expect(user.manageable_namespaces).to contain_exactly(user.namespace, group, subgroup) 1882 end 1883 end 1884 1885 describe '#manageable_groups' do 1886 shared_examples 'manageable groups examples' do 1887 it 'includes all the namespaces the user can manage' do 1888 expect(user.manageable_groups).to contain_exactly(group, subgroup) 1889 end 1890 1891 it 'does not include duplicates if a membership was added for the subgroup' do 1892 subgroup.add_owner(user) 1893 1894 expect(user.manageable_groups).to contain_exactly(group, subgroup) 1895 end 1896 end 1897 1898 it_behaves_like 'manageable groups examples' 1899 1900 context 'when feature flag :linear_user_manageable_groups is disabled' do 1901 before do 1902 stub_feature_flags(linear_user_manageable_groups: false) 1903 end 1904 1905 it_behaves_like 'manageable groups examples' 1906 end 1907 end 1908 1909 describe '#manageable_groups_with_routes' do 1910 it 'eager loads routes from manageable groups' do 1911 control_count = 1912 ActiveRecord::QueryRecorder.new(skip_cached: false) do 1913 user.manageable_groups_with_routes.map(&:route) 1914 end.count 1915 1916 create(:group, parent: subgroup) 1917 1918 expect do 1919 user.manageable_groups_with_routes.map(&:route) 1920 end.not_to exceed_all_query_limit(control_count) 1921 end 1922 end 1923 end 1924 end 1925 1926 describe 'group multiple owners' do 1927 before do 1928 @user = create :user 1929 @user2 = create :user 1930 @group = create :group 1931 @group.add_owner(@user) 1932 1933 @group.add_user(@user2, GroupMember::OWNER) 1934 end 1935 1936 it { expect(@user2.several_namespaces?).to be_truthy } 1937 end 1938 1939 describe 'namespaced' do 1940 before do 1941 @user = create :user 1942 @project = create(:project, namespace: @user.namespace) 1943 end 1944 1945 it { expect(@user.several_namespaces?).to be_falsey } 1946 it { expect(@user.namespaces).to eq([@user.namespace]) } 1947 end 1948 1949 describe 'blocking user' do 1950 let_it_be_with_refind(:user) { create(:user, name: 'John Smith') } 1951 1952 it 'blocks user' do 1953 user.block 1954 1955 expect(user.blocked?).to be_truthy 1956 end 1957 1958 context 'when user has running CI pipelines' do 1959 let(:pipelines) { build_list(:ci_pipeline, 3, :running) } 1960 1961 it 'drops all running pipelines and related jobs' do 1962 drop_service = double 1963 disable_service = double 1964 1965 expect(user).to receive(:pipelines).and_return(pipelines) 1966 expect(Ci::DropPipelineService).to receive(:new).and_return(drop_service) 1967 expect(drop_service).to receive(:execute_async_for_all).with(pipelines, :user_blocked, user) 1968 1969 expect(Ci::DisableUserPipelineSchedulesService).to receive(:new).and_return(disable_service) 1970 expect(disable_service).to receive(:execute).with(user) 1971 1972 user.block! 1973 end 1974 1975 it 'does not drop running pipelines if the transaction rolls back' do 1976 expect(Ci::DropPipelineService).not_to receive(:new) 1977 expect(Ci::DisableUserPipelineSchedulesService).not_to receive(:new) 1978 1979 User.transaction do 1980 user.block 1981 1982 raise ActiveRecord::Rollback 1983 end 1984 end 1985 end 1986 1987 context 'when user has active CI pipeline schedules' do 1988 let_it_be(:schedule) { create(:ci_pipeline_schedule, active: true, owner: user) } 1989 1990 it 'disables any pipeline schedules' do 1991 expect { user.block }.to change { schedule.reload.active? }.to(false) 1992 end 1993 end 1994 end 1995 1996 describe 'deactivating a user' do 1997 let(:user) { create(:user, name: 'John Smith') } 1998 1999 context 'an active user' do 2000 it 'can be deactivated' do 2001 user.deactivate 2002 2003 expect(user.deactivated?).to be_truthy 2004 end 2005 2006 context 'when user deactivation emails are disabled' do 2007 before do 2008 stub_application_setting(user_deactivation_emails_enabled: false) 2009 end 2010 it 'does not send deactivated user an email' do 2011 expect(NotificationService).not_to receive(:new) 2012 2013 user.deactivate 2014 end 2015 end 2016 2017 context 'when user deactivation emails are enabled' do 2018 it 'sends deactivated user an email' do 2019 expect_next_instance_of(NotificationService) do |notification| 2020 allow(notification).to receive(:user_deactivated).with(user.name, user.notification_email_or_default) 2021 end 2022 2023 user.deactivate 2024 end 2025 end 2026 end 2027 2028 context 'a user who is blocked' do 2029 before do 2030 user.block 2031 end 2032 2033 it 'cannot be deactivated' do 2034 user.deactivate 2035 2036 expect(user.reload.deactivated?).to be_falsy 2037 end 2038 end 2039 end 2040 2041 describe 'blocking a user pending approval' do 2042 let(:user) { create(:user) } 2043 2044 before do 2045 user.block_pending_approval 2046 end 2047 2048 context 'an active user' do 2049 it 'can be blocked pending approval' do 2050 expect(user.blocked_pending_approval?).to eq(true) 2051 end 2052 2053 it 'behaves like a blocked user' do 2054 expect(user.blocked?).to eq(true) 2055 end 2056 end 2057 end 2058 2059 describe '.instance_access_request_approvers_to_be_notified' do 2060 let_it_be(:admin_issue_board_list) { create_list(:user, 12, :admin, :with_sign_ins) } 2061 2062 it 'returns up to the ten most recently active instance admins' do 2063 active_admins_in_recent_sign_in_desc_order = User.admins.active.order_recent_sign_in.limit(10) 2064 2065 expect(User.instance_access_request_approvers_to_be_notified).to eq(active_admins_in_recent_sign_in_desc_order) 2066 end 2067 end 2068 2069 describe 'banning and unbanning a user', :aggregate_failures do 2070 let(:user) { create(:user) } 2071 2072 context 'banning a user' do 2073 it 'bans and blocks the user' do 2074 user.ban 2075 2076 expect(user.banned?).to eq(true) 2077 expect(user.blocked?).to eq(true) 2078 end 2079 2080 it 'creates a BannedUser record' do 2081 expect { user.ban }.to change { Users::BannedUser.count }.by(1) 2082 expect(Users::BannedUser.last.user_id).to eq(user.id) 2083 end 2084 end 2085 2086 context 'unbanning a user' do 2087 before do 2088 user.ban! 2089 end 2090 2091 it 'unbans the user' do 2092 user.unban 2093 2094 expect(user.banned?).to eq(false) 2095 expect(user.active?).to eq(true) 2096 end 2097 2098 it 'deletes the BannedUser record' do 2099 expect { user.unban }.to change { Users::BannedUser.count }.by(-1) 2100 expect(Users::BannedUser.where(user_id: user.id)).not_to exist 2101 end 2102 end 2103 end 2104 2105 describe '.filter_items' do 2106 let(:user) { double } 2107 2108 it 'filters by active users by default' do 2109 expect(described_class).to receive(:active_without_ghosts).and_return([user]) 2110 2111 expect(described_class.filter_items(nil)).to include user 2112 end 2113 2114 it 'filters by admins' do 2115 expect(described_class).to receive(:admins).and_return([user]) 2116 2117 expect(described_class.filter_items('admins')).to include user 2118 end 2119 2120 it 'filters by blocked' do 2121 expect(described_class).to receive(:blocked).and_return([user]) 2122 2123 expect(described_class.filter_items('blocked')).to include user 2124 end 2125 2126 it 'filters by banned' do 2127 expect(described_class).to receive(:banned).and_return([user]) 2128 2129 expect(described_class.filter_items('banned')).to include user 2130 end 2131 2132 it 'filters by blocked pending approval' do 2133 expect(described_class).to receive(:blocked_pending_approval).and_return([user]) 2134 2135 expect(described_class.filter_items('blocked_pending_approval')).to include user 2136 end 2137 2138 it 'filters by deactivated' do 2139 expect(described_class).to receive(:deactivated).and_return([user]) 2140 2141 expect(described_class.filter_items('deactivated')).to include user 2142 end 2143 2144 it 'filters by two_factor_disabled' do 2145 expect(described_class).to receive(:without_two_factor).and_return([user]) 2146 2147 expect(described_class.filter_items('two_factor_disabled')).to include user 2148 end 2149 2150 it 'filters by two_factor_enabled' do 2151 expect(described_class).to receive(:with_two_factor).and_return([user]) 2152 2153 expect(described_class.filter_items('two_factor_enabled')).to include user 2154 end 2155 2156 it 'filters by wop' do 2157 expect(described_class).to receive(:without_projects).and_return([user]) 2158 2159 expect(described_class.filter_items('wop')).to include user 2160 end 2161 end 2162 2163 describe '.without_projects' do 2164 let!(:project) { create(:project, :public) } 2165 let!(:user) { create(:user) } 2166 let!(:user_without_project) { create(:user) } 2167 let!(:user_without_project2) { create(:user) } 2168 2169 before do 2170 # add user to project 2171 project.add_maintainer(user) 2172 2173 # create invite to project 2174 create(:project_member, :developer, project: project, invite_token: '1234', invite_email: 'inviteduser1@example.com') 2175 2176 # create request to join project 2177 project.request_access(user_without_project2) 2178 end 2179 2180 it { expect(described_class.without_projects).not_to include user } 2181 it { expect(described_class.without_projects).to include user_without_project } 2182 it { expect(described_class.without_projects).to include user_without_project2 } 2183 end 2184 2185 describe 'user creation' do 2186 describe 'normal user' do 2187 let(:user) { create(:user, name: 'John Smith') } 2188 2189 it { expect(user.admin?).to be_falsey } 2190 it { expect(user.require_ssh_key?).to be_truthy } 2191 it { expect(user.can_create_group?).to be_truthy } 2192 it { expect(user.can_create_project?).to be_truthy } 2193 it { expect(user.first_name).to eq('John') } 2194 it { expect(user.external).to be_falsey } 2195 end 2196 2197 describe 'with defaults' do 2198 let(:user) { described_class.new } 2199 2200 it 'applies defaults to user' do 2201 expect(user.projects_limit).to eq(Gitlab.config.gitlab.default_projects_limit) 2202 expect(user.can_create_group).to eq(Gitlab.config.gitlab.default_can_create_group) 2203 expect(user.theme_id).to eq(Gitlab.config.gitlab.default_theme) 2204 expect(user.external).to be_falsey 2205 expect(user.private_profile).to eq(false) 2206 end 2207 end 2208 2209 describe 'with default overrides' do 2210 let(:user) { described_class.new(projects_limit: 123, can_create_group: false, can_create_team: true) } 2211 2212 it 'applies defaults to user' do 2213 expect(user.projects_limit).to eq(123) 2214 expect(user.can_create_group).to be_falsey 2215 expect(user.theme_id).to eq(1) 2216 end 2217 2218 it 'does not undo projects_limit setting if it matches old DB default of 10' do 2219 # If the real default project limit is 10 then this test is worthless 2220 expect(Gitlab.config.gitlab.default_projects_limit).not_to eq(10) 2221 user = described_class.new(projects_limit: 10) 2222 expect(user.projects_limit).to eq(10) 2223 end 2224 end 2225 2226 context 'when Gitlab::CurrentSettings.user_default_external is true' do 2227 before do 2228 stub_application_setting(user_default_external: true) 2229 end 2230 2231 it 'creates external user by default' do 2232 user = create(:user) 2233 2234 expect(user.external).to be_truthy 2235 expect(user.can_create_group).to be_falsey 2236 expect(user.projects_limit).to be 0 2237 end 2238 2239 describe 'with default overrides' do 2240 it 'creates a non-external user' do 2241 user = create(:user, external: false) 2242 2243 expect(user.external).to be_falsey 2244 end 2245 end 2246 end 2247 2248 describe '#require_ssh_key?', :use_clean_rails_memory_store_caching do 2249 protocol_and_expectation = { 2250 'http' => false, 2251 'ssh' => true, 2252 '' => true 2253 } 2254 2255 protocol_and_expectation.each do |protocol, expected| 2256 it 'has correct require_ssh_key?' do 2257 stub_application_setting(enabled_git_access_protocol: protocol) 2258 user = build(:user) 2259 2260 expect(user.require_ssh_key?).to eq(expected) 2261 end 2262 end 2263 2264 it 'returns false when the user has 1 or more SSH keys' do 2265 key = create(:personal_key) 2266 2267 expect(key.user.require_ssh_key?).to eq(false) 2268 end 2269 end 2270 end 2271 2272 describe '.find_for_database_authentication' do 2273 it 'strips whitespace from login' do 2274 user = create(:user) 2275 2276 expect(described_class.find_for_database_authentication({ login: " #{user.username} " })).to eq user 2277 end 2278 end 2279 2280 describe '.find_by_any_email' do 2281 it 'finds user through private commit email' do 2282 user = create(:user) 2283 private_email = user.private_commit_email 2284 2285 expect(described_class.find_by_any_email(private_email)).to eq(user) 2286 expect(described_class.find_by_any_email(private_email, confirmed: true)).to eq(user) 2287 end 2288 2289 it 'finds by primary email' do 2290 user = create(:user, email: 'foo@example.com') 2291 2292 expect(described_class.find_by_any_email(user.email)).to eq user 2293 expect(described_class.find_by_any_email(user.email, confirmed: true)).to eq user 2294 end 2295 2296 it 'finds by uppercased email' do 2297 user = create(:user, email: 'foo@example.com') 2298 2299 expect(described_class.find_by_any_email(user.email.upcase)).to eq user 2300 expect(described_class.find_by_any_email(user.email.upcase, confirmed: true)).to eq user 2301 end 2302 2303 context 'finds by secondary email' do 2304 let(:user) { email.user } 2305 2306 context 'primary email confirmed' do 2307 context 'secondary email confirmed' do 2308 let!(:email) { create(:email, :confirmed, email: 'foo@example.com') } 2309 2310 it 'finds user respecting the confirmed flag' do 2311 expect(described_class.find_by_any_email(email.email)).to eq user 2312 expect(described_class.find_by_any_email(email.email, confirmed: true)).to eq user 2313 end 2314 end 2315 2316 context 'secondary email not confirmed' do 2317 let!(:email) { create(:email, email: 'foo@example.com') } 2318 2319 it 'finds user respecting the confirmed flag' do 2320 expect(described_class.find_by_any_email(email.email)).to eq user 2321 expect(described_class.find_by_any_email(email.email, confirmed: true)).to be_nil 2322 end 2323 end 2324 end 2325 2326 context 'primary email not confirmed' do 2327 let(:user) { create(:user, :unconfirmed) } 2328 let!(:email) { create(:email, :confirmed, user: user, email: 'foo@example.com') } 2329 2330 it 'finds user respecting the confirmed flag' do 2331 expect(described_class.find_by_any_email(email.email)).to eq user 2332 expect(described_class.find_by_any_email(email.email, confirmed: true)).to be_nil 2333 end 2334 end 2335 end 2336 2337 it 'returns nil when nothing found' do 2338 expect(described_class.find_by_any_email('')).to be_nil 2339 end 2340 2341 it 'returns nil when user is not confirmed' do 2342 user = create(:user, :unconfirmed, email: 'foo@example.com') 2343 2344 expect(described_class.find_by_any_email(user.email, confirmed: false)).to eq(user) 2345 expect(described_class.find_by_any_email(user.email, confirmed: true)).to be_nil 2346 end 2347 end 2348 2349 describe '.by_any_email' do 2350 it 'returns an ActiveRecord::Relation' do 2351 expect(described_class.by_any_email('foo@example.com')) 2352 .to be_a_kind_of(ActiveRecord::Relation) 2353 end 2354 2355 it 'returns a relation of users' do 2356 user = create(:user) 2357 2358 expect(described_class.by_any_email(user.email)).to eq([user]) 2359 end 2360 2361 it 'returns a relation of users for confirmed users' do 2362 user = create(:user) 2363 2364 expect(described_class.by_any_email(user.email, confirmed: true)).to eq([user]) 2365 end 2366 2367 it 'finds user through a private commit email' do 2368 user = create(:user) 2369 private_email = user.private_commit_email 2370 2371 expect(described_class.by_any_email(private_email)).to eq([user]) 2372 expect(described_class.by_any_email(private_email, confirmed: true)).to eq([user]) 2373 end 2374 2375 it 'finds user through a private commit email in an array' do 2376 user = create(:user) 2377 private_email = user.private_commit_email 2378 2379 expect(described_class.by_any_email([private_email])).to eq([user]) 2380 expect(described_class.by_any_email([private_email], confirmed: true)).to eq([user]) 2381 end 2382 end 2383 2384 describe '.search' do 2385 let_it_be(:user) { create(:user, name: 'user', username: 'usern', email: 'email@example.com') } 2386 let_it_be(:user2) { create(:user, name: 'user name', username: 'username', email: 'someemail@example.com') } 2387 let_it_be(:user3) { create(:user, name: 'us', username: 'se', email: 'foo@example.com') } 2388 let_it_be(:email) { create(:email, user: user, email: 'alias@example.com') } 2389 2390 describe 'name matching' do 2391 it 'returns users with a matching name with exact match first' do 2392 expect(described_class.search(user.name)).to eq([user, user2]) 2393 end 2394 2395 it 'returns users with a partially matching name' do 2396 expect(described_class.search(user.name[0..2])).to eq([user, user2]) 2397 end 2398 2399 it 'returns users with a matching name regardless of the casing' do 2400 expect(described_class.search(user2.name.upcase)).to eq([user2]) 2401 end 2402 2403 it 'returns users with a exact matching name shorter than 3 chars' do 2404 expect(described_class.search(user3.name)).to eq([user3]) 2405 end 2406 2407 it 'returns users with a exact matching name shorter than 3 chars regardless of the casing' do 2408 expect(described_class.search(user3.name.upcase)).to eq([user3]) 2409 end 2410 end 2411 2412 describe 'email matching' do 2413 it 'returns users with a matching Email' do 2414 expect(described_class.search(user.email)).to eq([user]) 2415 end 2416 2417 it 'does not return users with a partially matching Email' do 2418 expect(described_class.search(user.email[1...-1])).to be_empty 2419 end 2420 2421 it 'returns users with a matching Email regardless of the casing' do 2422 expect(described_class.search(user2.email.upcase)).to eq([user2]) 2423 end 2424 end 2425 2426 describe 'secondary email matching' do 2427 it 'returns users with a matching secondary email' do 2428 expect(described_class.search(email.email)).to include(email.user) 2429 end 2430 2431 it 'does not return users with a matching part of secondary email' do 2432 expect(described_class.search(email.email[1...-1])).to be_empty 2433 end 2434 2435 it 'returns users with a matching secondary email regardless of the casing' do 2436 expect(described_class.search(email.email.upcase)).to include(email.user) 2437 end 2438 end 2439 2440 describe 'username matching' do 2441 it 'returns users with a matching username' do 2442 expect(described_class.search(user.username)).to eq([user, user2]) 2443 end 2444 2445 it 'returns users with a matching username starting with a @' do 2446 expect(described_class.search("@#{user.username}")).to eq([user, user2]) 2447 end 2448 2449 it 'returns users with a partially matching username' do 2450 expect(described_class.search(user.username[0..2])).to eq([user, user2]) 2451 end 2452 2453 it 'returns users with a partially matching username starting with @' do 2454 expect(described_class.search("@#{user.username[0..2]}")).to eq([user, user2]) 2455 end 2456 2457 it 'returns users with a matching username regardless of the casing' do 2458 expect(described_class.search(user2.username.upcase)).to eq([user2]) 2459 end 2460 2461 it 'returns users with a exact matching username shorter than 3 chars' do 2462 expect(described_class.search(user3.username)).to eq([user3]) 2463 end 2464 2465 it 'returns users with a exact matching username shorter than 3 chars regardless of the casing' do 2466 expect(described_class.search(user3.username.upcase)).to eq([user3]) 2467 end 2468 end 2469 2470 it 'returns no matches for an empty string' do 2471 expect(described_class.search('')).to be_empty 2472 end 2473 2474 it 'returns no matches for nil' do 2475 expect(described_class.search(nil)).to be_empty 2476 end 2477 end 2478 2479 describe '.search_without_secondary_emails' do 2480 let_it_be(:user) { create(:user, name: 'John Doe', username: 'john.doe', email: 'someone.1@example.com' ) } 2481 let_it_be(:another_user) { create(:user, name: 'Albert Smith', username: 'albert.smith', email: 'another.2@example.com' ) } 2482 let_it_be(:email) { create(:email, user: another_user, email: 'alias@example.com') } 2483 2484 it 'returns users with a matching name' do 2485 expect(described_class.search_without_secondary_emails(user.name)).to eq([user]) 2486 end 2487 2488 it 'returns users with a partially matching name' do 2489 expect(described_class.search_without_secondary_emails(user.name[0..2])).to eq([user]) 2490 end 2491 2492 it 'returns users with a matching name regardless of the casing' do 2493 expect(described_class.search_without_secondary_emails(user.name.upcase)).to eq([user]) 2494 end 2495 2496 it 'returns users with a matching email' do 2497 expect(described_class.search_without_secondary_emails(user.email)).to eq([user]) 2498 end 2499 2500 it 'does not return users with a partially matching email' do 2501 expect(described_class.search_without_secondary_emails(user.email[1...-1])).to be_empty 2502 end 2503 2504 it 'returns users with a matching email regardless of the casing' do 2505 expect(described_class.search_without_secondary_emails(user.email.upcase)).to eq([user]) 2506 end 2507 2508 it 'returns users with a matching username' do 2509 expect(described_class.search_without_secondary_emails(user.username)).to eq([user]) 2510 end 2511 2512 it 'returns users with a partially matching username' do 2513 expect(described_class.search_without_secondary_emails(user.username[0..2])).to eq([user]) 2514 end 2515 2516 it 'returns users with a matching username regardless of the casing' do 2517 expect(described_class.search_without_secondary_emails(user.username.upcase)).to eq([user]) 2518 end 2519 2520 it 'does not return users with a matching whole secondary email' do 2521 expect(described_class.search_without_secondary_emails(email.email)).not_to include(email.user) 2522 end 2523 2524 it 'does not return users with a matching part of secondary email' do 2525 expect(described_class.search_without_secondary_emails(email.email[1...-1])).to be_empty 2526 end 2527 2528 it 'returns no matches for an empty string' do 2529 expect(described_class.search_without_secondary_emails('')).to be_empty 2530 end 2531 2532 it 'returns no matches for nil' do 2533 expect(described_class.search_without_secondary_emails(nil)).to be_empty 2534 end 2535 end 2536 2537 describe '.search_with_secondary_emails' do 2538 let_it_be(:user) { create(:user, name: 'John Doe', username: 'john.doe', email: 'someone.1@example.com' ) } 2539 let_it_be(:another_user) { create(:user, name: 'Albert Smith', username: 'albert.smith', email: 'another.2@example.com' ) } 2540 let_it_be(:email) { create(:email, user: another_user, email: 'alias@example.com') } 2541 2542 it 'returns users with a matching name' do 2543 expect(described_class.search_with_secondary_emails(user.name)).to eq([user]) 2544 end 2545 2546 it 'returns users with a partially matching name' do 2547 expect(described_class.search_with_secondary_emails(user.name[0..2])).to eq([user]) 2548 end 2549 2550 it 'returns users with a matching name regardless of the casing' do 2551 expect(described_class.search_with_secondary_emails(user.name.upcase)).to eq([user]) 2552 end 2553 2554 it 'returns users with a matching email' do 2555 expect(described_class.search_with_secondary_emails(user.email)).to eq([user]) 2556 end 2557 2558 it 'does not return users with a partially matching email' do 2559 expect(described_class.search_with_secondary_emails(user.email[1...-1])).to be_empty 2560 end 2561 2562 it 'returns users with a matching email regardless of the casing' do 2563 expect(described_class.search_with_secondary_emails(user.email.upcase)).to eq([user]) 2564 end 2565 2566 it 'returns users with a matching username' do 2567 expect(described_class.search_with_secondary_emails(user.username)).to eq([user]) 2568 end 2569 2570 it 'returns users with a partially matching username' do 2571 expect(described_class.search_with_secondary_emails(user.username[0..2])).to eq([user]) 2572 end 2573 2574 it 'returns users with a matching username regardless of the casing' do 2575 expect(described_class.search_with_secondary_emails(user.username.upcase)).to eq([user]) 2576 end 2577 2578 it 'returns users with a matching whole secondary email' do 2579 expect(described_class.search_with_secondary_emails(email.email)).to eq([email.user]) 2580 end 2581 2582 it 'does not return users with a matching part of secondary email' do 2583 expect(described_class.search_with_secondary_emails(email.email[1...-1])).to be_empty 2584 end 2585 2586 it 'returns no matches for an empty string' do 2587 expect(described_class.search_with_secondary_emails('')).to be_empty 2588 end 2589 2590 it 'returns no matches for nil' do 2591 expect(described_class.search_with_secondary_emails(nil)).to be_empty 2592 end 2593 end 2594 2595 describe '.find_by_ssh_key_id' do 2596 let_it_be(:user) { create(:user) } 2597 let_it_be(:key) { create(:key, user: user) } 2598 2599 context 'using an existing SSH key ID' do 2600 it 'returns the corresponding User' do 2601 expect(described_class.find_by_ssh_key_id(key.id)).to eq(user) 2602 end 2603 end 2604 2605 it 'only performs a single query' do 2606 key # Don't count the queries for creating the key and user 2607 2608 expect { described_class.find_by_ssh_key_id(key.id) } 2609 .not_to exceed_query_limit(1) 2610 end 2611 2612 context 'using an invalid SSH key ID' do 2613 it 'returns nil' do 2614 expect(described_class.find_by_ssh_key_id(-1)).to be_nil 2615 end 2616 end 2617 end 2618 2619 describe '.by_login' do 2620 let(:username) { 'John' } 2621 let!(:user) { create(:user, username: username) } 2622 2623 it 'gets the correct user' do 2624 expect(described_class.by_login(user.email.upcase)).to eq user 2625 expect(described_class.by_login(user.email)).to eq user 2626 expect(described_class.by_login(username.downcase)).to eq user 2627 expect(described_class.by_login(username)).to eq user 2628 expect(described_class.by_login(nil)).to be_nil 2629 expect(described_class.by_login('')).to be_nil 2630 end 2631 end 2632 2633 describe '.find_by_username' do 2634 it 'returns nil if not found' do 2635 expect(described_class.find_by_username('JohnDoe')).to be_nil 2636 end 2637 2638 it 'is case-insensitive' do 2639 user = create(:user, username: 'JohnDoe') 2640 2641 expect(described_class.find_by_username('JOHNDOE')).to eq user 2642 end 2643 end 2644 2645 describe '.find_by_username!' do 2646 it 'raises RecordNotFound' do 2647 expect { described_class.find_by_username!('JohnDoe') } 2648 .to raise_error(ActiveRecord::RecordNotFound) 2649 end 2650 2651 it 'is case-insensitive' do 2652 user = create(:user, username: 'JohnDoe') 2653 2654 expect(described_class.find_by_username!('JOHNDOE')).to eq user 2655 end 2656 end 2657 2658 describe '.find_by_full_path' do 2659 let!(:user) { create(:user, namespace: create(:user_namespace)) } 2660 2661 context 'with a route matching the given path' do 2662 let!(:route) { user.namespace.route } 2663 2664 it 'returns the user' do 2665 expect(described_class.find_by_full_path(route.path)).to eq(user) 2666 end 2667 2668 it 'is case-insensitive' do 2669 expect(described_class.find_by_full_path(route.path.upcase)).to eq(user) 2670 expect(described_class.find_by_full_path(route.path.downcase)).to eq(user) 2671 end 2672 2673 context 'with a redirect route matching the given path' do 2674 let!(:redirect_route) { user.namespace.redirect_routes.create!(path: 'foo') } 2675 2676 context 'without the follow_redirects option' do 2677 it 'returns nil' do 2678 expect(described_class.find_by_full_path(redirect_route.path)).to eq(nil) 2679 end 2680 end 2681 2682 context 'with the follow_redirects option set to true' do 2683 it 'returns the user' do 2684 expect(described_class.find_by_full_path(redirect_route.path, follow_redirects: true)).to eq(user) 2685 end 2686 2687 it 'is case-insensitive' do 2688 expect(described_class.find_by_full_path(redirect_route.path.upcase, follow_redirects: true)).to eq(user) 2689 expect(described_class.find_by_full_path(redirect_route.path.downcase, follow_redirects: true)).to eq(user) 2690 end 2691 end 2692 end 2693 2694 context 'without a route or a redirect route matching the given path' do 2695 context 'without the follow_redirects option' do 2696 it 'returns nil' do 2697 expect(described_class.find_by_full_path('unknown')).to eq(nil) 2698 end 2699 end 2700 context 'with the follow_redirects option set to true' do 2701 it 'returns nil' do 2702 expect(described_class.find_by_full_path('unknown', follow_redirects: true)).to eq(nil) 2703 end 2704 end 2705 end 2706 2707 context 'with a group route matching the given path' do 2708 let!(:group) { create(:group, path: 'group_path') } 2709 2710 context 'when the group namespace has an owner_id (legacy data)' do 2711 before do 2712 group.update!(owner_id: user.id) 2713 end 2714 2715 it 'returns nil' do 2716 expect(described_class.find_by_full_path('group_path')).to eq(nil) 2717 end 2718 end 2719 2720 context 'when the group namespace does not have an owner_id' do 2721 it 'returns nil' do 2722 expect(described_class.find_by_full_path('group_path')).to eq(nil) 2723 end 2724 end 2725 end 2726 end 2727 end 2728 2729 describe 'all_ssh_keys' do 2730 it { is_expected.to have_many(:keys).dependent(:destroy) } 2731 2732 it 'has all ssh keys' do 2733 user = create :user 2734 key = create :key, key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD33bWLBxu48Sev9Fert1yzEO4WGcWglWF7K/AwblIUFselOt/QdOL9DSjpQGxLagO1s9wl53STIO8qGS4Ms0EJZyIXOEFMjFJ5xmjSy+S37By4sG7SsltQEHMxtbtFOaW5LV2wCrX+rUsRNqLMamZjgjcPO0/EgGCXIGMAYW4O7cwGZdXWYIhQ1Vwy+CsVMDdPkPgBXqK7nR/ey8KMs8ho5fMNgB5hBw/AL9fNGhRw3QTD6Q12Nkhl4VZES2EsZqlpNnJttnPdp847DUsT6yuLRlfiQfz5Cn9ysHFdXObMN5VYIiPFwHeYCZp1X2S4fDZooRE8uOLTfxWHPXwrhqSH", user_id: user.id 2735 2736 expect(user.all_ssh_keys).to include(a_string_starting_with(key.key)) 2737 end 2738 end 2739 2740 describe '#avatar_type' do 2741 let(:user) { create(:user) } 2742 2743 it 'is true if avatar is image' do 2744 user.update_attribute(:avatar, 'uploads/avatar.png') 2745 2746 expect(user.avatar_type).to be_truthy 2747 end 2748 2749 it 'is false if avatar is html page' do 2750 user.update_attribute(:avatar, 'uploads/avatar.html') 2751 user.avatar_type 2752 2753 expect(user.errors.added?(:avatar, "file format is not supported. Please try one of the following supported formats: png, jpg, jpeg, gif, bmp, tiff, ico, webp")).to be true 2754 end 2755 end 2756 2757 describe '#avatar_url' do 2758 let(:user) { create(:user, :with_avatar) } 2759 2760 context 'when avatar file is uploaded' do 2761 it 'shows correct avatar url' do 2762 expect(user.avatar_url).to eq(user.avatar.url) 2763 expect(user.avatar_url(only_path: false)).to eq([Gitlab.config.gitlab.url, user.avatar.url].join) 2764 end 2765 end 2766 end 2767 2768 describe '#clear_avatar_caches' do 2769 let(:user) { create(:user) } 2770 2771 it 'clears the avatar cache when saving' do 2772 allow(user).to receive(:avatar_changed?).and_return(true) 2773 2774 expect(Gitlab::AvatarCache).to receive(:delete_by_email).with(*user.verified_emails) 2775 2776 user.update!(avatar: fixture_file_upload('spec/fixtures/dk.png')) 2777 end 2778 end 2779 2780 describe '#accept_pending_invitations!' do 2781 let(:user) { create(:user, email: 'user@email.com') } 2782 let!(:project_member_invite) { create(:project_member, :invited, invite_email: user.email) } 2783 let!(:group_member_invite) { create(:group_member, :invited, invite_email: user.email) } 2784 let!(:external_project_member_invite) { create(:project_member, :invited, invite_email: 'external@email.com') } 2785 let!(:external_group_member_invite) { create(:group_member, :invited, invite_email: 'external@email.com') } 2786 2787 it 'accepts all the user members pending invitations and returns the accepted_members' do 2788 accepted_members = user.accept_pending_invitations! 2789 2790 expect(accepted_members).to match_array([project_member_invite, group_member_invite]) 2791 expect(group_member_invite.reload).not_to be_invite 2792 expect(project_member_invite.reload).not_to be_invite 2793 expect(external_project_member_invite.reload).to be_invite 2794 expect(external_group_member_invite.reload).to be_invite 2795 end 2796 end 2797 2798 describe '#all_emails' do 2799 let(:user) { create(:user) } 2800 let!(:email_confirmed) { create :email, user: user, confirmed_at: Time.current } 2801 let!(:email_unconfirmed) { create :email, user: user } 2802 2803 context 'when `include_private_email` is true' do 2804 it 'returns all emails' do 2805 expect(user.reload.all_emails).to contain_exactly( 2806 user.email, 2807 user.private_commit_email, 2808 email_unconfirmed.email, 2809 email_confirmed.email 2810 ) 2811 end 2812 end 2813 2814 context 'when `include_private_email` is false' do 2815 it 'does not include the private commit email' do 2816 expect(user.reload.all_emails(include_private_email: false)).to contain_exactly( 2817 user.email, 2818 email_unconfirmed.email, 2819 email_confirmed.email 2820 ) 2821 end 2822 end 2823 end 2824 2825 describe '#verified_emails' do 2826 let(:user) { create(:user) } 2827 2828 it 'returns only confirmed emails' do 2829 email_confirmed = create :email, user: user, confirmed_at: Time.current 2830 create :email, user: user 2831 2832 expect(user.verified_emails).to contain_exactly( 2833 user.email, 2834 user.private_commit_email, 2835 email_confirmed.email 2836 ) 2837 end 2838 end 2839 2840 describe '#public_verified_emails' do 2841 let(:user) { create(:user) } 2842 2843 it 'returns only confirmed public emails' do 2844 email_confirmed = create :email, user: user, confirmed_at: Time.current 2845 create :email, user: user 2846 2847 expect(user.public_verified_emails).to contain_exactly( 2848 user.email, 2849 email_confirmed.email 2850 ) 2851 end 2852 2853 it 'returns confirmed public emails plus main user email when user is not confirmed' do 2854 user = create(:user, confirmed_at: nil) 2855 email_confirmed = create :email, user: user, confirmed_at: Time.current 2856 create :email, user: user 2857 2858 expect(user.public_verified_emails).to contain_exactly( 2859 user.email, 2860 email_confirmed.email 2861 ) 2862 end 2863 end 2864 2865 describe '#verified_email?' do 2866 let(:user) { create(:user) } 2867 2868 it 'returns true when the email is verified/confirmed' do 2869 email_confirmed = create :email, user: user, confirmed_at: Time.current 2870 create :email, user: user 2871 user.reload 2872 2873 expect(user.verified_email?(user.email)).to be_truthy 2874 expect(user.verified_email?(email_confirmed.email.titlecase)).to be_truthy 2875 end 2876 2877 it 'returns true when user is found through private commit email' do 2878 expect(user.verified_email?(user.private_commit_email)).to be_truthy 2879 end 2880 2881 it 'returns true for an outdated private commit email' do 2882 old_email = user.private_commit_email 2883 2884 user.update!(username: 'changed-username') 2885 2886 expect(user.verified_email?(old_email)).to be_truthy 2887 end 2888 2889 it 'returns false when the email is not verified/confirmed' do 2890 email_unconfirmed = create :email, user: user 2891 user.reload 2892 2893 expect(user.verified_email?(email_unconfirmed.email)).to be_falsy 2894 end 2895 end 2896 2897 context 'crowd synchronized user' do 2898 describe '#crowd_user?' do 2899 it 'is true if provider is crowd' do 2900 user = create(:omniauth_user, provider: 'crowd') 2901 2902 expect(user.crowd_user?).to be_truthy 2903 end 2904 2905 it 'is false for other providers' do 2906 user = create(:omniauth_user, provider: 'other-provider') 2907 2908 expect(user.crowd_user?).to be_falsey 2909 end 2910 2911 it 'is false if no extern_uid is provided' do 2912 user = create(:omniauth_user, extern_uid: nil) 2913 2914 expect(user.crowd_user?).to be_falsey 2915 end 2916 end 2917 end 2918 2919 describe '#requires_ldap_check?' do 2920 let(:user) { described_class.new } 2921 2922 it 'is false when LDAP is disabled' do 2923 # Create a condition which would otherwise cause 'true' to be returned 2924 allow(user).to receive(:ldap_user?).and_return(true) 2925 user.last_credential_check_at = nil 2926 2927 expect(user.requires_ldap_check?).to be_falsey 2928 end 2929 2930 context 'when LDAP is enabled' do 2931 before do 2932 allow(Gitlab.config.ldap).to receive(:enabled).and_return(true) 2933 end 2934 2935 it 'is false for non-LDAP users' do 2936 allow(user).to receive(:ldap_user?).and_return(false) 2937 2938 expect(user.requires_ldap_check?).to be_falsey 2939 end 2940 2941 context 'and when the user is an LDAP user' do 2942 before do 2943 allow(user).to receive(:ldap_user?).and_return(true) 2944 end 2945 2946 it 'is true when the user has never had an LDAP check before' do 2947 user.last_credential_check_at = nil 2948 2949 expect(user.requires_ldap_check?).to be_truthy 2950 end 2951 2952 it 'is true when the last LDAP check happened over 1 hour ago' do 2953 user.last_credential_check_at = 2.hours.ago 2954 2955 expect(user.requires_ldap_check?).to be_truthy 2956 end 2957 end 2958 end 2959 end 2960 2961 context 'ldap synchronized user' do 2962 describe '#ldap_user?' do 2963 it 'is true if provider name starts with ldap' do 2964 user = create(:omniauth_user, provider: 'ldapmain') 2965 2966 expect(user.ldap_user?).to be_truthy 2967 end 2968 2969 it 'is false for other providers' do 2970 user = create(:omniauth_user, provider: 'other-provider') 2971 2972 expect(user.ldap_user?).to be_falsey 2973 end 2974 2975 it 'is false if no extern_uid is provided' do 2976 user = create(:omniauth_user, extern_uid: nil) 2977 2978 expect(user.ldap_user?).to be_falsey 2979 end 2980 end 2981 2982 describe '#ldap_identity' do 2983 it 'returns ldap identity' do 2984 user = create :omniauth_user 2985 2986 expect(user.ldap_identity.provider).not_to be_empty 2987 end 2988 end 2989 2990 describe '#matches_identity?' do 2991 it 'finds the identity when the DN is formatted differently' do 2992 user = create(:omniauth_user, provider: 'ldapmain', extern_uid: 'uid=john smith,ou=people,dc=example,dc=com') 2993 2994 expect(user.matches_identity?('ldapmain', 'uid=John Smith, ou=People, dc=example, dc=com')).to eq(true) 2995 end 2996 end 2997 2998 describe '#ldap_block' do 2999 let(:user) { create(:omniauth_user, provider: 'ldapmain', name: 'John Smith') } 3000 3001 it 'blocks user flaging the action caming from ldap' do 3002 user.ldap_block 3003 3004 expect(user.blocked?).to be_truthy 3005 expect(user.ldap_blocked?).to be_truthy 3006 end 3007 3008 context 'on a read-only instance' do 3009 before do 3010 allow(Gitlab::Database).to receive(:read_only?).and_return(true) 3011 end 3012 3013 it 'does not block user' do 3014 user.ldap_block 3015 3016 expect(user.blocked?).to be_falsey 3017 expect(user.ldap_blocked?).to be_falsey 3018 end 3019 end 3020 end 3021 end 3022 3023 describe '#full_website_url' do 3024 let(:user) { create(:user) } 3025 3026 it 'begins with http if website url omits it' do 3027 user.website_url = 'test.com' 3028 3029 expect(user.full_website_url).to eq 'http://test.com' 3030 end 3031 3032 it 'begins with http if website url begins with http' do 3033 user.website_url = 'http://test.com' 3034 3035 expect(user.full_website_url).to eq 'http://test.com' 3036 end 3037 3038 it 'begins with https if website url begins with https' do 3039 user.website_url = 'https://test.com' 3040 3041 expect(user.full_website_url).to eq 'https://test.com' 3042 end 3043 end 3044 3045 describe '#short_website_url' do 3046 let(:user) { create(:user) } 3047 3048 it 'does not begin with http if website url omits it' do 3049 user.website_url = 'test.com' 3050 3051 expect(user.short_website_url).to eq 'test.com' 3052 end 3053 3054 it 'does not begin with http if website url begins with http' do 3055 user.website_url = 'http://test.com' 3056 3057 expect(user.short_website_url).to eq 'test.com' 3058 end 3059 3060 it 'does not begin with https if website url begins with https' do 3061 user.website_url = 'https://test.com' 3062 3063 expect(user.short_website_url).to eq 'test.com' 3064 end 3065 end 3066 3067 describe '#sanitize_attrs' do 3068 let(:user) { build(:user, name: 'test <& user', skype: 'test&user') } 3069 3070 it 'encodes HTML entities in the Skype attribute' do 3071 expect { user.sanitize_attrs }.to change { user.skype }.to('test&user') 3072 end 3073 3074 it 'does not encode HTML entities in the name attribute' do 3075 expect { user.sanitize_attrs }.not_to change { user.name } 3076 end 3077 3078 it 'sanitizes attr from html tags' do 3079 user = create(:user, name: '<a href="//example.com">Test<a>', twitter: '<a href="//evil.com">https://twitter.com<a>') 3080 3081 expect(user.name).to eq('Test') 3082 expect(user.twitter).to eq('https://twitter.com') 3083 end 3084 3085 it 'sanitizes attr from js scripts' do 3086 user = create(:user, name: '<script>alert("Test")</script>') 3087 3088 expect(user.name).to eq("alert(\"Test\")") 3089 end 3090 3091 it 'sanitizes attr from iframe scripts' do 3092 user = create(:user, name: 'User"><iframe src=javascript:alert()><iframe>') 3093 3094 expect(user.name).to eq('User">') 3095 end 3096 end 3097 3098 describe '#starred?' do 3099 it 'determines if user starred a project' do 3100 user = create :user 3101 project1 = create(:project, :public) 3102 project2 = create(:project, :public) 3103 3104 expect(user.starred?(project1)).to be_falsey 3105 expect(user.starred?(project2)).to be_falsey 3106 3107 star1 = UsersStarProject.create!(project: project1, user: user) 3108 3109 expect(user.starred?(project1)).to be_truthy 3110 expect(user.starred?(project2)).to be_falsey 3111 3112 star2 = UsersStarProject.create!(project: project2, user: user) 3113 3114 expect(user.starred?(project1)).to be_truthy 3115 expect(user.starred?(project2)).to be_truthy 3116 3117 star1.destroy! 3118 3119 expect(user.starred?(project1)).to be_falsey 3120 expect(user.starred?(project2)).to be_truthy 3121 3122 star2.destroy! 3123 3124 expect(user.starred?(project1)).to be_falsey 3125 expect(user.starred?(project2)).to be_falsey 3126 end 3127 end 3128 3129 describe '#toggle_star' do 3130 it 'toggles stars' do 3131 user = create :user 3132 project = create(:project, :public) 3133 3134 expect(user.starred?(project)).to be_falsey 3135 3136 user.toggle_star(project) 3137 3138 expect(user.starred?(project)).to be_truthy 3139 3140 user.toggle_star(project) 3141 3142 expect(user.starred?(project)).to be_falsey 3143 end 3144 end 3145 3146 describe '#following?' do 3147 it 'check if following another user' do 3148 user = create :user 3149 followee1 = create :user 3150 3151 expect(user.follow(followee1)).to be_truthy 3152 3153 expect(user.following?(followee1)).to be_truthy 3154 3155 expect(user.unfollow(followee1)).to be_truthy 3156 3157 expect(user.following?(followee1)).to be_falsey 3158 end 3159 end 3160 3161 describe '#follow' do 3162 it 'follow another user' do 3163 user = create :user 3164 followee1 = create :user 3165 followee2 = create :user 3166 3167 expect(user.followees).to be_empty 3168 3169 expect(user.follow(followee1)).to be_truthy 3170 expect(user.follow(followee1)).to be_falsey 3171 3172 expect(user.followees).to contain_exactly(followee1) 3173 3174 expect(user.follow(followee2)).to be_truthy 3175 expect(user.follow(followee2)).to be_falsey 3176 3177 expect(user.followees).to contain_exactly(followee1, followee2) 3178 end 3179 3180 it 'follow itself is not possible' do 3181 user = create :user 3182 3183 expect(user.followees).to be_empty 3184 3185 expect(user.follow(user)).to be_falsey 3186 3187 expect(user.followees).to be_empty 3188 end 3189 end 3190 3191 describe '#unfollow' do 3192 it 'unfollow another user' do 3193 user = create :user 3194 followee1 = create :user 3195 followee2 = create :user 3196 3197 expect(user.followees).to be_empty 3198 3199 expect(user.follow(followee1)).to be_truthy 3200 expect(user.follow(followee1)).to be_falsey 3201 3202 expect(user.follow(followee2)).to be_truthy 3203 expect(user.follow(followee2)).to be_falsey 3204 3205 expect(user.followees).to contain_exactly(followee1, followee2) 3206 3207 expect(user.unfollow(followee1)).to be_truthy 3208 expect(user.unfollow(followee1)).to be_falsey 3209 3210 expect(user.followees).to contain_exactly(followee2) 3211 3212 expect(user.unfollow(followee2)).to be_truthy 3213 expect(user.unfollow(followee2)).to be_falsey 3214 3215 expect(user.followees).to be_empty 3216 end 3217 end 3218 3219 describe '#notification_email_or_default' do 3220 let(:email) { 'gonzo@muppets.com' } 3221 3222 context 'when the column in the database is null' do 3223 subject { create(:user, email: email, notification_email: nil) } 3224 3225 it 'defaults to the primary email' do 3226 expect(subject.notification_email).to be nil 3227 expect(subject.notification_email_or_default).to eq(email) 3228 end 3229 end 3230 end 3231 3232 describe '.find_by_private_commit_email' do 3233 context 'with email' do 3234 let_it_be(:user) { create(:user) } 3235 3236 it 'returns user through private commit email' do 3237 expect(described_class.find_by_private_commit_email(user.private_commit_email)).to eq(user) 3238 end 3239 3240 it 'returns nil when email other than private_commit_email is used' do 3241 expect(described_class.find_by_private_commit_email(user.email)).to be_nil 3242 end 3243 end 3244 3245 it 'returns nil when email is nil' do 3246 expect(described_class.find_by_private_commit_email(nil)).to be_nil 3247 end 3248 end 3249 3250 describe '#sort_by_attribute' do 3251 before do 3252 described_class.delete_all 3253 @user = create :user, created_at: Date.today, current_sign_in_at: Date.today, name: 'Alpha' 3254 @user1 = create :user, created_at: Date.today - 1, current_sign_in_at: Date.today - 1, name: 'Omega' 3255 @user2 = create :user, created_at: Date.today - 2, name: 'Beta' 3256 end 3257 3258 context 'when sort by recent_sign_in' do 3259 let(:users) { described_class.sort_by_attribute('recent_sign_in') } 3260 3261 it 'sorts users by recent sign-in time' do 3262 expect(users.first).to eq(@user) 3263 expect(users.second).to eq(@user1) 3264 end 3265 3266 it 'pushes users who never signed in to the end' do 3267 expect(users.third).to eq(@user2) 3268 end 3269 end 3270 3271 context 'when sort by oldest_sign_in' do 3272 let(:users) { described_class.sort_by_attribute('oldest_sign_in') } 3273 3274 it 'sorts users by the oldest sign-in time' do 3275 expect(users.first).to eq(@user1) 3276 expect(users.second).to eq(@user) 3277 end 3278 3279 it 'pushes users who never signed in to the end' do 3280 expect(users.third).to eq(@user2) 3281 end 3282 end 3283 3284 it 'sorts users in descending order by their creation time' do 3285 expect(described_class.sort_by_attribute('created_desc').first).to eq(@user) 3286 end 3287 3288 it 'sorts users in ascending order by their creation time' do 3289 expect(described_class.sort_by_attribute('created_asc').first).to eq(@user2) 3290 end 3291 3292 it 'sorts users by id in descending order when nil is passed' do 3293 expect(described_class.sort_by_attribute(nil).first).to eq(@user2) 3294 end 3295 end 3296 3297 describe '#last_active_at' do 3298 let(:last_activity_on) { 5.days.ago.to_date } 3299 let(:current_sign_in_at) { 8.days.ago } 3300 3301 context 'for a user that has `last_activity_on` set' do 3302 let(:user) { create(:user, last_activity_on: last_activity_on) } 3303 3304 it 'returns `last_activity_on` with current time zone' do 3305 expect(user.last_active_at).to eq(last_activity_on.to_time.in_time_zone) 3306 end 3307 end 3308 3309 context 'for a user that has `current_sign_in_at` set' do 3310 let(:user) { create(:user, current_sign_in_at: current_sign_in_at) } 3311 3312 it 'returns `current_sign_in_at`' do 3313 expect(user.last_active_at).to eq(current_sign_in_at) 3314 end 3315 end 3316 3317 context 'for a user that has both `current_sign_in_at` & ``last_activity_on`` set' do 3318 let(:user) { create(:user, current_sign_in_at: current_sign_in_at, last_activity_on: last_activity_on) } 3319 3320 it 'returns the latest among `current_sign_in_at` & `last_activity_on`' do 3321 latest_event = [current_sign_in_at, last_activity_on.to_time.in_time_zone].max 3322 expect(user.last_active_at).to eq(latest_event) 3323 end 3324 end 3325 3326 context 'for a user that does not have both `current_sign_in_at` & `last_activity_on` set' do 3327 let(:user) { create(:user, current_sign_in_at: nil, last_activity_on: nil) } 3328 3329 it 'returns nil' do 3330 expect(user.last_active_at).to eq(nil) 3331 end 3332 end 3333 end 3334 3335 describe '#can_be_deactivated?' do 3336 let(:activity) { {} } 3337 let(:user) { create(:user, name: 'John Smith', **activity) } 3338 let(:day_within_minium_inactive_days_threshold) { User::MINIMUM_INACTIVE_DAYS.pred.days.ago } 3339 let(:day_outside_minium_inactive_days_threshold) { User::MINIMUM_INACTIVE_DAYS.next.days.ago } 3340 3341 shared_examples 'not eligible for deactivation' do 3342 it 'returns false' do 3343 expect(user.can_be_deactivated?).to be_falsey 3344 end 3345 end 3346 3347 shared_examples 'eligible for deactivation' do 3348 it 'returns true' do 3349 expect(user.can_be_deactivated?).to be_truthy 3350 end 3351 end 3352 3353 context 'a user who is not active' do 3354 before do 3355 user.block 3356 end 3357 3358 it_behaves_like 'not eligible for deactivation' 3359 end 3360 3361 context 'a user who has activity within the specified minimum inactive days' do 3362 let(:activity) { { last_activity_on: day_within_minium_inactive_days_threshold } } 3363 3364 it_behaves_like 'not eligible for deactivation' 3365 end 3366 3367 context 'a user who has signed in within the specified minimum inactive days' do 3368 let(:activity) { { current_sign_in_at: day_within_minium_inactive_days_threshold } } 3369 3370 it_behaves_like 'not eligible for deactivation' 3371 end 3372 3373 context 'a user who has no activity within the specified minimum inactive days' do 3374 let(:activity) { { last_activity_on: day_outside_minium_inactive_days_threshold } } 3375 3376 it_behaves_like 'eligible for deactivation' 3377 end 3378 3379 context 'a user who has not signed in within the specified minimum inactive days' do 3380 let(:activity) { { current_sign_in_at: day_outside_minium_inactive_days_threshold } } 3381 3382 it_behaves_like 'eligible for deactivation' 3383 end 3384 3385 context 'a user who is internal' do 3386 it 'returns false' do 3387 internal_user = create(:user, :bot) 3388 3389 expect(internal_user.can_be_deactivated?).to be_falsey 3390 end 3391 end 3392 end 3393 3394 describe '#contributed_projects' do 3395 subject { create(:user) } 3396 3397 let!(:project1) { create(:project) } 3398 let!(:project2) { fork_project(project3) } 3399 let!(:project3) { create(:project) } 3400 let!(:merge_request) { create(:merge_request, source_project: project2, target_project: project3, author: subject) } 3401 let!(:push_event) { create(:push_event, project: project1, author: subject) } 3402 let!(:merge_event) { create(:event, :created, project: project3, target: merge_request, author: subject) } 3403 3404 before do 3405 project1.add_maintainer(subject) 3406 project2.add_maintainer(subject) 3407 end 3408 3409 it 'includes IDs for projects the user has pushed to' do 3410 expect(subject.contributed_projects).to include(project1) 3411 end 3412 3413 it 'includes IDs for projects the user has had merge requests merged into' do 3414 expect(subject.contributed_projects).to include(project3) 3415 end 3416 3417 it "doesn't include IDs for unrelated projects" do 3418 expect(subject.contributed_projects).not_to include(project2) 3419 end 3420 end 3421 3422 describe '#fork_of' do 3423 let(:user) { create(:user) } 3424 3425 it "returns a user's fork of a project" do 3426 project = create(:project, :public) 3427 user_fork = fork_project(project, user, namespace: user.namespace) 3428 3429 expect(user.fork_of(project)).to eq(user_fork) 3430 end 3431 3432 it 'returns nil if the project does not have a fork network' do 3433 project = create(:project) 3434 3435 expect(user.fork_of(project)).to be_nil 3436 end 3437 end 3438 3439 describe '#can_be_removed?' do 3440 subject { create(:user) } 3441 3442 context 'no owned groups' do 3443 it { expect(subject.can_be_removed?).to be_truthy } 3444 end 3445 3446 context 'has owned groups' do 3447 before do 3448 group = create(:group) 3449 group.add_owner(subject) 3450 end 3451 3452 it { expect(subject.can_be_removed?).to be_falsey } 3453 end 3454 end 3455 3456 describe '#solo_owned_groups' do 3457 let_it_be_with_refind(:user) { create(:user) } 3458 3459 subject(:solo_owned_groups) { user.solo_owned_groups } 3460 3461 context 'no owned groups' do 3462 it { is_expected.to be_empty } 3463 end 3464 3465 context 'has owned groups' do 3466 let_it_be(:group) { create(:group) } 3467 3468 before do 3469 group.add_owner(user) 3470 end 3471 3472 context 'not solo owner' do 3473 let_it_be(:user2) { create(:user) } 3474 3475 before do 3476 group.add_owner(user2) 3477 end 3478 3479 it { is_expected.to be_empty } 3480 end 3481 3482 context 'solo owner' do 3483 it { is_expected.to include(group) } 3484 3485 it 'avoids N+1 queries' do 3486 fresh_user = User.find(user.id) 3487 control_count = ActiveRecord::QueryRecorder.new do 3488 fresh_user.solo_owned_groups 3489 end.count 3490 3491 create(:group).add_owner(user) 3492 3493 expect { solo_owned_groups }.not_to exceed_query_limit(control_count) 3494 end 3495 end 3496 end 3497 end 3498 3499 describe '#can_remove_self?' do 3500 let(:user) { create(:user) } 3501 3502 it 'returns true' do 3503 expect(user.can_remove_self?).to eq true 3504 end 3505 end 3506 3507 describe '#recent_push' do 3508 let(:user) { build(:user) } 3509 let(:project) { build(:project) } 3510 let(:event) { build(:push_event) } 3511 3512 it 'returns the last push event for the user' do 3513 expect_any_instance_of(Users::LastPushEventService) 3514 .to receive(:last_event_for_user) 3515 .and_return(event) 3516 3517 expect(user.recent_push).to eq(event) 3518 end 3519 3520 it 'returns the last push event for a project when one is given' do 3521 expect_any_instance_of(Users::LastPushEventService) 3522 .to receive(:last_event_for_project) 3523 .and_return(event) 3524 3525 expect(user.recent_push(project)).to eq(event) 3526 end 3527 end 3528 3529 describe '#authorized_groups' do 3530 let!(:user) { create(:user) } 3531 let!(:private_group) { create(:group) } 3532 let!(:child_group) { create(:group, parent: private_group) } 3533 3534 let!(:project_group) { create(:group) } 3535 let!(:project) { create(:project, group: project_group) } 3536 3537 before do 3538 private_group.add_user(user, Gitlab::Access::MAINTAINER) 3539 project.add_maintainer(user) 3540 end 3541 3542 subject { user.authorized_groups } 3543 3544 it { is_expected.to contain_exactly private_group, project_group } 3545 3546 context 'with shared memberships' do 3547 let!(:shared_group) { create(:group) } 3548 let!(:other_group) { create(:group) } 3549 3550 before do 3551 create(:group_group_link, shared_group: shared_group, shared_with_group: private_group) 3552 create(:group_group_link, shared_group: private_group, shared_with_group: other_group) 3553 end 3554 3555 it { is_expected.to include shared_group } 3556 it { is_expected.not_to include other_group } 3557 end 3558 end 3559 3560 describe '#membership_groups' do 3561 let_it_be(:user) { create(:user) } 3562 3563 let_it_be(:parent_group) do 3564 create(:group).tap do |g| 3565 g.add_user(user, Gitlab::Access::MAINTAINER) 3566 end 3567 end 3568 3569 let_it_be(:child_group) { create(:group, parent: parent_group) } 3570 let_it_be(:other_group) { create(:group) } 3571 3572 subject { user.membership_groups } 3573 3574 specify { is_expected.to contain_exactly(parent_group, child_group) } 3575 end 3576 3577 describe '#authorizations_for_projects' do 3578 let!(:user) { create(:user) } 3579 3580 subject { Project.where("EXISTS (?)", user.authorizations_for_projects) } 3581 3582 it 'includes projects that belong to a user, but no other projects' do 3583 owned = create(:project, :private, namespace: user.namespace) 3584 member = create(:project, :private).tap { |p| p.add_maintainer(user) } 3585 other = create(:project) 3586 3587 expect(subject).to include(owned) 3588 expect(subject).to include(member) 3589 expect(subject).not_to include(other) 3590 end 3591 3592 it 'includes projects a user has access to, but no other projects' do 3593 other_user = create(:user) 3594 accessible = create(:project, :private, namespace: other_user.namespace) do |project| 3595 project.add_developer(user) 3596 end 3597 other = create(:project) 3598 3599 expect(subject).to include(accessible) 3600 expect(subject).not_to include(other) 3601 end 3602 3603 context 'with min_access_level' do 3604 let!(:user) { create(:user) } 3605 let!(:project) { create(:project, :private, namespace: user.namespace) } 3606 3607 before do 3608 project.add_developer(user) 3609 end 3610 3611 subject { Project.where("EXISTS (?)", user.authorizations_for_projects(min_access_level: min_access_level)) } 3612 3613 context 'when developer access' do 3614 let(:min_access_level) { Gitlab::Access::DEVELOPER } 3615 3616 it 'includes projects a user has access to' do 3617 expect(subject).to include(project) 3618 end 3619 end 3620 3621 context 'when owner access' do 3622 let(:min_access_level) { Gitlab::Access::OWNER } 3623 3624 it 'does not include projects with higher access level' do 3625 expect(subject).not_to include(project) 3626 end 3627 end 3628 end 3629 end 3630 3631 describe '#authorized_projects', :delete do 3632 context 'with a minimum access level' do 3633 it 'includes projects for which the user is an owner' do 3634 user = create(:user) 3635 project = create(:project, :private, namespace: user.namespace) 3636 3637 expect(user.authorized_projects(Gitlab::Access::REPORTER)) 3638 .to contain_exactly(project) 3639 end 3640 3641 it 'includes projects for which the user is a maintainer' do 3642 user = create(:user) 3643 project = create(:project, :private) 3644 3645 project.add_maintainer(user) 3646 3647 expect(user.authorized_projects(Gitlab::Access::REPORTER)) 3648 .to contain_exactly(project) 3649 end 3650 end 3651 3652 it "includes user's personal projects" do 3653 user = create(:user) 3654 project = create(:project, :private, namespace: user.namespace) 3655 3656 expect(user.authorized_projects).to include(project) 3657 end 3658 3659 it 'includes personal projects user has been given access to' do 3660 user1 = create(:user) 3661 user2 = create(:user) 3662 project = create(:project, :private, namespace: user1.namespace) 3663 3664 project.add_developer(user2) 3665 3666 expect(user2.authorized_projects).to include(project) 3667 end 3668 3669 it 'includes projects of groups user has been added to' do 3670 group = create(:group) 3671 project = create(:project, group: group) 3672 user = create(:user) 3673 3674 group.add_developer(user) 3675 3676 expect(user.authorized_projects).to include(project) 3677 end 3678 3679 it 'does not include projects of groups user has been removed from', :sidekiq_inline do 3680 group = create(:group) 3681 project = create(:project, group: group) 3682 user = create(:user) 3683 3684 member = group.add_developer(user) 3685 3686 expect(user.authorized_projects).to include(project) 3687 3688 member.destroy! 3689 3690 expect(user.authorized_projects).not_to include(project) 3691 end 3692 3693 it "includes projects shared with user's group" do 3694 user = create(:user) 3695 project = create(:project, :private) 3696 group = create(:group) do |group| 3697 group.add_reporter(user) 3698 end 3699 create(:project_group_link, group: group, project: project) 3700 3701 expect(user.authorized_projects).to include(project) 3702 end 3703 3704 it 'does not include destroyed projects user had access to' do 3705 user1 = create(:user) 3706 user2 = create(:user) 3707 project = create(:project, :private, namespace: user1.namespace) 3708 3709 project.add_developer(user2) 3710 3711 expect(user2.authorized_projects).to include(project) 3712 3713 project.destroy! 3714 3715 expect(user2.authorized_projects).not_to include(project) 3716 end 3717 3718 it 'does not include projects of destroyed groups user had access to' do 3719 group = create(:group) 3720 project = create(:project, namespace: group) 3721 user = create(:user) 3722 3723 group.add_developer(user) 3724 3725 expect(user.authorized_projects).to include(project) 3726 3727 group.destroy! 3728 3729 expect(user.authorized_projects).not_to include(project) 3730 end 3731 end 3732 3733 describe '#projects_where_can_admin_issues' do 3734 let(:user) { create(:user) } 3735 3736 it 'includes projects for which the user access level is above or equal to reporter' do 3737 reporter_project = create(:project) { |p| p.add_reporter(user) } 3738 developer_project = create(:project) { |p| p.add_developer(user) } 3739 maintainer_project = create(:project) { |p| p.add_maintainer(user) } 3740 3741 expect(user.projects_where_can_admin_issues.to_a).to match_array([maintainer_project, developer_project, reporter_project]) 3742 expect(user.can?(:admin_issue, maintainer_project)).to eq(true) 3743 expect(user.can?(:admin_issue, developer_project)).to eq(true) 3744 expect(user.can?(:admin_issue, reporter_project)).to eq(true) 3745 end 3746 3747 it 'does not include for which the user access level is below reporter' do 3748 project = create(:project) 3749 guest_project = create(:project) { |p| p.add_guest(user) } 3750 3751 expect(user.projects_where_can_admin_issues.to_a).to be_empty 3752 expect(user.can?(:admin_issue, guest_project)).to eq(false) 3753 expect(user.can?(:admin_issue, project)).to eq(false) 3754 end 3755 3756 it 'does not include archived projects' do 3757 project = create(:project, :archived) 3758 3759 expect(user.projects_where_can_admin_issues.to_a).to be_empty 3760 expect(user.can?(:admin_issue, project)).to eq(false) 3761 end 3762 3763 it 'does not include projects for which issues are disabled' do 3764 project = create(:project, :issues_disabled) 3765 3766 expect(user.projects_where_can_admin_issues.to_a).to be_empty 3767 expect(user.can?(:admin_issue, project)).to eq(false) 3768 end 3769 end 3770 3771 describe '#ci_owned_runners' do 3772 let(:user) { create(:user) } 3773 3774 shared_examples :nested_groups_owner do 3775 context 'when the user is the owner of a multi-level group' do 3776 before do 3777 set_permissions_for_users 3778 end 3779 3780 it 'loads all the runners in the tree of groups' do 3781 expect(user.ci_owned_runners).to contain_exactly(runner, group_runner) 3782 end 3783 3784 it 'returns true for owns_runner?' do 3785 expect(user.owns_runner?(runner)).to eq(true) 3786 expect(user.owns_runner?(group_runner)).to eq(true) 3787 end 3788 end 3789 end 3790 3791 shared_examples :group_owner do 3792 context 'when the user is the owner of a one level group' do 3793 before do 3794 group.add_owner(user) 3795 end 3796 3797 it 'loads the runners in the group' do 3798 expect(user.ci_owned_runners).to contain_exactly(group_runner) 3799 end 3800 3801 it 'returns true for owns_runner?' do 3802 expect(user.owns_runner?(group_runner)).to eq(true) 3803 end 3804 end 3805 end 3806 3807 shared_examples :project_owner do 3808 context 'when the user is the owner of a project' do 3809 it 'loads the runner belonging to the project' do 3810 expect(user.ci_owned_runners).to contain_exactly(runner) 3811 end 3812 3813 it 'returns true for owns_runner?' do 3814 expect(user.owns_runner?(runner)).to eq(true) 3815 end 3816 end 3817 end 3818 3819 shared_examples :project_member do 3820 context 'when the user is a maintainer' do 3821 before do 3822 add_user(:maintainer) 3823 end 3824 3825 it 'loads the runners of the project' do 3826 expect(user.ci_owned_runners).to contain_exactly(project_runner) 3827 end 3828 3829 it 'returns true for owns_runner?' do 3830 expect(user.owns_runner?(project_runner)).to eq(true) 3831 end 3832 end 3833 3834 context 'when the user is a developer' do 3835 before do 3836 add_user(:developer) 3837 end 3838 3839 it 'does not load any runner' do 3840 expect(user.ci_owned_runners).to be_empty 3841 end 3842 3843 it 'returns false for owns_runner?' do 3844 expect(user.owns_runner?(project_runner)).to eq(false) 3845 end 3846 end 3847 3848 context 'when the user is a reporter' do 3849 before do 3850 add_user(:reporter) 3851 end 3852 3853 it 'does not load any runner' do 3854 expect(user.ci_owned_runners).to be_empty 3855 end 3856 3857 it 'returns false for owns_runner?' do 3858 expect(user.owns_runner?(project_runner)).to eq(false) 3859 end 3860 end 3861 3862 context 'when the user is a guest' do 3863 before do 3864 add_user(:guest) 3865 end 3866 3867 it 'does not load any runner' do 3868 expect(user.ci_owned_runners).to be_empty 3869 end 3870 3871 it 'returns false for owns_runner?' do 3872 expect(user.owns_runner?(project_runner)).to eq(false) 3873 end 3874 end 3875 end 3876 3877 shared_examples :group_member do 3878 context 'when the user is a maintainer' do 3879 before do 3880 add_user(:maintainer) 3881 end 3882 3883 it 'does not load the runners of the group' do 3884 expect(user.ci_owned_runners).to be_empty 3885 end 3886 3887 it 'returns false for owns_runner?' do 3888 expect(user.owns_runner?(runner)).to eq(false) 3889 end 3890 end 3891 3892 context 'when the user is a developer' do 3893 before do 3894 add_user(:developer) 3895 end 3896 3897 it 'does not load any runner' do 3898 expect(user.ci_owned_runners).to be_empty 3899 end 3900 3901 it 'returns false for owns_runner?' do 3902 expect(user.owns_runner?(runner)).to eq(false) 3903 end 3904 end 3905 3906 context 'when the user is a reporter' do 3907 before do 3908 add_user(:reporter) 3909 end 3910 3911 it 'does not load any runner' do 3912 expect(user.ci_owned_runners).to be_empty 3913 end 3914 3915 it 'returns false for owns_runner?' do 3916 expect(user.owns_runner?(runner)).to eq(false) 3917 end 3918 end 3919 3920 context 'when the user is a guest' do 3921 before do 3922 add_user(:guest) 3923 end 3924 3925 it 'does not load any runner' do 3926 expect(user.ci_owned_runners).to be_empty 3927 end 3928 3929 it 'returns false for owns_runner?' do 3930 expect(user.owns_runner?(runner)).to eq(false) 3931 end 3932 end 3933 end 3934 3935 context 'without any projects nor groups' do 3936 it 'does not load any runner' do 3937 expect(user.ci_owned_runners).to be_empty 3938 end 3939 3940 it 'returns false for owns_runner?' do 3941 expect(user.owns_runner?(create(:ci_runner))).to eq(false) 3942 end 3943 end 3944 3945 context 'with runner in a personal project' do 3946 let!(:namespace) { create(:user_namespace, owner: user) } 3947 let!(:project) { create(:project, namespace: namespace) } 3948 let!(:runner) { create(:ci_runner, :project, projects: [project]) } 3949 3950 it_behaves_like :project_owner 3951 end 3952 3953 context 'with group runner in a non owned group' do 3954 let!(:group) { create(:group) } 3955 let!(:runner) { create(:ci_runner, :group, groups: [group]) } 3956 3957 def add_user(access) 3958 group.add_user(user, access) 3959 end 3960 3961 it_behaves_like :group_member 3962 end 3963 3964 context 'with group runner in an owned group' do 3965 let!(:group) { create(:group) } 3966 let!(:group_runner) { create(:ci_runner, :group, groups: [group]) } 3967 3968 it_behaves_like :group_owner 3969 end 3970 3971 context 'with group runner in an owned group and group runner in a different owner subgroup' do 3972 let!(:group) { create(:group) } 3973 let!(:runner) { create(:ci_runner, :group, groups: [group]) } 3974 let!(:subgroup) { create(:group, parent: group) } 3975 let!(:group_runner) { create(:ci_runner, :group, groups: [subgroup]) } 3976 let!(:another_user) { create(:user) } 3977 3978 def set_permissions_for_users 3979 group.add_owner(user) 3980 subgroup.add_owner(another_user) 3981 end 3982 3983 it_behaves_like :nested_groups_owner 3984 end 3985 3986 context 'with personal project runner in an an owned group and a group runner in that same group' do 3987 let!(:group) { create(:group) } 3988 let!(:group_runner) { create(:ci_runner, :group, groups: [group]) } 3989 let!(:project) { create(:project, group: group) } 3990 let!(:runner) { create(:ci_runner, :project, projects: [project]) } 3991 3992 def set_permissions_for_users 3993 group.add_owner(user) 3994 end 3995 3996 it_behaves_like :nested_groups_owner 3997 end 3998 3999 context 'with personal project runner in an owned group and a group runner in a subgroup' do 4000 let!(:group) { create(:group) } 4001 let!(:subgroup) { create(:group, parent: group) } 4002 let!(:group_runner) { create(:ci_runner, :group, groups: [subgroup]) } 4003 let!(:project) { create(:project, group: group) } 4004 let!(:runner) { create(:ci_runner, :project, projects: [project]) } 4005 4006 def set_permissions_for_users 4007 group.add_owner(user) 4008 end 4009 4010 it_behaves_like :nested_groups_owner 4011 end 4012 4013 context 'with personal project runner in an owned group in an owned namespace and a group runner in that group' do 4014 let!(:namespace) { create(:user_namespace, owner: user) } 4015 let!(:group) { create(:group) } 4016 let!(:group_runner) { create(:ci_runner, :group, groups: [group]) } 4017 let!(:project) { create(:project, namespace: namespace, group: group) } 4018 let!(:runner) { create(:ci_runner, :project, projects: [project]) } 4019 4020 def set_permissions_for_users 4021 group.add_owner(user) 4022 end 4023 4024 it_behaves_like :nested_groups_owner 4025 end 4026 4027 context 'with personal project runner in an owned namespace, an owned group, a subgroup and a group runner in that subgroup' do 4028 let!(:namespace) { create(:user_namespace, owner: user) } 4029 let!(:group) { create(:group) } 4030 let!(:subgroup) { create(:group, parent: group) } 4031 let!(:group_runner) { create(:ci_runner, :group, groups: [subgroup]) } 4032 let!(:project) { create(:project, namespace: namespace, group: group) } 4033 let!(:runner) { create(:ci_runner, :project, projects: [project]) } 4034 4035 def set_permissions_for_users 4036 group.add_owner(user) 4037 end 4038 4039 it_behaves_like :nested_groups_owner 4040 end 4041 4042 context 'with a project runner that belong to projects that belong to a not owned group' do 4043 let!(:group) { create(:group) } 4044 let!(:project) { create(:project, group: group) } 4045 let!(:project_runner) { create(:ci_runner, :project, projects: [project]) } 4046 4047 def add_user(access) 4048 project.add_user(user, access) 4049 end 4050 4051 it_behaves_like :project_member 4052 end 4053 4054 context 'with project runners that belong to projects that do not belong to any group' do 4055 let!(:project) { create(:project) } 4056 let!(:runner) { create(:ci_runner, :project, projects: [project]) } 4057 4058 it 'does not load any runner' do 4059 expect(user.ci_owned_runners).to be_empty 4060 end 4061 end 4062 4063 context 'with a group runner that belongs to a subgroup of a group owned by another user' do 4064 let!(:group) { create(:group) } 4065 let!(:subgroup) { create(:group, parent: group) } 4066 let!(:runner) { create(:ci_runner, :group, groups: [subgroup]) } 4067 let!(:another_user) { create(:user) } 4068 4069 def add_user(access) 4070 subgroup.add_user(user, access) 4071 group.add_user(another_user, :owner) 4072 end 4073 4074 it_behaves_like :group_member 4075 end 4076 end 4077 4078 describe '#projects_with_reporter_access_limited_to' do 4079 let(:project1) { create(:project) } 4080 let(:project2) { create(:project) } 4081 let(:user) { create(:user) } 4082 4083 before do 4084 project1.add_reporter(user) 4085 project2.add_guest(user) 4086 end 4087 4088 it 'returns the projects when using a single project ID' do 4089 projects = user.projects_with_reporter_access_limited_to(project1.id) 4090 4091 expect(projects).to eq([project1]) 4092 end 4093 4094 it 'returns the projects when using an Array of project IDs' do 4095 projects = user.projects_with_reporter_access_limited_to([project1.id]) 4096 4097 expect(projects).to eq([project1]) 4098 end 4099 4100 it 'returns the projects when using an ActiveRecord relation' do 4101 projects = user 4102 .projects_with_reporter_access_limited_to(Project.select(:id)) 4103 4104 expect(projects).to eq([project1]) 4105 end 4106 4107 it 'does not return projects you do not have reporter access to' do 4108 projects = user.projects_with_reporter_access_limited_to(project2.id) 4109 4110 expect(projects).to be_empty 4111 end 4112 end 4113 4114 describe '#all_expanded_groups' do 4115 # foo/bar would also match foo/barbaz instead of just foo/bar and foo/bar/baz 4116 let!(:user) { create(:user) } 4117 4118 # group 4119 # _______ (foo) _______ 4120 # | | 4121 # | | 4122 # nested_group_1 nested_group_2 4123 # (bar) (barbaz) 4124 # | | 4125 # | | 4126 # nested_group_1_1 nested_group_2_1 4127 # (baz) (baz) 4128 # 4129 let!(:group) { create :group } 4130 let!(:nested_group_1) { create :group, parent: group, name: 'bar' } 4131 let!(:nested_group_1_1) { create :group, parent: nested_group_1, name: 'baz' } 4132 let!(:nested_group_2) { create :group, parent: group, name: 'barbaz' } 4133 let!(:nested_group_2_1) { create :group, parent: nested_group_2, name: 'baz' } 4134 4135 subject { user.all_expanded_groups } 4136 4137 context 'user is not a member of any group' do 4138 it 'returns an empty array' do 4139 is_expected.to eq([]) 4140 end 4141 end 4142 4143 context 'user is member of all groups' do 4144 before do 4145 group.add_reporter(user) 4146 nested_group_1.add_developer(user) 4147 nested_group_1_1.add_maintainer(user) 4148 nested_group_2.add_developer(user) 4149 nested_group_2_1.add_maintainer(user) 4150 end 4151 4152 it 'returns all groups' do 4153 is_expected.to match_array [ 4154 group, 4155 nested_group_1, nested_group_1_1, 4156 nested_group_2, nested_group_2_1 4157 ] 4158 end 4159 end 4160 4161 context 'user is member of the top group' do 4162 before do 4163 group.add_owner(user) 4164 end 4165 4166 it 'returns all groups' do 4167 is_expected.to match_array [ 4168 group, 4169 nested_group_1, nested_group_1_1, 4170 nested_group_2, nested_group_2_1 4171 ] 4172 end 4173 end 4174 4175 context 'user is member of the first child (internal node), branch 1' do 4176 before do 4177 nested_group_1.add_owner(user) 4178 end 4179 4180 it 'returns the groups in the hierarchy' do 4181 is_expected.to match_array [ 4182 group, 4183 nested_group_1, nested_group_1_1 4184 ] 4185 end 4186 end 4187 4188 context 'user is member of the first child (internal node), branch 2' do 4189 before do 4190 nested_group_2.add_owner(user) 4191 end 4192 4193 it 'returns the groups in the hierarchy' do 4194 is_expected.to match_array [ 4195 group, 4196 nested_group_2, nested_group_2_1 4197 ] 4198 end 4199 end 4200 4201 context 'user is member of the last child (leaf node)' do 4202 before do 4203 nested_group_1_1.add_owner(user) 4204 end 4205 4206 it 'returns the groups in the hierarchy' do 4207 is_expected.to match_array [ 4208 group, 4209 nested_group_1, nested_group_1_1 4210 ] 4211 end 4212 end 4213 4214 context 'when the user is not saved' do 4215 let(:user) { build(:user) } 4216 4217 it 'returns empty when there are no groups or ancestor groups for the user' do 4218 is_expected.to eq([]) 4219 end 4220 end 4221 end 4222 4223 describe '#refresh_authorized_projects', :clean_gitlab_redis_shared_state do 4224 let(:project1) { create(:project) } 4225 let(:project2) { create(:project) } 4226 let(:user) { create(:user) } 4227 4228 before do 4229 project1.add_reporter(user) 4230 project2.add_guest(user) 4231 4232 user.project_authorizations.delete_all 4233 user.refresh_authorized_projects 4234 end 4235 4236 it 'refreshes the list of authorized projects' do 4237 expect(user.project_authorizations.count).to eq(2) 4238 end 4239 4240 it 'stores the correct access levels' do 4241 expect(user.project_authorizations.where(access_level: Gitlab::Access::GUEST).exists?).to eq(true) 4242 expect(user.project_authorizations.where(access_level: Gitlab::Access::REPORTER).exists?).to eq(true) 4243 end 4244 end 4245 4246 describe '#remove_project_authorizations' do 4247 let_it_be(:project1) { create(:project) } 4248 let_it_be(:project2) { create(:project) } 4249 let_it_be(:project3) { create(:project) } 4250 let_it_be(:user) { create(:user) } 4251 4252 it 'removes the project authorizations of the user, in specified projects' do 4253 create(:project_authorization, user: user, project: project1) 4254 create(:project_authorization, user: user, project: project2) 4255 create(:project_authorization, user: user, project: project3) 4256 4257 user.remove_project_authorizations([project1.id, project2.id]) 4258 4259 expect(user.project_authorizations.pluck(:project_id)).to match_array([project3.id]) 4260 end 4261 end 4262 4263 describe '#access_level=' do 4264 let(:user) { build(:user) } 4265 4266 it 'does nothing for an invalid access level' do 4267 user.access_level = :invalid_access_level 4268 4269 expect(user.access_level).to eq(:regular) 4270 expect(user.admin).to be false 4271 end 4272 4273 it "assigns the 'admin' access level" do 4274 user.access_level = :admin 4275 4276 expect(user.access_level).to eq(:admin) 4277 expect(user.admin).to be true 4278 end 4279 4280 it "doesn't clear existing access levels when an invalid access level is passed in" do 4281 user.access_level = :admin 4282 user.access_level = :invalid_access_level 4283 4284 expect(user.access_level).to eq(:admin) 4285 expect(user.admin).to be true 4286 end 4287 4288 it 'accepts string values in addition to symbols' do 4289 user.access_level = 'admin' 4290 4291 expect(user.access_level).to eq(:admin) 4292 expect(user.admin).to be true 4293 end 4294 end 4295 4296 describe '#can_read_all_resources?', :request_store do 4297 it 'returns false for regular user' do 4298 user = build_stubbed(:user) 4299 4300 expect(user.can_read_all_resources?).to be_falsy 4301 end 4302 4303 context 'for admin user' do 4304 include_context 'custom session' 4305 4306 let(:user) { build_stubbed(:user, :admin) } 4307 4308 context 'when admin mode is disabled' do 4309 it 'returns false' do 4310 expect(user.can_read_all_resources?).to be_falsy 4311 end 4312 end 4313 4314 context 'when admin mode is enabled' do 4315 before do 4316 Gitlab::Auth::CurrentUserMode.new(user).request_admin_mode! 4317 Gitlab::Auth::CurrentUserMode.new(user).enable_admin_mode!(password: user.password) 4318 end 4319 4320 it 'returns true' do 4321 expect(user.can_read_all_resources?).to be_truthy 4322 end 4323 end 4324 end 4325 end 4326 4327 describe '#can_admin_all_resources?', :request_store do 4328 it 'returns false for regular user' do 4329 user = build_stubbed(:user) 4330 4331 expect(user.can_admin_all_resources?).to be_falsy 4332 end 4333 4334 context 'for admin user' do 4335 include_context 'custom session' 4336 4337 let(:user) { build_stubbed(:user, :admin) } 4338 4339 context 'when admin mode is disabled' do 4340 it 'returns false' do 4341 expect(user.can_admin_all_resources?).to be_falsy 4342 end 4343 end 4344 4345 context 'when admin mode is enabled' do 4346 before do 4347 Gitlab::Auth::CurrentUserMode.new(user).request_admin_mode! 4348 Gitlab::Auth::CurrentUserMode.new(user).enable_admin_mode!(password: user.password) 4349 end 4350 4351 it 'returns true' do 4352 expect(user.can_admin_all_resources?).to be_truthy 4353 end 4354 end 4355 end 4356 end 4357 4358 describe '.ghost' do 4359 it "creates a ghost user if one isn't already present" do 4360 ghost = described_class.ghost 4361 4362 expect(ghost).to be_ghost 4363 expect(ghost).to be_persisted 4364 expect(ghost.namespace).not_to be_nil 4365 expect(ghost.namespace).to be_persisted 4366 expect(ghost.user_type).to eq 'ghost' 4367 end 4368 4369 it 'does not create a second ghost user if one is already present' do 4370 expect do 4371 described_class.ghost 4372 described_class.ghost 4373 end.to change { described_class.count }.by(1) 4374 expect(described_class.ghost).to eq(described_class.ghost) 4375 end 4376 4377 context "when a regular user exists with the username 'ghost'" do 4378 it 'creates a ghost user with a non-conflicting username' do 4379 create(:user, username: 'ghost') 4380 ghost = described_class.ghost 4381 4382 expect(ghost).to be_persisted 4383 expect(ghost.username).to eq('ghost1') 4384 end 4385 end 4386 4387 context "when a regular user exists with the email 'ghost@example.com'" do 4388 it 'creates a ghost user with a non-conflicting email' do 4389 create(:user, email: 'ghost@example.com') 4390 ghost = described_class.ghost 4391 4392 expect(ghost).to be_persisted 4393 expect(ghost.email).to eq('ghost1@example.com') 4394 end 4395 end 4396 4397 context 'when a domain allowlist is in place' do 4398 before do 4399 stub_application_setting(domain_allowlist: ['gitlab.com']) 4400 end 4401 4402 it 'creates a ghost user' do 4403 expect(described_class.ghost).to be_persisted 4404 end 4405 end 4406 end 4407 4408 describe '#update_two_factor_requirement' do 4409 let(:user) { create :user } 4410 4411 context 'with 2FA requirement on groups' do 4412 let(:group1) { create :group, require_two_factor_authentication: true, two_factor_grace_period: 23 } 4413 let(:group2) { create :group, require_two_factor_authentication: true, two_factor_grace_period: 32 } 4414 4415 before do 4416 group1.add_user(user, GroupMember::OWNER) 4417 group2.add_user(user, GroupMember::OWNER) 4418 4419 user.update_two_factor_requirement 4420 end 4421 4422 it 'requires 2FA' do 4423 expect(user.require_two_factor_authentication_from_group).to be true 4424 end 4425 4426 it 'uses the shortest grace period' do 4427 expect(user.two_factor_grace_period).to be 23 4428 end 4429 end 4430 4431 context 'with 2FA requirement from expanded groups' do 4432 let!(:group1) { create :group, require_two_factor_authentication: true } 4433 let!(:group1a) { create :group, parent: group1 } 4434 4435 before do 4436 group1a.add_user(user, GroupMember::OWNER) 4437 4438 user.update_two_factor_requirement 4439 end 4440 4441 it 'requires 2FA' do 4442 expect(user.require_two_factor_authentication_from_group).to be true 4443 end 4444 end 4445 4446 context 'with 2FA requirement on nested child group' do 4447 let!(:group1) { create :group, require_two_factor_authentication: false } 4448 let!(:group1a) { create :group, require_two_factor_authentication: true, parent: group1 } 4449 4450 before do 4451 group1.add_user(user, GroupMember::OWNER) 4452 4453 user.update_two_factor_requirement 4454 end 4455 4456 it 'requires 2FA' do 4457 expect(user.require_two_factor_authentication_from_group).to be true 4458 end 4459 end 4460 4461 context "with 2FA requirement from shared project's group" do 4462 let!(:group1) { create :group, require_two_factor_authentication: true } 4463 let!(:group2) { create :group } 4464 let(:shared_project) { create(:project, namespace: group1) } 4465 4466 before do 4467 shared_project.project_group_links.create!( 4468 group: group2, 4469 group_access: ProjectGroupLink.default_access 4470 ) 4471 4472 group2.add_user(user, GroupMember::OWNER) 4473 end 4474 4475 it 'does not require 2FA' do 4476 user.update_two_factor_requirement 4477 4478 expect(user.require_two_factor_authentication_from_group).to be false 4479 end 4480 end 4481 4482 context 'without 2FA requirement on groups' do 4483 let(:group) { create :group } 4484 4485 before do 4486 group.add_user(user, GroupMember::OWNER) 4487 4488 user.update_two_factor_requirement 4489 end 4490 4491 it 'does not require 2FA' do 4492 expect(user.require_two_factor_authentication_from_group).to be false 4493 end 4494 4495 it 'falls back to the default grace period' do 4496 expect(user.two_factor_grace_period).to be 48 4497 end 4498 end 4499 4500 context 'when the user is not saved' do 4501 let(:user) { build(:user) } 4502 4503 it 'does not raise an ActiveRecord::StatementInvalid statement exception' do 4504 expect { user.update_two_factor_requirement }.not_to raise_error 4505 end 4506 end 4507 end 4508 4509 describe '#source_groups_of_two_factor_authentication_requirement' do 4510 let_it_be(:group_not_requiring_2FA) { create :group } 4511 4512 let(:user) { create :user } 4513 4514 before do 4515 group.add_user(user, GroupMember::OWNER) 4516 group_not_requiring_2FA.add_user(user, GroupMember::OWNER) 4517 end 4518 4519 context 'when user is direct member of group requiring 2FA' do 4520 let_it_be(:group) { create :group, require_two_factor_authentication: true } 4521 4522 it 'returns group requiring 2FA' do 4523 expect(user.source_groups_of_two_factor_authentication_requirement).to contain_exactly(group) 4524 end 4525 end 4526 4527 context 'when user is member of group which parent requires 2FA' do 4528 let_it_be(:parent_group) { create :group, require_two_factor_authentication: true } 4529 let_it_be(:group) { create :group, parent: parent_group } 4530 4531 it 'returns group requiring 2FA' do 4532 expect(user.source_groups_of_two_factor_authentication_requirement).to contain_exactly(group) 4533 end 4534 end 4535 4536 context 'when user is member of group which child requires 2FA' do 4537 let_it_be(:group) { create :group } 4538 let_it_be(:child_group) { create :group, require_two_factor_authentication: true, parent: group } 4539 4540 it 'returns group requiring 2FA' do 4541 expect(user.source_groups_of_two_factor_authentication_requirement).to contain_exactly(group) 4542 end 4543 end 4544 end 4545 4546 describe '.active' do 4547 before do 4548 described_class.ghost 4549 create(:user, name: 'user', state: 'active') 4550 create(:user, name: 'user', state: 'blocked') 4551 end 4552 4553 it 'only counts active and non internal users' do 4554 expect(described_class.active.count).to eq(1) 4555 end 4556 end 4557 4558 describe 'preferred language' do 4559 it 'is English by default' do 4560 user = create(:user) 4561 4562 expect(user.preferred_language).to eq('en') 4563 end 4564 end 4565 4566 describe '#invalidate_issue_cache_counts' do 4567 let(:user) { build_stubbed(:user) } 4568 4569 it 'invalidates cache for issue counter' do 4570 cache_mock = double 4571 4572 expect(cache_mock).to receive(:delete).with(['users', user.id, 'assigned_open_issues_count']) 4573 4574 allow(Rails).to receive(:cache).and_return(cache_mock) 4575 4576 user.invalidate_issue_cache_counts 4577 end 4578 end 4579 4580 describe '#invalidate_merge_request_cache_counts' do 4581 let(:user) { build_stubbed(:user) } 4582 4583 it 'invalidates cache for Merge Request counter' do 4584 cache_mock = double 4585 4586 expect(cache_mock).to receive(:delete).with(['users', user.id, 'assigned_open_merge_requests_count']) 4587 expect(cache_mock).to receive(:delete).with(['users', user.id, 'review_requested_open_merge_requests_count']) 4588 4589 allow(Rails).to receive(:cache).and_return(cache_mock) 4590 4591 user.invalidate_merge_request_cache_counts 4592 end 4593 end 4594 4595 describe '#invalidate_personal_projects_count' do 4596 let(:user) { build_stubbed(:user) } 4597 4598 it 'invalidates cache for personal projects counter' do 4599 cache_mock = double 4600 4601 expect(cache_mock).to receive(:delete).with(['users', user.id, 'personal_projects_count']) 4602 4603 allow(Rails).to receive(:cache).and_return(cache_mock) 4604 4605 user.invalidate_personal_projects_count 4606 end 4607 end 4608 4609 describe '#allow_password_authentication_for_web?' do 4610 context 'regular user' do 4611 let(:user) { build(:user) } 4612 4613 it 'returns true when password authentication is enabled for the web interface' do 4614 expect(user.allow_password_authentication_for_web?).to be_truthy 4615 end 4616 4617 it 'returns false when password authentication is disabled for the web interface' do 4618 stub_application_setting(password_authentication_enabled_for_web: false) 4619 4620 expect(user.allow_password_authentication_for_web?).to be_falsey 4621 end 4622 end 4623 4624 it 'returns false for ldap user' do 4625 user = create(:omniauth_user, provider: 'ldapmain') 4626 4627 expect(user.allow_password_authentication_for_web?).to be_falsey 4628 end 4629 end 4630 4631 describe '#allow_password_authentication_for_git?' do 4632 context 'regular user' do 4633 let(:user) { build(:user) } 4634 4635 it 'returns true when password authentication is enabled for Git' do 4636 expect(user.allow_password_authentication_for_git?).to be_truthy 4637 end 4638 4639 it 'returns false when password authentication is disabled Git' do 4640 stub_application_setting(password_authentication_enabled_for_git: false) 4641 4642 expect(user.allow_password_authentication_for_git?).to be_falsey 4643 end 4644 end 4645 4646 it 'returns false for ldap user' do 4647 user = create(:omniauth_user, provider: 'ldapmain') 4648 4649 expect(user.allow_password_authentication_for_git?).to be_falsey 4650 end 4651 end 4652 4653 describe '#assigned_open_merge_requests_count' do 4654 it 'returns number of open merge requests from non-archived projects' do 4655 user = create(:user) 4656 project = create(:project, :public) 4657 archived_project = create(:project, :public, :archived) 4658 4659 create(:merge_request, source_project: project, author: user, assignees: [user]) 4660 create(:merge_request, :closed, source_project: project, author: user, assignees: [user]) 4661 create(:merge_request, source_project: archived_project, author: user, assignees: [user]) 4662 4663 expect(user.assigned_open_merge_requests_count(force: true)).to eq 1 4664 end 4665 end 4666 4667 describe '#review_requested_open_merge_requests_count' do 4668 it 'returns number of open merge requests from non-archived projects' do 4669 user = create(:user) 4670 project = create(:project, :public) 4671 archived_project = create(:project, :public, :archived) 4672 4673 create(:merge_request, source_project: project, author: user, reviewers: [user]) 4674 create(:merge_request, :closed, source_project: project, author: user, reviewers: [user]) 4675 create(:merge_request, source_project: archived_project, author: user, reviewers: [user]) 4676 4677 expect(user.review_requested_open_merge_requests_count(force: true)).to eq 1 4678 end 4679 end 4680 4681 describe '#assigned_open_issues_count' do 4682 it 'returns number of open issues from non-archived projects' do 4683 user = create(:user) 4684 project = create(:project, :public) 4685 archived_project = create(:project, :public, :archived) 4686 4687 create(:issue, project: project, author: user, assignees: [user]) 4688 create(:issue, :closed, project: project, author: user, assignees: [user]) 4689 create(:issue, project: archived_project, author: user, assignees: [user]) 4690 4691 expect(user.assigned_open_issues_count(force: true)).to eq 1 4692 end 4693 end 4694 4695 describe '#personal_projects_count' do 4696 it 'returns the number of personal projects using a single query' do 4697 user = build(:user) 4698 projects = double(:projects, count: 1) 4699 4700 expect(user).to receive(:personal_projects).and_return(projects) 4701 4702 expect(user.personal_projects_count).to eq(1) 4703 end 4704 end 4705 4706 describe '#projects_limit_left' do 4707 it 'returns the number of projects that can be created by the user' do 4708 user = build(:user) 4709 4710 allow(user).to receive(:projects_limit).and_return(10) 4711 allow(user).to receive(:personal_projects_count).and_return(5) 4712 4713 expect(user.projects_limit_left).to eq(5) 4714 end 4715 end 4716 4717 describe '#ensure_namespace_correct' do 4718 context 'for a new user' do 4719 let(:user) { build(:user) } 4720 4721 it 'creates the namespace' do 4722 expect(user.namespace).to be_nil 4723 4724 user.save! 4725 4726 expect(user.namespace).not_to be_nil 4727 expect(user.namespace).to be_kind_of(Namespaces::UserNamespace) 4728 end 4729 4730 it 'creates the namespace setting' do 4731 user.save! 4732 4733 expect(user.namespace.namespace_settings).to be_persisted 4734 end 4735 end 4736 4737 context 'for an existing user' do 4738 let(:username) { 'foo' } 4739 let(:user) { create(:user, username: username) } 4740 4741 context 'when the user is updated' do 4742 context 'when the username or name is changed' do 4743 let(:new_username) { 'bar' } 4744 4745 it 'changes the namespace (just to compare to when username is not changed)' do 4746 expect do 4747 travel_to(1.second.from_now) do 4748 user.update!(username: new_username) 4749 end 4750 end.to change { user.namespace.updated_at } 4751 end 4752 4753 it 'updates the namespace path when the username was changed' do 4754 user.update!(username: new_username) 4755 4756 expect(user.namespace.path).to eq(new_username) 4757 end 4758 4759 it 'updates the namespace name if the name was changed' do 4760 user.update!(name: 'New name') 4761 4762 expect(user.namespace.name).to eq('New name') 4763 end 4764 4765 it 'updates nested routes for the namespace if the name was changed' do 4766 project = create(:project, namespace: user.namespace) 4767 4768 user.update!(name: 'New name') 4769 4770 expect(project.route.reload.name).to include('New name') 4771 end 4772 4773 context 'when there is a validation error (namespace name taken) while updating namespace' do 4774 let!(:conflicting_namespace) { create(:group, path: new_username) } 4775 4776 it 'causes the user save to fail' do 4777 expect(user.update(username: new_username)).to be_falsey 4778 expect(user.namespace.errors.messages[:path].first).to eq(_('has already been taken')) 4779 end 4780 4781 it 'adds the namespace errors to the user' do 4782 user.username = new_username 4783 4784 expect(user).to be_invalid 4785 expect(user.errors[:base]).to include('A user, alias, or group already exists with that username.') 4786 end 4787 end 4788 end 4789 4790 context 'when the username is not changed' do 4791 it 'does not change the namespace' do 4792 expect do 4793 user.update!(email: 'asdf@asdf.com') 4794 end.not_to change { user.namespace.updated_at } 4795 end 4796 end 4797 end 4798 end 4799 end 4800 4801 describe '#username_changed_hook' do 4802 context 'for a new user' do 4803 let(:user) { build(:user) } 4804 4805 it 'does not trigger system hook' do 4806 expect(user).not_to receive(:system_hook_service) 4807 4808 user.save! 4809 end 4810 end 4811 4812 context 'for an existing user' do 4813 let(:user) { create(:user, username: 'old-username') } 4814 4815 context 'when the username is changed' do 4816 let(:new_username) { 'very-new-name' } 4817 4818 it 'triggers the rename system hook' do 4819 system_hook_service = SystemHooksService.new 4820 expect(system_hook_service).to receive(:execute_hooks_for).with(user, :rename) 4821 expect(user).to receive(:system_hook_service).and_return(system_hook_service) 4822 4823 user.update!(username: new_username) 4824 end 4825 end 4826 4827 context 'when the username is not changed' do 4828 it 'does not trigger system hook' do 4829 expect(user).not_to receive(:system_hook_service) 4830 4831 user.update!(email: 'asdf@asdf.com') 4832 end 4833 end 4834 end 4835 end 4836 4837 describe '#will_save_change_to_login?' do 4838 let(:user) { create(:user, username: 'old-username', email: 'old-email@example.org') } 4839 let(:new_username) { 'new-name' } 4840 let(:new_email) { 'new-email@example.org' } 4841 4842 subject { user.will_save_change_to_login? } 4843 4844 context 'when the username is changed' do 4845 before do 4846 user.username = new_username 4847 end 4848 4849 it { is_expected.to be true } 4850 end 4851 4852 context 'when the email is changed' do 4853 before do 4854 user.email = new_email 4855 end 4856 4857 it { is_expected.to be true } 4858 end 4859 4860 context 'when both email and username are changed' do 4861 before do 4862 user.username = new_username 4863 user.email = new_email 4864 end 4865 4866 it { is_expected.to be true } 4867 end 4868 4869 context "when email and username aren't changed" do 4870 before do 4871 user.name = 'new_name' 4872 end 4873 4874 it { is_expected.to be_falsy } 4875 end 4876 end 4877 4878 describe '#sync_attribute?' do 4879 let(:user) { described_class.new } 4880 4881 context 'oauth user' do 4882 it 'returns true if name can be synced' do 4883 stub_omniauth_setting(sync_profile_attributes: %w(name location)) 4884 4885 expect(user.sync_attribute?(:name)).to be_truthy 4886 end 4887 4888 it 'returns true if email can be synced' do 4889 stub_omniauth_setting(sync_profile_attributes: %w(name email)) 4890 4891 expect(user.sync_attribute?(:email)).to be_truthy 4892 end 4893 4894 it 'returns true if location can be synced' do 4895 stub_omniauth_setting(sync_profile_attributes: %w(location email)) 4896 4897 expect(user.sync_attribute?(:email)).to be_truthy 4898 end 4899 4900 it 'returns false if name can not be synced' do 4901 stub_omniauth_setting(sync_profile_attributes: %w(location email)) 4902 4903 expect(user.sync_attribute?(:name)).to be_falsey 4904 end 4905 4906 it 'returns false if email can not be synced' do 4907 stub_omniauth_setting(sync_profile_attributes: %w(location name)) 4908 4909 expect(user.sync_attribute?(:email)).to be_falsey 4910 end 4911 4912 it 'returns false if location can not be synced' do 4913 stub_omniauth_setting(sync_profile_attributes: %w(name email)) 4914 4915 expect(user.sync_attribute?(:location)).to be_falsey 4916 end 4917 4918 it 'returns true for all syncable attributes if all syncable attributes can be synced' do 4919 stub_omniauth_setting(sync_profile_attributes: true) 4920 4921 expect(user.sync_attribute?(:name)).to be_truthy 4922 expect(user.sync_attribute?(:email)).to be_truthy 4923 expect(user.sync_attribute?(:location)).to be_truthy 4924 end 4925 4926 it 'returns false for all syncable attributes but email if no syncable attributes are declared' do 4927 expect(user.sync_attribute?(:name)).to be_falsey 4928 expect(user.sync_attribute?(:email)).to be_truthy 4929 expect(user.sync_attribute?(:location)).to be_falsey 4930 end 4931 end 4932 4933 context 'ldap user' do 4934 it 'returns true for email if ldap user' do 4935 allow(user).to receive(:ldap_user?).and_return(true) 4936 4937 expect(user.sync_attribute?(:name)).to be_falsey 4938 expect(user.sync_attribute?(:email)).to be_truthy 4939 expect(user.sync_attribute?(:location)).to be_falsey 4940 end 4941 4942 it 'returns true for email and location if ldap user and location declared as syncable' do 4943 allow(user).to receive(:ldap_user?).and_return(true) 4944 stub_omniauth_setting(sync_profile_attributes: %w(location)) 4945 4946 expect(user.sync_attribute?(:name)).to be_falsey 4947 expect(user.sync_attribute?(:email)).to be_truthy 4948 expect(user.sync_attribute?(:location)).to be_truthy 4949 end 4950 end 4951 end 4952 4953 describe '#confirm_deletion_with_password?' do 4954 where( 4955 password_automatically_set: [true, false], 4956 ldap_user: [true, false], 4957 password_authentication_disabled: [true, false] 4958 ) 4959 4960 with_them do 4961 let!(:user) { create(:user, password_automatically_set: password_automatically_set) } 4962 let!(:identity) { create(:identity, user: user) if ldap_user } 4963 4964 # Only confirm deletion with password if all inputs are false 4965 let(:expected) { !(password_automatically_set || ldap_user || password_authentication_disabled) } 4966 4967 before do 4968 stub_application_setting(password_authentication_enabled_for_web: !password_authentication_disabled) 4969 stub_application_setting(password_authentication_enabled_for_git: !password_authentication_disabled) 4970 end 4971 4972 it 'returns false unless all inputs are true' do 4973 expect(user.confirm_deletion_with_password?).to eq(expected) 4974 end 4975 end 4976 end 4977 4978 describe '#delete_async' do 4979 let(:user) { create(:user) } 4980 let(:deleted_by) { create(:user) } 4981 4982 it 'blocks the user then schedules them for deletion if a hard delete is specified' do 4983 expect(DeleteUserWorker).to receive(:perform_async).with(deleted_by.id, user.id, hard_delete: true) 4984 4985 user.delete_async(deleted_by: deleted_by, params: { hard_delete: true }) 4986 4987 expect(user).to be_blocked 4988 end 4989 4990 it 'schedules user for deletion without blocking them' do 4991 expect(DeleteUserWorker).to receive(:perform_async).with(deleted_by.id, user.id, {}) 4992 4993 user.delete_async(deleted_by: deleted_by) 4994 4995 expect(user).not_to be_blocked 4996 end 4997 end 4998 4999 describe '#max_member_access_for_project_ids' do 5000 shared_examples 'max member access for projects' do 5001 let(:user) { create(:user) } 5002 let(:group) { create(:group) } 5003 let(:owner_project) { create(:project, group: group) } 5004 let(:maintainer_project) { create(:project) } 5005 let(:reporter_project) { create(:project) } 5006 let(:developer_project) { create(:project) } 5007 let(:guest_project) { create(:project) } 5008 let(:no_access_project) { create(:project) } 5009 5010 let(:projects) do 5011 [owner_project, maintainer_project, reporter_project, developer_project, guest_project, no_access_project].map(&:id) 5012 end 5013 5014 let(:expected) do 5015 { 5016 owner_project.id => Gitlab::Access::OWNER, 5017 maintainer_project.id => Gitlab::Access::MAINTAINER, 5018 reporter_project.id => Gitlab::Access::REPORTER, 5019 developer_project.id => Gitlab::Access::DEVELOPER, 5020 guest_project.id => Gitlab::Access::GUEST, 5021 no_access_project.id => Gitlab::Access::NO_ACCESS 5022 } 5023 end 5024 5025 before do 5026 create(:group_member, user: user, group: group) 5027 maintainer_project.add_maintainer(user) 5028 reporter_project.add_reporter(user) 5029 developer_project.add_developer(user) 5030 guest_project.add_guest(user) 5031 end 5032 5033 it 'returns correct roles for different projects' do 5034 expect(user.max_member_access_for_project_ids(projects)).to eq(expected) 5035 end 5036 end 5037 5038 context 'with RequestStore enabled', :request_store do 5039 include_examples 'max member access for projects' 5040 5041 def access_levels(projects) 5042 user.max_member_access_for_project_ids(projects) 5043 end 5044 5045 it 'does not perform extra queries when asked for projects who have already been found' do 5046 access_levels(projects) 5047 5048 expect { access_levels(projects) }.not_to exceed_query_limit(0) 5049 5050 expect(access_levels(projects)).to eq(expected) 5051 end 5052 5053 it 'only requests the extra projects when uncached projects are passed' do 5054 second_maintainer_project = create(:project) 5055 second_developer_project = create(:project) 5056 second_maintainer_project.add_maintainer(user) 5057 second_developer_project.add_developer(user) 5058 5059 all_projects = projects + [second_maintainer_project.id, second_developer_project.id] 5060 5061 expected_all = expected.merge(second_maintainer_project.id => Gitlab::Access::MAINTAINER, 5062 second_developer_project.id => Gitlab::Access::DEVELOPER) 5063 5064 access_levels(projects) 5065 5066 queries = ActiveRecord::QueryRecorder.new { access_levels(all_projects) } 5067 5068 expect(queries.count).to eq(1) 5069 expect(queries.log_message).to match(/\W(#{second_maintainer_project.id}, #{second_developer_project.id})\W/) 5070 expect(access_levels(all_projects)).to eq(expected_all) 5071 end 5072 end 5073 5074 context 'with RequestStore disabled' do 5075 include_examples 'max member access for projects' 5076 end 5077 end 5078 5079 describe '#max_member_access_for_group_ids' do 5080 shared_examples 'max member access for groups' do 5081 let(:user) { create(:user) } 5082 let(:owner_group) { create(:group) } 5083 let(:maintainer_group) { create(:group) } 5084 let(:reporter_group) { create(:group) } 5085 let(:developer_group) { create(:group) } 5086 let(:guest_group) { create(:group) } 5087 let(:no_access_group) { create(:group) } 5088 5089 let(:groups) do 5090 [owner_group, maintainer_group, reporter_group, developer_group, guest_group, no_access_group].map(&:id) 5091 end 5092 5093 let(:expected) do 5094 { 5095 owner_group.id => Gitlab::Access::OWNER, 5096 maintainer_group.id => Gitlab::Access::MAINTAINER, 5097 reporter_group.id => Gitlab::Access::REPORTER, 5098 developer_group.id => Gitlab::Access::DEVELOPER, 5099 guest_group.id => Gitlab::Access::GUEST, 5100 no_access_group.id => Gitlab::Access::NO_ACCESS 5101 } 5102 end 5103 5104 before do 5105 owner_group.add_owner(user) 5106 maintainer_group.add_maintainer(user) 5107 reporter_group.add_reporter(user) 5108 developer_group.add_developer(user) 5109 guest_group.add_guest(user) 5110 end 5111 5112 it 'returns correct roles for different groups' do 5113 expect(user.max_member_access_for_group_ids(groups)).to eq(expected) 5114 end 5115 end 5116 5117 context 'with RequestStore enabled', :request_store do 5118 include_examples 'max member access for groups' 5119 5120 def access_levels(groups) 5121 user.max_member_access_for_group_ids(groups) 5122 end 5123 5124 it 'does not perform extra queries when asked for groups who have already been found' do 5125 access_levels(groups) 5126 5127 expect { access_levels(groups) }.not_to exceed_query_limit(0) 5128 5129 expect(access_levels(groups)).to eq(expected) 5130 end 5131 5132 it 'only requests the extra groups when uncached groups are passed' do 5133 second_maintainer_group = create(:group) 5134 second_developer_group = create(:group) 5135 second_maintainer_group.add_maintainer(user) 5136 second_developer_group.add_developer(user) 5137 5138 all_groups = groups + [second_maintainer_group.id, second_developer_group.id] 5139 5140 expected_all = expected.merge(second_maintainer_group.id => Gitlab::Access::MAINTAINER, 5141 second_developer_group.id => Gitlab::Access::DEVELOPER) 5142 5143 access_levels(groups) 5144 5145 queries = ActiveRecord::QueryRecorder.new { access_levels(all_groups) } 5146 5147 expect(queries.count).to eq(1) 5148 expect(queries.log_message).to match(/\W(#{second_maintainer_group.id}, #{second_developer_group.id})\W/) 5149 expect(access_levels(all_groups)).to eq(expected_all) 5150 end 5151 end 5152 5153 context 'with RequestStore disabled' do 5154 include_examples 'max member access for groups' 5155 end 5156 end 5157 5158 context 'changing a username' do 5159 let(:user) { create(:user, username: 'foo') } 5160 5161 it 'creates a redirect route' do 5162 expect { user.update!(username: 'bar') } 5163 .to change { RedirectRoute.where(path: 'foo').count }.by(1) 5164 end 5165 5166 it 'deletes the redirect when a user with the old username was created' do 5167 user.update!(username: 'bar') 5168 5169 expect { create(:user, username: 'foo') } 5170 .to change { RedirectRoute.where(path: 'foo').count }.by(-1) 5171 end 5172 end 5173 5174 describe '#required_terms_not_accepted?' do 5175 let(:user) { build(:user) } 5176 let(:project_bot) { create(:user, :project_bot) } 5177 5178 subject { user.required_terms_not_accepted? } 5179 5180 context 'when terms are not enforced' do 5181 it { is_expected.to be_falsey } 5182 end 5183 5184 context 'when terms are enforced' do 5185 before do 5186 enforce_terms 5187 end 5188 5189 it 'is not accepted by the user' do 5190 expect(subject).to be_truthy 5191 end 5192 5193 it 'is accepted by the user' do 5194 accept_terms(user) 5195 5196 expect(subject).to be_falsey 5197 end 5198 5199 it 'auto accepts the term for project bots' do 5200 expect(project_bot.required_terms_not_accepted?).to be_falsey 5201 end 5202 end 5203 end 5204 5205 describe '#increment_failed_attempts!' do 5206 subject(:user) { create(:user, failed_attempts: 0) } 5207 5208 it 'logs failed sign-in attempts' do 5209 expect { user.increment_failed_attempts! }.to change(user, :failed_attempts).from(0).to(1) 5210 end 5211 5212 it 'does not log failed sign-in attempts when in a GitLab read-only instance' do 5213 allow(Gitlab::Database).to receive(:read_only?) { true } 5214 5215 expect { user.increment_failed_attempts! }.not_to change(user, :failed_attempts) 5216 end 5217 end 5218 5219 describe '#requires_usage_stats_consent?' do 5220 let(:user) { create(:user, :admin, created_at: 8.days.ago) } 5221 5222 before do 5223 allow(user).to receive(:has_current_license?).and_return false 5224 end 5225 5226 context 'in single-user environment' do 5227 it 'requires user consent after one week' do 5228 create(:user, :ghost) 5229 5230 expect(user.requires_usage_stats_consent?).to be true 5231 end 5232 5233 it 'requires user consent after one week if there is another ghost user' do 5234 expect(user.requires_usage_stats_consent?).to be true 5235 end 5236 5237 it 'does not require consent in the first week' do 5238 user.created_at = 6.days.ago 5239 5240 expect(user.requires_usage_stats_consent?).to be false 5241 end 5242 5243 it 'does not require consent if usage stats were set by this user' do 5244 create(:application_setting, usage_stats_set_by_user_id: user.id) 5245 5246 expect(user.requires_usage_stats_consent?).to be false 5247 end 5248 end 5249 5250 context 'in multi-user environment' do 5251 before do 5252 create(:user) 5253 end 5254 5255 it 'does not require consent' do 5256 expect(user.requires_usage_stats_consent?).to be false 5257 end 5258 end 5259 end 5260 5261 context 'with uploads' do 5262 it_behaves_like 'model with uploads', false do 5263 let(:model_object) { create(:user, :with_avatar) } 5264 let(:upload_attribute) { :avatar } 5265 let(:uploader_class) { AttachmentUploader } 5266 end 5267 end 5268 5269 describe '.union_with_user' do 5270 context 'when no user ID is provided' do 5271 it 'returns the input relation' do 5272 user = create(:user) 5273 5274 expect(described_class.union_with_user).to eq([user]) 5275 end 5276 end 5277 5278 context 'when a user ID is provided' do 5279 it 'includes the user object in the returned relation' do 5280 user1 = create(:user) 5281 user2 = create(:user) 5282 users = described_class.where(id: user1.id).union_with_user(user2.id) 5283 5284 expect(users).to include(user1) 5285 expect(users).to include(user2) 5286 end 5287 5288 it 'does not re-apply any WHERE conditions on the outer query' do 5289 relation = described_class.where(id: 1).union_with_user(2) 5290 5291 expect(relation.arel.where_sql).to be_nil 5292 end 5293 end 5294 end 5295 5296 describe '.optionally_search' do 5297 context 'using nil as the argument' do 5298 it 'returns the current relation' do 5299 user = create(:user) 5300 5301 expect(described_class.optionally_search).to eq([user]) 5302 end 5303 end 5304 5305 context 'using an empty String as the argument' do 5306 it 'returns the current relation' do 5307 user = create(:user) 5308 5309 expect(described_class.optionally_search('')).to eq([user]) 5310 end 5311 end 5312 5313 context 'using a non-empty String' do 5314 it 'returns users matching the search query' do 5315 user1 = create(:user) 5316 create(:user) 5317 5318 expect(described_class.optionally_search(user1.name)).to eq([user1]) 5319 end 5320 end 5321 end 5322 5323 describe '.where_not_in' do 5324 context 'without an argument' do 5325 it 'returns the current relation' do 5326 user = create(:user) 5327 5328 expect(described_class.where_not_in).to eq([user]) 5329 end 5330 end 5331 5332 context 'using a list of user IDs' do 5333 it 'excludes the users from the returned relation' do 5334 user1 = create(:user) 5335 user2 = create(:user) 5336 5337 expect(described_class.where_not_in([user2.id])).to eq([user1]) 5338 end 5339 end 5340 end 5341 5342 describe '.reorder_by_name' do 5343 it 'reorders the input relation' do 5344 user1 = create(:user, name: 'A') 5345 user2 = create(:user, name: 'B') 5346 5347 expect(described_class.reorder_by_name).to eq([user1, user2]) 5348 end 5349 end 5350 5351 describe '#notification_settings_for' do 5352 let(:user) { create(:user) } 5353 let(:source) { nil } 5354 5355 subject { user.notification_settings_for(source) } 5356 5357 context 'when source is nil' do 5358 it 'returns a blank global notification settings object' do 5359 expect(subject.source).to eq(nil) 5360 expect(subject.notification_email).to eq(nil) 5361 expect(subject.level).to eq('global') 5362 end 5363 end 5364 5365 context 'when source is a Group' do 5366 let(:group) { create(:group) } 5367 5368 subject { user.notification_settings_for(group, inherit: true) } 5369 5370 context 'when group has no existing notification settings' do 5371 context 'when group has no ancestors' do 5372 it 'will be a default Global notification setting' do 5373 expect(subject.notification_email).to eq(nil) 5374 expect(subject.level).to eq('global') 5375 end 5376 end 5377 5378 context 'when group has ancestors' do 5379 context 'when an ancestor has a level other than Global' do 5380 let(:ancestor) { create(:group) } 5381 let(:group) { create(:group, parent: ancestor) } 5382 let(:email) { create(:email, :confirmed, email: 'ancestor@example.com', user: user) } 5383 5384 before do 5385 create(:notification_setting, user: user, source: ancestor, level: 'participating', notification_email: email.email) 5386 end 5387 5388 it 'has the same level set' do 5389 expect(subject.level).to eq('participating') 5390 end 5391 5392 it 'has the same email set' do 5393 expect(subject.notification_email).to eq('ancestor@example.com') 5394 end 5395 5396 context 'when inherit is false' do 5397 subject { user.notification_settings_for(group) } 5398 5399 it 'does not inherit settings' do 5400 expect(subject.notification_email).to eq(nil) 5401 expect(subject.level).to eq('global') 5402 end 5403 end 5404 end 5405 5406 context 'when an ancestor has a Global level but has an email set' do 5407 let(:grand_ancestor) { create(:group) } 5408 let(:ancestor) { create(:group, parent: grand_ancestor) } 5409 let(:group) { create(:group, parent: ancestor) } 5410 let(:ancestor_email) { create(:email, :confirmed, email: 'ancestor@example.com', user: user) } 5411 let(:grand_email) { create(:email, :confirmed, email: 'grand@example.com', user: user) } 5412 5413 before do 5414 create(:notification_setting, user: user, source: grand_ancestor, level: 'participating', notification_email: grand_email.email) 5415 create(:notification_setting, user: user, source: ancestor, level: 'global', notification_email: ancestor_email.email) 5416 end 5417 5418 it 'has the same email set' do 5419 expect(subject.level).to eq('global') 5420 expect(subject.notification_email).to eq('ancestor@example.com') 5421 end 5422 end 5423 end 5424 end 5425 end 5426 end 5427 5428 describe '#notification_settings_for_groups' do 5429 let_it_be(:user) { create(:user) } 5430 let_it_be(:groups) { create_list(:group, 2) } 5431 5432 subject { user.notification_settings_for_groups(arg) } 5433 5434 before do 5435 groups.each do |group| 5436 group.add_maintainer(user) 5437 end 5438 end 5439 5440 shared_examples_for 'notification_settings_for_groups method' do 5441 it 'returns NotificationSetting objects for provided groups', :aggregate_failures do 5442 expect(subject.count).to eq(groups.count) 5443 expect(subject.map(&:source_id)).to match_array(groups.map(&:id)) 5444 end 5445 end 5446 5447 context 'when given an ActiveRecord relationship' do 5448 let_it_be(:arg) { Group.where(id: groups.map(&:id)) } 5449 5450 it_behaves_like 'notification_settings_for_groups method' 5451 5452 it 'uses #select to maintain lazy querying behavior' do 5453 expect(arg).to receive(:select).and_call_original 5454 5455 subject 5456 end 5457 end 5458 5459 context 'when given an Array of Groups' do 5460 let_it_be(:arg) { groups } 5461 5462 it_behaves_like 'notification_settings_for_groups method' 5463 end 5464 end 5465 5466 describe '#notification_email_for' do 5467 let(:user) { create(:user) } 5468 let(:group) { create(:group) } 5469 5470 subject { user.notification_email_for(group) } 5471 5472 context 'when group is nil' do 5473 let(:group) { nil } 5474 5475 it 'returns global notification email' do 5476 is_expected.to eq(user.notification_email_or_default) 5477 end 5478 end 5479 5480 context 'when group has no notification email set' do 5481 it 'returns global notification email' do 5482 create(:notification_setting, user: user, source: group, notification_email: '') 5483 5484 is_expected.to eq(user.notification_email_or_default) 5485 end 5486 end 5487 5488 context 'when group has notification email set' do 5489 it 'returns group notification email' do 5490 group_notification_email = 'user+group@example.com' 5491 create(:email, :confirmed, user: user, email: group_notification_email) 5492 create(:notification_setting, user: user, source: group, notification_email: group_notification_email) 5493 5494 is_expected.to eq(group_notification_email) 5495 end 5496 end 5497 end 5498 5499 describe '#password_expired?' do 5500 let(:user) { build(:user, password_expires_at: password_expires_at) } 5501 5502 subject { user.password_expired? } 5503 5504 context 'when password_expires_at is not set' do 5505 let(:password_expires_at) {} 5506 5507 it 'returns false' do 5508 is_expected.to be_falsey 5509 end 5510 end 5511 5512 context 'when password_expires_at is in the past' do 5513 let(:password_expires_at) { 1.minute.ago } 5514 5515 it 'returns true' do 5516 is_expected.to be_truthy 5517 end 5518 end 5519 5520 context 'when password_expires_at is in the future' do 5521 let(:password_expires_at) { 1.minute.from_now } 5522 5523 it 'returns false' do 5524 is_expected.to be_falsey 5525 end 5526 end 5527 end 5528 5529 describe '#password_expired_if_applicable?' do 5530 let(:user) { build(:user, password_expires_at: password_expires_at) } 5531 5532 subject { user.password_expired_if_applicable? } 5533 5534 shared_examples 'password expired not applicable' do 5535 context 'when password_expires_at is not set' do 5536 let(:password_expires_at) {} 5537 5538 it 'returns false' do 5539 is_expected.to be_falsey 5540 end 5541 end 5542 5543 context 'when password_expires_at is in the past' do 5544 let(:password_expires_at) { 1.minute.ago } 5545 5546 it 'returns false' do 5547 is_expected.to be_falsey 5548 end 5549 end 5550 5551 context 'when password_expires_at is in the future' do 5552 let(:password_expires_at) { 1.minute.from_now } 5553 5554 it 'returns false' do 5555 is_expected.to be_falsey 5556 end 5557 end 5558 end 5559 5560 context 'with a regular user' do 5561 context 'when password_expires_at is not set' do 5562 let(:password_expires_at) {} 5563 5564 it 'returns false' do 5565 is_expected.to be_falsey 5566 end 5567 end 5568 5569 context 'when password_expires_at is in the past' do 5570 let(:password_expires_at) { 1.minute.ago } 5571 5572 it 'returns true' do 5573 is_expected.to be_truthy 5574 end 5575 end 5576 5577 context 'when password_expires_at is in the future' do 5578 let(:password_expires_at) { 1.minute.from_now } 5579 5580 it 'returns false' do 5581 is_expected.to be_falsey 5582 end 5583 end 5584 end 5585 5586 context 'when user is a bot' do 5587 before do 5588 allow(user).to receive(:bot?).and_return(true) 5589 end 5590 5591 it_behaves_like 'password expired not applicable' 5592 end 5593 5594 context 'when password_automatically_set is true' do 5595 let(:user) { create(:omniauth_user, provider: 'ldap')} 5596 5597 it_behaves_like 'password expired not applicable' 5598 end 5599 5600 context 'when allow_password_authentication is false' do 5601 before do 5602 allow(user).to receive(:allow_password_authentication?).and_return(false) 5603 end 5604 5605 it_behaves_like 'password expired not applicable' 5606 end 5607 end 5608 5609 describe '#read_only_attribute?' do 5610 context 'when synced attributes metadata is present' do 5611 it 'delegates to synced_attributes_metadata' do 5612 subject.build_user_synced_attributes_metadata 5613 5614 expect(subject.build_user_synced_attributes_metadata) 5615 .to receive(:read_only?).with(:email).and_return('return-value') 5616 expect(subject.read_only_attribute?(:email)).to eq('return-value') 5617 end 5618 end 5619 5620 context 'when synced attributes metadata is not present' do 5621 it 'is false for any attribute' do 5622 expect(subject.read_only_attribute?(:email)).to be_falsey 5623 end 5624 end 5625 end 5626 5627 describe '.active_without_ghosts' do 5628 let_it_be(:user1) { create(:user, :external) } 5629 let_it_be(:user2) { create(:user, state: 'blocked') } 5630 let_it_be(:user3) { create(:user, :ghost) } 5631 let_it_be(:user4) { create(:user, user_type: :support_bot) } 5632 let_it_be(:user5) { create(:user, state: 'blocked', user_type: :support_bot) } 5633 let_it_be(:user6) { create(:user, user_type: :automation_bot) } 5634 5635 it 'returns all active users including active bots but ghost users' do 5636 expect(described_class.active_without_ghosts).to match_array([user1, user4, user6]) 5637 end 5638 end 5639 5640 describe '#dismissed_callout?' do 5641 let_it_be(:user, refind: true) { create(:user) } 5642 let_it_be(:feature_name) { Users::Callout.feature_names.each_key.first } 5643 5644 context 'when no callout dismissal record exists' do 5645 it 'returns false when no ignore_dismissal_earlier_than provided' do 5646 expect(user.dismissed_callout?(feature_name: feature_name)).to eq false 5647 end 5648 end 5649 5650 context 'when dismissed callout exists' do 5651 before_all do 5652 create(:callout, user: user, feature_name: feature_name, dismissed_at: 4.months.ago) 5653 end 5654 5655 it 'returns true when no ignore_dismissal_earlier_than provided' do 5656 expect(user.dismissed_callout?(feature_name: feature_name)).to eq true 5657 end 5658 5659 it 'returns true when ignore_dismissal_earlier_than is earlier than dismissed_at' do 5660 expect(user.dismissed_callout?(feature_name: feature_name, ignore_dismissal_earlier_than: 6.months.ago)).to eq true 5661 end 5662 5663 it 'returns false when ignore_dismissal_earlier_than is later than dismissed_at' do 5664 expect(user.dismissed_callout?(feature_name: feature_name, ignore_dismissal_earlier_than: 3.months.ago)).to eq false 5665 end 5666 end 5667 end 5668 5669 describe '#find_or_initialize_callout' do 5670 let_it_be(:user, refind: true) { create(:user) } 5671 let_it_be(:feature_name) { Users::Callout.feature_names.each_key.first } 5672 5673 subject(:find_or_initialize_callout) { user.find_or_initialize_callout(feature_name) } 5674 5675 context 'when callout exists' do 5676 let!(:callout) { create(:callout, user: user, feature_name: feature_name) } 5677 5678 it 'returns existing callout' do 5679 expect(find_or_initialize_callout).to eq(callout) 5680 end 5681 end 5682 5683 context 'when callout does not exist' do 5684 context 'when feature name is valid' do 5685 it 'initializes a new callout' do 5686 expect(find_or_initialize_callout).to be_a_new(Users::Callout) 5687 end 5688 5689 it 'is valid' do 5690 expect(find_or_initialize_callout).to be_valid 5691 end 5692 end 5693 5694 context 'when feature name is not valid' do 5695 let(:feature_name) { 'notvalid' } 5696 5697 it 'initializes a new callout' do 5698 expect(find_or_initialize_callout).to be_a_new(Users::Callout) 5699 end 5700 5701 it 'is not valid' do 5702 expect(find_or_initialize_callout).not_to be_valid 5703 end 5704 end 5705 end 5706 end 5707 5708 describe '#dismissed_callout_for_group?' do 5709 let_it_be(:user, refind: true) { create(:user) } 5710 let_it_be(:group) { create(:group) } 5711 let_it_be(:feature_name) { Users::GroupCallout.feature_names.each_key.first } 5712 5713 context 'when no callout dismissal record exists' do 5714 it 'returns false when no ignore_dismissal_earlier_than provided' do 5715 expect(user.dismissed_callout_for_group?(feature_name: feature_name, group: group)).to eq false 5716 end 5717 end 5718 5719 context 'when dismissed callout exists' do 5720 before_all do 5721 create(:group_callout, 5722 user: user, 5723 group_id: group.id, 5724 feature_name: feature_name, 5725 dismissed_at: 4.months.ago) 5726 end 5727 5728 it 'returns true when no ignore_dismissal_earlier_than provided' do 5729 expect(user.dismissed_callout_for_group?(feature_name: feature_name, group: group)).to eq true 5730 end 5731 5732 it 'returns true when ignore_dismissal_earlier_than is earlier than dismissed_at' do 5733 expect(user.dismissed_callout_for_group?(feature_name: feature_name, group: group, ignore_dismissal_earlier_than: 6.months.ago)).to eq true 5734 end 5735 5736 it 'returns false when ignore_dismissal_earlier_than is later than dismissed_at' do 5737 expect(user.dismissed_callout_for_group?(feature_name: feature_name, group: group, ignore_dismissal_earlier_than: 3.months.ago)).to eq false 5738 end 5739 end 5740 end 5741 5742 describe '#find_or_initialize_group_callout' do 5743 let_it_be(:user, refind: true) { create(:user) } 5744 let_it_be(:group) { create(:group) } 5745 let_it_be(:feature_name) { Users::GroupCallout.feature_names.each_key.first } 5746 5747 subject(:callout_with_source) do 5748 user.find_or_initialize_group_callout(feature_name, group.id) 5749 end 5750 5751 context 'when callout exists' do 5752 let!(:callout) do 5753 create(:group_callout, user: user, feature_name: feature_name, group_id: group.id) 5754 end 5755 5756 it 'returns existing callout' do 5757 expect(callout_with_source).to eq(callout) 5758 end 5759 end 5760 5761 context 'when callout does not exist' do 5762 context 'when feature name is valid' do 5763 it 'initializes a new callout' do 5764 expect(callout_with_source).to be_a_new(Users::GroupCallout) 5765 end 5766 5767 it 'is valid' do 5768 expect(callout_with_source).to be_valid 5769 end 5770 end 5771 5772 context 'when feature name is not valid' do 5773 let(:feature_name) { 'notvalid' } 5774 5775 it 'initializes a new callout' do 5776 expect(callout_with_source).to be_a_new(Users::GroupCallout) 5777 end 5778 5779 it 'is not valid' do 5780 expect(callout_with_source).not_to be_valid 5781 end 5782 end 5783 end 5784 end 5785 5786 describe '#hook_attrs' do 5787 let(:user) { create(:user) } 5788 let(:user_attributes) do 5789 { 5790 id: user.id, 5791 name: user.name, 5792 username: user.username, 5793 avatar_url: user.avatar_url(only_path: false) 5794 } 5795 end 5796 5797 context 'with a public email' do 5798 it 'includes id, name, username, avatar_url, and email' do 5799 user.public_email = "hello@hello.com" 5800 user_attributes[:email] = user.public_email 5801 expect(user.hook_attrs).to eq(user_attributes) 5802 end 5803 end 5804 5805 context 'without a public email' do 5806 it "does not include email if user's email is private" do 5807 user_attributes[:email] = "[REDACTED]" 5808 expect(user.hook_attrs).to eq(user_attributes) 5809 end 5810 end 5811 end 5812 5813 describe 'user credit card validation' do 5814 context 'when user is initialized' do 5815 let(:user) { build(:user) } 5816 5817 it { expect(user.credit_card_validation).not_to be_present } 5818 end 5819 5820 context 'when create user without credit card validation' do 5821 let(:user) { create(:user) } 5822 5823 it { expect(user.credit_card_validation).not_to be_present } 5824 end 5825 5826 context 'when user credit card validation exists' do 5827 let(:user) { create(:user, :with_credit_card_validation) } 5828 5829 it { expect(user.credit_card_validation).to be_persisted } 5830 end 5831 end 5832 5833 describe 'user detail' do 5834 context 'when user is initialized' do 5835 let(:user) { build(:user) } 5836 5837 it { expect(user.user_detail).to be_present } 5838 it { expect(user.user_detail).not_to be_persisted } 5839 end 5840 5841 context 'when user detail exists' do 5842 let(:user) { create(:user, job_title: 'Engineer') } 5843 5844 it { expect(user.user_detail).to be_persisted } 5845 end 5846 end 5847 5848 describe '#current_highest_access_level' do 5849 let_it_be(:user) { create(:user) } 5850 5851 context 'when no memberships exist' do 5852 it 'returns nil' do 5853 expect(user.current_highest_access_level).to be_nil 5854 end 5855 end 5856 5857 context 'when memberships exist' do 5858 it 'returns the highest access level for non requested memberships' do 5859 create(:group_member, :reporter, user_id: user.id) 5860 create(:project_member, :guest, user_id: user.id) 5861 create(:project_member, :maintainer, user_id: user.id, requested_at: Time.current) 5862 5863 expect(user.current_highest_access_level).to eq(Gitlab::Access::REPORTER) 5864 end 5865 end 5866 end 5867 5868 context 'when after_commit :update_highest_role' do 5869 describe 'create user' do 5870 subject { create(:user) } 5871 5872 it 'schedules a job in the future', :aggregate_failures, :clean_gitlab_redis_shared_state do 5873 allow_next_instance_of(Gitlab::ExclusiveLease) do |instance| 5874 allow(instance).to receive(:try_obtain).and_return('uuid') 5875 end 5876 5877 expect(UpdateHighestRoleWorker).to receive(:perform_in).and_call_original 5878 5879 expect { subject }.to change(UpdateHighestRoleWorker.jobs, :size).by(1) 5880 end 5881 end 5882 5883 context 'when user already exists' do 5884 let!(:user) { create(:user) } 5885 let(:user_id) { user.id } 5886 5887 describe 'update user' do 5888 using RSpec::Parameterized::TableSyntax 5889 5890 where(:attributes) do 5891 [ 5892 { state: 'blocked' }, 5893 { user_type: :ghost }, 5894 { user_type: :alert_bot }, 5895 { user_type: :support_bot }, 5896 { user_type: :security_bot }, 5897 { user_type: :automation_bot } 5898 ] 5899 end 5900 5901 with_them do 5902 context 'when state was changed' do 5903 subject { user.update!(attributes) } 5904 5905 include_examples 'update highest role with exclusive lease' 5906 end 5907 end 5908 5909 context 'when state was not changed' do 5910 subject { user.update!(email: 'newmail@example.com') } 5911 5912 include_examples 'does not update the highest role' 5913 end 5914 end 5915 5916 describe 'destroy user' do 5917 subject { user.destroy! } 5918 5919 include_examples 'does not update the highest role' 5920 end 5921 end 5922 end 5923 5924 describe '#active_for_authentication?' do 5925 subject(:active_for_authentication?) { user.active_for_authentication? } 5926 5927 let(:user) { create(:user) } 5928 5929 context 'when user is blocked' do 5930 before do 5931 user.block 5932 end 5933 5934 it { is_expected.to be false } 5935 5936 it 'does not check if LDAP is allowed' do 5937 stub_ldap_setting(enabled: true) 5938 5939 expect(Gitlab::Auth::Ldap::Access).not_to receive(:allowed?) 5940 5941 active_for_authentication? 5942 end 5943 end 5944 5945 context 'when user is a ghost user' do 5946 before do 5947 user.update!(user_type: :ghost) 5948 end 5949 5950 it { is_expected.to be false } 5951 end 5952 5953 context 'when user is ldap_blocked' do 5954 before do 5955 user.ldap_block 5956 end 5957 5958 it 'rechecks if LDAP is allowed when LDAP is enabled' do 5959 stub_ldap_setting(enabled: true) 5960 5961 expect(Gitlab::Auth::Ldap::Access).to receive(:allowed?) 5962 5963 active_for_authentication? 5964 end 5965 5966 it 'does not check if LDAP is allowed when LDAP is not enabled' do 5967 stub_ldap_setting(enabled: false) 5968 5969 expect(Gitlab::Auth::Ldap::Access).not_to receive(:allowed?) 5970 5971 active_for_authentication? 5972 end 5973 end 5974 5975 context 'based on user type' do 5976 using RSpec::Parameterized::TableSyntax 5977 5978 where(:user_type, :expected_result) do 5979 'human' | true 5980 'alert_bot' | false 5981 'support_bot' | false 5982 'security_bot' | false 5983 'automation_bot' | false 5984 end 5985 5986 with_them do 5987 before do 5988 user.update!(user_type: user_type) 5989 end 5990 5991 it { is_expected.to be expected_result } 5992 end 5993 end 5994 end 5995 5996 describe '#inactive_message' do 5997 subject { user.inactive_message } 5998 5999 let(:user) { create(:user) } 6000 6001 context 'when user is blocked' do 6002 before do 6003 user.block 6004 end 6005 6006 it { is_expected.to eq :blocked } 6007 end 6008 6009 context 'when user is an internal user' do 6010 before do 6011 user.update!(user_type: :ghost) 6012 end 6013 6014 it { is_expected.to be :forbidden } 6015 end 6016 6017 context 'when user is locked' do 6018 before do 6019 user.lock_access! 6020 end 6021 6022 it { is_expected.to be :locked } 6023 end 6024 6025 context 'when user is blocked pending approval' do 6026 before do 6027 user.block_pending_approval! 6028 end 6029 6030 it { is_expected.to be :blocked_pending_approval } 6031 end 6032 end 6033 6034 describe '#password_required?' do 6035 let_it_be(:user) { create(:user) } 6036 6037 shared_examples 'does not require password to be present' do 6038 it { expect(user).not_to validate_presence_of(:password) } 6039 6040 it { expect(user).not_to validate_presence_of(:password_confirmation) } 6041 end 6042 6043 context 'when user is an internal user' do 6044 before do 6045 user.update!(user_type: 'alert_bot') 6046 end 6047 6048 it_behaves_like 'does not require password to be present' 6049 end 6050 6051 context 'when user is a project bot user' do 6052 before do 6053 user.update!(user_type: 'project_bot') 6054 end 6055 6056 it_behaves_like 'does not require password to be present' 6057 end 6058 end 6059 6060 describe 'can_trigger_notifications?' do 6061 context 'when user is not confirmed' do 6062 let_it_be(:user) { create(:user, :unconfirmed) } 6063 6064 it 'returns false' do 6065 expect(user.can_trigger_notifications?).to be(false) 6066 end 6067 end 6068 6069 context 'when user is blocked' do 6070 let_it_be(:user) { create(:user, :blocked) } 6071 6072 it 'returns false' do 6073 expect(user.can_trigger_notifications?).to be(false) 6074 end 6075 end 6076 6077 context 'when user is a ghost' do 6078 let_it_be(:user) { create(:user, :ghost) } 6079 6080 it 'returns false' do 6081 expect(user.can_trigger_notifications?).to be(false) 6082 end 6083 end 6084 6085 context 'when user is confirmed and neither blocked or a ghost' do 6086 let_it_be(:user) { create(:user) } 6087 6088 it 'returns true' do 6089 expect(user.can_trigger_notifications?).to be(true) 6090 end 6091 end 6092 end 6093 6094 context 'bot users' do 6095 shared_examples 'bot users' do |bot_type| 6096 it 'creates the user if it does not exist' do 6097 expect do 6098 described_class.public_send(bot_type) 6099 end.to change { User.where(user_type: bot_type).count }.by(1) 6100 end 6101 6102 it 'creates a route for the namespace of the created user' do 6103 bot_user = described_class.public_send(bot_type) 6104 6105 expect(bot_user.namespace.route).to be_present 6106 end 6107 6108 it 'does not create a new user if it already exists' do 6109 described_class.public_send(bot_type) 6110 6111 expect do 6112 described_class.public_send(bot_type) 6113 end.not_to change { User.count } 6114 end 6115 end 6116 6117 shared_examples 'bot user avatars' do |bot_type, avatar_filename| 6118 it 'sets the custom avatar for the created bot' do 6119 bot_user = described_class.public_send(bot_type) 6120 6121 expect(bot_user.avatar.url).to be_present 6122 expect(bot_user.avatar.filename).to eq(avatar_filename) 6123 end 6124 end 6125 6126 it_behaves_like 'bot users', :alert_bot 6127 it_behaves_like 'bot users', :support_bot 6128 it_behaves_like 'bot users', :migration_bot 6129 it_behaves_like 'bot users', :security_bot 6130 it_behaves_like 'bot users', :ghost 6131 it_behaves_like 'bot users', :automation_bot 6132 6133 it_behaves_like 'bot user avatars', :alert_bot, 'alert-bot.png' 6134 it_behaves_like 'bot user avatars', :support_bot, 'support-bot.png' 6135 it_behaves_like 'bot user avatars', :security_bot, 'security-bot.png' 6136 it_behaves_like 'bot user avatars', :automation_bot, 'support-bot.png' 6137 6138 context 'when bot is the support_bot' do 6139 subject { described_class.support_bot } 6140 6141 it { is_expected.to be_confirmed } 6142 end 6143 end 6144 6145 describe '#confirmation_required_on_sign_in?' do 6146 subject { user.confirmation_required_on_sign_in? } 6147 6148 context 'when user is confirmed' do 6149 let(:user) { create(:user) } 6150 6151 it 'is falsey' do 6152 expect(user.confirmed?).to be_truthy 6153 expect(subject).to be_falsey 6154 end 6155 end 6156 6157 context 'when user is not confirmed' do 6158 let_it_be(:user) { build_stubbed(:user, :unconfirmed, confirmation_sent_at: Time.current) } 6159 6160 it 'is truthy when soft_email_confirmation feature is disabled' do 6161 stub_feature_flags(soft_email_confirmation: false) 6162 expect(subject).to be_truthy 6163 end 6164 6165 context 'when soft_email_confirmation feature is enabled' do 6166 before do 6167 stub_feature_flags(soft_email_confirmation: true) 6168 end 6169 6170 it 'is falsey when confirmation period is valid' do 6171 expect(subject).to be_falsey 6172 end 6173 6174 it 'is truthy when confirmation period is expired' do 6175 travel_to(User.allow_unconfirmed_access_for.from_now + 1.day) do 6176 expect(subject).to be_truthy 6177 end 6178 end 6179 6180 context 'when user has no confirmation email sent' do 6181 let(:user) { build(:user, :unconfirmed, confirmation_sent_at: nil) } 6182 6183 it 'is truthy' do 6184 expect(subject).to be_truthy 6185 end 6186 end 6187 end 6188 end 6189 end 6190 6191 describe '.dormant' do 6192 it 'returns dormant users' do 6193 freeze_time do 6194 not_that_long_ago = (described_class::MINIMUM_INACTIVE_DAYS - 1).days.ago.to_date 6195 too_long_ago = described_class::MINIMUM_INACTIVE_DAYS.days.ago.to_date 6196 6197 create(:user, :deactivated, last_activity_on: too_long_ago) 6198 6199 User::INTERNAL_USER_TYPES.map do |user_type| 6200 create(:user, state: :active, user_type: user_type, last_activity_on: too_long_ago) 6201 end 6202 6203 create(:user, last_activity_on: not_that_long_ago) 6204 6205 dormant_user = create(:user, last_activity_on: too_long_ago) 6206 6207 expect(described_class.dormant).to contain_exactly(dormant_user) 6208 end 6209 end 6210 end 6211 6212 describe '.with_no_activity' do 6213 it 'returns users with no activity' do 6214 freeze_time do 6215 not_that_long_ago = (described_class::MINIMUM_INACTIVE_DAYS - 1).days.ago.to_date 6216 too_long_ago = described_class::MINIMUM_INACTIVE_DAYS.days.ago.to_date 6217 6218 create(:user, :deactivated, last_activity_on: nil) 6219 6220 User::INTERNAL_USER_TYPES.map do |user_type| 6221 create(:user, state: :active, user_type: user_type, last_activity_on: nil) 6222 end 6223 6224 create(:user, last_activity_on: not_that_long_ago) 6225 create(:user, last_activity_on: too_long_ago) 6226 6227 user_with_no_activity = create(:user, last_activity_on: nil) 6228 6229 expect(described_class.with_no_activity).to contain_exactly(user_with_no_activity) 6230 end 6231 end 6232 end 6233 6234 describe '.by_provider_and_extern_uid' do 6235 it 'calls Identity model scope to ensure case-insensitive query', :aggregate_failures do 6236 expected_user = create(:user) 6237 create(:identity, extern_uid: 'some-other-name-id', provider: :github) 6238 create(:identity, extern_uid: 'my_github_id', provider: :gitlab) 6239 create(:identity) 6240 create(:identity, user: expected_user, extern_uid: 'my_github_id', provider: :github) 6241 6242 expect(Identity).to receive(:with_extern_uid).and_call_original 6243 expect(described_class.by_provider_and_extern_uid(:github, 'my_github_id')).to match_array([expected_user]) 6244 end 6245 end 6246 6247 describe '#unset_secondary_emails_matching_deleted_email!' do 6248 let(:deleted_email) { 'kermit@muppets.com' } 6249 6250 subject { build(:user, commit_email: commit_email) } 6251 6252 context 'when no secondary email matches the deleted email' do 6253 let(:commit_email) { 'fozzie@muppets.com' } 6254 6255 it 'does nothing' do 6256 expect(subject).not_to receive(:save) 6257 subject.unset_secondary_emails_matching_deleted_email!(deleted_email) 6258 expect(subject.commit_email).to eq commit_email 6259 end 6260 end 6261 6262 context 'when a secondary email matches the deleted_email' do 6263 let(:commit_email) { deleted_email } 6264 6265 it 'un-sets the secondary email' do 6266 expect(subject).to receive(:save) 6267 subject.unset_secondary_emails_matching_deleted_email!(deleted_email) 6268 expect(subject.commit_email).to be nil 6269 end 6270 end 6271 end 6272 6273 describe '#groups_with_developer_maintainer_project_access' do 6274 let_it_be(:user) { create(:user) } 6275 let_it_be(:group1) { create(:group) } 6276 6277 let_it_be(:developer_group1) do 6278 create(:group).tap do |g| 6279 g.add_developer(user) 6280 end 6281 end 6282 6283 let_it_be(:developer_group2) do 6284 create(:group, project_creation_level: ::Gitlab::Access::DEVELOPER_MAINTAINER_PROJECT_ACCESS).tap do |g| 6285 g.add_developer(user) 6286 end 6287 end 6288 6289 let_it_be(:guest_group1) do 6290 create(:group, project_creation_level: ::Gitlab::Access::DEVELOPER_MAINTAINER_PROJECT_ACCESS).tap do |g| 6291 g.add_guest(user) 6292 end 6293 end 6294 6295 let_it_be(:developer_group1) do 6296 create(:group, project_creation_level: ::Gitlab::Access::DEVELOPER_MAINTAINER_PROJECT_ACCESS).tap do |g| 6297 g.add_maintainer(user) 6298 end 6299 end 6300 6301 subject { user.send(:groups_with_developer_maintainer_project_access) } 6302 6303 specify { is_expected.to contain_exactly(developer_group2) } 6304 end 6305 6306 describe '.get_ids_by_username' do 6307 let(:user_name) { 'user_name' } 6308 let!(:user) { create(:user, username: user_name) } 6309 let(:user_id) { user.id } 6310 6311 it 'returns the id of each record matching username' do 6312 expect(described_class.get_ids_by_username([user_name])).to match_array([user_id]) 6313 end 6314 end 6315 6316 describe 'user_project' do 6317 it 'returns users project matched by username and public visibility' do 6318 user = create(:user) 6319 public_project = create(:project, :public, path: user.username, namespace: user.namespace) 6320 create(:project, namespace: user.namespace) 6321 6322 expect(user.user_project).to eq(public_project) 6323 end 6324 end 6325 6326 describe 'user_readme' do 6327 it 'returns readme from user project' do 6328 user = create(:user) 6329 create(:project, :repository, :public, path: user.username, namespace: user.namespace) 6330 6331 expect(user.user_readme.name).to eq('README.md') 6332 expect(user.user_readme.data).to include('testme') 6333 end 6334 6335 it 'returns nil if project is private' do 6336 user = create(:user) 6337 create(:project, :repository, :private, path: user.username, namespace: user.namespace) 6338 6339 expect(user.user_readme).to be(nil) 6340 end 6341 end 6342 6343 it_behaves_like 'it has loose foreign keys' do 6344 let(:factory_name) { :user } 6345 end 6346end 6347