PageRenderTime 67ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 0ms

/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

  1. require 'rails_helper'
  2. describe UsersController do
  3. describe '.show' do
  4. context "anon" do
  5. let(:user) { Discourse.system_user }
  6. it "returns success" do
  7. get :show, params: { username: user.username }, format: :json
  8. expect(response).to be_success
  9. end
  10. it "should redirect to login page for anonymous user when profiles are hidden" do
  11. SiteSetting.hide_user_profiles_from_public = true
  12. get :show, params: { username: user.username }, format: :json
  13. expect(response).to redirect_to '/login'
  14. end
  15. end
  16. context "logged in" do
  17. let(:user) { log_in }
  18. it 'returns success' do
  19. get :show, params: { username: user.username, format: :json }, format: :json
  20. expect(response).to be_success
  21. json = JSON.parse(response.body)
  22. expect(json["user"]["has_title_badges"]).to eq(false)
  23. end
  24. it "returns not found when the username doesn't exist" do
  25. get :show, params: { username: 'madeuppity' }, format: :json
  26. expect(response).not_to be_success
  27. end
  28. it 'returns not found when the user is inactive' do
  29. inactive = Fabricate(:user, active: false)
  30. get :show, params: { username: inactive.username }, format: :json
  31. expect(response).not_to be_success
  32. end
  33. it 'returns success when show_inactive_accounts is true and user is logged in' do
  34. SiteSetting.show_inactive_accounts = true
  35. log_in_user(user)
  36. inactive = Fabricate(:user, active: false)
  37. get :show, params: { username: inactive.username }, format: :json
  38. expect(response).to be_success
  39. end
  40. it "raises an error on invalid access" do
  41. Guardian.any_instance.expects(:can_see?).with(user).returns(false)
  42. get :show, params: { username: user.username }, format: :json
  43. expect(response).to be_forbidden
  44. end
  45. describe "user profile views" do
  46. let(:other_user) { Fabricate(:user) }
  47. it "should track a user profile view for a signed in user" do
  48. UserProfileView.expects(:add).with(other_user.user_profile.id, request.remote_ip, user.id)
  49. get :show, params: { username: other_user.username }, format: :json
  50. end
  51. it "should not track a user profile view for a user viewing his own profile" do
  52. UserProfileView.expects(:add).never
  53. get :show, params: { username: user.username }, format: :json
  54. end
  55. it "should track a user profile view for an anon user" do
  56. UserProfileView.expects(:add).with(other_user.user_profile.id, request.remote_ip, nil)
  57. get :show, params: { username: other_user.username }, format: :json
  58. end
  59. it "skips tracking" do
  60. UserProfileView.expects(:add).never
  61. get :show, params: { username: user.username, skip_track_visit: true }, format: :json
  62. end
  63. end
  64. context "fetching a user by external_id" do
  65. before { user.create_single_sign_on_record(external_id: '997', last_payload: '') }
  66. it "returns fetch for a matching external_id" do
  67. get :show, params: { external_id: '997' }, format: :json
  68. expect(response).to be_success
  69. end
  70. it "returns not found when external_id doesn't match" do
  71. get :show, params: { external_id: '99' }, format: :json
  72. expect(response).not_to be_success
  73. end
  74. end
  75. describe "include_post_count_for" do
  76. let(:admin) { Fabricate(:admin) }
  77. let(:topic) { Fabricate(:topic) }
  78. before do
  79. Fabricate(:post, user: user, topic: topic)
  80. Fabricate(:post, user: admin, topic: topic)
  81. Fabricate(:post, user: admin, topic: topic, post_type: Post.types[:whisper])
  82. end
  83. it "includes only visible posts" do
  84. get :show,
  85. params: { username: admin.username, include_post_count_for: topic.id },
  86. format: :json
  87. topic_post_count = JSON.parse(response.body).dig("user", "topic_post_count")
  88. expect(topic_post_count[topic.id.to_s]).to eq(1)
  89. end
  90. it "includes all post types for staff members" do
  91. log_in_user(admin)
  92. get :show,
  93. params: { username: admin.username, include_post_count_for: topic.id },
  94. format: :json
  95. topic_post_count = JSON.parse(response.body).dig("user", "topic_post_count")
  96. expect(topic_post_count[topic.id.to_s]).to eq(2)
  97. end
  98. end
  99. end
  100. end
  101. describe '.activate_account' do
  102. before do
  103. UsersController.any_instance.stubs(:honeypot_or_challenge_fails?).returns(false)
  104. end
  105. context 'invalid token' do
  106. it 'return success' do
  107. EmailToken.expects(:confirm).with('asdfasdf').returns(nil)
  108. put :perform_account_activation, params: { token: 'asdfasdf' }
  109. expect(response).to be_success
  110. expect(flash[:error]).to be_present
  111. end
  112. end
  113. context 'valid token' do
  114. let(:user) { Fabricate(:user) }
  115. context 'welcome message' do
  116. before do
  117. EmailToken.expects(:confirm).with('asdfasdf').returns(user)
  118. end
  119. it 'enqueues a welcome message if the user object indicates so' do
  120. user.send_welcome_message = true
  121. user.expects(:enqueue_welcome_message).with('welcome_user')
  122. put :perform_account_activation, params: { token: 'asdfasdf' }
  123. end
  124. it "doesn't enqueue the welcome message if the object returns false" do
  125. user.send_welcome_message = false
  126. user.expects(:enqueue_welcome_message).with('welcome_user').never
  127. put :perform_account_activation, params: { token: 'asdfasdf' }
  128. end
  129. end
  130. context "honeypot" do
  131. it "raises an error if the honeypot is invalid" do
  132. UsersController.any_instance.stubs(:honeypot_or_challenge_fails?).returns(true)
  133. put :perform_account_activation, params: { token: 'asdfasdf' }, format: :json
  134. expect(response).not_to be_success
  135. end
  136. end
  137. context 'response' do
  138. render_views
  139. before do
  140. Guardian.any_instance.expects(:can_access_forum?).returns(true)
  141. EmailToken.expects(:confirm).with('asdfasdf').returns(user)
  142. end
  143. it 'correctly logs on user' do
  144. events = DiscourseEvent.track_events do
  145. put :perform_account_activation, params: { token: 'asdfasdf' }
  146. end
  147. expect(events.map { |event| event[:event_name] }).to include(
  148. :user_logged_in, :user_first_logged_in
  149. )
  150. expect(response).to be_success
  151. expect(flash[:error]).to be_blank
  152. expect(session[:current_user_id]).to be_present
  153. expect(response).to be_success
  154. expect(CGI.unescapeHTML(response.body))
  155. .to_not include(I18n.t('activation.approval_required'))
  156. end
  157. end
  158. context 'user is not approved' do
  159. render_views
  160. before do
  161. SiteSetting.must_approve_users = true
  162. EmailToken.expects(:confirm).with('asdfasdf').returns(user)
  163. put :perform_account_activation, params: { token: 'asdfasdf' }
  164. end
  165. it 'should return the right response' do
  166. expect(response).to be_success
  167. expect(CGI.unescapeHTML(response.body))
  168. .to include(I18n.t('activation.approval_required'))
  169. expect(response.body).to_not have_tag(:script, with: {
  170. src: '/assets/application.js'
  171. })
  172. expect(flash[:error]).to be_blank
  173. expect(session[:current_user_id]).to be_blank
  174. end
  175. end
  176. end
  177. end
  178. describe '#perform_account_activation' do
  179. describe 'when cookies contains a destination URL' do
  180. let(:token) { 'asdadwewq' }
  181. let(:user) { Fabricate(:user) }
  182. before do
  183. UsersController.any_instance.stubs(:honeypot_or_challenge_fails?).returns(false)
  184. EmailToken.expects(:confirm).with(token).returns(user)
  185. end
  186. it 'should redirect to the URL' do
  187. destination_url = 'http://thisisasite.com/somepath'
  188. request.cookies[:destination_url] = destination_url
  189. put :perform_account_activation, params: { token: token }
  190. expect(response).to redirect_to(destination_url)
  191. end
  192. end
  193. end
  194. describe '.password_reset' do
  195. let(:user) { Fabricate(:user) }
  196. context "you can view it even if login is required" do
  197. it "returns success" do
  198. SiteSetting.login_required = true
  199. get :password_reset, params: { token: 'asdfasdf' }
  200. expect(response).to be_success
  201. end
  202. end
  203. context 'missing token' do
  204. render_views
  205. before do
  206. get :password_reset, params: { token: SecureRandom.hex }
  207. end
  208. it 'disallows login' do
  209. expect(response).to be_success
  210. expect(CGI.unescapeHTML(response.body))
  211. .to include(I18n.t('password_reset.no_token'))
  212. expect(response.body).to_not have_tag(:script, with: {
  213. src: '/assets/application.js'
  214. })
  215. expect(session[:current_user_id]).to be_blank
  216. end
  217. end
  218. context 'invalid token' do
  219. render_views
  220. it 'disallows login' do
  221. get :password_reset, params: { token: "evil_trout!" }
  222. expect(response).to be_success
  223. expect(CGI.unescapeHTML(response.body))
  224. .to include(I18n.t('password_reset.no_token'))
  225. expect(response.body).to_not have_tag(:script, with: {
  226. src: '/assets/application.js'
  227. })
  228. expect(session[:current_user_id]).to be_blank
  229. end
  230. it "responds with proper error message" do
  231. put :password_reset, params: {
  232. token: "evil_trout!", password: "awesomeSecretPassword"
  233. }, format: :json
  234. expect(response).to be_success
  235. expect(JSON.parse(response.body)["message"]).to eq(I18n.t('password_reset.no_token'))
  236. expect(session[:current_user_id]).to be_blank
  237. end
  238. end
  239. context 'valid token' do
  240. render_views
  241. context 'when rendered' do
  242. it 'renders referrer never on get requests' do
  243. user = Fabricate(:user)
  244. token = user.email_tokens.create(email: user.email).token
  245. get :password_reset, params: { token: token }
  246. expect(response.body).to include('<meta name="referrer" content="never">')
  247. end
  248. end
  249. it 'returns success' do
  250. user = Fabricate(:user)
  251. user_auth_token = UserAuthToken.generate!(user_id: user.id)
  252. token = user.email_tokens.create(email: user.email).token
  253. get :password_reset, params: { token: token }
  254. events = DiscourseEvent.track_events do
  255. put :password_reset,
  256. params: { token: token, password: 'hg9ow8yhg98o' }
  257. end
  258. expect(events.map { |event| event[:event_name] }).to include(
  259. :user_logged_in, :user_first_logged_in
  260. )
  261. expect(response).to be_success
  262. expect(response.body).to include('{"is_developer":false,"admin":false,"second_factor_required":false}')
  263. user.reload
  264. expect(session["password-#{token}"]).to be_blank
  265. expect(UserAuthToken.where(id: user_auth_token.id).count).to eq(0)
  266. end
  267. it 'disallows double password reset' do
  268. user = Fabricate(:user)
  269. token = user.email_tokens.create(email: user.email).token
  270. get :password_reset, params: { token: token }
  271. put :password_reset,
  272. params: { token: token, password: 'hg9ow8yHG32O' }
  273. put :password_reset,
  274. params: { token: token, password: 'test123987AsdfXYZ' }
  275. user.reload
  276. expect(user.confirm_password?('hg9ow8yHG32O')).to eq(true)
  277. # logged in now
  278. expect(user.user_auth_tokens.count).to eq(1)
  279. end
  280. it "doesn't redirect to wizard on get" do
  281. user = Fabricate(:admin)
  282. UserAuthToken.generate!(user_id: user.id)
  283. token = user.email_tokens.create(email: user.email).token
  284. get :password_reset, params: { token: token }, format: :json
  285. expect(response).not_to redirect_to(wizard_path)
  286. end
  287. it "redirects to the wizard if you're the first admin" do
  288. user = Fabricate(:admin)
  289. UserAuthToken.generate!(user_id: user.id)
  290. token = user.email_tokens.create(email: user.email).token
  291. get :password_reset, params: { token: token }
  292. put :password_reset, params: {
  293. token: token, password: 'hg9ow8yhg98oadminlonger'
  294. }
  295. expect(response).to redirect_to(wizard_path)
  296. end
  297. it "doesn't invalidate the token when loading the page" do
  298. user = Fabricate(:user)
  299. user_token = UserAuthToken.generate!(user_id: user.id)
  300. email_token = user.email_tokens.create(email: user.email)
  301. get :password_reset, params: { token: email_token.token }, format: :json
  302. email_token.reload
  303. expect(email_token.confirmed).to eq(false)
  304. expect(UserAuthToken.where(id: user_token.id).count).to eq(1)
  305. end
  306. context '2 factor authentication required' do
  307. let!(:second_factor) { Fabricate(:user_second_factor, user: user) }
  308. it 'does not change with an invalid token' do
  309. token = user.email_tokens.create!(email: user.email).token
  310. get :password_reset, params: { token: token }
  311. expect(response.body).to include('{"is_developer":false,"admin":false,"second_factor_required":true}')
  312. put :password_reset,
  313. params: { token: token, password: 'hg9ow8yHG32O', second_factor_token: '000000' }
  314. expect(response.body).to include(I18n.t("login.invalid_second_factor_code"))
  315. user.reload
  316. expect(user.confirm_password?('hg9ow8yHG32O')).not_to eq(true)
  317. expect(user.user_auth_tokens.count).not_to eq(1)
  318. end
  319. it 'changes password with valid 2-factor tokens' do
  320. token = user.email_tokens.create(email: user.email).token
  321. get :password_reset, params: { token: token }
  322. put :password_reset, params: {
  323. token: token,
  324. password: 'hg9ow8yHG32O',
  325. second_factor_token: ROTP::TOTP.new(second_factor.data).now
  326. }
  327. user.reload
  328. expect(user.confirm_password?('hg9ow8yHG32O')).to eq(true)
  329. expect(user.user_auth_tokens.count).to eq(1)
  330. end
  331. end
  332. end
  333. context 'submit change' do
  334. let(:token) { EmailToken.generate_token }
  335. before do
  336. EmailToken.expects(:confirm).with(token).returns(user)
  337. end
  338. it "fails when the password is blank" do
  339. put :password_reset, params: {
  340. token: token, password: ''
  341. }, format: :json
  342. expect(response).to be_success
  343. expect(JSON.parse(response.body)["errors"]).to be_present
  344. expect(session[:current_user_id]).to be_blank
  345. end
  346. it "fails when the password is too long" do
  347. put :password_reset, params: {
  348. token: token, password: ('x' * (User.max_password_length + 1))
  349. }, format: :json
  350. expect(response).to be_success
  351. expect(JSON.parse(response.body)["errors"]).to be_present
  352. expect(session[:current_user_id]).to be_blank
  353. end
  354. it "logs in the user" do
  355. put :password_reset, params: {
  356. token: token, password: 'ksjafh928r'
  357. }, format: :json
  358. expect(response).to be_success
  359. expect(JSON.parse(response.body)["errors"]).to be_blank
  360. expect(session[:current_user_id]).to be_present
  361. end
  362. it "doesn't log in the user when not approved" do
  363. SiteSetting.must_approve_users = true
  364. put :password_reset, params: {
  365. token: token, password: 'ksjafh928r'
  366. }, format: :json
  367. expect(JSON.parse(response.body)["errors"]).to be_blank
  368. expect(session[:current_user_id]).to be_blank
  369. end
  370. end
  371. end
  372. describe '.confirm_email_token' do
  373. let(:user) { Fabricate(:user) }
  374. it "token doesn't match any records" do
  375. email_token = user.email_tokens.create(email: user.email)
  376. get :confirm_email_token, params: { token: SecureRandom.hex }, format: :json
  377. expect(response).to be_success
  378. expect(email_token.reload.confirmed).to eq(false)
  379. end
  380. it "token matches" do
  381. email_token = user.email_tokens.create(email: user.email)
  382. get :confirm_email_token, params: { token: email_token.token }, format: :json
  383. expect(response).to be_success
  384. expect(email_token.reload.confirmed).to eq(true)
  385. end
  386. end
  387. describe '#admin_login' do
  388. let(:admin) { Fabricate(:admin) }
  389. let(:user) { Fabricate(:user) }
  390. context 'enqueues mail' do
  391. it 'enqueues mail with admin email and sso enabled' do
  392. Jobs.expects(:enqueue).with(:critical_user_email, has_entries(type: :admin_login, user_id: admin.id))
  393. put :admin_login, params: { email: admin.email }
  394. end
  395. end
  396. context 'when email is incorrect' do
  397. render_views
  398. it 'should return the right response' do
  399. put :admin_login, params: { email: 'random' }
  400. expect(response.status).to eq(200)
  401. response_body = response.body
  402. expect(response_body).to match(I18n.t("admin_login.errors.unknown_email_address"))
  403. expect(response_body).to_not match(I18n.t("login.second_factor_description"))
  404. end
  405. end
  406. context 'logs in admin' do
  407. it 'does not log in admin with invalid token' do
  408. SiteSetting.sso_url = "https://www.example.com/sso"
  409. SiteSetting.enable_sso = true
  410. get :admin_login, params: { token: "invalid" }
  411. expect(session[:current_user_id]).to be_blank
  412. end
  413. context 'valid token' do
  414. it 'does log in admin with SSO disabled' do
  415. SiteSetting.enable_sso = false
  416. token = admin.email_tokens.create(email: admin.email).token
  417. get :admin_login, params: { token: token }
  418. expect(response).to redirect_to('/')
  419. expect(session[:current_user_id]).to eq(admin.id)
  420. end
  421. it 'logs in admin with SSO enabled' do
  422. SiteSetting.sso_url = "https://www.example.com/sso"
  423. SiteSetting.enable_sso = true
  424. token = admin.email_tokens.create(email: admin.email).token
  425. get :admin_login, params: { token: token }
  426. expect(response).to redirect_to('/')
  427. expect(session[:current_user_id]).to eq(admin.id)
  428. end
  429. end
  430. describe 'when 2 factor authentication is enabled' do
  431. let(:second_factor) { Fabricate(:user_second_factor, user: admin) }
  432. let(:email_token) { Fabricate(:email_token, user: admin) }
  433. render_views
  434. it 'does not log in when token required' do
  435. second_factor
  436. get :admin_login, params: { token: email_token.token }
  437. expect(response).not_to redirect_to('/')
  438. expect(session[:current_user_id]).not_to eq(admin.id)
  439. expect(response.body).to include(I18n.t('login.second_factor_description'));
  440. end
  441. describe 'invalid 2 factor token' do
  442. it 'should display the right error' do
  443. second_factor
  444. put :admin_login, params: {
  445. token: email_token.token,
  446. second_factor_token: '13213'
  447. }
  448. expect(response.status).to eq(200)
  449. expect(response.body).to include(I18n.t('login.second_factor_description'));
  450. expect(response.body).to include(I18n.t('login.invalid_second_factor_code'));
  451. end
  452. end
  453. it 'logs in when a valid 2-factor token is given' do
  454. put :admin_login, params: {
  455. token: email_token.token,
  456. second_factor_token: ROTP::TOTP.new(second_factor.data).now
  457. }
  458. expect(response).to redirect_to('/')
  459. expect(session[:current_user_id]).to eq(admin.id)
  460. end
  461. end
  462. end
  463. end
  464. describe '#toggle_anon' do
  465. it 'allows you to toggle anon if enabled' do
  466. SiteSetting.allow_anonymous_posting = true
  467. user = log_in
  468. user.trust_level = 1
  469. user.save
  470. post :toggle_anon, format: :json
  471. expect(response).to be_success
  472. expect(session[:current_user_id]).to eq(AnonymousShadowCreator.get(user).id)
  473. post :toggle_anon, format: :json
  474. expect(response).to be_success
  475. expect(session[:current_user_id]).to eq(user.id)
  476. end
  477. end
  478. describe '#create' do
  479. before do
  480. UsersController.any_instance.stubs(:honeypot_value).returns(nil)
  481. UsersController.any_instance.stubs(:challenge_value).returns(nil)
  482. SiteSetting.allow_new_registrations = true
  483. @user = Fabricate.build(:user)
  484. @user.password = "strongpassword"
  485. end
  486. let(:post_user_params) do
  487. { name: @user.name,
  488. username: @user.username,
  489. password: "strongpassword",
  490. email: @user.email }
  491. end
  492. def post_user
  493. post :create, params: post_user_params, format: :json
  494. end
  495. context 'when email params is missing' do
  496. it 'should raise the right error' do
  497. expect do
  498. post :create, params: {
  499. name: @user.name,
  500. username: @user.username,
  501. passsword: 'tesing12352343'
  502. }, format: :json
  503. end.to raise_error(ActionController::ParameterMissing)
  504. end
  505. end
  506. context 'when creating a user' do
  507. it 'sets the user locale to I18n.locale' do
  508. SiteSetting.default_locale = 'en'
  509. I18n.stubs(:locale).returns(:fr)
  510. post_user
  511. expect(User.find_by(username: @user.username).locale).to eq('fr')
  512. end
  513. end
  514. context 'when creating a non active user (unconfirmed email)' do
  515. it 'returns a 500 when local logins are disabled' do
  516. SiteSetting.enable_local_logins = false
  517. post_user
  518. expect(response.status).to eq(500)
  519. end
  520. it 'returns an error when new registrations are disabled' do
  521. SiteSetting.allow_new_registrations = false
  522. post_user
  523. json = JSON.parse(response.body)
  524. expect(json['success']).to eq(false)
  525. expect(json['message']).to be_present
  526. end
  527. it 'creates a user correctly' do
  528. Jobs.expects(:enqueue).with(:critical_user_email, has_entries(type: :signup))
  529. User.any_instance.expects(:enqueue_welcome_message).with('welcome_user').never
  530. post_user
  531. expect(JSON.parse(response.body)['active']).to be_falsey
  532. # should save user_created_message in session
  533. expect(session["user_created_message"]).to be_present
  534. expect(session[SessionController::ACTIVATE_USER_KEY]).to be_present
  535. end
  536. context "`must approve users` site setting is enabled" do
  537. before { SiteSetting.must_approve_users = true }
  538. it 'creates a user correctly' do
  539. Jobs.expects(:enqueue).with(:critical_user_email, has_entries(type: :signup))
  540. User.any_instance.expects(:enqueue_welcome_message).with('welcome_user').never
  541. post_user
  542. expect(JSON.parse(response.body)['active']).to be_falsey
  543. # should save user_created_message in session
  544. expect(session["user_created_message"]).to be_present
  545. expect(session[SessionController::ACTIVATE_USER_KEY]).to be_present
  546. end
  547. end
  548. context 'users already exists with given email' do
  549. let!(:existing) { Fabricate(:user, email: post_user_params[:email]) }
  550. it 'returns an error if hide_email_address_taken is disabled' do
  551. SiteSetting.hide_email_address_taken = false
  552. post_user
  553. json = JSON.parse(response.body)
  554. expect(json['success']).to eq(false)
  555. expect(json['message']).to be_present
  556. end
  557. it 'returns success if hide_email_address_taken is enabled' do
  558. SiteSetting.hide_email_address_taken = true
  559. expect {
  560. post_user
  561. }.to_not change { User.count }
  562. json = JSON.parse(response.body)
  563. expect(json['active']).to be_falsey
  564. expect(session["user_created_message"]).to be_present
  565. end
  566. end
  567. end
  568. context "creating as active" do
  569. it "won't create the user as active" do
  570. post :create, params: post_user_params.merge(active: true), format: :json
  571. expect(JSON.parse(response.body)['active']).to be_falsey
  572. end
  573. context "with a regular api key" do
  574. let(:user) { Fabricate(:user) }
  575. let(:api_key) { Fabricate(:api_key, user: user) }
  576. it "won't create the user as active with a regular key" do
  577. post :create,
  578. params: post_user_params.merge(active: true, api_key: api_key.key),
  579. format: :json
  580. expect(JSON.parse(response.body)['active']).to be_falsey
  581. end
  582. end
  583. context "with an admin api key" do
  584. let(:admin) { Fabricate(:admin) }
  585. let(:api_key) { Fabricate(:api_key, user: admin) }
  586. it "creates the user as active with a regular key" do
  587. SiteSetting.queue_jobs = true
  588. SiteSetting.send_welcome_message = true
  589. SiteSetting.must_approve_users = true
  590. Sidekiq::Client.expects(:enqueue).never
  591. post :create,
  592. params: post_user_params.merge(approved: true, active: true, api_key: api_key.key),
  593. format: :json
  594. json = JSON.parse(response.body)
  595. new_user = User.find(json["user_id"])
  596. expect(json['active']).to be_truthy
  597. expect(new_user.active).to eq(true)
  598. expect(new_user.approved).to eq(true)
  599. expect(new_user.approved_by_id).to eq(admin.id)
  600. expect(new_user.approved_at).to_not eq(nil)
  601. end
  602. it "won't create the developer as active" do
  603. UsernameCheckerService.expects(:is_developer?).returns(true)
  604. post :create,
  605. params: post_user_params.merge(active: true, api_key: api_key.key),
  606. format: :json
  607. expect(JSON.parse(response.body)['active']).to be_falsy
  608. end
  609. end
  610. end
  611. context "creating as staged" do
  612. it "won't create the user as staged" do
  613. post :create,
  614. params: post_user_params.merge(staged: true),
  615. format: :json
  616. new_user = User.where(username: post_user_params[:username]).first
  617. expect(new_user.staged?).to eq(false)
  618. end
  619. context "with a regular api key" do
  620. let(:user) { Fabricate(:user) }
  621. let(:api_key) { Fabricate(:api_key, user: user) }
  622. it "won't create the user as staged with a regular key" do
  623. post :create,
  624. params: post_user_params.merge(staged: true, api_key: api_key.key),
  625. format: :json
  626. new_user = User.where(username: post_user_params[:username]).first
  627. expect(new_user.staged?).to eq(false)
  628. end
  629. end
  630. context "with an admin api key" do
  631. let(:user) { Fabricate(:admin) }
  632. let(:api_key) { Fabricate(:api_key, user: user) }
  633. it "creates the user as staged with a regular key" do
  634. post :create,
  635. params: post_user_params.merge(staged: true, api_key: api_key.key),
  636. format: :json
  637. new_user = User.where(username: post_user_params[:username]).first
  638. expect(new_user.staged?).to eq(true)
  639. end
  640. it "won't create the developer as staged" do
  641. UsernameCheckerService.expects(:is_developer?).returns(true)
  642. post :create,
  643. params: post_user_params.merge(staged: true, api_key: api_key.key),
  644. format: :json
  645. new_user = User.where(username: post_user_params[:username]).first
  646. expect(new_user.staged?).to eq(false)
  647. end
  648. end
  649. end
  650. context 'when creating an active user (confirmed email)' do
  651. before { User.any_instance.stubs(:active?).returns(true) }
  652. it 'enqueues a welcome email' do
  653. User.any_instance.expects(:enqueue_welcome_message).with('welcome_user')
  654. post_user
  655. # should save user_created_message in session
  656. expect(session["user_created_message"]).to be_present
  657. expect(session[SessionController::ACTIVATE_USER_KEY]).to be_present
  658. end
  659. it "shows the 'active' message" do
  660. User.any_instance.expects(:enqueue_welcome_message)
  661. post_user
  662. expect(JSON.parse(response.body)['message']).to eq(
  663. I18n.t 'login.active'
  664. )
  665. end
  666. it "should be logged in" do
  667. User.any_instance.expects(:enqueue_welcome_message)
  668. post_user
  669. expect(session[:current_user_id]).to be_present
  670. end
  671. it 'indicates the user is active in the response' do
  672. User.any_instance.expects(:enqueue_welcome_message)
  673. post_user
  674. expect(JSON.parse(response.body)['active']).to be_truthy
  675. end
  676. it 'returns 500 status when new registrations are disabled' do
  677. SiteSetting.allow_new_registrations = false
  678. post_user
  679. json = JSON.parse(response.body)
  680. expect(json['success']).to eq(false)
  681. expect(json['message']).to be_present
  682. end
  683. context 'authentication records for' do
  684. it 'should create twitter user info if required' do
  685. SiteSetting.must_approve_users = true
  686. SiteSetting.enable_twitter_logins = true
  687. twitter_auth = { twitter_user_id: 42, twitter_screen_name: "bruce" }
  688. auth = session[:authentication] = {}
  689. auth[:authenticator_name] = 'twitter'
  690. auth[:extra_data] = twitter_auth
  691. post_user
  692. expect(TwitterUserInfo.count).to eq(1)
  693. end
  694. end
  695. it "returns an error when email has been changed from the validated email address" do
  696. auth = session[:authentication] = {}
  697. auth[:email_valid] = 'true'
  698. auth[:email] = 'therealone@gmail.com'
  699. post_user
  700. json = JSON.parse(response.body)
  701. expect(json['success']).to eq(false)
  702. expect(json['message']).to be_present
  703. end
  704. it "will create the user successfully if email validation is required" do
  705. auth = session[:authentication] = {}
  706. auth[:email] = post_user_params[:email]
  707. post_user
  708. json = JSON.parse(response.body)
  709. expect(json['success']).to eq(true)
  710. end
  711. end
  712. context 'after success' do
  713. before { post_user }
  714. it 'should succeed' do
  715. is_expected.to respond_with(:success)
  716. end
  717. it 'has the proper JSON' do
  718. json = JSON::parse(response.body)
  719. expect(json["success"]).to eq(true)
  720. end
  721. it 'should not result in an active account' do
  722. expect(User.find_by(username: @user.username).active).to eq(false)
  723. end
  724. end
  725. shared_examples 'honeypot fails' do
  726. it 'should not create a new user' do
  727. expect {
  728. post :create, params: create_params, format: :json
  729. }.to_not change { User.count }
  730. end
  731. it 'should not send an email' do
  732. User.any_instance.expects(:enqueue_welcome_message).never
  733. post :create, params: create_params, format: :json
  734. end
  735. it 'should say it was successful' do
  736. post :create, params: create_params, format: :json
  737. json = JSON::parse(response.body)
  738. expect(json["success"]).to eq(true)
  739. # should not change the session
  740. expect(session["user_created_message"]).to be_blank
  741. expect(session[SessionController::ACTIVATE_USER_KEY]).to be_blank
  742. end
  743. end
  744. context 'when honeypot value is wrong' do
  745. before do
  746. UsersController.any_instance.stubs(:honeypot_value).returns('abc')
  747. end
  748. let(:create_params) { { name: @user.name, username: @user.username, password: "strongpassword", email: @user.email, password_confirmation: 'wrong' } }
  749. include_examples 'honeypot fails'
  750. end
  751. context 'when challenge answer is wrong' do
  752. before do
  753. UsersController.any_instance.stubs(:challenge_value).returns('abc')
  754. end
  755. let(:create_params) { { name: @user.name, username: @user.username, password: "strongpassword", email: @user.email, challenge: 'abc' } }
  756. include_examples 'honeypot fails'
  757. end
  758. context "when 'invite only' setting is enabled" do
  759. before { SiteSetting.invite_only = true }
  760. let(:create_params) { {
  761. name: @user.name,
  762. username: @user.username,
  763. password: 'strongpassword',
  764. email: @user.email
  765. }}
  766. include_examples 'honeypot fails'
  767. end
  768. shared_examples 'failed signup' do
  769. it 'should not create a new User' do
  770. expect { post :create, params: create_params, format: :json }.to_not change { User.count }
  771. end
  772. it 'should report failed' do
  773. post :create, params: create_params, format: :json
  774. json = JSON::parse(response.body)
  775. expect(json["success"]).not_to eq(true)
  776. # should not change the session
  777. expect(session["user_created_message"]).to be_blank
  778. expect(session[SessionController::ACTIVATE_USER_KEY]).to be_blank
  779. end
  780. end
  781. context 'when password is blank' do
  782. let(:create_params) { { name: @user.name, username: @user.username, password: "", email: @user.email } }
  783. include_examples 'failed signup'
  784. end
  785. context 'when password is too long' do
  786. let(:create_params) { { name: @user.name, username: @user.username, password: "x" * (User.max_password_length + 1), email: @user.email } }
  787. include_examples 'failed signup'
  788. end
  789. context 'when password param is missing' do
  790. let(:create_params) { { name: @user.name, username: @user.username, email: @user.email } }
  791. include_examples 'failed signup'
  792. end
  793. context 'with a reserved username' do
  794. let(:create_params) { { name: @user.name, username: 'Reserved', email: @user.email, password: "x" * 20 } }
  795. before { SiteSetting.reserved_usernames = 'a|reserved|b' }
  796. after { SiteSetting.reserved_usernames = nil }
  797. include_examples 'failed signup'
  798. end
  799. context 'when an Exception is raised' do
  800. before { User.any_instance.stubs(:save).raises(ActiveRecord::StatementInvalid.new('Oh no')) }
  801. let(:create_params) {
  802. { name: @user.name, username: @user.username,
  803. password: "strongpassword", email: @user.email }
  804. }
  805. include_examples 'failed signup'
  806. end
  807. context "with custom fields" do
  808. let!(:user_field) { Fabricate(:user_field) }
  809. let!(:another_field) { Fabricate(:user_field) }
  810. let!(:optional_field) { Fabricate(:user_field, required: false) }
  811. context "without a value for the fields" do
  812. let(:create_params) { { name: @user.name, password: 'watwatwat', username: @user.username, email: @user.email } }
  813. include_examples 'failed signup'
  814. end
  815. context "with values for the fields" do
  816. let(:create_params) { {
  817. name: @user.name,
  818. password: 'suChS3cuRi7y',
  819. username: @user.username,
  820. email: @user.email,
  821. user_fields: {
  822. user_field.id.to_s => 'value1',
  823. another_field.id.to_s => 'value2',
  824. }
  825. } }
  826. it "should succeed without the optional field" do
  827. post :create, params: create_params, format: :json
  828. expect(response).to be_success
  829. inserted = User.find_by_email(@user.email)
  830. expect(inserted).to be_present
  831. expect(inserted.custom_fields).to be_present
  832. expect(inserted.custom_fields["user_field_#{user_field.id}"]).to eq('value1')
  833. expect(inserted.custom_fields["user_field_#{another_field.id}"]).to eq('value2')
  834. expect(inserted.custom_fields["user_field_#{optional_field.id}"]).to be_blank
  835. end
  836. it "should succeed with the optional field" do
  837. create_params[:user_fields][optional_field.id.to_s] = 'value3'
  838. post :create, params: create_params.merge(create_params), format: :json
  839. expect(response).to be_success
  840. inserted = User.find_by_email(@user.email)
  841. expect(inserted).to be_present
  842. expect(inserted.custom_fields).to be_present
  843. expect(inserted.custom_fields["user_field_#{user_field.id}"]).to eq('value1')
  844. expect(inserted.custom_fields["user_field_#{another_field.id}"]).to eq('value2')
  845. expect(inserted.custom_fields["user_field_#{optional_field.id}"]).to eq('value3')
  846. end
  847. it "trims excessively long fields" do
  848. create_params[:user_fields][optional_field.id.to_s] = ('x' * 3000)
  849. post :create, params: create_params.merge(create_params), format: :json
  850. expect(response).to be_success
  851. inserted = User.find_by_email(@user.email)
  852. val = inserted.custom_fields["user_field_#{optional_field.id}"]
  853. expect(val.length).to eq(UserField.max_length)
  854. end
  855. end
  856. end
  857. context "with only optional custom fields" do
  858. let!(:user_field) { Fabricate(:user_field, required: false) }
  859. context "without values for the fields" do
  860. let(:create_params) { {
  861. name: @user.name,
  862. password: 'suChS3cuRi7y',
  863. username: @user.username,
  864. email: @user.email,
  865. } }
  866. it "should succeed" do
  867. post :create, params: create_params, format: :json
  868. expect(response).to be_success
  869. inserted = User.find_by_email(@user.email)
  870. expect(inserted).to be_present
  871. expect(inserted.custom_fields).not_to be_present
  872. expect(inserted.custom_fields["user_field_#{user_field.id}"]).to be_blank
  873. end
  874. end
  875. end
  876. end
  877. context '#username' do
  878. it 'raises an error when not logged in' do
  879. put :username, params: { username: 'somename' }, format: :json
  880. expect(response.status).to eq(403)
  881. end
  882. context 'while logged in' do
  883. let(:old_username) { "OrigUsrname" }
  884. let(:new_username) { "#{old_username}1234" }
  885. let(:user) { Fabricate(:user, username: old_username) }
  886. before do
  887. user.username = old_username
  888. log_in_user(user)
  889. end
  890. it 'raises an error without a new_username param' do
  891. expect do
  892. put :username, params: { username: user.username }, format: :json
  893. end.to raise_error(ActionController::ParameterMissing)
  894. expect(user.reload.username).to eq(old_username)
  895. end
  896. it 'raises an error when you don\'t have permission to change the username' do
  897. Guardian.any_instance.expects(:can_edit_username?).with(user).returns(false)
  898. put :username, params: {
  899. username: user.username, new_username: new_username
  900. }, format: :json
  901. expect(response).to be_forbidden
  902. expect(user.reload.username).to eq(old_username)
  903. end
  904. it 'raises an error when change_username fails' do
  905. put :username,
  906. params: { username: user.username, new_username: '@' },
  907. format: :json
  908. expect(response).to_not be_success
  909. body = JSON.parse(response.body)
  910. expect(body['errors'].first).to include(I18n.t(
  911. 'user.username.short', min: User.username_length.begin
  912. ))
  913. expect(user.reload.username).to eq(old_username)
  914. end
  915. it 'should succeed in normal circumstances' do
  916. put :username,
  917. params: { username: user.username, new_username: new_username },
  918. format: :json
  919. expect(response).to be_success
  920. expect(user.reload.username).to eq(new_username)
  921. end
  922. it 'should fail if the user is old' do
  923. # Older than the change period and >1 post
  924. user.created_at = Time.now - (SiteSetting.username_change_period + 1).days
  925. PostCreator.new(user,
  926. title: 'This is a test topic',
  927. raw: 'This is a test this is a test'
  928. ).create
  929. put :username, params: {
  930. username: user.username, new_username: new_username
  931. }, format: :json
  932. expect(response).to be_forbidden
  933. expect(user.reload.username).to eq(old_username)
  934. end
  935. it 'should create a staff action log when a staff member changes the username' do
  936. acting_user = Fabricate(:admin)
  937. log_in_user(acting_user)
  938. put :username, params: {
  939. username: user.username, new_username: new_username
  940. }, format: :json
  941. expect(response).to be_success
  942. expect(UserHistory.where(action: UserHistory.actions[:change_username], target_user_id: user.id, acting_user_id: acting_user.id)).to be_present
  943. expect(user.reload.username).to eq(new_username)
  944. end
  945. it 'should return a JSON response with the updated username' do
  946. put :username, params: {
  947. username: user.username, new_username: new_username
  948. }, format: :json
  949. expect(::JSON.parse(response.body)['username']).to eq(new_username)
  950. end
  951. end
  952. end
  953. context '.check_username' do
  954. it 'raises an error without any parameters' do
  955. expect do
  956. get :check_username, format: :json
  957. end.to raise_error(ActionController::ParameterMissing)
  958. end
  959. shared_examples 'when username is unavailable' do
  960. it 'should return success' do
  961. expect(response).to be_success
  962. end
  963. it 'should return available as false in the JSON' do
  964. expect(::JSON.parse(response.body)['available']).to eq(false)
  965. end
  966. it 'should return a suggested username' do
  967. expect(::JSON.parse(response.body)['suggestion']).to be_present
  968. end
  969. end
  970. shared_examples 'when username is available' do
  971. it 'should return success' do
  972. expect(response).to be_success
  973. end
  974. it 'should return available in the JSON' do
  975. expect(::JSON.parse(response.body)['available']).to eq(true)
  976. end
  977. end
  978. it 'returns nothing when given an email param but no username' do
  979. get :check_username, params: { email: 'dood@example.com' }, format: :json
  980. expect(response).to be_success
  981. end
  982. context 'username is available' do
  983. before do
  984. get :check_username, params: { username: 'BruceWayne' }, format: :json
  985. end
  986. include_examples 'when username is available'
  987. end
  988. context 'username is unavailable' do
  989. let!(:user) { Fabricate(:user) }
  990. before do
  991. get :check_username, params: { username: user.username }, format: :json
  992. end
  993. include_examples 'when username is unavailable'
  994. end
  995. shared_examples 'checking an invalid username' do
  996. it 'should return success' do
  997. expect(response).to be_success
  998. end
  999. it 'should not return an available key' do
  1000. expect(::JSON.parse(response.body)['available']).to eq(nil)
  1001. end
  1002. it 'should return an error message' do
  1003. expect(::JSON.parse(response.body)['errors']).not_to be_empty
  1004. end
  1005. end
  1006. context 'has invalid characters' do
  1007. before do
  1008. get :check_username, params: {
  1009. username: 'bad username'
  1010. }, format: :json
  1011. end
  1012. include_examples 'checking an invalid username'
  1013. it 'should return the invalid characters message' do
  1014. expect(::JSON.parse(response.body)['errors']).to include(I18n.t(:'user.username.characters'))
  1015. end
  1016. end
  1017. context 'is too long' do
  1018. before do
  1019. get :check_username, params: {
  1020. username: generate_username(User.username_length.last + 1)
  1021. }, format: :json
  1022. end
  1023. include_examples 'checking an invalid username'
  1024. it 'should return the "too long" message' do
  1025. expect(::JSON.parse(response.body)['errors']).to include(I18n.t(:'user.username.long', max: User.username_length.end))
  1026. end
  1027. end
  1028. describe 'different case of existing username' do
  1029. context "it's my username" do
  1030. let!(:user) { Fabricate(:user, username: 'hansolo') }
  1031. before do
  1032. log_in_user(user)
  1033. get :check_username, params: {
  1034. username: 'HanSolo'
  1035. }, format: :json
  1036. end
  1037. include_examples 'when username is available'
  1038. end
  1039. context "it's someone else's username" do
  1040. let!(:user) { Fabricate(:user, username: 'hansolo') }
  1041. before do
  1042. log_in
  1043. get :check_username, params: {
  1044. username: 'HanSolo'
  1045. }, format: :json
  1046. end
  1047. include_examples 'when username is unavailable'
  1048. end
  1049. context "an admin changing it for someone else" do
  1050. let!(:user) { Fabricate(:user, username: 'hansolo') }
  1051. before do
  1052. log_in_user(Fabricate(:admin))
  1053. get :check_username, params: {
  1054. username: 'HanSolo', for_user_id: user.id
  1055. }, format: :json
  1056. end
  1057. include_examples 'when username is available'
  1058. end
  1059. end
  1060. end
  1061. describe '#invited' do
  1062. it 'returns success' do
  1063. user = Fabricate(:user)
  1064. get :invited, params: { username: user.username }, format: :json
  1065. expect(response).to be_success
  1066. end
  1067. it 'filters by email' do
  1068. inviter = Fabricate(:user)
  1069. invitee = Fabricate(:user)
  1070. _invite = Fabricate(
  1071. :invite,
  1072. email: 'billybob@example.com',
  1073. invited_by: inviter,
  1074. user: invitee
  1075. )
  1076. Fabricate(
  1077. :invite,
  1078. email: 'jimtom@example.com',
  1079. invited_by: inviter,
  1080. user: invitee
  1081. )
  1082. get :invited, params: {
  1083. username: inviter.username, search: 'billybob'
  1084. }, format: :json
  1085. invites = JSON.parse(response.body)['invites']
  1086. expect(invites.size).to eq(1)
  1087. expect(invites.first).to include('email' => 'billybob@example.com')
  1088. end
  1089. it 'filters by username' do
  1090. inviter = Fabricate(:user)
  1091. invitee = Fabricate(:user, username: 'billybob')
  1092. _invite = Fabricate(
  1093. :invite,
  1094. invited_by: inviter,
  1095. email: 'billybob@example.com',
  1096. user: invitee
  1097. )
  1098. Fabricate(
  1099. :invite,
  1100. invited_by: inviter,
  1101. user: Fabricate(:user, username: 'jimtom')
  1102. )
  1103. get :invited, params: {
  1104. username: inviter.username, search: 'billybob'
  1105. }, format: :json
  1106. invites = JSON.parse(response.body)['invites']
  1107. expect(invites.size).to eq(1)
  1108. expect(invites.first).to include('email' => 'billybob@example.com')
  1109. end
  1110. context 'with guest' do
  1111. context 'with pending invites' do
  1112. it 'does not return invites' do
  1113. inviter = Fabricate(:user)
  1114. Fabricate(:invite, invited_by: inviter)
  1115. get :invited,
  1116. params: { username: inviter.username, filter: 'pending' },
  1117. format: :json
  1118. invites = JSON.parse(response.body)['invites']
  1119. expect(invites).to be_empty
  1120. end
  1121. end
  1122. context 'with redeemed invites' do
  1123. it 'returns invites' do
  1124. inviter = Fabricate(:user)
  1125. invitee = Fabricate(:user)
  1126. invite = Fabricate(:invite, invited_by: inviter, user: invitee)
  1127. get :invited,
  1128. params: { username: inviter.username },
  1129. format: :json
  1130. invites = JSON.parse(response.body)['invites']
  1131. expect(invites.size).to eq(1)
  1132. expect(invites.first).to include('email' => invite.email)
  1133. end
  1134. end
  1135. end
  1136. context 'with authenticated user' do
  1137. context 'with pending invites' do
  1138. context 'with permission to see pending invites' do
  1139. it 'returns invites' do
  1140. user = log_in
  1141. inviter = Fabricate(:user)
  1142. invite = Fabricate(:invite, invited_by: inviter)
  1143. stub_guardian(user) do |guardian|
  1144. guardian.stubs(:can_see_invite_details?).
  1145. with(inviter).returns(true)
  1146. end
  1147. get :invited, params: {
  1148. username: inviter.username, filter: 'pending'
  1149. }, format: :json
  1150. invites = JSON.parse(response.body)['invites']
  1151. expect(invites.size).to eq(1)
  1152. expect(invites.first).to include("email" => invite.email)
  1153. end
  1154. end
  1155. context 'without permission to see pending invites' do
  1156. it 'does not return invites' do
  1157. user = log_in
  1158. inviter = Fabricate(:user)
  1159. _invitee = Fabricate(:user)
  1160. Fabricate(:invite, invited_by: inviter)
  1161. stub_guardian(user) do |guardian|
  1162. guardian.stubs(:can_see_invite_details?).
  1163. with(inviter).returns(false)
  1164. end
  1165. get :invited, params: {
  1166. username: inviter.username, filter: 'pending'
  1167. }, format: :json
  1168. json = JSON.parse(response.body)['invites']
  1169. expect(json).to be_empty
  1170. end
  1171. end
  1172. end
  1173. context 'with redeemed invites' do
  1174. it 'returns invites' do
  1175. _user = log_in
  1176. inviter = Fabricate(:user)
  1177. invitee = Fabricate(:user)
  1178. invite = Fabricate(:invite, invited_by: inviter, user: invitee)
  1179. get :invited, params: { username: inviter.username }, format: :json
  1180. invites = JSON.parse(response.body)['invites']
  1181. expect(invites.size).to eq(1)
  1182. expect(invites.first).to include('email' => invite.email)
  1183. end
  1184. end
  1185. end
  1186. end
  1187. describe '#update' do
  1188. context 'with guest' do
  1189. it 'raises an error' do
  1190. put :update, params: { username: 'guest' }, format: :json
  1191. expect(response.status).to eq(403)
  1192. end
  1193. end
  1194. context "as a staff user" do
  1195. let!(:user) { log_in(:admin) }
  1196. context "uneditable field" do
  1197. let!(:user_field) { Fabricate(:user_field, editable: false) }
  1198. it "allows staff to edit the field" do
  1199. put :update, params: {
  1200. username: user.username,
  1201. name: 'Jim Tom',
  1202. title: "foobar",
  1203. user_fields: { user_field.id.to_s => 'happy'

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