forked from wikispeedruns/wikipedia-speedruns
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtest_users.py
204 lines (142 loc) · 6.44 KB
/
test_users.py
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
from flask import session
import datetime
import pytest
import re
import bcrypt
import hashlib
def test_create_user(cursor, user):
cursor.execute("SELECT * FROM users WHERE username=%s", (user["username"],))
result = cursor.fetchone()
assert(result["join_date"] == datetime.date.today())
def test_create_existing_user(client, cursor, user):
response = client.post("/api/users/create/email", json={
"username" : user["username"],
"email" : "[email protected]",
"password" : "test"
})
assert response.status_code == 409
response = client.post("/api/users/create/email", json={
"username" : "test",
"email" : user["email"],
"password" : "test"
})
assert response.status_code == 409
cursor.execute("SELECT COUNT(*) as num_users FROM users")
assert cursor.fetchone()["num_users"] == 1
def test_old_hash_login(cursor, client):
"""
Test our logic that converts our old buggy password hashes into new ones upon login
"""
query = """
INSERT INTO users (`username`, `hash`, `email`, `email_confirmed`, `is_old_hash`, `join_date`)
VALUES ('test', %s, '[email protected]', 0, 1, CURRENT_DATE())
"""
password = "test"
hash = bcrypt.hashpw(hashlib.sha256(password.encode()).digest(), bcrypt.gensalt())
try:
cursor.execute(query, (hash,))
# abc is a password that used to generate null bytes
response = client.post("/api/users/login", json={"username": "test", "password": "abc"})
assert response.status_code == 401
response = client.post("/api/users/login", json={"username": "test", "password": password})
assert response.status_code == 200
cursor.execute("SELECT * FROM users WHERE username='test'")
user = cursor.fetchone()
assert user is not None and not user["is_old_hash"]
finally:
cursor.execute("DELETE FROM users")
def test_login_logout(client, user):
def no_session():
return all([field not in session for field in ["username", "user_id", "admin"]])
def has_session():
return "user_id" in session and session["username"] == user["username"] and not session["admin"]
assert no_session()
response = client.post("/api/users/login", json={"username": user["username"], "password": "wrongpassword"})
assert response.status_code == 401
assert no_session()
response = client.post("/api/users/login", json={"username": user["username"], "password": user["password"]})
assert response.status_code == 200
assert has_session()
response = client.post("/api/users/logout")
assert response.status_code == 200
assert no_session()
response = client.post("/api/users/login", json={"email": user["email"], "password": user["password"]})
assert response.status_code == 200
assert has_session()
def test_confirm_email(client, cursor, user_with_outbox):
user, outbox = user_with_outbox
assert len(outbox) == 1
msg = outbox[0]
assert msg.recipients == [user["email"]]
# Make sure our templating is done correctly
assert user["username"] in msg.html
assert user["username"] in msg.body
regex = r"confirm/([-_\.\w]+)" # match alphanumeric characters and '_', '.', '-'
token = re.search(regex, msg.html).groups()[0]
# make sure token is the same in html and text
assert token == re.search(regex, msg.body).groups()[0]
# Try fake token
assert client.post("/api/users/confirm_email", json={"token": "abc"}).status_code == 400
# Use Token
assert client.post("/api/users/confirm_email", json={"token": token}).status_code == 200
# make sure it actually worked
cursor.execute("SELECT email_confirmed FROM users WHERE username=%s", (user["username"],))
assert cursor.fetchone()["email_confirmed"]
def test_change_password_bad(client, user):
new_password = user["password"] + "2"
# While not logged in, should return 401
assert client.post("/api/users/change_password", json={
"old_password": user["password"],
"new_password": new_password
}).status_code == 401
def test_change_password(client, user, session):
new_password = user["password"] + "2"
# Change for
assert client.post("/api/users/change_password", json={
"old_password": user["password"],
"new_password": new_password
}).status_code == 200
# Check old password doesn't work
assert client.post("/api/users/login", json={
"email": user["email"],
"password": user["password"]
}).status_code == 401
# And new password does
assert client.post("/api/users/login", json={
"email": user["email"],
"password": new_password
}).status_code == 200
def test_reset_password(client, mail, cursor, user, session):
new_password = user["password"] + "2"
# Send request to reset
with mail.record_messages() as outbox:
# Send request for our user
assert client.post("/api/users/reset_password_request", json={"email": user["email"]}).status_code == 200
# Try a non existent email for good measure, will still return 200 because we don't want ppls emails to leak
assert client.post("/api/users/reset_password_request", json={"email": "[email protected]"}).status_code == 200
# Check email is right
assert len(outbox) == 1
msg = outbox[0]
assert msg.recipients == [user["email"]]
assert user["username"] in msg.html and user["username"] in msg.body
res = re.search( r"reset/([0-9]+)/([-_\.\w]+)", msg.html)
id, token = res.groups()
request = {"user_id": int(id), "password": new_password, "token": "test"}
# try bad token, then good token
assert client.post("/api/users/reset_password", json=request).status_code == 400
# Try real token
request["token"] = token
resp = client.post("/api/users/reset_password", json=request)
assert resp.status_code == 200
# Try real token again to see if it expires properly
client.post("/api/users/reset_password", json=request).status_code == 400
# Check old password doesn't work
assert client.post("/api/users/login", json={
"email": user["email"],
"password": user["password"]
}).status_code == 401
# And new password does
assert client.post("/api/users/login", json={
"email": user["email"],
"password": new_password
}).status_code == 200