Skip to content
This repository was archived by the owner on Feb 22, 2024. It is now read-only.

Commit 87b5299

Browse files
committed
Add some tests about role handling
1 parent 583e2d8 commit 87b5299

File tree

2 files changed

+270
-1
lines changed

2 files changed

+270
-1
lines changed

tests/conftest.py

Lines changed: 127 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,20 @@
1111
import pytest
1212

1313
from flask import Flask
14+
from datetime import datetime, timedelta
1415

1516
import flask_jwt
1617

1718
logging.basicConfig(level=logging.DEBUG)
1819

1920

2021
class User(object):
21-
def __init__(self, id, username, password):
22+
def __init__(self, id, username, password, role=None):
2223
self.id = id
2324
self.username = username
2425
self.password = password
26+
if role:
27+
self.role = role
2528

2629
def __str__(self):
2730
return "User(id='%s')" % self.id
@@ -37,6 +40,16 @@ def user():
3740
return User(id=1, username='joe', password='pass')
3841

3942

43+
@pytest.fixture(scope='function')
44+
def user_with_role():
45+
return User(id=2, username='jane', password='pass', role='user')
46+
47+
48+
@pytest.fixture(scope='function')
49+
def user_with_roles():
50+
return User(id=3, username='alice', password='pass', role=['user', 'foo', 'bar'])
51+
52+
4053
@pytest.fixture(scope='function')
4154
def app(jwt, user):
4255
app = Flask(__name__)
@@ -64,6 +77,119 @@ def protected():
6477
return app
6578

6679

80+
@pytest.fixture(scope='function')
81+
def app_with_role(jwt, user, user_with_role, user_with_roles):
82+
app = Flask(__name__)
83+
app.debug = True
84+
app.config['SECRET_KEY'] = 'super-secret'
85+
users = [user, user_with_role, user_with_roles]
86+
87+
@jwt.authentication_handler
88+
def authenticate(username, password):
89+
for u in users:
90+
if username == u.username and password == u.password:
91+
return u
92+
return None
93+
94+
@jwt.identity_handler
95+
def load_user(payload):
96+
for u in users:
97+
if payload['identity'] == u.id:
98+
return u
99+
100+
@jwt.jwt_payload_handler
101+
def make_payload(identity):
102+
iat = datetime.utcnow()
103+
exp = iat + timedelta(seconds=300)
104+
nbf = iat
105+
id = getattr(identity, 'id')
106+
try:
107+
role = getattr(identity, 'role')
108+
return {'exp': exp, 'iat': iat, 'nbf': nbf, 'identity': id, 'role': role}
109+
except AttributeError:
110+
return {'exp': exp, 'iat': iat, 'nbf': nbf, 'identity': id}
111+
112+
jwt.init_app(app)
113+
114+
@app.route('/protected')
115+
@flask_jwt.jwt_required()
116+
def protected():
117+
return 'success'
118+
119+
@app.route('/role/protected/admin')
120+
@flask_jwt.jwt_required(roles='admin')
121+
def admin_protected():
122+
return 'success'
123+
124+
@app.route('/role/protected/multi')
125+
@flask_jwt.jwt_required(roles=['admin', 'user'])
126+
def admin_user_protected():
127+
return 'success'
128+
129+
@app.route('/role/protected/user')
130+
@flask_jwt.jwt_required(roles='user')
131+
def user_protected():
132+
return 'success'
133+
134+
return app
135+
136+
137+
@pytest.fixture(scope='function')
138+
def app_with_role_trust_jwt(jwt, user, user_with_role, user_with_roles):
139+
app = Flask(__name__)
140+
app.debug = True
141+
app.config['SECRET_KEY'] = 'super-secret'
142+
app.config['JWT_ROLE'] = 'my_role'
143+
users = [user, user_with_role, user_with_roles]
144+
145+
@jwt.authentication_handler
146+
def authenticate(username, password):
147+
for u in users:
148+
if username == u.username and password == u.password:
149+
return u
150+
return None
151+
152+
@jwt.identity_handler
153+
def load_user(payload):
154+
return payload
155+
156+
@jwt.jwt_payload_handler
157+
def make_payload(identity):
158+
iat = datetime.utcnow()
159+
exp = iat + timedelta(seconds=300)
160+
nbf = iat
161+
id = getattr(identity, 'id')
162+
try:
163+
role = getattr(identity, 'role')
164+
return {'exp': exp, 'iat': iat, 'nbf': nbf, 'identity': id, 'my_role': role}
165+
except AttributeError:
166+
return {'exp': exp, 'iat': iat, 'nbf': nbf, 'identity': id}
167+
168+
jwt.init_app(app)
169+
170+
@app.route('/protected')
171+
@flask_jwt.jwt_required()
172+
def protected():
173+
return 'success'
174+
175+
@app.route('/role/protected/user')
176+
@flask_jwt.jwt_required(roles='user')
177+
def user_protected():
178+
return 'success'
179+
180+
@app.route('/role/protected/multi')
181+
@flask_jwt.jwt_required(roles=['admin', 'user'])
182+
def admin_user_protected():
183+
return 'success'
184+
185+
@app.route('/role/protected/admin')
186+
@flask_jwt.jwt_required(roles='admin')
187+
def admin_protected():
188+
return 'success'
189+
190+
return app
191+
192+
67193
@pytest.fixture(scope='function')
68194
def client(app):
69195
return app.test_client()

