pypomes-jwt 1.2.8__py3-none-any.whl → 1.2.9__py3-none-any.whl

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/jwt_config.py CHANGED
@@ -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.
pypomes_jwt/jwt_pomes.py CHANGED
@@ -440,7 +440,10 @@ def jwt_refresh_tokens(account_id: str,
440
440
 
441
441
  if logger:
442
442
  logger.debug(msg=f"Refreshing a JWT token pair for '{account_id}'")
443
- op_errors: list[str] = []
443
+
444
+ # make sure to have an errors list
445
+ if not isinstance(errors, list):
446
+ errors = []
444
447
 
445
448
  # assert the refresh token
446
449
  if refresh_token:
@@ -448,7 +451,7 @@ def jwt_refresh_tokens(account_id: str,
448
451
  token_claims: dict[str, Any] = jwt_validate_token(token=refresh_token,
449
452
  nature="R",
450
453
  account_id=account_id,
451
- errors=op_errors,
454
+ errors=errors,
452
455
  logger=logger)
453
456
  if token_claims:
454
457
  # yes, proceed
@@ -457,7 +460,7 @@ def jwt_refresh_tokens(account_id: str,
457
460
  # start the database transaction
458
461
  db_conn: Any = db_connect(autocommit=False,
459
462
  engine=DbEngine(JwtDbConfig.ENGINE),
460
- errors=op_errors,
463
+ errors=errors,
461
464
  logger=logger)
462
465
  if db_conn:
463
466
  # delete current refresh token
@@ -469,11 +472,11 @@ def jwt_refresh_tokens(account_id: str,
469
472
  engine=DbEngine(JwtDbConfig.ENGINE),
470
473
  connection=db_conn,
471
474
  committable=False,
472
- errors=op_errors,
475
+ errors=errors,
473
476
  logger=logger)
474
477
 
475
478
  # issue the token pair
476
- if not op_errors:
479
+ if not errors:
477
480
  try:
478
481
  result = __jwt_registry.issue_tokens(account_id=account_id,
479
482
  account_claims=token_claims.get("payload"),
@@ -487,27 +490,24 @@ def jwt_refresh_tokens(account_id: str,
487
490
  exc_info=sys.exc_info())
488
491
  if logger:
489
492
  logger.error(msg=f"Error refreshing the token pair: {exc_err}")
490
- op_errors.append(exc_err)
493
+ errors.append(exc_err)
491
494
 
492
495
  # wrap-up the transaction
493
- if op_errors:
496
+ if errors:
494
497
  db_rollback(connection=db_conn,
495
498
  logger=logger)
496
499
  else:
497
500
  db_commit(connection=db_conn,
498
- errors=op_errors,
501
+ errors=errors,
499
502
  logger=logger)
500
503
  db_close(connection=db_conn,
501
504
  logger=logger)
502
505
  else:
503
506
  # refresh token not found
504
- op_errors.append("Refresh token was not provided")
507
+ errors.append("Refresh token was not provided")
505
508
 
506
- if op_errors:
507
- if logger:
508
- logger.error("; ".join(op_errors))
509
- if isinstance(errors, list):
510
- errors.extend(op_errors)
509
+ if errors and logger:
510
+ logger.error(msg="; ".join(errors))
511
511
 
512
512
  return result
513
513
 
@@ -62,14 +62,14 @@ def provider_register(provider_id: str,
62
62
  }
63
63
 
64
64
 
65
- def provider_get_token(errors: list[str] | None,
66
- provider_id: str,
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
- # retrieve the account's tokens
363
- errors: list[str] = []
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
- if logger:
377
- logger.debug(msg=f"Retrieved {len(recs)} tokens from storage for account '{account_id}'")
378
- # remove the expired tokens
379
- just_now: int = int(datetime.now(tz=UTC).timestamp())
380
- oldest_ts: int = sys.maxsize
381
- oldest_id: int | None = None
382
- expired: list[int] = []
383
- for rec in recs:
384
- token: str = rec[1]
385
- token_id: int = rec[0]
386
- token_payload: dict[str, Any] = (jwt_get_claims(token=token,
387
- errors=errors,
388
- logger=logger) or {}).get("payload")
389
- if errors:
390
- raise RuntimeError("; ".join(errors))
391
-
392
- # find expired tokens
393
- exp: int = token_payload.get("exp", sys.maxsize)
394
- if exp < just_now:
395
- expired.append(token_id)
396
-
397
- # find oldest token
398
- iat: int = token_payload.get("iat", sys.maxsize)
399
- if iat < oldest_ts:
400
- oldest_ts = iat
401
- oldest_id = token_id
402
-
403
- # remove expired tokens from persistence
404
- if expired:
405
- db_delete(delete_stmt=f"DELETE FROM {JwtDbConfig.TABLE}",
406
- where_data={JwtDbConfig.COL_KID: expired},
407
- engine=DbEngine(JwtDbConfig.ENGINE),
408
- connection=db_conn,
409
- errors=errors,
410
- logger=logger)
411
- if errors:
412
- raise RuntimeError("; ".join(errors))
413
- if logger:
414
- logger.debug(msg=f"{len(expired)} tokens of account "
415
- f"'{account_id}' removed from storage")
416
-
417
- if 0 < JwtConfig.ACCOUNT_LIMIT.value <= len(recs) - len(expired):
418
- # delete the oldest token to make way for the new one
419
- db_delete(delete_stmt=f"DELETE FROM {JwtDbConfig.TABLE}",
420
- where_data={JwtDbConfig.COL_KID: oldest_id},
421
- engine=DbEngine(JwtDbConfig.ENGINE),
422
- connection=db_conn,
423
- errors=errors,
424
- logger=logger)
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
- raise RuntimeError("; ".join(errors))
427
- if logger:
428
- logger.debug(msg="Oldest active token of account "
429
- f"'{account_id}' removed from storage")
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 reply[0][0]
460
+ return result
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pypomes_jwt
3
- Version: 1.2.8
3
+ Version: 1.2.9
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.8
17
+ Requires-Dist: pypomes-db>=2.5.9
@@ -0,0 +1,9 @@
1
+ pypomes_jwt/__init__.py,sha256=vXAeaEnuUqpvGtV465TsW2Lf3ihijrMP2Hm4My79y88,968
2
+ pypomes_jwt/jwt_config.py,sha256=E8fGof_krCx2gZ_QCo87tF46J_2OLZk1m9erf3oX4O4,3398
3
+ pypomes_jwt/jwt_pomes.py,sha256=5EZ0gYj-zRJx1iQHfdmtdk-4V7NuWnhof69Vr6_TpRs,23836
4
+ pypomes_jwt/jwt_providers.py,sha256=LL2OxdyGH3_O-qEOVjg_GsPQVRtaSi37AE-BOZ6tiqs,5928
5
+ pypomes_jwt/jwt_registry.py,sha256=SDP2pFPsbjJ9w3r9c_DPJuN86rdwhHkg3lyX3gTBuNY,22305
6
+ pypomes_jwt-1.2.9.dist-info/METADATA,sha256=ptV7ecaz2x0IuwO_xGzNAozIOBN15Powzl9-utmMFgM,660
7
+ pypomes_jwt-1.2.9.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
8
+ pypomes_jwt-1.2.9.dist-info/licenses/LICENSE,sha256=NdakochSXm_H_-DSL_x2JlRCkYikj3snYYvTwgR5d_c,1086
9
+ pypomes_jwt-1.2.9.dist-info/RECORD,,
@@ -1,9 +0,0 @@
1
- pypomes_jwt/__init__.py,sha256=vXAeaEnuUqpvGtV465TsW2Lf3ihijrMP2Hm4My79y88,968
2
- pypomes_jwt/jwt_config.py,sha256=3r9XPWXXAG_wKUs_FDZoTj9j6lmTdNymud_q4E4Opk0,3338
3
- pypomes_jwt/jwt_pomes.py,sha256=P7d_8h3VPmrbtZWCcLnGdFV31c59B5CcmBrBSgILT1Q,23881
4
- pypomes_jwt/jwt_providers.py,sha256=wDIP6W-l_X1zrWeCNFGcRsb8Ui1Sja-3StcuRtLTjR4,5928
5
- pypomes_jwt/jwt_registry.py,sha256=AyaoSK4KMhRiRACTImK5z0AzQBwhG5cBkazPjkrzdaI,22046
6
- pypomes_jwt-1.2.8.dist-info/METADATA,sha256=3Kd-oLzz7qrIBH7fl-FFtW64G3NkyHgBJQcXnjXkwxw,660
7
- pypomes_jwt-1.2.8.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
8
- pypomes_jwt-1.2.8.dist-info/licenses/LICENSE,sha256=NdakochSXm_H_-DSL_x2JlRCkYikj3snYYvTwgR5d_c,1086
9
- pypomes_jwt-1.2.8.dist-info/RECORD,,