PageRenderTime 8ms CodeModel.GetById 3ms app.highlight 200ms 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

Large files files are truncated, but you can click here to view the full 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'

Large files files are truncated, but you can click here to view the full file