PageRenderTime 59ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/spec/controllers/users_controller_spec.rb

https://github.com/ddollar/discourse
Ruby | 1235 lines | 1105 code | 130 blank | 0 comment | 6 complexity | 2619a75720a029cf371212120518d9ce MD5 | raw file
Possible License(s): Apache-2.0
  1. require 'spec_helper'
  2. describe UsersController do
  3. describe '.show' do
  4. let!(:user) { log_in }
  5. it 'returns success' do
  6. xhr :get, :show, username: user.username, format: :json
  7. response.should be_success
  8. json = JSON.parse(response.body)
  9. json["user"]["has_title_badges"].should == false
  10. end
  11. it "returns not found when the username doesn't exist" do
  12. xhr :get, :show, username: 'madeuppity'
  13. response.should_not be_success
  14. end
  15. it 'returns not found when the user is inactive' do
  16. inactive = Fabricate(:user, active: false)
  17. xhr :get, :show, username: inactive.username
  18. response.should_not be_success
  19. end
  20. it "raises an error on invalid access" do
  21. Guardian.any_instance.expects(:can_see?).with(user).returns(false)
  22. xhr :get, :show, username: user.username
  23. response.should be_forbidden
  24. end
  25. context "fetching a user by external_id" do
  26. before { user.create_single_sign_on_record(external_id: '997', last_payload: '') }
  27. it "returns fetch for a matching external_id" do
  28. xhr :get, :show, external_id: '997'
  29. response.should be_success
  30. end
  31. it "returns not found when external_id doesn't match" do
  32. xhr :get, :show, external_id: '99'
  33. response.should_not be_success
  34. end
  35. end
  36. end
  37. describe '.user_preferences_redirect' do
  38. it 'requires the user to be logged in' do
  39. lambda { get :user_preferences_redirect }.should raise_error(Discourse::NotLoggedIn)
  40. end
  41. it "redirects to their profile when logged in" do
  42. user = log_in
  43. get :user_preferences_redirect
  44. response.should redirect_to("/users/#{user.username_lower}/preferences")
  45. end
  46. end
  47. describe '.authorize_email' do
  48. it 'errors out for invalid tokens' do
  49. get :authorize_email, token: 'asdfasdf'
  50. response.should be_success
  51. flash[:error].should be_present
  52. end
  53. context 'valid token' do
  54. it 'authorizes with a correct token' do
  55. user = Fabricate(:user)
  56. email_token = user.email_tokens.create(email: user.email)
  57. get :authorize_email, token: email_token.token
  58. response.should be_success
  59. flash[:error].should be_blank
  60. session[:current_user_id].should be_present
  61. end
  62. end
  63. end
  64. describe '.activate_account' do
  65. before do
  66. UsersController.any_instance.stubs(:honeypot_or_challenge_fails?).returns(false)
  67. end
  68. context 'invalid token' do
  69. before do
  70. EmailToken.expects(:confirm).with('asdfasdf').returns(nil)
  71. put :perform_account_activation, token: 'asdfasdf'
  72. end
  73. it 'return success' do
  74. response.should be_success
  75. end
  76. it 'sets a flash error' do
  77. flash[:error].should be_present
  78. end
  79. end
  80. context 'valid token' do
  81. let(:user) { Fabricate(:user) }
  82. context 'welcome message' do
  83. before do
  84. EmailToken.expects(:confirm).with('asdfasdf').returns(user)
  85. end
  86. it 'enqueues a welcome message if the user object indicates so' do
  87. user.send_welcome_message = true
  88. user.expects(:enqueue_welcome_message).with('welcome_user')
  89. put :perform_account_activation, token: 'asdfasdf'
  90. end
  91. it "doesn't enqueue the welcome message if the object returns false" do
  92. user.send_welcome_message = false
  93. user.expects(:enqueue_welcome_message).with('welcome_user').never
  94. put :perform_account_activation, token: 'asdfasdf'
  95. end
  96. end
  97. context "honeypot" do
  98. it "raises an error if the honeypot is invalid" do
  99. UsersController.any_instance.stubs(:honeypot_or_challenge_fails?).returns(true)
  100. put :perform_account_activation, token: 'asdfasdf'
  101. response.should_not be_success
  102. end
  103. end
  104. context 'response' do
  105. before do
  106. Guardian.any_instance.expects(:can_access_forum?).returns(true)
  107. EmailToken.expects(:confirm).with('asdfasdf').returns(user)
  108. put :perform_account_activation, token: 'asdfasdf'
  109. end
  110. it 'returns success' do
  111. response.should be_success
  112. end
  113. it "doesn't set an error" do
  114. flash[:error].should be_blank
  115. end
  116. it 'logs in as the user' do
  117. session[:current_user_id].should be_present
  118. end
  119. it "doesn't set @needs_approval" do
  120. assigns[:needs_approval].should be_blank
  121. end
  122. end
  123. context 'user is not approved' do
  124. before do
  125. Guardian.any_instance.expects(:can_access_forum?).returns(false)
  126. EmailToken.expects(:confirm).with('asdfasdf').returns(user)
  127. put :perform_account_activation, token: 'asdfasdf'
  128. end
  129. it 'returns success' do
  130. response.should be_success
  131. end
  132. it 'sets @needs_approval' do
  133. assigns[:needs_approval].should be_present
  134. end
  135. it "doesn't set an error" do
  136. flash[:error].should be_blank
  137. end
  138. it "doesn't log the user in" do
  139. session[:current_user_id].should be_blank
  140. end
  141. end
  142. end
  143. end
  144. describe '.change_email' do
  145. let(:new_email) { 'bubblegum@adventuretime.ooo' }
  146. it "requires you to be logged in" do
  147. lambda { xhr :put, :change_email, username: 'asdf', email: new_email }.should raise_error(Discourse::NotLoggedIn)
  148. end
  149. context 'when logged in' do
  150. let!(:user) { log_in }
  151. it 'raises an error without an email parameter' do
  152. lambda { xhr :put, :change_email, username: user.username }.should raise_error(ActionController::ParameterMissing)
  153. end
  154. it "raises an error if you can't edit the user's email" do
  155. Guardian.any_instance.expects(:can_edit_email?).with(user).returns(false)
  156. xhr :put, :change_email, username: user.username, email: new_email
  157. response.should be_forbidden
  158. end
  159. context 'when the new email address is taken' do
  160. let!(:other_user) { Fabricate(:coding_horror) }
  161. it 'raises an error' do
  162. lambda { xhr :put, :change_email, username: user.username, email: other_user.email }.should raise_error(Discourse::InvalidParameters)
  163. end
  164. it 'raises an error if there is whitespace too' do
  165. lambda { xhr :put, :change_email, username: user.username, email: other_user.email + ' ' }.should raise_error(Discourse::InvalidParameters)
  166. end
  167. end
  168. context 'when new email is different case of existing email' do
  169. let!(:other_user) { Fabricate(:user, email: 'case.insensitive@gmail.com')}
  170. it 'raises an error' do
  171. lambda { xhr :put, :change_email, username: user.username, email: other_user.email.upcase }.should raise_error(Discourse::InvalidParameters)
  172. end
  173. end
  174. context 'success' do
  175. it 'has an email token' do
  176. lambda { xhr :put, :change_email, username: user.username, email: new_email }.should change(EmailToken, :count)
  177. end
  178. it 'enqueues an email authorization' do
  179. Jobs.expects(:enqueue).with(:user_email, has_entries(type: :authorize_email, user_id: user.id, to_address: new_email))
  180. xhr :put, :change_email, username: user.username, email: new_email
  181. end
  182. end
  183. end
  184. end
  185. describe '.password_reset' do
  186. let(:user) { Fabricate(:user) }
  187. context "you can view it even if login is required" do
  188. it "returns success" do
  189. SiteSetting.login_required = true
  190. get :password_reset, token: 'asdfasdf'
  191. response.should be_success
  192. end
  193. end
  194. context 'missing token' do
  195. before do
  196. get :password_reset, token: SecureRandom.hex
  197. end
  198. it 'disallows login' do
  199. flash[:error].should be_present
  200. session[:current_user_id].should be_blank
  201. assigns[:invalid_token].should be_nil
  202. response.should be_success
  203. end
  204. end
  205. context 'invalid token' do
  206. before do
  207. get :password_reset, token: "evil_trout!"
  208. end
  209. it 'disallows login' do
  210. flash[:error].should be_present
  211. session[:current_user_id].should be_blank
  212. assigns[:invalid_token].should be_true
  213. response.should be_success
  214. end
  215. end
  216. context 'valid token' do
  217. it 'returns success' do
  218. user = Fabricate(:user)
  219. token = user.email_tokens.create(email: user.email).token
  220. get :password_reset, token: token
  221. put :password_reset, token: token, password: 'newpassword'
  222. response.should be_success
  223. flash[:error].should be_blank
  224. end
  225. end
  226. context 'submit change' do
  227. let(:token) { EmailToken.generate_token }
  228. before do
  229. EmailToken.expects(:confirm).with(token).returns(user)
  230. end
  231. it "logs in the user" do
  232. put :password_reset, token: token, password: 'newpassword'
  233. session[:current_user_id].should be_present
  234. end
  235. it "doesn't log in the user when not approved" do
  236. SiteSetting.expects(:must_approve_users?).returns(true)
  237. put :password_reset, token: token, password: 'newpassword'
  238. session[:current_user_id].should be_blank
  239. end
  240. end
  241. end
  242. describe '#create' do
  243. before do
  244. UsersController.any_instance.stubs(:honeypot_value).returns(nil)
  245. UsersController.any_instance.stubs(:challenge_value).returns(nil)
  246. SiteSetting.stubs(:allow_new_registrations).returns(true)
  247. @user = Fabricate.build(:user)
  248. @user.password = "strongpassword"
  249. end
  250. def post_user
  251. xhr :post, :create,
  252. name: @user.name,
  253. username: @user.username,
  254. password: "strongpassword",
  255. email: @user.email
  256. end
  257. context 'when creating a non active user (unconfirmed email)' do
  258. it 'returns a 500 when local logins are disabled' do
  259. SiteSetting.expects(:enable_local_logins).returns(false)
  260. post_user
  261. expect(response.status).to eq(500)
  262. end
  263. it 'returns an error when new registrations are disabled' do
  264. SiteSetting.stubs(:allow_new_registrations).returns(false)
  265. post_user
  266. json = JSON.parse(response.body)
  267. json['success'].should be_false
  268. json['message'].should be_present
  269. end
  270. it 'creates a user correctly' do
  271. Jobs.expects(:enqueue).with(:user_email, has_entries(type: :signup))
  272. User.any_instance.expects(:enqueue_welcome_message).with('welcome_user').never
  273. post_user
  274. expect(JSON.parse(response.body)['active']).to be_false
  275. end
  276. context "and 'must approve users' site setting is enabled" do
  277. before { SiteSetting.expects(:must_approve_users).returns(true) }
  278. it 'does not enqueue an email' do
  279. Jobs.expects(:enqueue).never
  280. post_user
  281. end
  282. it 'does not login the user' do
  283. post_user
  284. expect(session[:current_user_id]).to be_blank
  285. end
  286. it 'indicates the user is not active in the response' do
  287. post_user
  288. expect(JSON.parse(response.body)['active']).to be_false
  289. end
  290. it "shows the 'waiting approval' message" do
  291. post_user
  292. expect(JSON.parse(response.body)['message']).to eq(
  293. I18n.t 'login.wait_approval'
  294. )
  295. end
  296. end
  297. end
  298. context 'when creating an active user (confirmed email)' do
  299. before { User.any_instance.stubs(:active?).returns(true) }
  300. it 'enqueues a welcome email' do
  301. User.any_instance.expects(:enqueue_welcome_message).with('welcome_user')
  302. post_user
  303. end
  304. it "shows the 'active' message" do
  305. User.any_instance.expects(:enqueue_welcome_message)
  306. post_user
  307. expect(JSON.parse(response.body)['message']).to eq(
  308. I18n.t 'login.active'
  309. )
  310. end
  311. it "should be logged in" do
  312. User.any_instance.expects(:enqueue_welcome_message)
  313. post_user
  314. session[:current_user_id].should be_present
  315. end
  316. it 'indicates the user is active in the response' do
  317. User.any_instance.expects(:enqueue_welcome_message)
  318. post_user
  319. expect(JSON.parse(response.body)['active']).to be_true
  320. end
  321. it 'returns 500 status when new registrations are disabled' do
  322. SiteSetting.stubs(:allow_new_registrations).returns(false)
  323. post_user
  324. json = JSON.parse(response.body)
  325. json['success'].should be_false
  326. json['message'].should be_present
  327. end
  328. context 'authentication records for' do
  329. before do
  330. SiteSetting.expects(:must_approve_users).returns(true)
  331. end
  332. it 'should create twitter user info if required' do
  333. SiteSetting.stubs(:enable_twitter_logins?).returns(true)
  334. twitter_auth = { twitter_user_id: 42, twitter_screen_name: "bruce" }
  335. auth = session[:authentication] = {}
  336. auth[:authenticator_name] = 'twitter'
  337. auth[:extra_data] = twitter_auth
  338. TwitterUserInfo.expects(:create)
  339. post_user
  340. end
  341. end
  342. end
  343. context 'after success' do
  344. before { post_user }
  345. it 'should succeed' do
  346. should respond_with(:success)
  347. end
  348. it 'has the proper JSON' do
  349. json = JSON::parse(response.body)
  350. json["success"].should be_true
  351. end
  352. it 'should not result in an active account' do
  353. User.find_by(username: @user.username).active.should be_false
  354. end
  355. end
  356. shared_examples 'honeypot fails' do
  357. it 'should not create a new user' do
  358. expect {
  359. xhr :post, :create, create_params
  360. }.to_not change { User.count }
  361. end
  362. it 'should not send an email' do
  363. User.any_instance.expects(:enqueue_welcome_message).never
  364. xhr :post, :create, create_params
  365. end
  366. it 'should say it was successful' do
  367. xhr :post, :create, create_params
  368. json = JSON::parse(response.body)
  369. json["success"].should be_true
  370. end
  371. end
  372. context 'when honeypot value is wrong' do
  373. before do
  374. UsersController.any_instance.stubs(:honeypot_value).returns('abc')
  375. end
  376. let(:create_params) { {name: @user.name, username: @user.username, password: "strongpassword", email: @user.email, password_confirmation: 'wrong'} }
  377. include_examples 'honeypot fails'
  378. end
  379. context 'when challenge answer is wrong' do
  380. before do
  381. UsersController.any_instance.stubs(:challenge_value).returns('abc')
  382. end
  383. let(:create_params) { {name: @user.name, username: @user.username, password: "strongpassword", email: @user.email, challenge: 'abc'} }
  384. include_examples 'honeypot fails'
  385. end
  386. context "when 'invite only' setting is enabled" do
  387. before { SiteSetting.expects(:invite_only?).returns(true) }
  388. let(:create_params) {{
  389. name: @user.name,
  390. username: @user.username,
  391. password: 'strongpassword',
  392. email: @user.email
  393. }}
  394. include_examples 'honeypot fails'
  395. end
  396. shared_examples 'failed signup' do
  397. it 'should not create a new User' do
  398. expect { xhr :post, :create, create_params }.to_not change { User.count }
  399. end
  400. it 'should report failed' do
  401. xhr :post, :create, create_params
  402. json = JSON::parse(response.body)
  403. json["success"].should_not be_true
  404. end
  405. end
  406. context 'when password is blank' do
  407. let(:create_params) { {name: @user.name, username: @user.username, password: "", email: @user.email} }
  408. include_examples 'failed signup'
  409. end
  410. context 'when password param is missing' do
  411. let(:create_params) { {name: @user.name, username: @user.username, email: @user.email} }
  412. include_examples 'failed signup'
  413. end
  414. context 'when an Exception is raised' do
  415. [ ActiveRecord::StatementInvalid,
  416. RestClient::Forbidden ].each do |exception|
  417. before { User.any_instance.stubs(:save).raises(exception) }
  418. let(:create_params) {
  419. { name: @user.name, username: @user.username,
  420. password: "strongpassword", email: @user.email}
  421. }
  422. include_examples 'failed signup'
  423. end
  424. end
  425. end
  426. context '.username' do
  427. it 'raises an error when not logged in' do
  428. lambda { xhr :put, :username, username: 'somename' }.should raise_error(Discourse::NotLoggedIn)
  429. end
  430. context 'while logged in' do
  431. let!(:user) { log_in }
  432. let(:new_username) { "#{user.username}1234" }
  433. it 'raises an error without a new_username param' do
  434. lambda { xhr :put, :username, username: user.username }.should raise_error(ActionController::ParameterMissing)
  435. end
  436. it 'raises an error when you don\'t have permission to change the username' do
  437. Guardian.any_instance.expects(:can_edit_username?).with(user).returns(false)
  438. xhr :put, :username, username: user.username, new_username: new_username
  439. response.should be_forbidden
  440. end
  441. it 'raises an error when change_username fails' do
  442. User.any_instance.expects(:change_username).with(new_username).returns(false)
  443. lambda { xhr :put, :username, username: user.username, new_username: new_username }.should raise_error(Discourse::InvalidParameters)
  444. end
  445. it 'should succeed when the change_username returns true' do
  446. User.any_instance.expects(:change_username).with(new_username).returns(true)
  447. xhr :put, :username, username: user.username, new_username: new_username
  448. response.should be_success
  449. end
  450. end
  451. end
  452. context '.check_username' do
  453. it 'raises an error without any parameters' do
  454. lambda { xhr :get, :check_username }.should raise_error(ActionController::ParameterMissing)
  455. end
  456. shared_examples 'when username is unavailable' do
  457. it 'should return success' do
  458. response.should be_success
  459. end
  460. it 'should return available as false in the JSON' do
  461. ::JSON.parse(response.body)['available'].should be_false
  462. end
  463. it 'should return a suggested username' do
  464. ::JSON.parse(response.body)['suggestion'].should be_present
  465. end
  466. end
  467. shared_examples 'when username is available' do
  468. it 'should return success' do
  469. response.should be_success
  470. end
  471. it 'should return available in the JSON' do
  472. ::JSON.parse(response.body)['available'].should be_true
  473. end
  474. end
  475. it 'returns nothing when given an email param but no username' do
  476. xhr :get, :check_username, email: 'dood@example.com'
  477. response.should be_success
  478. end
  479. context 'username is available' do
  480. before do
  481. xhr :get, :check_username, username: 'BruceWayne'
  482. end
  483. include_examples 'when username is available'
  484. end
  485. context 'username is unavailable' do
  486. let!(:user) { Fabricate(:user) }
  487. before do
  488. xhr :get, :check_username, username: user.username
  489. end
  490. include_examples 'when username is unavailable'
  491. end
  492. shared_examples 'checking an invalid username' do
  493. it 'should return success' do
  494. response.should be_success
  495. end
  496. it 'should not return an available key' do
  497. ::JSON.parse(response.body)['available'].should be_nil
  498. end
  499. it 'should return an error message' do
  500. ::JSON.parse(response.body)['errors'].should_not be_empty
  501. end
  502. end
  503. context 'has invalid characters' do
  504. before do
  505. xhr :get, :check_username, username: 'bad username'
  506. end
  507. include_examples 'checking an invalid username'
  508. it 'should return the invalid characters message' do
  509. ::JSON.parse(response.body)['errors'].should include(I18n.t(:'user.username.characters'))
  510. end
  511. end
  512. context 'is too long' do
  513. before do
  514. xhr :get, :check_username, username: generate_username(User.username_length.last + 1)
  515. end
  516. include_examples 'checking an invalid username'
  517. it 'should return the "too long" message' do
  518. ::JSON.parse(response.body)['errors'].should include(I18n.t(:'user.username.long', max: User.username_length.end))
  519. end
  520. end
  521. describe 'different case of existing username' do
  522. context "it's my username" do
  523. let!(:user) { Fabricate(:user, username: 'hansolo') }
  524. before do
  525. log_in_user(user)
  526. xhr :get, :check_username, username: 'HanSolo'
  527. end
  528. include_examples 'when username is available'
  529. end
  530. context "it's someone else's username" do
  531. let!(:user) { Fabricate(:user, username: 'hansolo') }
  532. before do
  533. log_in
  534. xhr :get, :check_username, username: 'HanSolo'
  535. end
  536. include_examples 'when username is unavailable'
  537. end
  538. context "an admin changing it for someone else" do
  539. let!(:user) { Fabricate(:user, username: 'hansolo') }
  540. before do
  541. log_in_user(Fabricate(:admin))
  542. xhr :get, :check_username, username: 'HanSolo', for_user_id: user.id
  543. end
  544. include_examples 'when username is available'
  545. end
  546. end
  547. end
  548. describe '#invited' do
  549. it 'returns success' do
  550. user = Fabricate(:user)
  551. xhr :get, :invited, username: user.username
  552. expect(response).to be_success
  553. end
  554. it 'filters by email' do
  555. inviter = Fabricate(:user)
  556. invitee = Fabricate(:user)
  557. invite = Fabricate(
  558. :invite,
  559. email: 'billybob@example.com',
  560. invited_by: inviter,
  561. user: invitee
  562. )
  563. Fabricate(
  564. :invite,
  565. email: 'jimtom@example.com',
  566. invited_by: inviter,
  567. user: invitee
  568. )
  569. xhr :get, :invited, username: inviter.username, filter: 'billybob'
  570. invites = JSON.parse(response.body)['invites']
  571. expect(invites).to have(1).item
  572. expect(invites.first).to include('email' => 'billybob@example.com')
  573. end
  574. it 'filters by username' do
  575. inviter = Fabricate(:user)
  576. invitee = Fabricate(:user, username: 'billybob')
  577. invite = Fabricate(
  578. :invite,
  579. invited_by: inviter,
  580. email: 'billybob@example.com',
  581. user: invitee
  582. )
  583. Fabricate(
  584. :invite,
  585. invited_by: inviter,
  586. user: Fabricate(:user, username: 'jimtom')
  587. )
  588. xhr :get, :invited, username: inviter.username, filter: 'billybob'
  589. invites = JSON.parse(response.body)['invites']
  590. expect(invites).to have(1).item
  591. expect(invites.first).to include('email' => 'billybob@example.com')
  592. end
  593. context 'with guest' do
  594. context 'with pending invites' do
  595. it 'does not return invites' do
  596. inviter = Fabricate(:user)
  597. Fabricate(:invite, invited_by: inviter)
  598. xhr :get, :invited, username: inviter.username
  599. invites = JSON.parse(response.body)['invites']
  600. expect(invites).to be_empty
  601. end
  602. end
  603. context 'with redeemed invites' do
  604. it 'returns invites' do
  605. inviter = Fabricate(:user)
  606. invitee = Fabricate(:user)
  607. invite = Fabricate(:invite, invited_by: inviter, user: invitee)
  608. xhr :get, :invited, username: inviter.username
  609. invites = JSON.parse(response.body)['invites']
  610. expect(invites).to have(1).item
  611. expect(invites.first).to include('email' => invite.email)
  612. end
  613. end
  614. end
  615. context 'with authenticated user' do
  616. context 'with pending invites' do
  617. context 'with permission to see pending invites' do
  618. it 'returns invites' do
  619. user = log_in
  620. inviter = Fabricate(:user)
  621. invite = Fabricate(:invite, invited_by: inviter)
  622. stub_guardian(user) do |guardian|
  623. guardian.stubs(:can_see_invite_details?).
  624. with(inviter).returns(true)
  625. end
  626. xhr :get, :invited, username: inviter.username
  627. invites = JSON.parse(response.body)['invites']
  628. expect(invites).to have(1).item
  629. expect(invites.first).to include("email" => invite.email)
  630. end
  631. end
  632. context 'without permission to see pending invites' do
  633. it 'does not return invites' do
  634. user = log_in
  635. inviter = Fabricate(:user)
  636. invitee = Fabricate(:user)
  637. Fabricate(:invite, invited_by: inviter)
  638. stub_guardian(user) do |guardian|
  639. guardian.stubs(:can_see_invite_details?).
  640. with(inviter).returns(false)
  641. end
  642. xhr :get, :invited, username: inviter.username
  643. json = JSON.parse(response.body)['invites']
  644. expect(json).to be_empty
  645. end
  646. end
  647. end
  648. context 'with redeemed invites' do
  649. it 'returns invites' do
  650. user = log_in
  651. inviter = Fabricate(:user)
  652. invitee = Fabricate(:user)
  653. invite = Fabricate(:invite, invited_by: inviter, user: invitee)
  654. xhr :get, :invited, username: inviter.username
  655. invites = JSON.parse(response.body)['invites']
  656. expect(invites).to have(1).item
  657. expect(invites.first).to include('email' => invite.email)
  658. end
  659. end
  660. end
  661. end
  662. describe '#update' do
  663. context 'with guest' do
  664. it 'raises an error' do
  665. expect do
  666. xhr :put, :update, username: 'guest'
  667. end.to raise_error(Discourse::NotLoggedIn)
  668. end
  669. end
  670. context 'with authenticated user' do
  671. context 'with permission to update' do
  672. it 'allows the update' do
  673. user = Fabricate(:user, name: 'Billy Bob')
  674. log_in_user(user)
  675. put :update, username: user.username, name: 'Jim Tom', custom_fields: {test: :it}
  676. expect(response).to be_success
  677. user.reload
  678. expect(user.name).to eq 'Jim Tom'
  679. expect(user.custom_fields['test']).to eq 'it'
  680. end
  681. it 'returns user JSON' do
  682. user = log_in
  683. put :update, username: user.username
  684. json = JSON.parse(response.body)
  685. expect(json['user']['id']).to eq user.id
  686. end
  687. end
  688. context 'without permission to update' do
  689. it 'does not allow the update' do
  690. user = Fabricate(:user, name: 'Billy Bob')
  691. log_in_user(user)
  692. guardian = Guardian.new(user)
  693. guardian.stubs(:ensure_can_edit!).with(user).raises(Discourse::InvalidAccess.new)
  694. Guardian.stubs(new: guardian).with(user)
  695. put :update, username: user.username, name: 'Jim Tom'
  696. expect(response).to be_forbidden
  697. expect(user.reload.name).not_to eq 'Jim Tom'
  698. end
  699. end
  700. end
  701. end
  702. describe "badge_title" do
  703. let(:user) { Fabricate(:user) }
  704. let(:badge) { Fabricate(:badge) }
  705. let(:user_badge) { BadgeGranter.grant(badge, user) }
  706. it "sets the user's title to the badge name if it is titleable" do
  707. log_in_user user
  708. xhr :put, :badge_title, user_badge_id: user_badge.id, username: user.username
  709. user.reload.title.should_not == badge.name
  710. badge.update_attributes allow_title: true
  711. xhr :put, :badge_title, user_badge_id: user_badge.id, username: user.username
  712. user.reload.title.should == badge.name
  713. end
  714. end
  715. describe "search_users" do
  716. let(:topic) { Fabricate :topic }
  717. let(:user) { Fabricate :user, username: "joecabot", name: "Lawrence Tierney" }
  718. before do
  719. ActiveRecord::Base.observers.enable :all
  720. Fabricate :post, user: user, topic: topic
  721. end
  722. it "searches when provided the term only" do
  723. xhr :post, :search_users, term: user.name.split(" ").last
  724. response.should be_success
  725. json = JSON.parse(response.body)
  726. json["users"].map { |u| u["username"] }.should include(user.username)
  727. end
  728. it "searches when provided the topic only" do
  729. xhr :post, :search_users, topic_id: topic.id
  730. response.should be_success
  731. json = JSON.parse(response.body)
  732. json["users"].map { |u| u["username"] }.should include(user.username)
  733. end
  734. it "searches when provided the term and topic" do
  735. xhr :post, :search_users, term: user.name.split(" ").last, topic_id: topic.id
  736. response.should be_success
  737. json = JSON.parse(response.body)
  738. json["users"].map { |u| u["username"] }.should include(user.username)
  739. end
  740. context "when `enable_names` is true" do
  741. before do
  742. SiteSetting.enable_names = true
  743. end
  744. it "returns names" do
  745. xhr :post, :search_users, term: user.name
  746. json = JSON.parse(response.body)
  747. json["users"].map { |u| u["name"] }.should include(user.name)
  748. end
  749. end
  750. context "when `enable_names` is false" do
  751. before do
  752. SiteSetting.stubs(:enable_names?).returns(false)
  753. end
  754. it "returns names" do
  755. xhr :post, :search_users, term: user.name
  756. json = JSON.parse(response.body)
  757. json["users"].map { |u| u["name"] }.should_not include(user.name)
  758. end
  759. end
  760. end
  761. describe 'send_activation_email' do
  762. context 'for an existing user' do
  763. let(:user) { Fabricate(:user) }
  764. before do
  765. UsersController.any_instance.stubs(:fetch_user_from_params).returns(user)
  766. end
  767. context 'with a valid email_token' do
  768. it 'should send the activation email' do
  769. Jobs.expects(:enqueue).with(:user_email, has_entries(type: :signup))
  770. xhr :post, :send_activation_email, username: user.username
  771. end
  772. end
  773. context 'without an existing email_token' do
  774. before do
  775. user.email_tokens.each {|t| t.destroy}
  776. user.reload
  777. end
  778. it 'should generate a new token' do
  779. expect {
  780. xhr :post, :send_activation_email, username: user.username
  781. }.to change{ user.email_tokens(true).count }.by(1)
  782. end
  783. it 'should send an email' do
  784. Jobs.expects(:enqueue).with(:user_email, has_entries(type: :signup))
  785. xhr :post, :send_activation_email, username: user.username
  786. end
  787. end
  788. end
  789. context 'when username does not exist' do
  790. it 'should not send an email' do
  791. Jobs.expects(:enqueue).never
  792. xhr :post, :send_activation_email, username: 'nopenopenopenope'
  793. end
  794. end
  795. end
  796. describe '.upload_user_image' do
  797. it 'raises an error when not logged in' do
  798. lambda { xhr :put, :upload_user_image, username: 'asdf' }.should raise_error(Discourse::NotLoggedIn)
  799. end
  800. context 'while logged in' do
  801. let!(:user) { log_in }
  802. let(:logo) { file_from_fixtures("logo.png") }
  803. let(:user_image) do
  804. ActionDispatch::Http::UploadedFile.new({ filename: 'logo.png', tempfile: logo })
  805. end
  806. it 'raises an error without a image_type param' do
  807. lambda { xhr :put, :upload_user_image, username: user.username }.should raise_error(ActionController::ParameterMissing)
  808. end
  809. describe "with uploaded file" do
  810. it 'raises an error when you don\'t have permission to upload an user image' do
  811. Guardian.any_instance.expects(:can_edit?).with(user).returns(false)
  812. xhr :post, :upload_user_image, username: user.username, image_type: "avatar"
  813. response.should be_forbidden
  814. end
  815. it 'rejects large images' do
  816. SiteSetting.stubs(:max_image_size_kb).returns(1)
  817. xhr :post, :upload_user_image, username: user.username, file: user_image, image_type: "avatar"
  818. response.status.should eq 422
  819. end
  820. it 'rejects unauthorized images' do
  821. SiteSetting.stubs(:authorized_extensions).returns(".txt")
  822. xhr :post, :upload_user_image, username: user.username, file: user_image, image_type: "avatar"
  823. response.status.should eq 422
  824. end
  825. it 'is successful for avatars' do
  826. upload = Fabricate(:upload)
  827. Upload.expects(:create_for).returns(upload)
  828. # enqueues the user_image generator job
  829. xhr :post, :upload_user_image, username: user.username, file: user_image, image_type: "avatar"
  830. # returns the url, width and height of the uploaded image
  831. json = JSON.parse(response.body)
  832. json['url'].should == "/uploads/default/1/1234567890123456.png"
  833. json['width'].should == 100
  834. json['height'].should == 200
  835. json['upload_id'].should == upload.id
  836. end
  837. it 'is successful for profile backgrounds' do
  838. upload = Fabricate(:upload)
  839. Upload.expects(:create_for).returns(upload)
  840. xhr :post, :upload_user_image, username: user.username, file: user_image, image_type: "profile_background"
  841. user.reload
  842. user.user_profile.profile_background.should == "/uploads/default/1/1234567890123456.png"
  843. # returns the url, width and height of the uploaded image
  844. json = JSON.parse(response.body)
  845. json['url'].should == "/uploads/default/1/1234567890123456.png"
  846. json['width'].should == 100
  847. json['height'].should == 200
  848. end
  849. end
  850. describe "with url" do
  851. let(:user_image_url) { "http://cdn.discourse.org/assets/logo.png" }
  852. before { UsersController.any_instance.stubs(:is_api?).returns(true) }
  853. describe "correct urls" do
  854. before { FileHelper.stubs(:download).returns(logo) }
  855. it 'rejects large images' do
  856. SiteSetting.stubs(:max_image_size_kb).returns(1)
  857. xhr :post, :upload_user_image, username: user.username, file: user_image_url, image_type: "profile_background"
  858. response.status.should eq 422
  859. end
  860. it 'rejects unauthorized images' do
  861. SiteSetting.stubs(:authorized_extensions).returns(".txt")
  862. xhr :post, :upload_user_image, username: user.username, file: user_image_url, image_type: "profile_background"
  863. response.status.should eq 422
  864. end
  865. it 'is successful for avatars' do
  866. upload = Fabricate(:upload)
  867. Upload.expects(:create_for).returns(upload)
  868. # enqueues the user_image generator job
  869. xhr :post, :upload_avatar, username: user.username, file: user_image_url, image_type: "avatar"
  870. json = JSON.parse(response.body)
  871. json['url'].should == "/uploads/default/1/1234567890123456.png"
  872. json['width'].should == 100
  873. json['height'].should == 200
  874. json['upload_id'].should == upload.id
  875. end
  876. it 'is successful for profile backgrounds' do
  877. upload = Fabricate(:upload)
  878. Upload.expects(:create_for).returns(upload)
  879. xhr :post, :upload_user_image, username: user.username, file: user_image_url, image_type: "profile_background"
  880. user.reload
  881. user.user_profile.profile_background.should == "/uploads/default/1/1234567890123456.png"
  882. # returns the url, width and height of the uploaded image
  883. json = JSON.parse(response.body)
  884. json['url'].should == "/uploads/default/1/1234567890123456.png"
  885. json['width'].should == 100
  886. json['height'].should == 200
  887. end
  888. end
  889. it "should handle malformed urls" do
  890. xhr :post, :upload_user_image, username: user.username, file: "foobar", image_type: "profile_background"
  891. response.status.should eq 422
  892. end
  893. end
  894. end
  895. end
  896. describe '.pick_avatar' do
  897. it 'raises an error when not logged in' do
  898. lambda { xhr :put, :pick_avatar, username: 'asdf', avatar_id: 1}.should raise_error(Discourse::NotLoggedIn)
  899. end
  900. context 'while logged in' do
  901. let!(:user) { log_in }
  902. it 'raises an error when you don\'t have permission to toggle the avatar' do
  903. another_user = Fabricate(:user)
  904. xhr :put, :pick_avatar, username: another_user.username, upload_id: 1
  905. response.should be_forbidden
  906. end
  907. it 'it successful' do
  908. xhr :put, :pick_avatar, username: user.username, upload_id: 111
  909. user.reload.uploaded_avatar_id.should == 111
  910. response.should be_success
  911. xhr :put, :pick_avatar, username: user.username
  912. user.reload.uploaded_avatar_id.should == nil
  913. response.should be_success
  914. end
  915. end
  916. end
  917. describe '.destroy_user_image' do
  918. it 'raises an error when not logged in' do
  919. lambda { xhr :delete, :destroy_user_image, type: 'profile_background', username: 'asdf' }.should raise_error(Discourse::NotLoggedIn)
  920. end
  921. context 'while logged in' do
  922. let!(:user) { log_in }
  923. it 'raises an error when you don\'t have permission to clear the profile background' do
  924. Guardian.any_instance.expects(:can_edit?).with(user).returns(false)
  925. xhr :delete, :destroy_user_image, username: user.username, image_type: 'profile_background'
  926. response.should be_forbidden
  927. end
  928. it "requires the `image_type` param" do
  929. -> { xhr :delete, :destroy_user_image, username: user.username }.should raise_error(ActionController::ParameterMissing)
  930. end
  931. it "only allows certain `image_types`" do
  932. -> { xhr :delete, :destroy_user_image, username: user.username, image_type: 'wat' }.should raise_error(Discourse::InvalidParameters)
  933. end
  934. it 'can clear the profile background' do
  935. xhr :delete, :destroy_user_image, image_type: 'profile_background', username: user.username
  936. user.reload.user_profile.profile_background.should == ""
  937. response.should be_success
  938. end
  939. end
  940. end
  941. describe '.destroy' do
  942. it 'raises an error when not logged in' do
  943. lambda { xhr :delete, :destroy, username: 'nobody' }.should raise_error(Discourse::NotLoggedIn)
  944. end
  945. context 'while logged in' do
  946. let!(:user) { log_in }
  947. it 'raises an error when you cannot delete your account' do
  948. Guardian.any_instance.stubs(:can_delete_user?).returns(false)
  949. UserDestroyer.any_instance.expects(:destroy).never
  950. xhr :delete, :destroy, username: user.username
  951. response.should be_forbidden
  952. end
  953. it "raises an error when you try to delete someone else's account" do
  954. UserDestroyer.any_instance.expects(:destroy).never
  955. xhr :delete, :destroy, username: Fabricate(:user).username
  956. response.should be_forbidden
  957. end
  958. it "deletes your account when you're allowed to" do
  959. Guardian.any_instance.stubs(:can_delete_user?).returns(true)
  960. UserDestroyer.any_instance.expects(:destroy).with(user, anything).returns(user)
  961. xhr :delete, :destroy, username: user.username
  962. response.should be_success
  963. end
  964. end
  965. end
  966. describe '.my_redirect' do
  967. it "returns 404 if the user is not logged in" do
  968. get :my_redirect, path: "wat"
  969. response.should_not be_success
  970. response.should_not be_redirect
  971. end
  972. context "when the user is logged in" do
  973. let!(:user) { log_in }
  974. it "will not redirect to an invalid path" do
  975. get :my_redirect, path: "wat/..password.txt"
  976. response.should_not be_redirect
  977. end
  978. it "will redirect to an valid path" do
  979. get :my_redirect, path: "preferences"
  980. response.should be_redirect
  981. end
  982. it "permits forward slashes" do
  983. get :my_redirect, path: "activity/posts"
  984. response.should be_redirect
  985. end
  986. end
  987. end
  988. end