/
update_test.rb
313 lines (255 loc) · 9.86 KB
/
update_test.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
# -*- coding: utf-8 -*-
require 'test_helper'
module RegistrationsControllerTests
#
# Tests over PUT /users
#
class UpdateTest < ActionDispatch::IntegrationTest
setup do
Honeybadger.expects(:notify).never
end
test "update student without user param returns 400 BAD REQUEST" do
student = create :student
sign_in student
assert_does_not_create(User) do
put '/users', params: {}
end
assert_response :bad_request
end
test "update student with utf8mb4 in name fails" do
student = create :student
sign_in student
assert_does_not_create(User) do
put '/users', params: {user: {name: panda_panda}}
end
assert_response :success # which actually means an error...
assert_equal ['Display Name is invalid'], assigns(:user).errors.full_messages
assert_select 'div#error_explanation', /Display Name is invalid/ # ... is rendered on the page
end
test "update student with age" do
Timecop.travel Time.local(2013, 9, 1, 12, 0, 0) do
student = create :student, birthday: '1981/03/24'
sign_in student
put '/users', params: {format: :js, user: {age: 9}}
assert_response :no_content
assert_equal Date.today - 9.years, assigns(:user).birthday
end
end
test "update student with age with weird params" do
# we are getting input that looks like this:
# "user" => {"age" => {"Pr" => ""}}
# https://www.honeybadger.io/projects/3240/faults/9963470
Timecop.travel Time.local(2013, 9, 1, 12, 0, 0) do
student = create :student, birthday: '1981/03/24'
sign_in student
put '/users', params: {format: :js, user: {age: {"Pr" => nil}}}
assert_response :no_content
# did not change
assert_equal '1981-03-24', assigns(:user).birthday.to_s
end
end
test 'update rejects unwanted parameters' do
user = create :user, name: 'non-admin'
sign_in user
put '/users', params: {user: {name: 'admin', admin: true}}
user.reload
assert_equal 'admin', user.name
refute user.admin
end
test "converting student to teacher is not allowed" do
test_email = 'me@example.com'
student = create :student, email: test_email
sign_in student
put '/users', as: :json, params: {
user: {
user_type: 'teacher',
email: test_email,
hashed_email: student.hashed_email
}
}
assert_response :bad_request
student.reload
assert_equal 'student', student.user_type
end
test "converting teacher to student is not allowed" do
test_email = 'me@example.com'
teacher = create :teacher, email: test_email
sign_in teacher
put '/users', as: :json, params: {
user: {
user_type: 'student',
email: '',
hashed_email: teacher.hashed_email
}
}
assert_response :bad_request
teacher.reload
assert_equal 'teacher', teacher.user_type
end
test "editing email is not allowed" do
current_password = 'oldpassword'
user = create :teacher, password: current_password
new_email = 'new@example.com'
sign_in user
put '/users', params: {
user: {email: new_email, current_password: current_password}
}
assert_response :bad_request
user = user.reload
refute user.email == new_email || user.hashed_email == User.hash_email(new_email)
end
test "editing hashed_email is not allowed" do
current_password = 'oldpassword'
user = create :student, password: current_password
new_hashed_email = '729980b94e1439aeed40122476b0f695'
sign_in user
put '/users', params: {
user: {hashed_email: new_hashed_email, current_password: current_password}
}
assert_response :bad_request
user = user.reload
refute user.hashed_email == new_hashed_email
end
test "single-auth student without a password can set parent_email without a password" do
# so it's possible to add a recovery option to their account. Once they are
# on multi-auth they can just add an email or another SSO, so this is no
# longer needed.
student = create :student, :unmigrated_clever_sso
assert_nil student.parent_email
assert_nil student.encrypted_password
sign_in student
put '/users', params: {
format: 'json',
user: {parent_email: 'parent@example.com'}
}
assert_response :no_content
student.reload
assert_equal 'parent@example.com', student.parent_email
end
test "single-auth student with a password can set parent_email with a password" do
# so it's possible to add a recovery option to their account. Once they are
# on multi-auth they can just add an email or another SSO, so this is no
# longer needed.
password = 'drowssap'
student = create :student, password: password
assert_nil student.parent_email
refute_nil student.encrypted_password
sign_in student
put '/users', params: {
format: 'json',
user: {
parent_email: 'parent@example.com',
current_password: password
}
}
assert_response :no_content
student.reload
assert_equal 'parent@example.com', student.parent_email
end
test "single-auth student with a password cannot set parent_email without a password" do
# so it's possible to add a recovery option to their account. Once they are
# on multi-auth they can just add an email or another SSO, so this is no
# longer needed.
student = create :student, password: 'drowssap'
assert_nil student.parent_email
refute_nil student.encrypted_password
sign_in student
put '/users', params: {
format: 'json',
user: {parent_email: 'parent@example.com'}
}
assert_response :unprocessable_entity
student.reload
assert_nil student.parent_email
end
test "single-auth student with a password cannot set parent_email with the wrong password" do
# so it's possible to add a recovery option to their account. Once they are
# on multi-auth they can just add an email or another SSO, so this is no
# longer needed.
student = create :student, password: 'drowssap'
assert_nil student.parent_email
refute_nil student.encrypted_password
sign_in student
put '/users', params: {
format: 'json',
user: {
parent_email: 'parent@example.com',
current_password: 'wrong-password'
}
}
assert_response :unprocessable_entity
student.reload
assert_nil student.parent_email
end
test "single-auth student can update with a blank parent email without password" do
student = create :student, :unmigrated_clever_sso
assert_nil student.hashed_email
assert_nil student.parent_email
sign_in student
put '/users', params: {
format: 'json',
user: {parent_email: '', age: '9'}
}
assert_response :no_content
student.reload
assert_nil student.parent_email
end
# The next several tests explore profile changes for users with or without
# passwords. Examples of users without passwords are users that authenticate
# via oauth (a third-party account), or students with a picture password.
test "editing password of student-without-password is allowed" do
student_without_password = create :student, encrypted_password: ''
assert student_without_password.encrypted_password.blank?
assert can_edit_password_without_password? student_without_password
# Current password is entirely ignored in this case
assert can_edit_password_with_password? student_without_password, 'wrongpassword'
assert can_edit_password_with_password? student_without_password, ''
end
test "editing password of student-with-password requires current password" do
student_with_password = create :student, password: 'oldpassword'
refute can_edit_password_without_password? student_with_password
refute can_edit_password_with_password? student_with_password, 'wrongpassword'
assert can_edit_password_with_password? student_with_password, 'oldpassword'
end
test "editing password of teacher-without-password is allowed" do
teacher_without_password = create :teacher, encrypted_password: ''
assert teacher_without_password.encrypted_password.blank?
assert can_edit_password_without_password? teacher_without_password
# Current password is entirely ignored in this case
assert can_edit_password_with_password? teacher_without_password, 'wrongpassword'
assert can_edit_password_with_password? teacher_without_password, ''
end
test "editing password of teacher-with-password requires current password" do
teacher_with_password = create :teacher, password: 'oldpassword'
refute can_edit_password_without_password? teacher_with_password
refute can_edit_password_with_password? teacher_with_password, 'wrongpassword'
assert can_edit_password_with_password? teacher_with_password, 'oldpassword'
end
private
def can_edit_password_without_password?(user)
new_password = 'newpassword'
sign_in user
put '/users', params: {
user: {
password: new_password,
password_confirmation: new_password
}
}
user = user.reload
user.valid_password? new_password
end
def can_edit_password_with_password?(user, current_password)
new_password = 'newpassword'
sign_in user
put '/users', params: {
user: {
password: new_password,
password_confirmation: new_password,
current_password: current_password
}
}
user = user.reload
user.valid_password? new_password
end
end
end