Skip to content

Commit e559d22

Browse files
tests and manual
1 parent e834913 commit e559d22

File tree

5 files changed

+59
-18
lines changed

5 files changed

+59
-18
lines changed

openatlas/__init__.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,9 @@ def check_incoming_tokens(
139139
jwt_payload: dict[str, Any]) -> bool:
140140
if not jwt_header['typ'] == 'JWT':
141141
return True
142-
# todo: add user active check. maybe add it to sql query
143142
token_ = check_token_revoked(jwt_payload["jti"])
144-
if token_['revoked'] or token_['valid_until'] < datetime.datetime.now():
143+
if token_['revoked'] \
144+
or not token_['active'] \
145+
or token_['valid_until'] < datetime.datetime.now():
145146
return True
146147
return False

openatlas/database/token.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,12 @@ def get_tokens(
1717
WHERE TRUE
1818
{'AND user_id = %(user_id)s' if int(user_id) else ''}
1919
{'AND revoked = %(revoked)s' if revoked != 'all' else ''}
20-
{'AND valid_until ' + valid + ' timestamp %(timestamp)s' if valid != 'all' else ''};
21-
""", {'user_id': user_id, 'revoked': revoked, 'timestamp': str(datetime.now())})
20+
{'AND valid_until ' + valid + ' timestamp %(timestamp)s'
21+
if valid != 'all' else ''};
22+
""", {
23+
'user_id': user_id,
24+
'revoked': revoked,
25+
'timestamp': str(datetime.now())})
2226
return [dict(row) for row in g.cursor.fetchall()]
2327

2428

@@ -72,10 +76,12 @@ def delete_invalid_tokens(inactive_user_ids: list[int]) -> None:
7276
def check_token_revoked(jti: str) -> dict[str, Any]:
7377
g.cursor.execute(
7478
"""
75-
SELECT revoked, valid_until FROM web.user_tokens WHERE jti = %(jti)s;
79+
SELECT t.revoked, t.valid_until, u.active
80+
FROM web.user_tokens t
81+
LEFT JOIN web.user u ON t.user_id = u.id
82+
WHERE jti = %(jti)s;
7683
""", {'jti': jti})
84+
token = {'revoked': True, 'valid_until': True, 'active': True}
7785
if row := g.cursor.fetchone():
78-
token = {'revoked': row[0], 'valid_until': row[1]}
79-
else:
80-
token = {'revoked': True, 'valid_until': True}
86+
token = {'revoked': row[0], 'valid_until': row[1], 'active': row[2]}
8187
return token

sphinx/source/admin/api.rst

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,35 @@ Description: :doc:`/technical/api`
2121
**Token**
2222
---------
2323

24-
API Tokens can be created to query the API if it is turned off.
24+
API Tokens can be created to query the API if it is turned off. Only Admins
25+
are allowed to create, revoke and delete tokens.
26+
27+
.. _valid tokens:
28+
29+
A token is valid if:
30+
* **valid from** is greater than current date
31+
* **revoked** is *false*, meaning the token is not revoked
32+
* :ref:`user` is active
33+
34+
Available options are:
35+
* **Generate**: :ref:`generate` a new token
36+
* **Revoke all tokens**: Revoke all available tokens
37+
* **Authorize all tokens**: All revoked tokens will be valid again
38+
* **Delete revoked tokens**: All revoked tokens will be deleted
39+
* **Delete invalid tokens**: All invalid tokens will be deleted (see :ref:`valid tokens`)
40+
41+
.. _generate:
42+
43+
**Generate Token**
44+
******************
45+
46+
* **Expiration**:
47+
Set how long a token is valid. Entered numbers are days. 0 means no expiration date
48+
* **Token name**:
49+
To better distinguish between tokens, a individual name can be entered
50+
* **User**:
51+
Select a :ref:`user` for which the token will be created
52+
53+
After the *Generate* button is clicked, the site will reload and a grey box appears.
54+
In this box the token string will be visible and is copied on click.
55+
Be aware, this is the only time, the token will be visible!

sphinx/source/admin/user.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
User
22
====
33

4+
.. _user:
5+
46
.. toctree::
57

68
In the overview users and information on their group, email, created/last

tests/test_token.py

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
from flask_jwt_extended import decode_token
33

44
from openatlas.database.token import get_tokens
5-
from openatlas.models.user import User
65
from openatlas import app, check_incoming_tokens
76
from tests.base import TestBaseCase
87

@@ -77,17 +76,19 @@ def test_token(self) -> None:
7776
g.settings['api_public'] = False
7877
c.get(url_for('logout'))
7978
for token in jwt_token_strings:
80-
#decoded = decode_token(token)
81-
#check = check_incoming_tokens({'typ': 'JWT'}, decoded)
82-
#assert check is True if decoded['sub'] in ['Alice', 'Inactive'] else False
83-
84-
# should fail if check_incoming_tokens checks for user active
79+
decoded = decode_token(token)
8580
rv = c.get(
8681
url_for('api_04.class_mapping', locale='de'),
8782
headers={'Authorization': f'Bearer {token}'})
88-
assert b'results' in rv.data
89-
90-
# assert check_incoming_tokens({'typ': 'Unknown'}, decoded) is True
83+
if decoded['sub'] in ['Alice', 'Inactive']:
84+
assert b'Token has been revoked' in rv.data
85+
else:
86+
assert b'results' in rv.data
87+
88+
assert check_incoming_tokens({'typ': 'Unknown'}, decoded) is True
89+
c.post(
90+
url_for('login'),
91+
data={'username': 'Alice', 'password': 'test'})
9192

9293
rv = c.get(url_for('delete_revoked_tokens'), follow_redirects=True)
9394
assert b'All revoked tokens deleted' in rv.data

0 commit comments

Comments
 (0)