PageRenderTime 11ms CodeModel.GetById 4ms app.highlight 324ms RepoModel.GetById 1ms app.codeStats 1ms

/spec/controllers/users_controller_spec.rb

https://bitbucket.org/bitworkvn/cs_discourse
Ruby | 2495 lines | 2130 code | 357 blank | 8 comment | 10 complexity | cb4decefaf040e61e8334e52b747cbfd MD5 | raw file
   1require 'rails_helper'
   2
   3describe UsersController do
   4
   5  describe '.show' do
   6
   7    context "anon" do
   8
   9      let(:user) { Discourse.system_user }
  10
  11      it "returns success" do
  12        get :show, params: { username: user.username }, format: :json
  13        expect(response).to be_success
  14      end
  15
  16      it "should redirect to login page for anonymous user when profiles are hidden" do
  17        SiteSetting.hide_user_profiles_from_public = true
  18        get :show, params: { username: user.username }, format: :json
  19        expect(response).to redirect_to '/login'
  20      end
  21
  22    end
  23
  24    context "logged in" do
  25
  26      let(:user) { log_in }
  27
  28      it 'returns success' do
  29        get :show, params: { username: user.username, format: :json }, format: :json
  30        expect(response).to be_success
  31        json = JSON.parse(response.body)
  32
  33        expect(json["user"]["has_title_badges"]).to eq(false)
  34      end
  35
  36      it "returns not found when the username doesn't exist" do
  37        get :show, params: { username: 'madeuppity' }, format: :json
  38        expect(response).not_to be_success
  39      end
  40
  41      it 'returns not found when the user is inactive' do
  42        inactive = Fabricate(:user, active: false)
  43        get :show, params: { username: inactive.username }, format: :json
  44        expect(response).not_to be_success
  45      end
  46
  47      it 'returns success when show_inactive_accounts is true and user is logged in' do
  48        SiteSetting.show_inactive_accounts = true
  49        log_in_user(user)
  50        inactive = Fabricate(:user, active: false)
  51        get :show, params: { username: inactive.username }, format: :json
  52        expect(response).to be_success
  53      end
  54
  55      it "raises an error on invalid access" do
  56        Guardian.any_instance.expects(:can_see?).with(user).returns(false)
  57        get :show, params: { username: user.username }, format: :json
  58        expect(response).to be_forbidden
  59      end
  60
  61      describe "user profile views" do
  62        let(:other_user) { Fabricate(:user) }
  63
  64        it "should track a user profile view for a signed in user" do
  65          UserProfileView.expects(:add).with(other_user.user_profile.id, request.remote_ip, user.id)
  66          get :show, params: { username: other_user.username }, format: :json
  67        end
  68
  69        it "should not track a user profile view for a user viewing his own profile" do
  70          UserProfileView.expects(:add).never
  71          get :show, params: { username: user.username }, format: :json
  72        end
  73
  74        it "should track a user profile view for an anon user" do
  75          UserProfileView.expects(:add).with(other_user.user_profile.id, request.remote_ip, nil)
  76          get :show, params: { username: other_user.username }, format: :json
  77        end
  78
  79        it "skips tracking" do
  80          UserProfileView.expects(:add).never
  81          get :show, params: { username: user.username, skip_track_visit: true }, format: :json
  82        end
  83      end
  84
  85      context "fetching a user by external_id" do
  86        before { user.create_single_sign_on_record(external_id: '997', last_payload: '') }
  87
  88        it "returns fetch for a matching external_id" do
  89          get :show, params: { external_id: '997' }, format: :json
  90          expect(response).to be_success
  91        end
  92
  93        it "returns not found when external_id doesn't match" do
  94          get :show, params: { external_id: '99' }, format: :json
  95          expect(response).not_to be_success
  96        end
  97      end
  98
  99      describe "include_post_count_for" do
 100
 101        let(:admin) { Fabricate(:admin) }
 102        let(:topic) { Fabricate(:topic) }
 103
 104        before do
 105          Fabricate(:post, user: user, topic: topic)
 106          Fabricate(:post, user: admin, topic: topic)
 107          Fabricate(:post, user: admin, topic: topic, post_type: Post.types[:whisper])
 108        end
 109
 110        it "includes only visible posts" do
 111          get :show,
 112            params: { username: admin.username, include_post_count_for: topic.id },
 113            format: :json
 114
 115          topic_post_count = JSON.parse(response.body).dig("user", "topic_post_count")
 116          expect(topic_post_count[topic.id.to_s]).to eq(1)
 117        end
 118
 119        it "includes all post types for staff members" do
 120          log_in_user(admin)
 121
 122          get :show,
 123            params: { username: admin.username, include_post_count_for: topic.id },
 124            format: :json
 125
 126          topic_post_count = JSON.parse(response.body).dig("user", "topic_post_count")
 127          expect(topic_post_count[topic.id.to_s]).to eq(2)
 128        end
 129      end
 130    end
 131  end
 132
 133  describe '.activate_account' do
 134    before do
 135      UsersController.any_instance.stubs(:honeypot_or_challenge_fails?).returns(false)
 136    end
 137
 138    context 'invalid token' do
 139
 140      it 'return success' do
 141        EmailToken.expects(:confirm).with('asdfasdf').returns(nil)
 142        put :perform_account_activation, params: { token: 'asdfasdf' }
 143        expect(response).to be_success
 144        expect(flash[:error]).to be_present
 145      end
 146    end
 147
 148    context 'valid token' do
 149      let(:user) { Fabricate(:user) }
 150
 151      context 'welcome message' do
 152        before do
 153          EmailToken.expects(:confirm).with('asdfasdf').returns(user)
 154        end
 155
 156        it 'enqueues a welcome message if the user object indicates so' do
 157          user.send_welcome_message = true
 158          user.expects(:enqueue_welcome_message).with('welcome_user')
 159
 160          put :perform_account_activation, params: { token: 'asdfasdf' }
 161        end
 162
 163        it "doesn't enqueue the welcome message if the object returns false" do
 164          user.send_welcome_message = false
 165          user.expects(:enqueue_welcome_message).with('welcome_user').never
 166
 167          put :perform_account_activation, params: { token: 'asdfasdf' }
 168        end
 169      end
 170
 171      context "honeypot" do
 172        it "raises an error if the honeypot is invalid" do
 173          UsersController.any_instance.stubs(:honeypot_or_challenge_fails?).returns(true)
 174          put :perform_account_activation, params: { token: 'asdfasdf' }, format: :json
 175          expect(response).not_to be_success
 176        end
 177      end
 178
 179      context 'response' do
 180        render_views
 181
 182        before do
 183          Guardian.any_instance.expects(:can_access_forum?).returns(true)
 184          EmailToken.expects(:confirm).with('asdfasdf').returns(user)
 185        end
 186
 187        it 'correctly logs on user' do
 188          events = DiscourseEvent.track_events do
 189            put :perform_account_activation, params: { token: 'asdfasdf' }
 190          end
 191
 192          expect(events.map { |event| event[:event_name] }).to include(
 193            :user_logged_in, :user_first_logged_in
 194          )
 195
 196          expect(response).to be_success
 197          expect(flash[:error]).to be_blank
 198          expect(session[:current_user_id]).to be_present
 199
 200          expect(response).to be_success
 201
 202          expect(CGI.unescapeHTML(response.body))
 203            .to_not include(I18n.t('activation.approval_required'))
 204        end
 205
 206      end
 207
 208      context 'user is not approved' do
 209        render_views
 210
 211        before do
 212          SiteSetting.must_approve_users = true
 213          EmailToken.expects(:confirm).with('asdfasdf').returns(user)
 214          put :perform_account_activation, params: { token: 'asdfasdf' }
 215        end
 216
 217        it 'should return the right response' do
 218          expect(response).to be_success
 219
 220          expect(CGI.unescapeHTML(response.body))
 221            .to include(I18n.t('activation.approval_required'))
 222
 223          expect(response.body).to_not have_tag(:script, with: {
 224            src: '/assets/application.js'
 225          })
 226
 227          expect(flash[:error]).to be_blank
 228          expect(session[:current_user_id]).to be_blank
 229        end
 230      end
 231
 232    end
 233  end
 234
 235  describe '#perform_account_activation' do
 236    describe 'when cookies contains a destination URL' do
 237      let(:token) { 'asdadwewq' }
 238      let(:user) { Fabricate(:user) }
 239
 240      before do
 241        UsersController.any_instance.stubs(:honeypot_or_challenge_fails?).returns(false)
 242        EmailToken.expects(:confirm).with(token).returns(user)
 243      end
 244
 245      it 'should redirect to the URL' do
 246        destination_url = 'http://thisisasite.com/somepath'
 247        request.cookies[:destination_url] = destination_url
 248
 249        put :perform_account_activation, params: { token: token }
 250
 251        expect(response).to redirect_to(destination_url)
 252      end
 253    end
 254  end
 255
 256  describe '.password_reset' do
 257    let(:user) { Fabricate(:user) }
 258
 259    context "you can view it even if login is required" do
 260      it "returns success" do
 261        SiteSetting.login_required = true
 262        get :password_reset, params: { token: 'asdfasdf' }
 263        expect(response).to be_success
 264      end
 265    end
 266
 267    context 'missing token' do
 268      render_views
 269
 270      before do
 271        get :password_reset, params: { token: SecureRandom.hex }
 272      end
 273
 274      it 'disallows login' do
 275        expect(response).to be_success
 276
 277        expect(CGI.unescapeHTML(response.body))
 278          .to include(I18n.t('password_reset.no_token'))
 279
 280        expect(response.body).to_not have_tag(:script, with: {
 281          src: '/assets/application.js'
 282        })
 283
 284        expect(session[:current_user_id]).to be_blank
 285      end
 286    end
 287
 288    context 'invalid token' do
 289      render_views
 290
 291      it 'disallows login' do
 292        get :password_reset, params: { token: "evil_trout!" }
 293
 294        expect(response).to be_success
 295
 296        expect(CGI.unescapeHTML(response.body))
 297          .to include(I18n.t('password_reset.no_token'))
 298
 299        expect(response.body).to_not have_tag(:script, with: {
 300          src: '/assets/application.js'
 301        })
 302
 303        expect(session[:current_user_id]).to be_blank
 304      end
 305
 306      it "responds with proper error message" do
 307        put :password_reset, params: {
 308          token: "evil_trout!", password: "awesomeSecretPassword"
 309        }, format: :json
 310
 311        expect(response).to be_success
 312        expect(JSON.parse(response.body)["message"]).to eq(I18n.t('password_reset.no_token'))
 313        expect(session[:current_user_id]).to be_blank
 314      end
 315    end
 316
 317    context 'valid token' do
 318      render_views
 319
 320      context 'when rendered' do
 321        it 'renders referrer never on get requests' do
 322          user = Fabricate(:user)
 323          token = user.email_tokens.create(email: user.email).token
 324          get :password_reset, params: { token: token }
 325
 326          expect(response.body).to include('<meta name="referrer" content="never">')
 327        end
 328      end
 329
 330      it 'returns success' do
 331        user = Fabricate(:user)
 332        user_auth_token = UserAuthToken.generate!(user_id: user.id)
 333        token = user.email_tokens.create(email: user.email).token
 334        get :password_reset, params: { token: token }
 335
 336        events = DiscourseEvent.track_events do
 337          put :password_reset,
 338            params: { token: token, password: 'hg9ow8yhg98o' }
 339        end
 340
 341        expect(events.map { |event| event[:event_name] }).to include(
 342          :user_logged_in, :user_first_logged_in
 343        )
 344
 345        expect(response).to be_success
 346        expect(response.body).to include('{"is_developer":false,"admin":false,"second_factor_required":false}')
 347
 348        user.reload
 349
 350        expect(session["password-#{token}"]).to be_blank
 351        expect(UserAuthToken.where(id: user_auth_token.id).count).to eq(0)
 352      end
 353
 354      it 'disallows double password reset' do
 355        user = Fabricate(:user)
 356        token = user.email_tokens.create(email: user.email).token
 357
 358        get :password_reset, params: { token: token }
 359
 360        put :password_reset,
 361          params: { token: token, password: 'hg9ow8yHG32O' }
 362
 363        put :password_reset,
 364          params: { token: token, password: 'test123987AsdfXYZ' }
 365
 366        user.reload
 367        expect(user.confirm_password?('hg9ow8yHG32O')).to eq(true)
 368
 369        # logged in now
 370        expect(user.user_auth_tokens.count).to eq(1)
 371      end
 372
 373      it "doesn't redirect to wizard on get" do
 374        user = Fabricate(:admin)
 375        UserAuthToken.generate!(user_id: user.id)
 376
 377        token = user.email_tokens.create(email: user.email).token
 378        get :password_reset, params: { token: token }, format: :json
 379        expect(response).not_to redirect_to(wizard_path)
 380      end
 381
 382      it "redirects to the wizard if you're the first admin" do
 383        user = Fabricate(:admin)
 384        UserAuthToken.generate!(user_id: user.id)
 385
 386        token = user.email_tokens.create(email: user.email).token
 387        get :password_reset, params: { token: token }
 388
 389        put :password_reset, params: {
 390          token: token, password: 'hg9ow8yhg98oadminlonger'
 391        }
 392
 393        expect(response).to redirect_to(wizard_path)
 394      end
 395
 396      it "doesn't invalidate the token when loading the page" do
 397        user = Fabricate(:user)
 398        user_token = UserAuthToken.generate!(user_id: user.id)
 399
 400        email_token = user.email_tokens.create(email: user.email)
 401
 402        get :password_reset, params: { token: email_token.token }, format: :json
 403
 404        email_token.reload
 405
 406        expect(email_token.confirmed).to eq(false)
 407        expect(UserAuthToken.where(id: user_token.id).count).to eq(1)
 408      end
 409
 410      context '2 factor authentication required' do
 411        let!(:second_factor) { Fabricate(:user_second_factor, user: user) }
 412
 413        it 'does not change with an invalid token' do
 414          token = user.email_tokens.create!(email: user.email).token
 415
 416          get :password_reset, params: { token: token }
 417
 418          expect(response.body).to include('{"is_developer":false,"admin":false,"second_factor_required":true}')
 419
 420          put :password_reset,
 421              params: { token: token, password: 'hg9ow8yHG32O', second_factor_token: '000000' }
 422
 423          expect(response.body).to include(I18n.t("login.invalid_second_factor_code"))
 424
 425          user.reload
 426          expect(user.confirm_password?('hg9ow8yHG32O')).not_to eq(true)
 427          expect(user.user_auth_tokens.count).not_to eq(1)
 428        end
 429
 430        it 'changes password with valid 2-factor tokens' do
 431          token = user.email_tokens.create(email: user.email).token
 432
 433          get :password_reset, params: { token: token }
 434
 435          put :password_reset, params: {
 436            token: token,
 437            password: 'hg9ow8yHG32O',
 438            second_factor_token: ROTP::TOTP.new(second_factor.data).now
 439          }
 440
 441          user.reload
 442          expect(user.confirm_password?('hg9ow8yHG32O')).to eq(true)
 443          expect(user.user_auth_tokens.count).to eq(1)
 444        end
 445      end
 446    end
 447
 448    context 'submit change' do
 449      let(:token) { EmailToken.generate_token }
 450
 451      before do
 452        EmailToken.expects(:confirm).with(token).returns(user)
 453      end
 454
 455      it "fails when the password is blank" do
 456        put :password_reset, params: {
 457          token: token, password: ''
 458        }, format: :json
 459
 460        expect(response).to be_success
 461        expect(JSON.parse(response.body)["errors"]).to be_present
 462        expect(session[:current_user_id]).to be_blank
 463      end
 464
 465      it "fails when the password is too long" do
 466        put :password_reset, params: {
 467          token: token, password: ('x' * (User.max_password_length + 1))
 468        }, format: :json
 469
 470        expect(response).to be_success
 471        expect(JSON.parse(response.body)["errors"]).to be_present
 472        expect(session[:current_user_id]).to be_blank
 473      end
 474
 475      it "logs in the user" do
 476        put :password_reset, params: {
 477          token: token, password: 'ksjafh928r'
 478        }, format: :json
 479
 480        expect(response).to be_success
 481        expect(JSON.parse(response.body)["errors"]).to be_blank
 482        expect(session[:current_user_id]).to be_present
 483      end
 484
 485      it "doesn't log in the user when not approved" do
 486        SiteSetting.must_approve_users = true
 487        put :password_reset, params: {
 488          token: token, password: 'ksjafh928r'
 489        }, format: :json
 490
 491        expect(JSON.parse(response.body)["errors"]).to be_blank
 492        expect(session[:current_user_id]).to be_blank
 493      end
 494    end
 495  end
 496
 497  describe '.confirm_email_token' do
 498    let(:user) { Fabricate(:user) }
 499
 500    it "token doesn't match any records" do
 501      email_token = user.email_tokens.create(email: user.email)
 502      get :confirm_email_token, params: { token: SecureRandom.hex }, format: :json
 503      expect(response).to be_success
 504      expect(email_token.reload.confirmed).to eq(false)
 505    end
 506
 507    it "token matches" do
 508      email_token = user.email_tokens.create(email: user.email)
 509      get :confirm_email_token, params: { token: email_token.token }, format: :json
 510      expect(response).to be_success
 511      expect(email_token.reload.confirmed).to eq(true)
 512    end
 513  end
 514
 515  describe '#admin_login' do
 516    let(:admin) { Fabricate(:admin) }
 517    let(:user) { Fabricate(:user) }
 518
 519    context 'enqueues mail' do
 520      it 'enqueues mail with admin email and sso enabled' do
 521        Jobs.expects(:enqueue).with(:critical_user_email, has_entries(type: :admin_login, user_id: admin.id))
 522        put :admin_login, params: { email: admin.email }
 523      end
 524    end
 525
 526    context 'when email is incorrect' do
 527      render_views
 528
 529      it 'should return the right response' do
 530        put :admin_login, params: { email: 'random' }
 531
 532        expect(response.status).to eq(200)
 533
 534        response_body = response.body
 535
 536        expect(response_body).to match(I18n.t("admin_login.errors.unknown_email_address"))
 537        expect(response_body).to_not match(I18n.t("login.second_factor_description"))
 538      end
 539    end
 540
 541    context 'logs in admin' do
 542      it 'does not log in admin with invalid token' do
 543        SiteSetting.sso_url = "https://www.example.com/sso"
 544        SiteSetting.enable_sso = true
 545        get :admin_login, params: { token: "invalid" }
 546        expect(session[:current_user_id]).to be_blank
 547      end
 548
 549      context 'valid token' do
 550        it 'does log in admin with SSO disabled' do
 551          SiteSetting.enable_sso = false
 552          token = admin.email_tokens.create(email: admin.email).token
 553
 554          get :admin_login, params: { token: token }
 555          expect(response).to redirect_to('/')
 556          expect(session[:current_user_id]).to eq(admin.id)
 557        end
 558
 559        it 'logs in admin with SSO enabled' do
 560          SiteSetting.sso_url = "https://www.example.com/sso"
 561          SiteSetting.enable_sso = true
 562          token = admin.email_tokens.create(email: admin.email).token
 563
 564          get :admin_login, params: { token: token }
 565          expect(response).to redirect_to('/')
 566          expect(session[:current_user_id]).to eq(admin.id)
 567        end
 568      end
 569
 570      describe 'when 2 factor authentication is enabled' do
 571        let(:second_factor) { Fabricate(:user_second_factor, user: admin) }
 572        let(:email_token) { Fabricate(:email_token, user: admin) }
 573        render_views
 574
 575        it 'does not log in when token required' do
 576          second_factor
 577          get :admin_login, params: { token: email_token.token }
 578          expect(response).not_to redirect_to('/')
 579          expect(session[:current_user_id]).not_to eq(admin.id)
 580          expect(response.body).to include(I18n.t('login.second_factor_description'));
 581        end
 582
 583        describe 'invalid 2 factor token' do
 584          it 'should display the right error' do
 585            second_factor
 586
 587            put :admin_login, params: {
 588              token: email_token.token,
 589              second_factor_token: '13213'
 590            }
 591
 592            expect(response.status).to eq(200)
 593            expect(response.body).to include(I18n.t('login.second_factor_description'));
 594            expect(response.body).to include(I18n.t('login.invalid_second_factor_code'));
 595          end
 596        end
 597
 598        it 'logs in when a valid 2-factor token is given' do
 599          put :admin_login, params: {
 600            token: email_token.token,
 601            second_factor_token: ROTP::TOTP.new(second_factor.data).now
 602          }
 603
 604          expect(response).to redirect_to('/')
 605          expect(session[:current_user_id]).to eq(admin.id)
 606        end
 607      end
 608    end
 609  end
 610
 611  describe '#toggle_anon' do
 612    it 'allows you to toggle anon if enabled' do
 613      SiteSetting.allow_anonymous_posting = true
 614
 615      user = log_in
 616      user.trust_level = 1
 617      user.save
 618
 619      post :toggle_anon, format: :json
 620      expect(response).to be_success
 621      expect(session[:current_user_id]).to eq(AnonymousShadowCreator.get(user).id)
 622
 623      post :toggle_anon, format: :json
 624      expect(response).to be_success
 625      expect(session[:current_user_id]).to eq(user.id)
 626
 627    end
 628  end
 629
 630  describe '#create' do
 631
 632    before do
 633      UsersController.any_instance.stubs(:honeypot_value).returns(nil)
 634      UsersController.any_instance.stubs(:challenge_value).returns(nil)
 635      SiteSetting.allow_new_registrations = true
 636      @user = Fabricate.build(:user)
 637      @user.password = "strongpassword"
 638    end
 639
 640    let(:post_user_params) do
 641      { name: @user.name,
 642        username: @user.username,
 643        password: "strongpassword",
 644        email: @user.email }
 645    end
 646
 647    def post_user
 648      post :create, params: post_user_params, format: :json
 649    end
 650
 651    context 'when email params is missing' do
 652      it 'should raise the right error' do
 653        expect do
 654          post :create, params: {
 655            name: @user.name,
 656            username: @user.username,
 657            passsword: 'tesing12352343'
 658          }, format: :json
 659        end.to raise_error(ActionController::ParameterMissing)
 660      end
 661    end
 662
 663    context 'when creating a user' do
 664      it 'sets the user locale to I18n.locale' do
 665        SiteSetting.default_locale = 'en'
 666        I18n.stubs(:locale).returns(:fr)
 667        post_user
 668        expect(User.find_by(username: @user.username).locale).to eq('fr')
 669      end
 670    end
 671
 672    context 'when creating a non active user (unconfirmed email)' do
 673
 674      it 'returns a 500 when local logins are disabled' do
 675        SiteSetting.enable_local_logins = false
 676        post_user
 677
 678        expect(response.status).to eq(500)
 679      end
 680
 681      it 'returns an error when new registrations are disabled' do
 682        SiteSetting.allow_new_registrations = false
 683        post_user
 684        json = JSON.parse(response.body)
 685        expect(json['success']).to eq(false)
 686        expect(json['message']).to be_present
 687      end
 688
 689      it 'creates a user correctly' do
 690        Jobs.expects(:enqueue).with(:critical_user_email, has_entries(type: :signup))
 691        User.any_instance.expects(:enqueue_welcome_message).with('welcome_user').never
 692
 693        post_user
 694
 695        expect(JSON.parse(response.body)['active']).to be_falsey
 696
 697        # should save user_created_message in session
 698        expect(session["user_created_message"]).to be_present
 699        expect(session[SessionController::ACTIVATE_USER_KEY]).to be_present
 700      end
 701
 702      context "`must approve users` site setting is enabled" do
 703        before { SiteSetting.must_approve_users = true }
 704
 705        it 'creates a user correctly' do
 706          Jobs.expects(:enqueue).with(:critical_user_email, has_entries(type: :signup))
 707          User.any_instance.expects(:enqueue_welcome_message).with('welcome_user').never
 708
 709          post_user
 710
 711          expect(JSON.parse(response.body)['active']).to be_falsey
 712
 713          # should save user_created_message in session
 714          expect(session["user_created_message"]).to be_present
 715          expect(session[SessionController::ACTIVATE_USER_KEY]).to be_present
 716        end
 717      end
 718
 719      context 'users already exists with given email' do
 720        let!(:existing) { Fabricate(:user, email: post_user_params[:email]) }
 721
 722        it 'returns an error if hide_email_address_taken is disabled' do
 723          SiteSetting.hide_email_address_taken = false
 724          post_user
 725          json = JSON.parse(response.body)
 726          expect(json['success']).to eq(false)
 727          expect(json['message']).to be_present
 728        end
 729
 730        it 'returns success if hide_email_address_taken is enabled' do
 731          SiteSetting.hide_email_address_taken = true
 732          expect {
 733            post_user
 734          }.to_not change { User.count }
 735          json = JSON.parse(response.body)
 736          expect(json['active']).to be_falsey
 737          expect(session["user_created_message"]).to be_present
 738        end
 739      end
 740    end
 741
 742    context "creating as active" do
 743      it "won't create the user as active" do
 744        post :create, params: post_user_params.merge(active: true), format: :json
 745        expect(JSON.parse(response.body)['active']).to be_falsey
 746      end
 747
 748      context "with a regular api key" do
 749        let(:user) { Fabricate(:user) }
 750        let(:api_key) { Fabricate(:api_key, user: user) }
 751
 752        it "won't create the user as active with a regular key" do
 753          post :create,
 754            params: post_user_params.merge(active: true, api_key: api_key.key),
 755            format: :json
 756
 757          expect(JSON.parse(response.body)['active']).to be_falsey
 758        end
 759      end
 760
 761      context "with an admin api key" do
 762        let(:admin) { Fabricate(:admin) }
 763        let(:api_key) { Fabricate(:api_key, user: admin) }
 764
 765        it "creates the user as active with a regular key" do
 766          SiteSetting.queue_jobs = true
 767          SiteSetting.send_welcome_message = true
 768          SiteSetting.must_approve_users = true
 769
 770          Sidekiq::Client.expects(:enqueue).never
 771
 772          post :create,
 773            params: post_user_params.merge(approved: true, active: true, api_key: api_key.key),
 774            format: :json
 775
 776          json = JSON.parse(response.body)
 777
 778          new_user = User.find(json["user_id"])
 779
 780          expect(json['active']).to be_truthy
 781
 782          expect(new_user.active).to eq(true)
 783          expect(new_user.approved).to eq(true)
 784          expect(new_user.approved_by_id).to eq(admin.id)
 785          expect(new_user.approved_at).to_not eq(nil)
 786        end
 787
 788        it "won't create the developer as active" do
 789          UsernameCheckerService.expects(:is_developer?).returns(true)
 790
 791          post :create,
 792            params: post_user_params.merge(active: true, api_key: api_key.key),
 793            format: :json
 794
 795          expect(JSON.parse(response.body)['active']).to be_falsy
 796        end
 797      end
 798    end
 799
 800    context "creating as staged" do
 801      it "won't create the user as staged" do
 802        post :create,
 803          params: post_user_params.merge(staged: true),
 804          format: :json
 805
 806        new_user = User.where(username: post_user_params[:username]).first
 807        expect(new_user.staged?).to eq(false)
 808      end
 809
 810      context "with a regular api key" do
 811        let(:user) { Fabricate(:user) }
 812        let(:api_key) { Fabricate(:api_key, user: user) }
 813
 814        it "won't create the user as staged with a regular key" do
 815          post :create,
 816            params: post_user_params.merge(staged: true, api_key: api_key.key),
 817            format: :json
 818
 819          new_user = User.where(username: post_user_params[:username]).first
 820          expect(new_user.staged?).to eq(false)
 821        end
 822      end
 823
 824      context "with an admin api key" do
 825        let(:user) { Fabricate(:admin) }
 826        let(:api_key) { Fabricate(:api_key, user: user) }
 827
 828        it "creates the user as staged with a regular key" do
 829          post :create,
 830            params: post_user_params.merge(staged: true, api_key: api_key.key),
 831            format: :json
 832
 833          new_user = User.where(username: post_user_params[:username]).first
 834          expect(new_user.staged?).to eq(true)
 835        end
 836
 837        it "won't create the developer as staged" do
 838          UsernameCheckerService.expects(:is_developer?).returns(true)
 839          post :create,
 840            params: post_user_params.merge(staged: true, api_key: api_key.key),
 841            format: :json
 842
 843          new_user = User.where(username: post_user_params[:username]).first
 844          expect(new_user.staged?).to eq(false)
 845        end
 846      end
 847    end
 848
 849    context 'when creating an active user (confirmed email)' do
 850      before { User.any_instance.stubs(:active?).returns(true) }
 851
 852      it 'enqueues a welcome email' do
 853        User.any_instance.expects(:enqueue_welcome_message).with('welcome_user')
 854        post_user
 855
 856        # should save user_created_message in session
 857        expect(session["user_created_message"]).to be_present
 858        expect(session[SessionController::ACTIVATE_USER_KEY]).to be_present
 859      end
 860
 861      it "shows the 'active' message" do
 862        User.any_instance.expects(:enqueue_welcome_message)
 863        post_user
 864        expect(JSON.parse(response.body)['message']).to eq(
 865          I18n.t 'login.active'
 866        )
 867      end
 868
 869      it "should be logged in" do
 870        User.any_instance.expects(:enqueue_welcome_message)
 871        post_user
 872        expect(session[:current_user_id]).to be_present
 873      end
 874
 875      it 'indicates the user is active in the response' do
 876        User.any_instance.expects(:enqueue_welcome_message)
 877        post_user
 878        expect(JSON.parse(response.body)['active']).to be_truthy
 879      end
 880
 881      it 'returns 500 status when new registrations are disabled' do
 882        SiteSetting.allow_new_registrations = false
 883
 884        post_user
 885
 886        json = JSON.parse(response.body)
 887        expect(json['success']).to eq(false)
 888        expect(json['message']).to be_present
 889      end
 890
 891      context 'authentication records for' do
 892
 893        it 'should create twitter user info if required' do
 894          SiteSetting.must_approve_users = true
 895          SiteSetting.enable_twitter_logins = true
 896          twitter_auth = { twitter_user_id: 42, twitter_screen_name: "bruce" }
 897          auth = session[:authentication] = {}
 898          auth[:authenticator_name] = 'twitter'
 899          auth[:extra_data] = twitter_auth
 900
 901          post_user
 902
 903          expect(TwitterUserInfo.count).to eq(1)
 904        end
 905      end
 906
 907      it "returns an error when email has been changed from the validated email address" do
 908        auth = session[:authentication] = {}
 909        auth[:email_valid] = 'true'
 910        auth[:email] = 'therealone@gmail.com'
 911        post_user
 912        json = JSON.parse(response.body)
 913        expect(json['success']).to eq(false)
 914        expect(json['message']).to be_present
 915      end
 916
 917      it "will create the user successfully if email validation is required" do
 918        auth = session[:authentication] = {}
 919        auth[:email] = post_user_params[:email]
 920        post_user
 921        json = JSON.parse(response.body)
 922        expect(json['success']).to eq(true)
 923      end
 924    end
 925
 926    context 'after success' do
 927      before { post_user }
 928
 929      it 'should succeed' do
 930        is_expected.to respond_with(:success)
 931      end
 932
 933      it 'has the proper JSON' do
 934        json = JSON::parse(response.body)
 935        expect(json["success"]).to eq(true)
 936      end
 937
 938      it 'should not result in an active account' do
 939        expect(User.find_by(username: @user.username).active).to eq(false)
 940      end
 941    end
 942
 943    shared_examples 'honeypot fails' do
 944      it 'should not create a new user' do
 945        expect {
 946          post :create, params: create_params, format: :json
 947        }.to_not change { User.count }
 948      end
 949
 950      it 'should not send an email' do
 951        User.any_instance.expects(:enqueue_welcome_message).never
 952        post :create, params: create_params, format: :json
 953      end
 954
 955      it 'should say it was successful' do
 956        post :create, params: create_params, format: :json
 957        json = JSON::parse(response.body)
 958        expect(json["success"]).to eq(true)
 959
 960        # should not change the session
 961        expect(session["user_created_message"]).to be_blank
 962        expect(session[SessionController::ACTIVATE_USER_KEY]).to be_blank
 963      end
 964    end
 965
 966    context 'when honeypot value is wrong' do
 967      before do
 968        UsersController.any_instance.stubs(:honeypot_value).returns('abc')
 969      end
 970      let(:create_params) { { name: @user.name, username: @user.username, password: "strongpassword", email: @user.email, password_confirmation: 'wrong' } }
 971      include_examples 'honeypot fails'
 972    end
 973
 974    context 'when challenge answer is wrong' do
 975      before do
 976        UsersController.any_instance.stubs(:challenge_value).returns('abc')
 977      end
 978      let(:create_params) { { name: @user.name, username: @user.username, password: "strongpassword", email: @user.email, challenge: 'abc' } }
 979      include_examples 'honeypot fails'
 980    end
 981
 982    context "when 'invite only' setting is enabled" do
 983      before { SiteSetting.invite_only = true }
 984
 985      let(:create_params) { {
 986        name: @user.name,
 987        username: @user.username,
 988        password: 'strongpassword',
 989        email: @user.email
 990      }}
 991
 992      include_examples 'honeypot fails'
 993    end
 994
 995    shared_examples 'failed signup' do
 996      it 'should not create a new User' do
 997        expect { post :create, params: create_params, format: :json }.to_not change { User.count }
 998      end
 999
