registrations_controller_spec.rb 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. # frozen_string_literal: true
  2. require 'rails_helper'
  3. RSpec.describe Auth::RegistrationsController do
  4. render_views
  5. shared_examples 'checks for enabled registrations' do |path|
  6. context 'when in single user mode and open for registration' do
  7. before do
  8. Setting.registrations_mode = 'open'
  9. allow(Rails.configuration.x).to receive(:single_user_mode).and_return(true)
  10. end
  11. it 'redirects to root' do
  12. Fabricate(:account)
  13. get path
  14. expect(response).to redirect_to '/'
  15. expect(Rails.configuration.x).to have_received(:single_user_mode)
  16. end
  17. end
  18. context 'when registrations closed and not in single user mode' do
  19. before do
  20. Setting.registrations_mode = 'none'
  21. allow(Rails.configuration.x).to receive(:single_user_mode).and_return(false)
  22. end
  23. it 'redirects to root' do
  24. get path
  25. expect(response).to redirect_to '/'
  26. expect(Rails.configuration.x).to have_received(:single_user_mode)
  27. end
  28. end
  29. end
  30. describe 'GET #edit' do
  31. before do
  32. request.env['devise.mapping'] = Devise.mappings[:user]
  33. sign_in(Fabricate(:user))
  34. get :edit
  35. end
  36. it 'returns http success and cache headers' do
  37. expect(response)
  38. .to have_http_status(200)
  39. expect(response.headers['Cache-Control'])
  40. .to include('private, no-store')
  41. end
  42. end
  43. describe 'PUT #update' do
  44. let(:current_password) { 'current password' }
  45. let(:user) { Fabricate(:user, password: current_password) }
  46. before do
  47. request.env['devise.mapping'] = Devise.mappings[:user]
  48. sign_in(user, scope: :user)
  49. end
  50. it 'returns http success and cache headers' do
  51. put :update
  52. expect(response)
  53. .to have_http_status(200)
  54. expect(response.headers['Cache-Control'])
  55. .to include('private, no-store')
  56. end
  57. it 'can update the user email' do
  58. expect do
  59. put :update, params: {
  60. user: {
  61. email: 'newemail@example.com',
  62. current_password: current_password,
  63. },
  64. }
  65. expect(response).to redirect_to(edit_user_registration_path)
  66. end.to change { user.reload.unconfirmed_email }.to('newemail@example.com')
  67. end
  68. it 'requires the current password to update the email' do
  69. expect do
  70. put :update, params: {
  71. user: {
  72. email: 'newemail@example.com',
  73. current_password: 'something',
  74. },
  75. }
  76. expect(response).to have_http_status(200)
  77. end.to_not(change { user.reload.unconfirmed_email })
  78. end
  79. it 'can update the user password' do
  80. expect do
  81. put :update, params: {
  82. user: {
  83. password: 'new password',
  84. password_confirmation: 'new password',
  85. current_password: current_password,
  86. },
  87. }
  88. expect(response).to redirect_to(edit_user_registration_path)
  89. end.to(change { user.reload.encrypted_password })
  90. end
  91. it 'requires the password confirmation' do
  92. expect do
  93. put :update, params: {
  94. user: {
  95. password: 'new password',
  96. password_confirmation: 'something else',
  97. current_password: current_password,
  98. },
  99. }
  100. expect(response).to have_http_status(200)
  101. end.to_not(change { user.reload.encrypted_password })
  102. end
  103. it 'requires the current password to update the password' do
  104. expect do
  105. put :update, params: {
  106. user: {
  107. password: 'new password',
  108. password_confirmation: 'new password',
  109. current_password: 'something',
  110. },
  111. }
  112. expect(response).to have_http_status(200)
  113. end.to_not(change { user.reload.encrypted_password })
  114. end
  115. context 'when suspended' do
  116. let(:user) { Fabricate(:user, account_attributes: { username: 'test', suspended_at: Time.now.utc }) }
  117. it 'returns http forbidden' do
  118. put :update
  119. expect(response).to have_http_status(403)
  120. end
  121. end
  122. end
  123. describe 'GET #new' do
  124. before do
  125. request.env['devise.mapping'] = Devise.mappings[:user]
  126. end
  127. context 'with open registrations' do
  128. it 'returns http success' do
  129. Setting.registrations_mode = 'open'
  130. get :new
  131. expect(response).to have_http_status(200)
  132. end
  133. end
  134. include_examples 'checks for enabled registrations', :new
  135. end
  136. describe 'POST #create' do
  137. let(:accept_language) { 'de' }
  138. before do
  139. session[:registration_form_time] = 5.seconds.ago
  140. request.env['devise.mapping'] = Devise.mappings[:user]
  141. end
  142. around do |example|
  143. I18n.with_locale(I18n.locale) do
  144. example.run
  145. end
  146. end
  147. context 'when an accept language is present in headers' do
  148. subject do
  149. Setting.registrations_mode = 'open'
  150. request.headers['Accept-Language'] = accept_language
  151. post :create, params: { user: { account_attributes: { username: 'test' }, email: 'test@example.com', password: '12345678', password_confirmation: '12345678', agreement: 'true' } }
  152. end
  153. it 'redirects to setup and creates user' do
  154. subject
  155. expect(response)
  156. .to redirect_to auth_setup_path
  157. expect(User.find_by(email: 'test@example.com'))
  158. .to be_present
  159. .and have_attributes(locale: eq(accept_language))
  160. end
  161. end
  162. context 'when user has not agreed to terms of service' do
  163. subject do
  164. Setting.registrations_mode = 'open'
  165. request.headers['Accept-Language'] = accept_language
  166. post :create, params: { user: { account_attributes: { username: 'test' }, email: 'test@example.com', password: '12345678', password_confirmation: '12345678', agreement: 'false' } }
  167. end
  168. it 'does not create user' do
  169. subject
  170. user = User.find_by(email: 'test@example.com')
  171. expect(user).to be_nil
  172. end
  173. end
  174. context 'when user has an email address requiring approval' do
  175. subject do
  176. request.headers['Accept-Language'] = accept_language
  177. post :create, params: { user: { account_attributes: { username: 'test' }, email: 'test@example.com', password: '12345678', password_confirmation: '12345678', agreement: 'true' } }
  178. end
  179. before do
  180. Setting.registrations_mode = 'open'
  181. Fabricate(:email_domain_block, allow_with_approval: true, domain: 'example.com')
  182. end
  183. it 'creates unapproved user and redirects to setup' do
  184. subject
  185. expect(response).to redirect_to auth_setup_path
  186. user = User.find_by(email: 'test@example.com')
  187. expect(user).to_not be_nil
  188. expect(user.locale).to eq(accept_language)
  189. expect(user.approved).to be(false)
  190. end
  191. end
  192. context 'when user has an email address requiring approval through a MX record' do
  193. subject do
  194. request.headers['Accept-Language'] = accept_language
  195. post :create, params: { user: { account_attributes: { username: 'test' }, email: 'test@example.com', password: '12345678', password_confirmation: '12345678', agreement: 'true' } }
  196. end
  197. before do
  198. Setting.registrations_mode = 'open'
  199. Fabricate(:email_domain_block, allow_with_approval: true, domain: 'mail.example.com')
  200. allow(User).to receive(:skip_mx_check?).and_return(false)
  201. configure_mx(domain: 'example.com', exchange: 'mail.example.com')
  202. end
  203. it 'creates unapproved user and redirects to setup' do
  204. subject
  205. expect(response).to redirect_to auth_setup_path
  206. user = User.find_by(email: 'test@example.com')
  207. expect(user).to_not be_nil
  208. expect(user.locale).to eq(accept_language)
  209. expect(user.approved).to be(false)
  210. end
  211. end
  212. context 'with Approval-based registrations without invite' do
  213. subject do
  214. Setting.registrations_mode = 'approved'
  215. request.headers['Accept-Language'] = accept_language
  216. post :create, params: { user: { account_attributes: { username: 'test' }, email: 'test@example.com', password: '12345678', password_confirmation: '12345678', agreement: 'true' } }
  217. end
  218. it 'redirects to setup and creates user' do
  219. subject
  220. expect(response)
  221. .to redirect_to auth_setup_path
  222. expect(User.find_by(email: 'test@example.com'))
  223. .to be_present
  224. .and have_attributes(
  225. locale: eq(accept_language),
  226. approved: be(false)
  227. )
  228. end
  229. end
  230. context 'with Approval-based registrations with expired invite' do
  231. subject do
  232. Setting.registrations_mode = 'approved'
  233. request.headers['Accept-Language'] = accept_language
  234. invite = Fabricate(:invite, max_uses: nil, expires_at: 1.hour.ago)
  235. post :create, params: { user: { account_attributes: { username: 'test' }, email: 'test@example.com', password: '12345678', password_confirmation: '12345678', invite_code: invite.code, agreement: 'true' } }
  236. end
  237. it 'redirects to setup and creates user' do
  238. subject
  239. expect(response).to redirect_to auth_setup_path
  240. expect(User.find_by(email: 'test@example.com'))
  241. .to be_present
  242. .and have_attributes(
  243. locale: eq(accept_language),
  244. approved: be(false)
  245. )
  246. end
  247. end
  248. context 'with Approval-based registrations with valid invite and required invite text' do
  249. subject do
  250. inviter = Fabricate(:user, confirmed_at: 2.days.ago)
  251. Setting.registrations_mode = 'approved'
  252. Setting.require_invite_text = true
  253. request.headers['Accept-Language'] = accept_language
  254. invite = Fabricate(:invite, user: inviter, max_uses: nil, expires_at: 1.hour.from_now)
  255. post :create, params: { user: { account_attributes: { username: 'test' }, email: 'test@example.com', password: '12345678', password_confirmation: '12345678', invite_code: invite.code, agreement: 'true' } }
  256. end
  257. it 'redirects to setup and creates user' do
  258. subject
  259. expect(response).to redirect_to auth_setup_path
  260. expect(User.find_by(email: 'test@example.com'))
  261. .to be_present
  262. .and have_attributes(
  263. locale: eq(accept_language),
  264. approved: be(true)
  265. )
  266. end
  267. end
  268. context 'with an already taken username' do
  269. subject do
  270. Setting.registrations_mode = 'open'
  271. post :create, params: { user: { account_attributes: { username: 'test' }, email: 'test@example.com', password: '12345678', password_confirmation: '12345678', agreement: 'true' } }
  272. end
  273. before do
  274. Fabricate(:account, username: 'test')
  275. end
  276. it 'responds with an error message about the username' do
  277. subject
  278. expect(response).to have_http_status(:success)
  279. expect(username_error_text).to eq(I18n.t('errors.messages.taken'))
  280. end
  281. def username_error_text
  282. response.parsed_body.css('.user_account_username .error').text
  283. end
  284. end
  285. include_examples 'checks for enabled registrations', :create
  286. end
  287. describe 'DELETE #destroy' do
  288. let(:user) { Fabricate(:user) }
  289. before do
  290. request.env['devise.mapping'] = Devise.mappings[:user]
  291. sign_in(user, scope: :user)
  292. delete :destroy
  293. end
  294. it 'returns http not found and keeps user' do
  295. expect(response)
  296. .to have_http_status(404)
  297. expect(User.find(user.id))
  298. .to_not be_nil
  299. end
  300. end
  301. end