]> cat aescling's git repositories - mastodon.git/blob - spec/controllers/auth/sessions_controller_spec.rb
update gem, test pam authentication (#7028)
[mastodon.git] / spec / controllers / auth / sessions_controller_spec.rb
1 # frozen_string_literal: true
2
3 require 'rails_helper'
4
5 RSpec.describe Auth::SessionsController, type: :controller do
6 render_views
7
8 describe 'GET #new' do
9 before do
10 request.env['devise.mapping'] = Devise.mappings[:user]
11 end
12
13 it 'returns http success' do
14 get :new
15 expect(response).to have_http_status(:success)
16 end
17 end
18
19 describe 'DELETE #destroy' do
20 let(:user) { Fabricate(:user) }
21
22 before do
23 request.env['devise.mapping'] = Devise.mappings[:user]
24 end
25
26 context 'with a regular user' do
27 it 'redirects to home after sign out' do
28 sign_in(user, scope: :user)
29 delete :destroy
30
31 expect(response).to redirect_to(new_user_session_path)
32 end
33 end
34
35 context 'with a suspended user' do
36 it 'redirects to home after sign out' do
37 Fabricate(:account, user: user, suspended: true)
38 sign_in(user, scope: :user)
39 delete :destroy
40
41 expect(response).to redirect_to(new_user_session_path)
42 end
43 end
44 end
45
46 describe 'POST #create' do
47 before do
48 request.env['devise.mapping'] = Devise.mappings[:user]
49 end
50
51 context 'using PAM authentication' do
52 context 'using a valid password' do
53 before do
54 post :create, params: { user: { email: "pam_user1", password: '123456' } }
55 end
56
57 it 'redirects to home' do
58 expect(response).to redirect_to(root_path)
59 end
60
61 it 'logs the user in' do
62 expect(controller.current_user).to be_instance_of(User)
63 end
64 end
65
66 context 'using an invalid password' do
67 before do
68 post :create, params: { user: { email: "pam_user1", password: 'WRONGPW' } }
69 end
70
71 it 'shows a login error' do
72 expect(flash[:alert]).to match I18n.t('devise.failure.invalid', authentication_keys: 'Email')
73 end
74
75 it "doesn't log the user in" do
76 expect(controller.current_user).to be_nil
77 end
78 end
79
80 context 'using a valid email and existing user' do
81 let(:user) do
82 account = Fabricate.build(:account, username: 'pam_user1')
83 account.save!(validate: false)
84 user = Fabricate(:user, email: 'pam@example.com', password: nil, account: account)
85 user
86 end
87
88 before do
89 post :create, params: { user: { email: user.email, password: '123456' } }
90 end
91
92 it 'redirects to home' do
93 expect(response).to redirect_to(root_path)
94 end
95
96 it 'logs the user in' do
97 expect(controller.current_user).to eq user
98 end
99 end
100 end
101
102 context 'using password authentication' do
103 let(:user) { Fabricate(:user, email: 'foo@bar.com', password: 'abcdefgh') }
104
105 context 'using a valid password' do
106 before do
107 post :create, params: { user: { email: user.email, password: user.password } }
108 end
109
110 it 'redirects to home' do
111 expect(response).to redirect_to(root_path)
112 end
113
114 it 'logs the user in' do
115 expect(controller.current_user).to eq user
116 end
117 end
118
119 context 'using email with uppercase letters' do
120 before do
121 post :create, params: { user: { email: user.email.upcase, password: user.password } }
122 end
123
124 it 'redirects to home' do
125 expect(response).to redirect_to(root_path)
126 end
127
128 it 'logs the user in' do
129 expect(controller.current_user).to eq user
130 end
131 end
132
133 context 'using an invalid password' do
134 before do
135 post :create, params: { user: { email: user.email, password: 'wrongpw' } }
136 end
137
138 it 'shows a login error' do
139 expect(flash[:alert]).to match I18n.t('devise.failure.invalid', authentication_keys: 'Email')
140 end
141
142 it "doesn't log the user in" do
143 expect(controller.current_user).to be_nil
144 end
145 end
146
147 context 'using an unconfirmed password' do
148 before do
149 request.headers['Accept-Language'] = accept_language
150 post :create, params: { user: { email: unconfirmed_user.email, password: unconfirmed_user.password } }
151 end
152
153 let(:unconfirmed_user) { user.tap { |u| u.update!(confirmed_at: nil) } }
154 let(:accept_language) { 'fr' }
155
156 it 'shows a translated login error' do
157 expect(flash[:alert]).to eq(I18n.t('devise.failure.unconfirmed', locale: accept_language))
158 end
159 end
160
161 context "logging in from the user's page" do
162 before do
163 allow(controller).to receive(:single_user_mode?).and_return(single_user_mode)
164 allow(controller).to receive(:stored_location_for).with(:user).and_return("/@#{user.account.username}")
165 post :create, params: { user: { email: user.email, password: user.password } }
166 end
167
168 context "in single user mode" do
169 let(:single_user_mode) { true }
170
171 it 'redirects to home' do
172 expect(response).to redirect_to(root_path)
173 end
174 end
175
176 context "in non-single user mode" do
177 let(:single_user_mode) { false }
178
179 it "redirects back to the user's page" do
180 expect(response).to redirect_to(short_account_path(username: user.account))
181 end
182 end
183 end
184 end
185
186 context 'using two-factor authentication' do
187 let(:user) do
188 Fabricate(:user, email: 'x@y.com', password: 'abcdefgh',
189 otp_required_for_login: true, otp_secret: User.generate_otp_secret(32))
190 end
191 let(:recovery_codes) do
192 codes = user.generate_otp_backup_codes!
193 user.save
194 return codes
195 end
196
197 context 'using email and password' do
198 before do
199 post :create, params: { user: { email: user.email, password: user.password } }
200 end
201
202 it 'renders two factor authentication page' do
203 expect(controller).to render_template("two_factor")
204 end
205 end
206
207 context 'using upcase email and password' do
208 before do
209 post :create, params: { user: { email: user.email.upcase, password: user.password } }
210 end
211
212 it 'renders two factor authentication page' do
213 expect(controller).to render_template("two_factor")
214 end
215 end
216
217 context 'using a valid OTP' do
218 before do
219 post :create, params: { user: { otp_attempt: user.current_otp } }, session: { otp_user_id: user.id }
220 end
221
222 it 'redirects to home' do
223 expect(response).to redirect_to(root_path)
224 end
225
226 it 'logs the user in' do
227 expect(controller.current_user).to eq user
228 end
229 end
230
231 context 'when the server has an decryption error' do
232 before do
233 allow_any_instance_of(User).to receive(:validate_and_consume_otp!).and_raise(OpenSSL::Cipher::CipherError)
234 post :create, params: { user: { otp_attempt: user.current_otp } }, session: { otp_user_id: user.id }
235 end
236
237 it 'shows a login error' do
238 expect(flash[:alert]).to match I18n.t('users.invalid_otp_token')
239 end
240
241 it "doesn't log the user in" do
242 expect(controller.current_user).to be_nil
243 end
244 end
245
246 context 'using a valid recovery code' do
247 before do
248 post :create, params: { user: { otp_attempt: recovery_codes.first } }, session: { otp_user_id: user.id }
249 end
250
251 it 'redirects to home' do
252 expect(response).to redirect_to(root_path)
253 end
254
255 it 'logs the user in' do
256 expect(controller.current_user).to eq user
257 end
258 end
259
260 context 'using an invalid OTP' do
261 before do
262 post :create, params: { user: { otp_attempt: 'wrongotp' } }, session: { otp_user_id: user.id }
263 end
264
265 it 'shows a login error' do
266 expect(flash[:alert]).to match I18n.t('users.invalid_otp_token')
267 end
268
269 it "doesn't log the user in" do
270 expect(controller.current_user).to be_nil
271 end
272 end
273 end
274 end
275 end
This page took 0.188069 seconds and 6 git commands to generate.