pypomes-jwt 1.2.8__tar.gz → 1.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pypomes-jwt might be problematic. Click here for more details.
- {pypomes_jwt-1.2.8 → pypomes_jwt-1.3.0}/PKG-INFO +2 -2
- {pypomes_jwt-1.2.8 → pypomes_jwt-1.3.0}/pyproject.toml +2 -2
- {pypomes_jwt-1.2.8 → pypomes_jwt-1.3.0}/src/pypomes_jwt/jwt_config.py +6 -1
- {pypomes_jwt-1.2.8 → pypomes_jwt-1.3.0}/src/pypomes_jwt/jwt_pomes.py +43 -52
- {pypomes_jwt-1.2.8 → pypomes_jwt-1.3.0}/src/pypomes_jwt/jwt_providers.py +3 -3
- {pypomes_jwt-1.2.8 → pypomes_jwt-1.3.0}/src/pypomes_jwt/jwt_registry.py +94 -94
- {pypomes_jwt-1.2.8 → pypomes_jwt-1.3.0}/.gitignore +0 -0
- {pypomes_jwt-1.2.8 → pypomes_jwt-1.3.0}/LICENSE +0 -0
- {pypomes_jwt-1.2.8 → pypomes_jwt-1.3.0}/README.md +0 -0
- {pypomes_jwt-1.2.8 → pypomes_jwt-1.3.0}/src/pypomes_jwt/__init__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pypomes_jwt
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.0
|
|
4
4
|
Summary: A collection of Python pomes, penyeach (JWT module)
|
|
5
5
|
Project-URL: Homepage, https://github.com/TheWiseCoder/PyPomes-JWT
|
|
6
6
|
Project-URL: Bug Tracker, https://github.com/TheWiseCoder/PyPomes-JWT/issues
|
|
@@ -14,4 +14,4 @@ Requires-Dist: cryptography>=45.0.6
|
|
|
14
14
|
Requires-Dist: flask>=3.1.2
|
|
15
15
|
Requires-Dist: pyjwt>=2.10.1
|
|
16
16
|
Requires-Dist: pypomes-core>=2.7.0
|
|
17
|
-
Requires-Dist: pypomes-db>=2.5.
|
|
17
|
+
Requires-Dist: pypomes-db>=2.5.9
|
|
@@ -6,7 +6,7 @@ build-backend = "hatchling.build"
|
|
|
6
6
|
|
|
7
7
|
[project]
|
|
8
8
|
name = "pypomes_jwt"
|
|
9
|
-
version = "1.
|
|
9
|
+
version = "1.3.0"
|
|
10
10
|
authors = [
|
|
11
11
|
{ name="GT Nunes", email="wisecoder01@gmail.com" }
|
|
12
12
|
]
|
|
@@ -23,7 +23,7 @@ dependencies = [
|
|
|
23
23
|
"Flask>=3.1.2",
|
|
24
24
|
"PyJWT>=2.10.1",
|
|
25
25
|
"pypomes_core>=2.7.0",
|
|
26
|
-
"pypomes_db>=2.5.
|
|
26
|
+
"pypomes_db>=2.5.9"
|
|
27
27
|
]
|
|
28
28
|
|
|
29
29
|
[project.urls]
|
|
@@ -52,14 +52,19 @@ class JwtConfig(Enum):
|
|
|
52
52
|
def_value=300)
|
|
53
53
|
ACCOUNT_LIMIT: int = env_get_int(key=f"{APP_PREFIX}_JWT_ACCOUNT_LIMIT",
|
|
54
54
|
def_value=5)
|
|
55
|
+
DEFAULT_ALGORITHM: _default_algorithm
|
|
55
56
|
ENCODING_KEY: bytes = _encoding_key
|
|
56
57
|
DECODING_KEY: bytes = _decoding_key
|
|
57
|
-
DEFAULT_ALGORITHM: str = _default_algorithm
|
|
58
58
|
# recommended: at least 2 hours (set to 24 hours)
|
|
59
59
|
REFRESH_MAX_AGE: int = env_get_int(key=f"{APP_PREFIX}_JWT_REFRESH_MAX_AGE",
|
|
60
60
|
def_value=86400)
|
|
61
61
|
|
|
62
62
|
|
|
63
|
+
del _decoding_key
|
|
64
|
+
del _encoding_key
|
|
65
|
+
del _default_algorithm
|
|
66
|
+
|
|
67
|
+
|
|
63
68
|
class JwtDbConfig(StrEnum):
|
|
64
69
|
"""
|
|
65
70
|
Parameters for JWT database connection.
|
|
@@ -158,7 +158,10 @@ def jwt_validate_token(token: str,
|
|
|
158
158
|
|
|
159
159
|
if logger:
|
|
160
160
|
logger.debug(msg="Validate JWT token")
|
|
161
|
-
|
|
161
|
+
|
|
162
|
+
# make sure to have an errors list
|
|
163
|
+
if not isinstance(errors, list):
|
|
164
|
+
errors = []
|
|
162
165
|
|
|
163
166
|
# extract needed data from token header
|
|
164
167
|
token_header: dict[str, Any] | None = None
|
|
@@ -169,9 +172,9 @@ def jwt_validate_token(token: str,
|
|
|
169
172
|
exc_info=sys.exc_info())
|
|
170
173
|
if logger:
|
|
171
174
|
logger.error(msg=f"Error retrieving the token's header: {exc_err}")
|
|
172
|
-
|
|
175
|
+
errors.append(exc_err)
|
|
173
176
|
|
|
174
|
-
if not
|
|
177
|
+
if not errors:
|
|
175
178
|
token_kid: str = token_header.get("kid")
|
|
176
179
|
token_alg: str | None = None
|
|
177
180
|
token_decoder: bytes | None = None
|
|
@@ -180,7 +183,7 @@ def jwt_validate_token(token: str,
|
|
|
180
183
|
if nature and not (token_kid and token_kid[0:1] == nature):
|
|
181
184
|
if logger:
|
|
182
185
|
logger.error(f"Nature of token's 'kid' ('{token_kid}') not '{nature}'")
|
|
183
|
-
|
|
186
|
+
errors.append("Invalid token")
|
|
184
187
|
elif token_kid and len(token_kid) > 1 and \
|
|
185
188
|
token_kid[0:1] in ["A", "R"] and token_kid[1:].isdigit():
|
|
186
189
|
# token was likely issued locally
|
|
@@ -192,24 +195,24 @@ def jwt_validate_token(token: str,
|
|
|
192
195
|
f"FROM {JwtDbConfig.TABLE}",
|
|
193
196
|
where_data=where_data,
|
|
194
197
|
engine=DbEngine(JwtDbConfig.ENGINE),
|
|
195
|
-
errors=
|
|
198
|
+
errors=errors,
|
|
196
199
|
logger=logger)
|
|
197
200
|
if recs:
|
|
198
201
|
token_alg = recs[0][0]
|
|
199
202
|
token_decoder = b64decode(recs[0][1])
|
|
200
|
-
elif
|
|
203
|
+
elif errors:
|
|
201
204
|
if logger:
|
|
202
|
-
logger.error(msg=f"Error retrieving the token's decoder: {'; '.join(
|
|
205
|
+
logger.error(msg=f"Error retrieving the token's decoder: {'; '.join(errors)}")
|
|
203
206
|
else:
|
|
204
207
|
if logger:
|
|
205
208
|
logger.error(msg="Token not in the database")
|
|
206
|
-
|
|
209
|
+
errors.append("Invalid token")
|
|
207
210
|
else:
|
|
208
211
|
token_alg = JwtConfig.DEFAULT_ALGORITHM.value
|
|
209
212
|
token_decoder = JwtConfig.DECODING_KEY.value
|
|
210
213
|
|
|
211
214
|
# validate the token
|
|
212
|
-
if not
|
|
215
|
+
if not errors:
|
|
213
216
|
try:
|
|
214
217
|
# raises:
|
|
215
218
|
# InvalidTokenError: token is invalid
|
|
@@ -232,7 +235,7 @@ def jwt_validate_token(token: str,
|
|
|
232
235
|
if account_id and payload.get("sub") != account_id:
|
|
233
236
|
if logger:
|
|
234
237
|
logger.error(msg=f"Token does not belong to account '{account_id}'")
|
|
235
|
-
|
|
238
|
+
errors.append("Invalid token")
|
|
236
239
|
else:
|
|
237
240
|
result = {
|
|
238
241
|
"header": token_header,
|
|
@@ -243,12 +246,9 @@ def jwt_validate_token(token: str,
|
|
|
243
246
|
exc_info=sys.exc_info())
|
|
244
247
|
if logger:
|
|
245
248
|
logger.error(msg=f"Error decoding the token: {exc_err}")
|
|
246
|
-
|
|
249
|
+
errors.append(exc_err)
|
|
247
250
|
|
|
248
|
-
if
|
|
249
|
-
if isinstance(errors, list):
|
|
250
|
-
errors.extend(op_errors)
|
|
251
|
-
elif logger:
|
|
251
|
+
if not errors and logger:
|
|
252
252
|
logger.debug(msg="Token is valid")
|
|
253
253
|
|
|
254
254
|
return result
|
|
@@ -275,15 +275,18 @@ def jwt_revoke_token(account_id: str,
|
|
|
275
275
|
if logger:
|
|
276
276
|
logger.debug(msg=f"Revoking token of account '{account_id}'")
|
|
277
277
|
|
|
278
|
-
|
|
278
|
+
# make sure to have an errors list
|
|
279
|
+
if not isinstance(errors, list):
|
|
280
|
+
errors = []
|
|
281
|
+
|
|
279
282
|
token_claims: dict[str, Any] = jwt_validate_token(token=token,
|
|
280
283
|
account_id=account_id,
|
|
281
|
-
errors=
|
|
284
|
+
errors=errors,
|
|
282
285
|
logger=logger)
|
|
283
|
-
if not
|
|
286
|
+
if not errors:
|
|
284
287
|
token_kid: str = token_claims["header"].get("kid")
|
|
285
288
|
if token_kid[0:1] not in ["A", "R"]:
|
|
286
|
-
|
|
289
|
+
errors.append("Invalid token")
|
|
287
290
|
else:
|
|
288
291
|
db_delete(delete_stmt=f"DELETE FROM {JwtDbConfig.TABLE}",
|
|
289
292
|
where_data={
|
|
@@ -291,15 +294,12 @@ def jwt_revoke_token(account_id: str,
|
|
|
291
294
|
JwtDbConfig.COL_ACCOUNT: account_id
|
|
292
295
|
},
|
|
293
296
|
engine=DbEngine(JwtDbConfig.ENGINE),
|
|
294
|
-
errors=
|
|
297
|
+
errors=errors,
|
|
295
298
|
logger=logger)
|
|
296
|
-
if
|
|
297
|
-
if logger:
|
|
298
|
-
logger.error(msg="; ".join(op_errors))
|
|
299
|
-
if isinstance(errors, list):
|
|
300
|
-
errors.extend(op_errors)
|
|
301
|
-
else:
|
|
299
|
+
if not errors:
|
|
302
300
|
result = True
|
|
301
|
+
elif logger:
|
|
302
|
+
logger.error(msg="; ".join(errors))
|
|
303
303
|
|
|
304
304
|
return result
|
|
305
305
|
|
|
@@ -333,7 +333,6 @@ def jwt_issue_token(account_id: str,
|
|
|
333
333
|
|
|
334
334
|
if logger:
|
|
335
335
|
logger.debug(msg=f"Issuing a JWT token for '{account_id}'")
|
|
336
|
-
op_errors: list[str] = []
|
|
337
336
|
|
|
338
337
|
try:
|
|
339
338
|
result = __jwt_registry.issue_token(account_id=account_id,
|
|
@@ -350,10 +349,8 @@ def jwt_issue_token(account_id: str,
|
|
|
350
349
|
exc_info=sys.exc_info())
|
|
351
350
|
if logger:
|
|
352
351
|
logger.error(msg=f"Error issuing the token: {exc_err}")
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
if op_errors and isinstance(errors, list):
|
|
356
|
-
errors.extend(op_errors)
|
|
352
|
+
if isinstance(errors, list):
|
|
353
|
+
errors.append(exc_err)
|
|
357
354
|
|
|
358
355
|
return result
|
|
359
356
|
|
|
@@ -387,7 +384,6 @@ def jwt_issue_tokens(account_id: str,
|
|
|
387
384
|
|
|
388
385
|
if logger:
|
|
389
386
|
logger.debug(msg=f"Issuing a JWT token pair for '{account_id}'")
|
|
390
|
-
op_errors: list[str] = []
|
|
391
387
|
|
|
392
388
|
try:
|
|
393
389
|
result = __jwt_registry.issue_tokens(account_id=account_id,
|
|
@@ -401,13 +397,8 @@ def jwt_issue_tokens(account_id: str,
|
|
|
401
397
|
exc_info=sys.exc_info())
|
|
402
398
|
if logger:
|
|
403
399
|
logger.error(msg=f"Error issuing the token pair: {exc_err}")
|
|
404
|
-
op_errors.append(exc_err)
|
|
405
|
-
|
|
406
|
-
if op_errors:
|
|
407
|
-
if logger:
|
|
408
|
-
logger.error("; ".join(op_errors))
|
|
409
400
|
if isinstance(errors, list):
|
|
410
|
-
errors.
|
|
401
|
+
errors.append(exc_err)
|
|
411
402
|
|
|
412
403
|
return result
|
|
413
404
|
|
|
@@ -440,7 +431,10 @@ def jwt_refresh_tokens(account_id: str,
|
|
|
440
431
|
|
|
441
432
|
if logger:
|
|
442
433
|
logger.debug(msg=f"Refreshing a JWT token pair for '{account_id}'")
|
|
443
|
-
|
|
434
|
+
|
|
435
|
+
# make sure to have an errors list
|
|
436
|
+
if not isinstance(errors, list):
|
|
437
|
+
errors = []
|
|
444
438
|
|
|
445
439
|
# assert the refresh token
|
|
446
440
|
if refresh_token:
|
|
@@ -448,7 +442,7 @@ def jwt_refresh_tokens(account_id: str,
|
|
|
448
442
|
token_claims: dict[str, Any] = jwt_validate_token(token=refresh_token,
|
|
449
443
|
nature="R",
|
|
450
444
|
account_id=account_id,
|
|
451
|
-
errors=
|
|
445
|
+
errors=errors,
|
|
452
446
|
logger=logger)
|
|
453
447
|
if token_claims:
|
|
454
448
|
# yes, proceed
|
|
@@ -457,7 +451,7 @@ def jwt_refresh_tokens(account_id: str,
|
|
|
457
451
|
# start the database transaction
|
|
458
452
|
db_conn: Any = db_connect(autocommit=False,
|
|
459
453
|
engine=DbEngine(JwtDbConfig.ENGINE),
|
|
460
|
-
errors=
|
|
454
|
+
errors=errors,
|
|
461
455
|
logger=logger)
|
|
462
456
|
if db_conn:
|
|
463
457
|
# delete current refresh token
|
|
@@ -469,11 +463,11 @@ def jwt_refresh_tokens(account_id: str,
|
|
|
469
463
|
engine=DbEngine(JwtDbConfig.ENGINE),
|
|
470
464
|
connection=db_conn,
|
|
471
465
|
committable=False,
|
|
472
|
-
errors=
|
|
466
|
+
errors=errors,
|
|
473
467
|
logger=logger)
|
|
474
468
|
|
|
475
469
|
# issue the token pair
|
|
476
|
-
if not
|
|
470
|
+
if not errors:
|
|
477
471
|
try:
|
|
478
472
|
result = __jwt_registry.issue_tokens(account_id=account_id,
|
|
479
473
|
account_claims=token_claims.get("payload"),
|
|
@@ -487,27 +481,24 @@ def jwt_refresh_tokens(account_id: str,
|
|
|
487
481
|
exc_info=sys.exc_info())
|
|
488
482
|
if logger:
|
|
489
483
|
logger.error(msg=f"Error refreshing the token pair: {exc_err}")
|
|
490
|
-
|
|
484
|
+
errors.append(exc_err)
|
|
491
485
|
|
|
492
486
|
# wrap-up the transaction
|
|
493
|
-
if
|
|
487
|
+
if errors:
|
|
494
488
|
db_rollback(connection=db_conn,
|
|
495
489
|
logger=logger)
|
|
496
490
|
else:
|
|
497
491
|
db_commit(connection=db_conn,
|
|
498
|
-
errors=
|
|
492
|
+
errors=errors,
|
|
499
493
|
logger=logger)
|
|
500
494
|
db_close(connection=db_conn,
|
|
501
495
|
logger=logger)
|
|
502
496
|
else:
|
|
503
497
|
# refresh token not found
|
|
504
|
-
|
|
498
|
+
errors.append("Refresh token was not provided")
|
|
505
499
|
|
|
506
|
-
if
|
|
507
|
-
|
|
508
|
-
logger.error("; ".join(op_errors))
|
|
509
|
-
if isinstance(errors, list):
|
|
510
|
-
errors.extend(op_errors)
|
|
500
|
+
if errors and logger:
|
|
501
|
+
logger.error(msg="; ".join(errors))
|
|
511
502
|
|
|
512
503
|
return result
|
|
513
504
|
|
|
@@ -62,14 +62,14 @@ def provider_register(provider_id: str,
|
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
|
|
65
|
-
def provider_get_token(
|
|
66
|
-
|
|
65
|
+
def provider_get_token(provider_id: str,
|
|
66
|
+
errors: list[str] | None,
|
|
67
67
|
logger: Logger = None) -> str | None:
|
|
68
68
|
"""
|
|
69
69
|
Obtain an authentication token from the external provider *provider_id*.
|
|
70
70
|
|
|
71
|
-
:param errors: incidental error messages
|
|
72
71
|
:param provider_id: the provider's identification
|
|
72
|
+
:param errors: incidental error messages
|
|
73
73
|
:param logger: optional logger
|
|
74
74
|
"""
|
|
75
75
|
# initialize the return variable
|
|
@@ -6,7 +6,7 @@ from datetime import datetime, UTC
|
|
|
6
6
|
from logging import Logger
|
|
7
7
|
from pypomes_core import str_random
|
|
8
8
|
from pypomes_db import (
|
|
9
|
-
DbEngine, db_connect, db_commit, db_rollback,
|
|
9
|
+
DbEngine, db_connect, db_commit, db_rollback, db_close,
|
|
10
10
|
db_select, db_insert, db_update, db_delete
|
|
11
11
|
)
|
|
12
12
|
from threading import Lock
|
|
@@ -296,6 +296,8 @@ class JwtRegistry:
|
|
|
296
296
|
db_commit(connection=curr_conn,
|
|
297
297
|
errors=errors,
|
|
298
298
|
logger=logger)
|
|
299
|
+
db_close(connection=curr_conn)
|
|
300
|
+
|
|
299
301
|
if errors:
|
|
300
302
|
raise RuntimeError("; ".join(errors))
|
|
301
303
|
|
|
@@ -359,102 +361,100 @@ class JwtRegistry:
|
|
|
359
361
|
"""
|
|
360
362
|
from .jwt_pomes import jwt_get_claims
|
|
361
363
|
|
|
362
|
-
#
|
|
363
|
-
|
|
364
|
-
# noinspection PyTypeChecker
|
|
365
|
-
recs: list[tuple[int, str, str, str]] = \
|
|
366
|
-
db_select(sel_stmt=f"SELECT {JwtDbConfig.COL_KID}, {JwtDbConfig.COL_TOKEN} "
|
|
367
|
-
f"FROM {JwtDbConfig.TABLE}",
|
|
368
|
-
where_data={JwtDbConfig.COL_ACCOUNT: account_id},
|
|
369
|
-
engine=DbEngine(JwtDbConfig.ENGINE),
|
|
370
|
-
connection=db_conn,
|
|
371
|
-
errors=errors,
|
|
372
|
-
logger=logger)
|
|
373
|
-
if errors:
|
|
374
|
-
raise RuntimeError("; ".join(errors))
|
|
364
|
+
# initialize the return variable
|
|
365
|
+
result: int | None = None
|
|
375
366
|
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
if
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
367
|
+
# make sure to have a database connection
|
|
368
|
+
errors: list[str] = []
|
|
369
|
+
curr_conn: Any = db_conn or db_connect(autocommit=False,
|
|
370
|
+
engine=DbEngine(JwtDbConfig.ENGINE),
|
|
371
|
+
errors=errors,
|
|
372
|
+
logger=logger)
|
|
373
|
+
if not errors:
|
|
374
|
+
|
|
375
|
+
# retrieve the account's tokens
|
|
376
|
+
# noinspection PyTypeChecker
|
|
377
|
+
recs: list[tuple[int, str, str, str]] = \
|
|
378
|
+
db_select(sel_stmt=f"SELECT {JwtDbConfig.COL_KID}, {JwtDbConfig.COL_TOKEN} "
|
|
379
|
+
f"FROM {JwtDbConfig.TABLE}",
|
|
380
|
+
where_data={JwtDbConfig.COL_ACCOUNT: account_id},
|
|
381
|
+
engine=DbEngine(JwtDbConfig.ENGINE),
|
|
382
|
+
connection=curr_conn,
|
|
383
|
+
errors=errors,
|
|
384
|
+
logger=logger)
|
|
385
|
+
if not errors:
|
|
386
|
+
if logger:
|
|
387
|
+
logger.debug(msg=f"Retrieved {len(recs)} tokens from storage for account '{account_id}'")
|
|
388
|
+
# remove the expired tokens
|
|
389
|
+
just_now: int = int(datetime.now(tz=UTC).timestamp())
|
|
390
|
+
oldest_ts: int = sys.maxsize
|
|
391
|
+
oldest_id: int | None = None
|
|
392
|
+
expired: list[int] = []
|
|
393
|
+
for rec in recs:
|
|
394
|
+
token: str = rec[1]
|
|
395
|
+
token_id: int = rec[0]
|
|
396
|
+
token_payload: dict[str, Any] = (jwt_get_claims(token=token,
|
|
397
|
+
errors=errors,
|
|
398
|
+
logger=logger) or {}).get("payload")
|
|
399
|
+
if errors:
|
|
400
|
+
break
|
|
401
|
+
# find expired tokens
|
|
402
|
+
exp: int = token_payload.get("exp", sys.maxsize)
|
|
403
|
+
if exp < just_now:
|
|
404
|
+
expired.append(token_id)
|
|
405
|
+
|
|
406
|
+
# find oldest token
|
|
407
|
+
iat: int = token_payload.get("iat", sys.maxsize)
|
|
408
|
+
if iat < oldest_ts:
|
|
409
|
+
oldest_ts = iat
|
|
410
|
+
oldest_id = token_id
|
|
411
|
+
|
|
412
|
+
# remove expired tokens from persistence
|
|
413
|
+
if not errors and expired:
|
|
414
|
+
db_delete(delete_stmt=f"DELETE FROM {JwtDbConfig.TABLE}",
|
|
415
|
+
where_data={JwtDbConfig.COL_KID: expired},
|
|
416
|
+
engine=DbEngine(JwtDbConfig.ENGINE),
|
|
417
|
+
connection=curr_conn,
|
|
418
|
+
errors=errors,
|
|
419
|
+
logger=logger)
|
|
420
|
+
if not errors and logger:
|
|
421
|
+
logger.debug(msg=f"{len(expired)} tokens of account "
|
|
422
|
+
f"'{account_id}' removed from storage")
|
|
423
|
+
|
|
424
|
+
if not errors and 0 < JwtConfig.ACCOUNT_LIMIT.value <= len(recs) - len(expired):
|
|
425
|
+
# delete the oldest token to make way for the new one
|
|
426
|
+
db_delete(delete_stmt=f"DELETE FROM {JwtDbConfig.TABLE}",
|
|
427
|
+
where_data={JwtDbConfig.COL_KID: oldest_id},
|
|
428
|
+
engine=DbEngine(JwtDbConfig.ENGINE),
|
|
429
|
+
connection=curr_conn,
|
|
430
|
+
errors=errors,
|
|
431
|
+
logger=logger)
|
|
432
|
+
if not errors and logger:
|
|
433
|
+
logger.debug(msg="Oldest active token of account "
|
|
434
|
+
f"'{account_id}' removed from storage")
|
|
435
|
+
# persist token
|
|
436
|
+
if not errors:
|
|
437
|
+
result = db_insert(insert_stmt=f"INSERT INTO {JwtDbConfig.TABLE}",
|
|
438
|
+
insert_data={
|
|
439
|
+
JwtDbConfig.COL_ACCOUNT: account_id,
|
|
440
|
+
JwtDbConfig.COL_TOKEN: jwt_token,
|
|
441
|
+
JwtDbConfig.COL_ALGORITHM: JwtConfig.DEFAULT_ALGORITHM.value,
|
|
442
|
+
JwtDbConfig.COL_DECODER: b64encode(s=JwtConfig.DECODING_KEY.value).decode()
|
|
443
|
+
},
|
|
444
|
+
return_cols={JwtDbConfig.COL_KID: int},
|
|
445
|
+
engine=DbEngine(JwtDbConfig.ENGINE),
|
|
446
|
+
connection=curr_conn,
|
|
447
|
+
errors=errors,
|
|
448
|
+
logger=logger)
|
|
449
|
+
# finish the operation
|
|
450
|
+
if not db_conn:
|
|
425
451
|
if errors:
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
# persist token
|
|
431
|
-
col_kid: int = db_insert(insert_stmt=f"INSERT INTO {JwtDbConfig.TABLE}",
|
|
432
|
-
insert_data={
|
|
433
|
-
JwtDbConfig.COL_ACCOUNT: account_id,
|
|
434
|
-
JwtDbConfig.COL_TOKEN: jwt_token,
|
|
435
|
-
JwtDbConfig.COL_ALGORITHM: JwtConfig.DEFAULT_ALGORITHM.value,
|
|
436
|
-
JwtDbConfig.COL_DECODER: b64encode(s=JwtConfig.DECODING_KEY.value).decode()
|
|
437
|
-
},
|
|
438
|
-
return_cols={JwtDbConfig.COL_KID: int},
|
|
439
|
-
engine=DbEngine(JwtDbConfig.ENGINE),
|
|
440
|
-
connection=db_conn,
|
|
441
|
-
errors=errors,
|
|
442
|
-
logger=logger)
|
|
443
|
-
if errors:
|
|
444
|
-
raise RuntimeError("; ".join(errors))
|
|
452
|
+
db_rollback(connection=curr_conn)
|
|
453
|
+
else:
|
|
454
|
+
db_commit(connection=curr_conn)
|
|
455
|
+
db_close(connection=curr_conn)
|
|
445
456
|
|
|
446
|
-
# obtain and return the token's storage id
|
|
447
|
-
reply: list[tuple[int]] = db_select(sel_stmt=f"SELECT {JwtDbConfig.COL_KID} "
|
|
448
|
-
f"FROM {JwtDbConfig.TABLE}",
|
|
449
|
-
where_data={JwtDbConfig.COL_KID: col_kid},
|
|
450
|
-
min_count=1,
|
|
451
|
-
max_count=1,
|
|
452
|
-
engine=DbEngine(JwtDbConfig.ENGINE),
|
|
453
|
-
connection=db_conn,
|
|
454
|
-
committable=False,
|
|
455
|
-
errors=errors,
|
|
456
|
-
logger=logger)
|
|
457
457
|
if errors:
|
|
458
458
|
raise RuntimeError("; ".join(errors))
|
|
459
459
|
|
|
460
|
-
return
|
|
460
|
+
return result
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|