1000      it 'should report failed' do
1001        post :create, params: create_params, format: :json
1002        json = JSON::parse(response.body)
1003        expect(json["success"]).not_to eq(true)
1004
1005        # should not change the session
1006        expect(session["user_created_message"]).to be_blank
1007        expect(session[SessionController::ACTIVATE_USER_KEY]).to be_blank
1008      end
1009    end
1010
1011    context 'when password is blank' do
1012      let(:create_params) { { name: @user.name, username: @user.username, password: "", email: @user.email } }
1013      include_examples 'failed signup'
1014    end
1015
1016    context 'when password is too long' do
1017      let(:create_params) { { name: @user.name, username: @user.username, password: "x" * (User.max_password_length + 1), email: @user.email } }
1018      include_examples 'failed signup'
1019    end
1020
1021    context 'when password param is missing' do
1022      let(:create_params) { { name: @user.name, username: @user.username, email: @user.email } }
1023      include_examples 'failed signup'
1024    end
1025
1026    context 'with a reserved username' do
1027      let(:create_params) { { name: @user.name, username: 'Reserved', email: @user.email, password: "x" * 20 } }
1028      before { SiteSetting.reserved_usernames = 'a|reserved|b' }
1029      after { SiteSetting.reserved_usernames = nil }
1030      include_examples 'failed signup'
1031    end
1032
1033    context 'when an Exception is raised' do
1034      before { User.any_instance.stubs(:save).raises(ActiveRecord::StatementInvalid.new('Oh no')) }
1035
1036      let(:create_params) {
1037        { name: @user.name, username: @user.username,
1038          password: "strongpassword", email: @user.email }
1039      }
1040
1041      include_examples 'failed signup'
1042    end
1043
1044    context "with custom fields" do
1045      let!(:user_field) { Fabricate(:user_field) }
1046      let!(:another_field) { Fabricate(:user_field) }
1047      let!(:optional_field) { Fabricate(:user_field, required: false) }
1048
1049      context "without a value for the fields" do
1050        let(:create_params) { { name: @user.name, password: 'watwatwat', username: @user.username, email: @user.email } }
1051        include_examples 'failed signup'
1052      end
1053
1054      context "with values for the fields" do
1055        let(:create_params) { {
1056          name: @user.name,
1057          password: 'suChS3cuRi7y',
1058          username: @user.username,
1059          email: @user.email,
1060          user_fields: {
1061            user_field.id.to_s => 'value1',
1062            another_field.id.to_s => 'value2',
1063          }
1064        } }
1065
1066        it "should succeed without the optional field" do
1067          post :create, params: create_params, format: :json
1068          expect(response).to be_success
1069          inserted = User.find_by_email(@user.email)
1070          expect(inserted).to be_present
1071          expect(inserted.custom_fields).to be_present
1072          expect(inserted.custom_fields["user_field_#{user_field.id}"]).to eq('value1')
1073          expect(inserted.custom_fields["user_field_#{another_field.id}"]).to eq('value2')
1074          expect(inserted.custom_fields["user_field_#{optional_field.id}"]).to be_blank
1075        end
1076
1077        it "should succeed with the optional field" do
1078          create_params[:user_fields][optional_field.id.to_s] = 'value3'
1079          post :create, params: create_params.merge(create_params), format: :json
1080          expect(response).to be_success
1081          inserted = User.find_by_email(@user.email)
1082          expect(inserted).to be_present
1083          expect(inserted.custom_fields).to be_present
1084          expect(inserted.custom_fields["user_field_#{user_field.id}"]).to eq('value1')
1085          expect(inserted.custom_fields["user_field_#{another_field.id}"]).to eq('value2')
1086          expect(inserted.custom_fields["user_field_#{optional_field.id}"]).to eq('value3')
1087        end
1088
1089        it "trims excessively long fields" do
1090          create_params[:user_fields][optional_field.id.to_s] = ('x' * 3000)
1091          post :create, params: create_params.merge(create_params), format: :json
1092          expect(response).to be_success
1093          inserted = User.find_by_email(@user.email)
1094
1095          val = inserted.custom_fields["user_field_#{optional_field.id}"]
1096          expect(val.length).to eq(UserField.max_length)
1097        end
1098      end
1099    end
1100
1101    context "with only optional custom fields" do
1102      let!(:user_field) { Fabricate(:user_field, required: false) }
1103
1104      context "without values for the fields" do
1105        let(:create_params) { {
1106          name: @user.name,
1107          password: 'suChS3cuRi7y',
1108          username: @user.username,
1109          email: @user.email,
1110        } }
1111
1112        it "should succeed" do
1113          post :create, params: create_params, format: :json
1114          expect(response).to be_success
1115          inserted = User.find_by_email(@user.email)
1116          expect(inserted).to be_present
1117          expect(inserted.custom_fields).not_to be_present
1118          expect(inserted.custom_fields["user_field_#{user_field.id}"]).to be_blank
1119        end
1120      end
1121    end
1122
1123  end
1124
1125  context '#username' do
1126    it 'raises an error when not logged in' do
1127      put :username, params: { username: 'somename' }, format: :json
1128      expect(response.status).to eq(403)
1129    end
1130
1131    context 'while logged in' do
1132      let(:old_username) { "OrigUsrname" }
1133      let(:new_username) { "#{old_username}1234" }
1134      let(:user) { Fabricate(:user, username: old_username) }
1135
1136      before do
1137        user.username = old_username
1138        log_in_user(user)
1139      end
1140
1141      it 'raises an error without a new_username param' do
1142        expect do
1143          put :username, params: { username: user.username }, format: :json
1144        end.to raise_error(ActionController::ParameterMissing)
1145
1146        expect(user.reload.username).to eq(old_username)
1147      end
1148
1149      it 'raises an error when you don\'t have permission to change the username' do
1150        Guardian.any_instance.expects(:can_edit_username?).with(user).returns(false)
1151
1152        put :username, params: {
1153          username: user.username, new_username: new_username
1154        }, format: :json
1155
1156        expect(response).to be_forbidden
1157        expect(user.reload.username).to eq(old_username)
1158      end
1159
1160      it 'raises an error when change_username fails' do
1161        put :username,
1162          params: { username: user.username, new_username: '@' },
1163          format: :json
1164
1165        expect(response).to_not be_success
1166
1167        body = JSON.parse(response.body)
1168
1169        expect(body['errors'].first).to include(I18n.t(
1170          'user.username.short', min: User.username_length.begin
1171        ))
1172
1173        expect(user.reload.username).to eq(old_username)
1174      end
1175
1176      it 'should succeed in normal circumstances' do
1177        put :username,
1178          params: { username: user.username, new_username: new_username },
1179          format: :json
1180
1181        expect(response).to be_success
1182        expect(user.reload.username).to eq(new_username)
1183      end
1184
1185      it 'should fail if the user is old' do
1186        # Older than the change period and >1 post
1187        user.created_at = Time.now - (SiteSetting.username_change_period + 1).days
1188        PostCreator.new(user,
1189          title: 'This is a test topic',
1190          raw: 'This is a test this is a test'
1191        ).create
1192
1193        put :username, params: {
1194          username: user.username, new_username: new_username
1195        }, format: :json
1196
1197        expect(response).to be_forbidden
1198        expect(user.reload.username).to eq(old_username)
1199      end
1200
1201      it 'should create a staff action log when a staff member changes the username' do
1202        acting_user = Fabricate(:admin)
1203        log_in_user(acting_user)
1204
1205        put :username, params: {
1206          username: user.username, new_username: new_username
1207        }, format: :json
1208
1209        expect(response).to be_success
1210        expect(UserHistory.where(action: UserHistory.actions[:change_username], target_user_id: user.id, acting_user_id: acting_user.id)).to be_present
1211        expect(user.reload.username).to eq(new_username)
1212      end
1213
1214      it 'should return a JSON response with the updated username' do
1215        put :username, params: {
1216          username: user.username, new_username: new_username
1217        }, format: :json
1218
1219        expect(::JSON.parse(response.body)['username']).to eq(new_username)
1220      end
1221
1222    end
1223  end
1224
1225  context '.check_username' do
1226    it 'raises an error without any parameters' do
1227      expect do
1228        get :check_username, format: :json
1229      end.to raise_error(ActionController::ParameterMissing)
1230    end
1231
1232    shared_examples 'when username is unavailable' do
1233      it 'should return success' do
1234        expect(response).to be_success
1235      end
1236
1237      it 'should return available as false in the JSON' do
1238        expect(::JSON.parse(response.body)['available']).to eq(false)
1239      end
1240
1241      it 'should return a suggested username' do
1242        expect(::JSON.parse(response.body)['suggestion']).to be_present
1243      end
1244    end
1245
1246    shared_examples 'when username is available' do
1247      it 'should return success' do
1248        expect(response).to be_success
1249      end
1250
1251      it 'should return available in the JSON' do
1252        expect(::JSON.parse(response.body)['available']).to eq(true)
1253      end
1254    end
1255
1256    it 'returns nothing when given an email param but no username' do
1257      get :check_username, params: { email: 'dood@example.com' }, format: :json
1258      expect(response).to be_success
1259    end
1260
1261    context 'username is available' do
1262      before do
1263        get :check_username, params: { username: 'BruceWayne' }, format: :json
1264      end
1265      include_examples 'when username is available'
1266    end
1267
1268    context 'username is unavailable' do
1269      let!(:user) { Fabricate(:user) }
1270      before do
1271        get :check_username, params: { username: user.username }, format: :json
1272      end
1273      include_examples 'when username is unavailable'
1274    end
1275
1276    shared_examples 'checking an invalid username' do
1277      it 'should return success' do
1278        expect(response).to be_success
1279      end
1280
1281      it 'should not return an available key' do
1282        expect(::JSON.parse(response.body)['available']).to eq(nil)
1283      end
1284
1285      it 'should return an error message' do
1286        expect(::JSON.parse(response.body)['errors']).not_to be_empty
1287      end
1288    end
1289
1290    context 'has invalid characters' do
1291      before do
1292        get :check_username, params: {
1293          username: 'bad username'
1294        }, format: :json
1295      end
1296      include_examples 'checking an invalid username'
1297
1298      it 'should return the invalid characters message' do
1299        expect(::JSON.parse(response.body)['errors']).to include(I18n.t(:'user.username.characters'))
1300      end
1301    end
1302
1303    context 'is too long' do
1304      before do
1305        get :check_username, params: {
1306          username: generate_username(User.username_length.last + 1)
1307        }, format: :json
1308      end
1309      include_examples 'checking an invalid username'
1310
1311      it 'should return the "too long" message' do
1312        expect(::JSON.parse(response.body)['errors']).to include(I18n.t(:'user.username.long', max: User.username_length.end))
1313      end
1314    end
1315
1316    describe 'different case of existing username' do
1317      context "it's my username" do
1318        let!(:user) { Fabricate(:user, username: 'hansolo') }
1319        before do
1320          log_in_user(user)
1321
1322          get :check_username, params: {
1323            username: 'HanSolo'
1324          }, format: :json
1325        end
1326        include_examples 'when username is available'
1327      end
1328
1329      context "it's someone else's username" do
1330        let!(:user) { Fabricate(:user, username: 'hansolo') }
1331        before do
1332          log_in
1333
1334          get :check_username, params: {
1335            username: 'HanSolo'
1336          }, format: :json
1337        end
1338        include_examples 'when username is unavailable'
1339      end
1340
1341      context "an admin changing it for someone else" do
1342        let!(:user) { Fabricate(:user, username: 'hansolo') }
1343        before do
1344          log_in_user(Fabricate(:admin))
1345
1346          get :check_username, params: {
1347            username: 'HanSolo', for_user_id: user.id
1348          }, format: :json
1349        end
1350        include_examples 'when username is available'
1351      end
1352    end
1353  end
1354
1355  describe '#invited' do
1356    it 'returns success' do
1357      user = Fabricate(:user)
1358      get :invited, params: { username: user.username }, format: :json
1359
1360      expect(response).to be_success
1361    end
1362
1363    it 'filters by email' do
1364      inviter = Fabricate(:user)
1365      invitee = Fabricate(:user)
1366      _invite = Fabricate(
1367        :invite,
1368        email: 'billybob@example.com',
1369        invited_by: inviter,
1370        user: invitee
1371      )
1372      Fabricate(
1373        :invite,
1374        email: 'jimtom@example.com',
1375        invited_by: inviter,
1376        user: invitee
1377      )
1378
1379      get :invited, params: {
1380        username: inviter.username, search: 'billybob'
1381      }, format: :json
1382
1383      invites = JSON.parse(response.body)['invites']
1384      expect(invites.size).to eq(1)
1385      expect(invites.first).to include('email' => 'billybob@example.com')
1386    end
1387
1388    it 'filters by username' do
1389      inviter = Fabricate(:user)
1390      invitee = Fabricate(:user, username: 'billybob')
1391      _invite = Fabricate(
1392        :invite,
1393        invited_by: inviter,
1394        email: 'billybob@example.com',
1395        user: invitee
1396      )
1397      Fabricate(
1398        :invite,
1399        invited_by: inviter,
1400        user: Fabricate(:user, username: 'jimtom')
1401      )
1402
1403      get :invited, params: {
1404        username: inviter.username, search: 'billybob'
1405      }, format: :json
1406
1407      invites = JSON.parse(response.body)['invites']
1408      expect(invites.size).to eq(1)
1409      expect(invites.first).to include('email' => 'billybob@example.com')
1410    end
1411
1412    context 'with guest' do
1413      context 'with pending invites' do
1414        it 'does not return invites' do
1415          inviter = Fabricate(:user)
1416          Fabricate(:invite, invited_by: inviter)
1417
1418          get :invited,
1419            params: { username: inviter.username, filter: 'pending' },
1420            format: :json
1421
1422          invites = JSON.parse(response.body)['invites']
1423          expect(invites).to be_empty
1424        end
1425      end
1426
1427      context 'with redeemed invites' do
1428        it 'returns invites' do
1429          inviter = Fabricate(:user)
1430          invitee = Fabricate(:user)
1431          invite = Fabricate(:invite, invited_by: inviter, user: invitee)
1432
1433          get :invited,
1434            params: { username: inviter.username },
1435            format: :json
1436
1437          invites = JSON.parse(response.body)['invites']
1438          expect(invites.size).to eq(1)
1439          expect(invites.first).to include('email' => invite.email)
1440        end
1441      end
1442    end
1443
1444    context 'with authenticated user' do
1445      context 'with pending invites' do
1446        context 'with permission to see pending invites' do
1447          it 'returns invites' do
1448            user = log_in
1449            inviter = Fabricate(:user)
1450            invite = Fabricate(:invite, invited_by: inviter)
1451            stub_guardian(user) do |guardian|
1452              guardian.stubs(:can_see_invite_details?).
1453                with(inviter).returns(true)
1454            end
1455
1456            get :invited, params: {
1457              username: inviter.username, filter: 'pending'
1458            }, format: :json
1459
1460            invites = JSON.parse(response.body)['invites']
1461            expect(invites.size).to eq(1)
1462            expect(invites.first).to include("email" => invite.email)
1463          end
1464        end
1465
1466        context 'without permission to see pending invites' do
1467          it 'does not return invites' do
1468            user = log_in
1469            inviter = Fabricate(:user)
1470            _invitee = Fabricate(:user)
1471            Fabricate(:invite, invited_by: inviter)
1472            stub_guardian(user) do |guardian|
1473              guardian.stubs(:can_see_invite_details?).
1474                with(inviter).returns(false)
1475            end
1476
1477            get :invited, params: {
1478              username: inviter.username, filter: 'pending'
1479            }, format: :json
1480
1481            json = JSON.parse(response.body)['invites']
1482            expect(json).to be_empty
1483          end
1484        end
1485      end
1486
1487      context 'with redeemed invites' do
1488        it 'returns invites' do
1489          _user = log_in
1490          inviter = Fabricate(:user)
1491          invitee = Fabricate(:user)
1492          invite = Fabricate(:invite, invited_by: inviter, user: invitee)
1493
1494          get :invited, params: { username: inviter.username }, format: :json
1495
1496          invites = JSON.parse(response.body)['invites']
1497          expect(invites.size).to eq(1)
1498          expect(invites.first).to include('email' => invite.email)
1499        end
1500      end
1501    end
1502  end
1503
1504  describe '#update' do
1505    context 'with guest' do
1506      it 'raises an error' do
1507        put :update, params: { username: 'guest' }, format: :json
1508        expect(response.status).to eq(403)
1509      end
1510    end
1511
1512    context "as a staff user" do
1513      let!(:user) { log_in(:admin) }
1514
1515      context "uneditable field" do
1516        let!(:user_field) { Fabricate(:user_field, editable: false) }
1517
1518        it "allows staff to edit the field" do
1519          put :update, params: {
1520            username: user.username,
1521            name: 'Jim Tom',
1522            title: "foobar",
1523            user_fields: { user_field.id.to_s => 'happy' }
1524          }, format: :json
1525
1526          expect(response).to be_success
1527
1528          user.reload
1529
1530          expect(user.user_fields[user_field.id.to_s]).to eq('happy')
1531          expect(user.title).to eq("foobar")
1532        end
1533      end
1534
1535    end
1536
1537    context 'with authenticated user' do
1538      context 'with permission to update' do
1539        let!(:user) { log_in(:user) }
1540
1541        it 'allows the update' do
1542          user2 = Fabricate(:user)
1543          user3 = Fabricate(:user)
1544          tags = [Fabricate(:tag), Fabricate(:tag)]
1545
1546          put :update, params: {
1547            username: user.username,
1548            name: 'Jim Tom',
1549            custom_fields: { test: :it },
1550            muted_usernames: "#{user2.username},#{user3.username}",
1551            watched_tags: "#{tags[0].name},#{tags[1].name}"
1552          }, format: :json
1553
1554          expect(response).to be_success
1555
1556          user.reload
1557
1558          expect(user.name).to eq 'Jim Tom'
1559          expect(user.custom_fields['test']).to eq 'it'
1560          expect(user.muted_users.pluck(:username).sort).to eq [user2.username, user3.username].sort
1561          expect(TagUser.where(
1562            user: user,
1563            notification_level: TagUser.notification_levels[:watching]
1564          ).pluck(:tag_id)).to contain_exactly(tags[0].id, tags[1].id)
1565
1566          theme = Theme.create(name: "test", user_selectable: true, user_id: -1)
1567
1568          put :update, params: {
1569            username: user.username,
1570            muted_usernames: "",
1571            theme_key: theme.key,
1572            email_direct: false
1573          }, format: :json
1574
1575          user.reload
1576
1577          expect(user.muted_users.pluck(:username).sort).to be_empty
1578          expect(user.user_option.theme_key).to eq(theme.key)
1579          expect(user.user_option.email_direct).to eq(false)
1580        end
1581
1582        context 'a locale is chosen that differs from I18n.locale' do
1583          it "updates the user's locale" do
1584            I18n.stubs(:locale).returns('fr')
1585
1586            put :update, params: {
1587              username: user.username,
1588              locale: :fa_IR
1589            }, format: :json
1590
1591            expect(User.find_by(username: user.username).locale).to eq('fa_IR')
1592          end
1593
1594        end
1595
1596        context "with user fields" do
1597          context "an editable field" do
1598            let!(:user_field) { Fabricate(:user_field) }
1599            let!(:optional_field) { Fabricate(:user_field, required: false) }
1600
1601            it "should update the user field" do
1602              put :update, params: {
1603                username: user.username, name: 'Jim Tom', user_fields: { user_field.id.to_s => 'happy' }
1604              }, format: :json
1605
1606              expect(response).to be_success
1607              expect(user.user_fields[user_field.id.to_s]).to eq 'happy'
1608            end
1609
1610            it "cannot be updated to blank" do
1611              put :update, params: {
1612                username: user.username, name: 'Jim Tom', user_fields: { user_field.id.to_s => '' }
1613              }, format: :json
1614
1615              expect(response).not_to be_success
1616              expect(user.user_fields[user_field.id.to_s]).not_to eq('happy')
1617            end
1618
1619            it "trims excessively large fields" do
1620              put :update, params: {
1621                username: user.username, name: 'Jim Tom', user_fields: { user_field.id.to_s => ('x' * 3000) }
1622              }, format: :json
1623
1624              expect(user.user_fields[user_field.id.to_s].size).to eq(UserField.max_length)
1625            end
1626
1627            it "should retain existing user fields" do
1628              put :update, params: {
1629                username: user.username, name: 'Jim Tom', user_fields: { user_field.id.to_s => 'happy', optional_field.id.to_s => 'feet' }
1630              }, format: :json
1631
1632              expect(response).to be_success
1633              expect(user.user_fields[user_field.id.to_s]).to eq('happy')
1634              expect(user.user_fields[optional_field.id.to_s]).to eq('feet')
1635
1636              put :update, params: {
1637                username: user.username, name: 'Jim Tom', user_fields: { user_field.id.to_s => 'sad' }
1638              }, format: :json
1639
1640              expect(response).to be_success
1641
1642              user.reload
1643
1644              expect(user.user_fields[user_field.id.to_s]).to eq('sad')
1645              expect(user.user_fields[optional_field.id.to_s]).to eq('feet')
1646            end
1647          end
1648
1649          context "uneditable field" do
1650            let!(:user_field) { Fabricate(:user_field, editable: false) }
1651
1652            it "does not update the user field" do
1653              put :update, params: {
1654                username: user.username, name: 'Jim Tom', user_fields: { user_field.id.to_s => 'happy' }
1655              }, format: :json
1656
1657              expect(response).to be_success
1658              expect(user.user_fields[user_field.id.to_s]).to be_blank
1659            end
1660          end
1661
1662        end
1663
1664        it 'returns user JSON' do
1665          put :update, params: { username: user.username }, format: :json
1666
1667          json = JSON.parse(response.body)
1668          expect(json['user']['id']).to eq user.id
1669        end
1670
1671      end
1672
1673      context 'without permission to update' do
1674        it 'does not allow the update' do
1675          user = Fabricate(:user, name: 'Billy Bob')
1676          log_in_user(user)
1677          Guardian.any_instance.expects(:can_edit?).with(user).returns(false)
1678
1679          put :update,
1680            params: { username: user.username, name: 'Jim Tom' },
1681            format: :json
1682
1683          expect(response).to be_forbidden
1684          expect(user.reload.name).not_to eq 'Jim Tom'
1685        end
1686      end
1687    end
1688  end
1689
1690  describe "badge_card" do
1691    let(:user) { Fabricate(:user) }
1692    let(:badge) { Fabricate(:badge) }
1693    let(:user_badge) { BadgeGranter.grant(badge, user) }
1694
1695    it "sets the user's card image to the badge" do
1696      log_in_user user
1697      put :update_card_badge, params: {
1698        user_badge_id: user_badge.id, username: user.username
1699      }, format: :json
1700
1701      expect(user.user_profile.reload.card_image_badge_id).to be_blank
1702      badge.update_attributes image: "wat.com/wat.jpg"
1703
1704      put :update_card_badge, params: {
1705        user_badge_id: user_badge.id, username: user.username
1706      }, format: :json
1707
1708      expect(user.user_profile.reload.card_image_badge_id).to eq(badge.id)
1709
1710      # Can set to nothing
1711      put :update_card_badge, params: {
1712        username: user.username
1713      }, format: :json
1714
1715      expect(user.user_profile.reload.card_image_badge_id).to be_blank
1716    end
1717  end
1718
1719  describe "badge_title" do
1720    let(:user) { Fabricate(:user) }
1721    let(:badge) { Fabricate(:badge) }
1722    let(:user_badge) { BadgeGranter.grant(badge, user) }
1723
1724    it "sets the user's title to the badge name if it is titleable" do
1725      log_in_user user
1726
1727      put :badge_title, params: {
1728        user_badge_id: user_badge.id, username: user.username
1729      }, format: :json
1730
1731      expect(user.reload.title).not_to eq(badge.display_name)
1732      badge.update_attributes allow_title: true
1733
1734      put :badge_title, params: {
1735        user_badge_id: user_badge.id, username: user.username
1736      }, format: :json
1737
1738      expect(user.reload.title).to eq(badge.display_name)
1739      expect(user.user_profile.badge_granted_title).to eq(true)
1740
1741      user.title = "testing"
1742      user.save
1743      user.user_profile.reload
1744      expect(user.user_profile.badge_granted_title).to eq(false)
1745
1746    end
1747  end
1748
1749  describe "badge_title with overrided name" do
1750    let(:user) { Fabricate(:user) }
1751    let(:badge) { Fabricate(:badge, name: 'Demogorgon', allow_title: true) }
1752    let(:user_badge) { BadgeGranter.grant(badge, user) }
1753
1754    before do
1755      TranslationOverride.upsert!('en', 'badges.demogorgon.name', 'Boss')
1756    end
1757
1758    after do
1759      TranslationOverride.revert!('en', ['badges.demogorgon.name'])
1760    end
1761
1762    it "uses the badge display name as user title" do
1763      log_in_user user
1764
1765      put :badge_title, params: {
1766        user_badge_id: user_badge.id, username: user.username
1767      }, format: :json
1768
1769      expect(user.reload.title).to eq(badge.display_name)
1770    end
1771  end
1772
1773  describe 'send_activation_email' do
1774    context 'for an existing user' do
1775      let(:user) { Fabricate(:user, active: false) }
1776
1777      context 'for an activated account with email confirmed' do
1778        it 'fails' do
1779          active_user = Fabricate(:user, active: true)
1780          email_token = active_user.email_tokens.create(email: active_user.email).token
1781          EmailToken.confirm(email_token)
1782          session[SessionController::ACTIVATE_USER_KEY] = active_user.id
1783
1784          post :send_activation_email, params: {
1785            username: active_user.username
1786          }, format: :json
1787
1788          expect(response.status).to eq(409)
1789
1790          expect(JSON.parse(response.body)['errors']).to include(I18n.t(
1791            'activation.activated'
1792          ))
1793
1794          expect(session[SessionController::ACTIVATE_USER_KEY]).to eq(nil)
1795        end
1796      end
1797
1798      context 'for an activated account with unconfirmed email' do
1799        it 'should send an email' do
1800          unconfirmed_email_user = Fabricate(:user, active: true)
1801          unconfirmed_email_user.email_tokens.create(email: unconfirmed_email_user.email)
1802          session[SessionController::ACTIVATE_USER_KEY] = unconfirmed_email_user.id
1803          Jobs.expects(:enqueue).with(:critical_user_email, has_entries(type: :signup, to_address: unconfirmed_email_user.email))
1804
1805          post :send_activation_email, params: {
1806            username: unconfirmed_email_user.username
1807          }, format: :json
1808
1809          expect(response.status).to eq(200)
1810
1811          expect(session[SessionController::ACTIVATE_USER_KEY]).to eq(nil)
1812        end
1813      end
1814
1815      context "approval is enabled" do
1816        before do
1817          SiteSetting.must_approve_users = true
1818        end
1819
1820        it "should raise an error" do
1821          unconfirmed_email_user = Fabricate(:user, active: true)
1822          unconfirmed_email_user.email_tokens.create(email: unconfirmed_email_user.email)
1823          session[SessionController::ACTIVATE_USER_KEY] = unconfirmed_email_user.id
1824          post :send_activation_email, params: {
1825            username: unconfirmed_email_user.username
1826          }, format: :json
1827
1828          expect(response.status).to eq(403)
1829        end
1830      end
1831
1832      describe 'when user does not have a valid session' do
1833        it 'should not be valid' do
1834          user = Fabricate(:user)
1835          post :send_activation_email, params: {
1836            username: user.username
1837          }, format: :json
1838
1839          expect(response.status).to eq(403)
1840        end
1841
1842        it 'should allow staff regardless' do
1843          log_in :admin
1844          user = Fabricate(:user, active: false)
1845
1846          post :send_activation_email, params: {
1847            username: user.username
1848          }, format: :json
1849
1850          expect(response.status).to eq(200)
1851        end
1852      end
1853
1854      context 'with a valid email_token' do
1855        it 'should send the activation email' do
1856          session[SessionController::ACTIVATE_USER_KEY] = user.id
1857          Jobs.expects(:enqueue).with(:critical_user_email, has_entries(type: :signup))
1858
1859          post :send_activation_email, params: {
1860            username: user.username
1861          }, format: :json
1862
1863          expect(session[SessionController::ACTIVATE_USER_KEY]).to eq(nil)
1864        end
1865      end
1866
1867      context 'without an existing email_token' do
1868        before do
1869          user.email_tokens.each { |t| t.destroy }
1870          user.reload
1871        end
1872
1873        it 'should generate a new token' do
1874          expect {
1875            session[SessionController::ACTIVATE_USER_KEY] = user.id
1876
1877            post :send_activation_email,
1878              params: { username: user.username },
1879              format: :json
1880          }.to change { user.reload.email_tokens.count }.by(1)
1881        end
1882
1883        it 'should send an email' do
1884          session[SessionController::ACTIVATE_USER_KEY] = user.id
1885          Jobs.expects(:enqueue).with(:critical_user_email, has_entries(type: :signup))
1886
1887          post :send_activation_email,
1888            params: { username: user.username },
1889            format: :json
1890
1891          expect(session[SessionController::ACTIVATE_USER_KEY]).to eq(nil)
1892        end
1893      end
1894    end
1895
1896    context 'when username does not exist' do
1897      it 'should not send an email' do
1898        Jobs.expects(:enqueue).never
1899
1900        post :send_activation_email,
1901          params: { username: 'nopenopenopenope' },
1902          format: :json
1903      end
1904    end
1905  end
1906
1907  describe '.pick_avatar' do
1908
1909    it 'raises an error when not logged in' do
1910      put :pick_avatar, params: {
1911        username: 'asdf', avatar_id: 1, type: "custom"
1912      }, format: :json
1913      expect(response.status).to eq(403)
1914    end
1915
1916    context 'while logged in' do
1917
1918      let!(:user) { log_in }
1919      let(:upload) { Fabricate(:upload) }
1920
1921      it "raises an error when you don't have permission to toggle the avatar" do
1922        another_user = Fabricate(:user)
1923        put :pick_avatar, params: {
1924          username: another_user.username, upload_id: upload.id, type: "custom"
1925        }, format: :json
1926
1927        expect(response).to be_forbidden
1928      end
1929
1930      it "raises an error when sso_overrides_avatar is disabled" do
1931        SiteSetting.sso_overrides_avatar = true
1932        put :pick_avatar, params: {
1933          username: user.username, upload_id: upload.id, type: "custom"
1934        }, format: :json
1935
1936        expect(response).to_not be_success
1937      end
1938
1939      it "raises an error when selecting the custom/uploaded avatar and allow_uploaded_avatars is disabled" do
1940        SiteSetting.allow_uploaded_avatars = false
1941        put :pick_avatar, params: {
1942          username: user.username, upload_id: upload.id, type: "custom"
1943        }, format: :json
1944
1945        expect(response).to_not be_success
1946      end
1947
1948      it 'can successfully pick the system avatar' do
1949        put :pick_avatar, params: {
1950          username: user.username
1951        }, format: :json
1952
1953        expect(response).to be_success
1954        expect(user.reload.uploaded_avatar_id).to eq(nil)
1955      end
1956
1957      it 'can successfully pick a gravatar' do
1958        put :pick_avatar, params: {
1959          username: user.username, upload_id: upload.id, type: "gravatar"
1960        }, format: :json
1961
1962        expect(response).to be_success
1963        expect(user.reload.uploaded_avatar_id).to eq(upload.id)
1964        expect(user.user_avatar.reload.gravatar_upload_id).to eq(upload.id)
1965      end
1966
1967      it 'can successfully pick a custom avatar' do
1968        put :pick_avatar, params: {
1969          username: user.username, upload_id: upload.id, type: "custom"
1970        }, format: :json
1971
1972        expect(response).to be_success
1973        expect(user.reload.uploaded_avatar_id).to eq(upload.id)
1974        expect(user.user_avatar.reload.custom_upload_id).to eq(upload.id)
1975      end
1976
1977    end
1978
1979  end
1980
1981  describe '.destroy_user_image' do
1982
1983    it 'raises an error when not logged in' do
1984      delete :destroy_user_image,
1985        params: { type: 'profile_background', username: 'asdf' },
1986        format: :json
1987      expect(response.status).to eq(403)
1988    end
1989
1990    context 'while logged in' do
1991
1992      let!(:user) { log_in }
1993
1994      it 'raises an error when you don\'t have permission to clear the profile background' do
1995        Guardian.any_instance.expects(:can_edit?).with(user).returns(false)
1996
1997        delete :destroy_user_image,
1998          params: { username: user.username, type: 'profile_background' },
1999          format: :json
2000
2001        expect(response).to be_forbidden
2002      end
2003
2004      it "requires the `type` param" do
2005        expect do
2006          delete :destroy_user_image, params: { username: user.username }, format: :json
2007        end.to raise_error(ActionController::ParameterMissing)
2008      end
2009
2010      it "only allows certain `types`" do
2011        delete :destroy_user_image,
2012          params: { username: user.username, type: 'wat' },
2013          format: :json
2014        expect(response.status).to eq(400)
2015      end
2016
2017      it 'can clear the profile background' do
2018        delete :destroy_user_image, params: {
2019          type: 'profile_background', username: user.username
2020        }, format: :json
2021
2022        expect(user.reload.user_profile.profile_background).to eq("")
2023        expect(response).to be_success
2024      end
2025
2026    end
2027  end
2028
2029  describe '.destroy' do
2030    it 'raises an error when not logged in' do
2031      delete :destroy, params: { username: 'nobody' }, format: :json
2032      expect(response.status).to eq(403)
2033    end
2034
2035    context 'while logged in' do
2036      let!(:user) { log_in }
2037
2038      it 'raises an error when you cannot delete your account' do
2039        Guardian.any_instance.stubs(:can_delete_user?).returns(false)
2040        UserDestroyer.any_instance.expects(:destroy).never
2041        delete :destroy, params: { username: user.username }, format: :json
2042        expect(response).to be_forbidden
2043      end
2044
2045      it "raises an error when you try to delete someone else's account" do
2046        UserDestroyer.any_instance.expects(:destroy).never
2047        delete :destroy, params: { username: Fabricate(:user).username }, format: :json
2048        expect(response).to be_forbidden
2049      end
2050
2051      it "deletes your account when you're allowed to" do
2052        Guardian.any_instance.stubs(:can_delete_user?).returns(true)
2053        UserDestroyer.any_instance.expects(:destroy).with(user, anything).returns(user)
2054        delete :destroy, params: { username: user.username }, format: :json
2055        expect(response).to be_success
2056      end
2057    end
2058  end
2059
2060  describe '.my_redirect' do
2061
2062    it "redirects if the user is not logged in" do
2063      get :my_redirect, params: { path: "wat" }, format: :json
2064      expect(response).not_to be_success
2065      expect(response).to be_redirect
2066    end
2067
2068    context "when the user is logged in" do
2069      let!(:user) { log_in }
2070
2071      it "will not redirect to an invalid path" do
2072        get :my_redirect, params: { path: "wat/..password.txt" }, format: :json
2073        expect(response).not_to be_redirect
2074      end
2075
2076      it "will redirect to an valid path" do
2077        get :my_redirect, params: { path: "preferences" }, format: :json
2078        expect(response).to be_redirect
2079      end
2080
2081      it "permits forward slashes" do
2082        get :my_redirect, params: { path: "activity/posts" }, format: :json
2083        expect(response).to be_redirect
2084      end
2085    end
2086  end
2087
2088  describe '.check_emails' do
2089
2090    it 'raises an error when not logged in' do
2091      put :check_emails, params: { username: 'zogstrip' }, format: :json
2092      expect(response.status).to eq(403)
2093    end
2094
2095    context 'while logged in' do
2096      let!(:user) { log_in }
2097
2098      it "raises an error when you aren't allowed to check emails" do
2099        Guardian.any_instance.expects(:can_check_emails?).returns(false)
2100
2101        put :check_emails,
2102          params: { username: Fabricate(:user).username },
2103          format: :json
2104
2105        expect(response).to be_forbidden
2106      end
2107
2108      it "returns both email and associated_accounts when you're allowed to see them" do
2109        Guardian.any_instance.expects(:can_check_emails?).returns(true)
2110
2111        put :check_emails,
2112          params: { username: Fabricate(:user).username },
2113          format: :json
2114
2115        expect(response).to be_success
2116        json = JSON.parse(response.body)
2117        expect(json["email"]).to be_present
2118        expect(json["associated_accounts"]).to be_present
2119      end
2120
2121      it "works on inactive users" do
2122        inactive_user = Fabricate(:user, active: false)
2123        Guardian.any_instance.expects(:can_check_emails?).returns(true)
2124
2125        put :check_emails, params: {
2126          username: inactive_user.username
2127        }, format: :json
2128
2129        expect(response).to be_success
2130        json = JSON.parse(response.body)
2131        expect(json["email"]).to be_present
2132        expect(json["associated_accounts"]).to be_present
2133      end
2134
2135    end
2136
2137  end
2138
2139  describe ".is_local_username" do
2140
2141    let(:user) { Fabricate(:user) }
2142    let(:group) { Fabricate(:group, name: "Discourse") }
2143    let(:topic) { Fabricate(:topic) }
2144    let(:allowed_user) { Fabricate(:user) }
2145    let(:private_topic) { Fabricate(:private_message_topic, user: allowed_user) }
2146
2147    it "finds the user" do
2148      get :is_local_username, params: {
2149        username: user.username
2150      }, format: :json
2151
2152      expect(response).to be_success
2153      json = JSON.parse(response.body)
2154      expect(json["valid"][0]).to eq(user.username)
2155    end
2156
2157    it "finds the group" do
2158      get :is_local_username, params: {
2159        username: group.name
2160      }, format: :json
2161
2162      expect(response).to be_success
2163      json = JSON.parse(response.body)
2164      expect(json["valid_groups"][0]).to eq(group.name)
2165    end
2166
2167    it "supports multiples usernames" do
2168      get :is_local_username, params: {
2169        usernames: [user.username, "system"]
2170      }, format: :json
2171
2172      expect(response).to be_success
2173      json = JSON.parse(response.body)
2174      expect(json["valid"].size).to eq(2)
2175    end
2176
2177    it "never includes staged accounts" do
2178      staged = Fabricate(:user, staged: true)
2179
2180      get :is_local_username, params: {
2181        usernames: [staged.username]
2182      }, format: :json
2183
2184      expect(response).to be_success
2185      json = JSON.parse(response.body)
2186      expect(json["valid"].size).to eq(0)
2187    end
2188
2189    it "returns user who cannot see topic" do
2190      Guardian.any_instance.expects(:can_see?).with(topic).returns(false)
2191
2192      get :is_local_username, params: {
2193        usernames: [user.username], topic_id: topic.id
2194      }, format: :json
2195
2196      expect(response).to be_success
2197      json = JSON.parse(response.body)
2198      expect(json["cannot_see"].size).to eq(1)
2199    end
2200
2201    it "never returns a user who can see the topic" do
2202      Guardian.any_instance.expects(:can_see?).with(topic).returns(true)
2203
2204      get :is_local_username, params: {
2205        usernames: [user.username], topic_id: topic.id
2206      }, format: :json
2207
2208      expect(response).to be_success
2209      json = JSON.parse(response.body)
2210      expect(json["cannot_see"].size).to eq(0)
2211    end
2212
2213    it "returns user who cannot see a private topic" do
2214      Guardian.any_instance.expects(:can_see?).with(private_topic).returns(false)
2215
2216      get :is_local_username, params: {
2217        usernames: [user.username], topic_id: private_topic.id
2218      }, format: :json
2219
2220      expect(response).to be_success
2221      json = JSON.parse(response.body)
2222      expect(json["cannot_see"].size).to eq(1)
2223    end
2224
2225    it "never returns a user who can see the topic" do
2226      Guardian.any_instance.expects(:can_see?).with(private_topic).returns(true)
2227
2228      get :is_local_username, params: {
2229        usernames: [allowed_user.username], topic_id: private_topic.id
2230      }, format: :json
2231
2232      expect(response).to be_success
2233      json = JSON.parse(response.body)
2234      expect(json["cannot_see"].size).to eq(0)
2235    end
2236
2237  end
2238
2239  describe '.topic_tracking_state' do
2240    let(:user) { Fabricate(:user) }
2241
2242    context 'anon' do
2243      it "raises an error on anon for topic_tracking_state" do
2244        get :topic_tracking_state, params: { username: user.username }, format: :json
2245        expect(response.status).to eq(403)
2246      end
2247    end
2248
2249    context 'logged on' do
2250      it "detects new topic" do
2251        log_in_user(user)
2252
2253        topic = Fabricate(:topic)
2254        get :topic_tracking_state, params: { username: user.username }, format: :json
2255
2256        states = JSON.parse(response.body)
2257
2258        expect(states[0]["topic_id"]).to eq(topic.id)
2259      end
2260    end
2261  end
2262
2263  describe '.summary' do
2264
2265    it "generates summary info" do
2266      user = Fabricate(:user)
2267      create_post(user: user)
2268
2269      get :summary, params: { username: user.username_lower }, format: :json
2270      expect(response).to be_success
2271      json = JSON.parse(response.body)
2272
2273      expect(json["user_summary"]["topic_count"]).to eq(1)
2274      expect(json["user_summary"]["post_count"]).to eq(0)
2275    end
2276  end
2277
2278  describe ".confirm_admin" do
2279    it "fails without a valid token" do
2280      expect {
2281        get :confirm_admin, params: { token: 'invalid-token' }, format: :json
2282      }.to raise_error(ActionController::UrlGenerationError)
2283    end
2284
2285    it "fails with a missing token" do
2286      get :confirm_admin, params: { token: 'a0a0a0a0a0' }, format: :json
2287      expect(response).to_not be_success
2288    end
2289
2290    it "succeeds with a valid code as anonymous" do
2291      user = Fabricate(:user)
2292      ac = AdminConfirmation.new(user, Fabricate(:admin))
2293      ac.create_confirmation
2294      get :confirm_admin, params: { token: ac.token }
2295      expect(response).to be_success
2296
2297      user.reload
2298      expect(user.admin?).to eq(false)
2299    end
2300
2301    it "succeeds with a valid code when logged in as that user" do
2302      admin = log_in(:admin)
2303      user = Fabricate(:user)
2304
2305      ac = AdminConfirmation.new(user, admin)
2306      ac.create_confirmation
2307      get :confirm_admin, params: { token: ac.token }
2308      expect(response).to be_success
2309
2310      user.reload
2311      expect(user.admin?).to eq(false)
2312    end
2313
2314    it "fails if you're logged in as a different account" do
2315      log_in(:admin)
2316      user = Fabricate(:user)
2317
2318      ac = AdminConfirmation.new(user, Fabricate(:admin))
2319      ac.create_confirmation
2320      get :confirm_admin, params: { token: ac.token }, format: :json
2321      expect(response).to_not be_success
2322
2323      user.reload
2324      expect(user.admin?).to eq(false)
2325    end
2326
2327    describe "post" do
2328      it "gives the user admin access when POSTed" do
2329        user = Fabricate(:user)
2330        ac = AdminConfirmation.new(user, Fabricate(:admin))
2331        ac.create_confirmation
2332        post :confirm_admin, params: { token: ac.token }
2333        expect(response).to be_success
2334
2335        user.reload
2336        expect(user.admin?).to eq(true)
2337      end
2338    end
2339
2340  end
2341
2342  describe '.update_activation_email' do
2343
2344    context "with a session variable" do
2345
2346      it "raises an error with an invalid session value" do
2347        session[SessionController::ACTIVATE_USER_KEY] = 1234
2348
2349        put :update_activation_email, params: {
2350          email: 'updatedemail@example.com'
2351        }, format: :json
2352
2353        expect(response).to_not be_success
2354      end
2355
2356      it "raises an error for an active user" do
2357        user = Fabricate(:walter_white)
2358        session[SessionController::ACTIVATE_USER_KEY] = user.id
2359
2360        put :update_activation_email, params: {
2361          email: 'updatedemail@example.com'
2362        }, format: :json
2363
2364        expect(response).to_not be_success
2365      end
2366
2367      it "raises an error when logged in" do
2368        moderator = log_in(:moderator)
2369        session[SessionController::ACTIVATE_USER_KEY] = moderator.id
2370
2371        put :update_activation_email, params: {
2372          email: 'updatedemail@example.com'
2373        }, format: :json
2374
2375        expect(response).to_not be_success
2376      end
2377
2378      it "raises an error when the new email is taken" do
2379        active_user = Fabricate(:user)
2380        user = Fabricate(:inactive_user)
2381        session[SessionController::ACTIVATE_USER_KEY] = user.id
2382
2383        put :update_activation_email, params: {
2384          email: active_user.email
2385        }, format: :json
2386
2387        expect(response).to_not be_success
2388      end
2389
2390      it "raises an error when the email is blacklisted" do
2391        user = Fabricate(:inactive_user)
2392        SiteSetting.email_domains_blacklist = 'example.com'
2393        session[SessionController::ACTIVATE_USER_KEY] = user.id
2394        put :update_activation_email, params: { email: 'test@example.com' }, format: :json
2395        expect(response).to_not be_success
2396      end
2397
2398      it "can be updated" do
2399        user = Fabricate(:inactive_user)
2400        token = user.email_tokens.first
2401
2402        session[SessionController::ACTIVATE_USER_KEY] = user.id
2403
2404        put :update_activation_email, params: {
2405          email: 'updatedemail@example.com'
2406        }, format: :json
2407
2408        expect(response).to be_success
2409
2410        user.reload
2411        expect(user.email).to eq('updatedemail@example.com')
2412        expect(user.email_tokens.where(email: 'updatedemail@example.com', expired: false)).to be_present
2413
2414        token.reload
2415        expect(token.expired?).to eq(true)
2416      end
2417    end
2418
2419    context "with a username and password" do
2420      it "raises an error with an invalid username" do
2421        put :update_activation_email, params: {
2422          username: 'eviltrout',
2423          password: 'invalid-password',
2424          email: 'updatedemail@example.com'
2425        }, format: :json
2426
2427        expect(response).to_not be_success
2428      end
2429
2430      it "raises an error with an invalid password" do
2431        put :update_activation_email, params: {
2432          username: Fabricate(:inactive_user).username,
2433          password: 'invalid-password',
2434          email: 'updatedemail@example.com'
2435        }, format: :json
2436
2437        expect(response).to_not be_success
2438      end
2439
2440      it "raises an error for an active user" do
2441        put :update_activation_email, params: {
2442          username: Fabricate(:walter_white).username,
2443          password: 'letscook',
2444          email: 'updatedemail@example.com'
2445        }, format: :json
2446
2447        expect(response).to_not be_success
2448      end
2449
2450      it "raises an error when logged in" do
2451        log_in(:moderator)
2452
2453        put :update_activation_email, params: {
2454          username: Fabricate(:inactive_user).username,
2455          password: 'qwerqwer123',
2456          email: 'updatedemail@example.com'
2457        }, format: :json
2458
2459        expect(response).to_not be_success
2460      end
2461
2462      it "raises an error when the new email is taken" do
2463        user = Fabricate(:user)
2464
2465        put :update_activation_email, params: {
2466          username: Fabricate(:inactive_user).username,
2467          password: 'qwerqwer123',
2468          email: user.email
2469        }, format: :json
2470
2471        expect(response).to_not be_success
2472      end
2473
2474      it "can be updated" do
2475        user = Fabricate(:inactive_user)
2476        token = user.email_tokens.first
2477
2478        put :update_activation_email, params: {
2479          username: user.username,
2480          password: 'qwerqwer123',
2481          email: 'updatedemail@example.com'
2482        }, format: :json
2483
2484        expect(response).to be_success
2485
2486        user.reload
2487        expect(user.email).to eq('updatedemail@example.com')
2488        expect(user.email_tokens.where(email: 'updatedemail@example.com', expired: false)).to be_present
2489
2490        token.reload
2491        expect(token.expired?).to eq(true)
2492      end
2493    end
2494  end
2495end