tests/test_jwt.py

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,3 +291,146 @@ def custom_auth_request_handler():
291291
with app.test_client() as c:
292292
resp, jdata = post_json(c, '/auth', {})
293293
assert jdata == {'hello': 'world'}
294+
295+
296+
def test_role_required(app_with_role, user_with_role):
297+
with app_with_role.test_client() as c:
298+
resp, jdata = post_json(
299+
c, '/auth', {'username': user_with_role.username, 'password': user_with_role.password})
300+
token = jdata['access_token']
301+
302+
# check if protected works with role set but not asked for this path
303+
resp = c.get('/protected', headers={'authorization': 'JWT ' + token})
304+
assert resp.status_code == 200
305+
assert resp.data == b'success'
306+
307+
# check if protected works wit role set but not asked for this path
308+
resp = c.get('/role/protected/user', headers={'Authorization': 'JWT ' + token})
309+
310+
assert resp.status_code == 200
311+
assert resp.data == b'success'
312+
313+
314+
def test_role_required_bad(app_with_role, user, user_with_role):
315+
with app_with_role.test_client() as c:
316+
317+
# test bad role
318+
resp, jdata = post_json(
319+
c, '/auth', {'username': user_with_role.username, 'password': user_with_role.password})
320+
321+
token = jdata['access_token']
322+
resp = c.get('/role/protected/admin', headers={'Authorization': 'JWT ' + token})
323+
324+
assert resp.status_code == 401
325+
326+
# test no role
327+
resp, jdata = post_json(
328+
c, '/auth', {'username': user.username, 'password': user.password})
329+
330+
token = jdata['access_token']
331+
resp = c.get('/role/protected/admin', headers={'Authorization': 'JWT ' + token})
332+
333+
assert resp.status_code == 401
334+
335+
336+
def test_role_required_multi(app_with_role, user_with_roles):
337+
with app_with_role.test_client() as c:
338+
resp, jdata = post_json(c, '/auth', {'username': user_with_roles.username,
339+
'password': user_with_roles.password})
340+
token = jdata['access_token']
341+
342+
# check if protected works with role set but not asked for this path
343+
resp = c.get('/protected', headers={'authorization': 'JWT ' + token})
344+
assert resp.status_code == 200
345+
assert resp.data == b'success'
346+
347+
resp = c.get('/role/protected/user', headers={'Authorization': 'JWT ' + token})
348+
349+
assert resp.status_code == 200
350+
assert resp.data == b'success'
351+
352+
353+
def test_role_required_multi_bad(app_with_role, user_with_roles):
354+
with app_with_role.test_client() as c:
355+
resp, jdata = post_json(c, '/auth', {'username': user_with_roles.username,
356+
'password': user_with_roles.password})
357+
358+
token = jdata['access_token']
359+
resp = c.get('/role/protected/admin', headers={'Authorization': 'JWT ' + token})
360+
361+
assert resp.status_code == 401
362+
363+
364+
def test_multirole_required_multi(app_with_role, user, user_with_roles):
365+
with app_with_role.test_client() as c:
366+
resp, jdata = post_json(c, '/auth', {'username': user_with_roles.username,
367+
'password': user_with_roles.password})
368+
token = jdata['access_token']
369+
370+
# check if protected works with role set but not asked for this path
371+
resp = c.get('/protected', headers={'authorization': 'JWT ' + token})
372+
assert resp.status_code == 200
373+
assert resp.data == b'success'
374+
375+
resp = c.get('/role/protected/multi', headers={'Authorization': 'JWT ' + token})
376+
377+
assert resp.status_code == 200
378+
assert resp.data == b'success'
379+
380+
# test no role
381+
resp, jdata = post_json(
382+
c, '/auth', {'username': user.username, 'password': user.password})
383+
384+
token = jdata['access_token']
385+
resp = c.get('/role/protected/multi', headers={'Authorization': 'JWT ' + token})
386+
387+
assert resp.status_code == 401
388+
389+
390+
def test_role_custom(app_with_role_trust_jwt, user, user_with_role, user_with_roles):
391+
with app_with_role_trust_jwt.test_client() as c:
392+
resp, jdata = post_json(c, '/auth', {'username': user_with_role.username,
393+
'password': user_with_role.password})
394+
token = jdata['access_token']
395+
396+
# check if protected works with role set but not asked for this path
397+
resp = c.get('/protected', headers={'authorization': 'JWT ' + token})
398+
assert resp.status_code == 200
399+
assert resp.data == b'success'
400+
401+
# check unauthorized role protection
402+
resp = c.get('/role/protected/admin', headers={'Authorization': 'JWT ' + token})
403+
404+
assert resp.status_code == 401
405+
406+
resp = c.get('/role/protected/multi', headers={'Authorization': 'JWT ' + token})
407+
408+
assert resp.status_code == 200
409+
assert resp.data == b'success'
410+
411+
resp = c.get('/role/protected/user', headers={'Authorization': 'JWT ' + token})
412+
413+
assert resp.status_code == 200
414+
assert resp.data == b'success'
415+
416+
resp, jdata = post_json(c, '/auth', {'username': user_with_roles.username,
417+
'password': user_with_roles.password})
418+
token = jdata['access_token']
419+
420+
# check if protected works with role set but not asked for this path
421+
resp = c.get('/protected', headers={'authorization': 'JWT ' + token})
422+
assert resp.status_code == 200
423+
assert resp.data == b'success'
424+
425+
resp = c.get('/role/protected/multi', headers={'Authorization': 'JWT ' + token})
426+
427+
assert resp.status_code == 200
428+
assert resp.data == b'success'
429+
# test no role
430+
resp, jdata = post_json(
431+
c, '/auth', {'username': user.username, 'password': user.password})
432+
433+
token = jdata['access_token']
434+
resp = c.get('/role/protected/multi', headers={'Authorization': 'JWT ' + token})
435+
436+
assert resp.status_code == 401

0 commit comments

Comments
 (0)