pypomes-iam 0.3.4__tar.gz → 0.3.6__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-iam might be problematic. Click here for more details.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pypomes_iam
3
- Version: 0.3.4
3
+ Version: 0.3.6
4
4
  Summary: A collection of Python pomes, penyeach (IAM modules)
5
5
  Project-URL: Homepage, https://github.com/TheWiseCoder/PyPomes-IAM
6
6
  Project-URL: Bug Tracker, https://github.com/TheWiseCoder/PyPomes-IAM/issues
@@ -6,7 +6,7 @@ build-backend = "hatchling.build"
6
6
 
7
7
  [project]
8
8
  name = "pypomes_iam"
9
- version = "0.3.4"
9
+ version = "0.3.6"
10
10
  authors = [
11
11
  { name="GT Nunes", email="wisecoder01@gmail.com" }
12
12
  ]
@@ -1,12 +1,11 @@
1
- import json
2
1
  import requests
3
2
  import sys
4
- from cachetools import Cache
5
3
  from datetime import datetime
6
4
  from enum import StrEnum
7
5
  from logging import Logger
8
6
  from pypomes_core import TZ_LOCAL, exc_format
9
7
  from pypomes_crypto import crypto_jwk_convert
8
+ from threading import Lock
10
9
  from typing import Any, Final
11
10
 
12
11
 
@@ -18,7 +17,8 @@ class IamServer(StrEnum):
18
17
  IAM_KEYCLOAK = "iam-keycloak"
19
18
 
20
19
 
21
- # the logger for IAM operations
20
+ # the logger for IAM service operations
21
+ # (used exclusively at the HTTP endpoint - all other functions receive the lgger as parameter)
22
22
  __IAM_LOGGER: Logger | None = None
23
23
 
24
24
  # registry structure:
@@ -53,11 +53,18 @@ __IAM_LOGGER: Logger | None = None
53
53
  # }
54
54
  _IAM_SERVERS: Final[dict[IamServer, dict[str, Any]]] = {}
55
55
 
56
+ # the lock protecting the data in '_IAM_SERVER'
57
+ # (because it is 'Final' and set at declaration time, it can be accessed through simple imports)
58
+ _iam_lock: Final[Lock] = Lock()
59
+
56
60
 
57
61
  def _get_logger() -> Logger | None:
58
62
  """
59
63
  Retrieve the registered logger for *IAM* operations.
60
64
 
65
+ This function is invoked exclusively from the HTTP endpoints.
66
+ All other functions receive the logger as parameter.
67
+
61
68
  :return: the registered logger for *IAM* operations.
62
69
  """
63
70
  return __IAM_LOGGER
@@ -175,11 +182,10 @@ def _get_user_data(iam_server: IamServer,
175
182
  # initialize the return variable
176
183
  result: dict[str, Any] | None = None
177
184
 
178
- cache: Cache = _get_iam_cache(iam_server=iam_server,
179
- errors=errors,
180
- logger=logger)
181
- if cache:
182
- users: dict[str, dict[str, Any]] = cache.get("users")
185
+ users: dict[str, dict[str, Any]] = _get_iam_users(iam_server=iam_server,
186
+ errors=errors,
187
+ logger=logger)
188
+ if users:
183
189
  result = users.get(user_id)
184
190
  if not result:
185
191
  result = {
@@ -256,9 +262,9 @@ def _get_iam_registry(iam_server: IamServer,
256
262
  return result
257
263
 
258
264
 
259
- def _get_iam_cache(iam_server: IamServer,
265
+ def _get_iam_users(iam_server: IamServer,
260
266
  errors: list[str] | None,
261
- logger: Logger | None) -> Cache:
267
+ logger: Logger | None) -> dict[str, dict[str, Any]]:
262
268
  """
263
269
  Retrieve the cache storage in *iam_server*'s registry.
264
270
 
@@ -270,97 +276,4 @@ def _get_iam_cache(iam_server: IamServer,
270
276
  registry: dict[str, Any] = _get_iam_registry(iam_server=iam_server,
271
277
  errors=errors,
272
278
  logger=logger)
273
- return registry["cache"] if registry else None
274
-
275
-
276
- def _post_for_token(iam_server: IamServer,
277
- body_data: dict[str, Any],
278
- errors: list[str] | None,
279
- logger: Logger | None) -> dict[str, Any] | None:
280
- """
281
- Send a POST request to obtain the authentication token data, and return the data received.
282
-
283
- For token acquisition, *body_data* will have the attributes:
284
- - "grant_type": "authorization_code"
285
- - "code": <16-character-random-code>
286
- - "redirect_uri": <redirect-uri>
287
-
288
- For token refresh, *body_data* will have the attributes:
289
- - "grant_type": "refresh_token"
290
- - "refresh_token": <current-refresh-token>
291
-
292
- For token exchange, *body_data* will have the attributes:
293
- - "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange",
294
- - "subject_token": <token-to-be-exchanged>,
295
- - "subject_token_type": "urn:ietf:params:oauth:token-type:access_token",
296
- - "requested_token_type": "urn:ietf:params:oauth:token-type:access_token",
297
- - "audience": <client-id>,
298
- - "subject_issuer": "oidc"
299
-
300
- These attributes are then added to *body_data*:
301
- - "client_id": <client-id>,
302
- - "client_secret": <client-secret>,
303
-
304
- If the operation is successful, the token data is stored in the registry.
305
- Otherwise, *errors* will contain the appropriate error message.
306
-
307
- :param iam_server: the reference registered *IAM* server
308
- :param body_data: the data to send in the body of the request
309
- :param errors: incidental errors
310
- :param logger: optional logger
311
- :return: the access token obtained, or *None* if error
312
- """
313
- # initialize the return variable
314
- result: dict[str, Any] | None = None
315
-
316
- # PBTAIN THE iam SERVER'S REGISTRY
317
- registry: dict[str, Any] = _get_iam_registry(iam_server=iam_server,
318
- errors=errors,
319
- logger=logger)
320
- err_msg: str | None = None
321
- if registry:
322
- # complete the data to send in body of request
323
- body_data["client_id"] = registry["client-id"]
324
- client_secret: str = registry["client-secret"]
325
- if client_secret:
326
- body_data["client_secret"] = client_secret
327
-
328
- # obtain the token
329
- url: str = registry["base-url"] + "/protocol/openid-connect/token"
330
- if logger:
331
- logger.debug(msg=f"POST '{url}', data {json.dumps(obj=body_data,
332
- ensure_ascii=False)}")
333
- try:
334
- # typical return on a token request:
335
- # {
336
- # "token_type": "Bearer",
337
- # "access_token": <str>,
338
- # "expires_in": <number-of-seconds>,
339
- # "refresh_token": <str>,
340
- # "refesh_expires_in": <number-of-seconds>
341
- # }
342
- response: requests.Response = requests.post(url=url,
343
- data=body_data)
344
- if response.status_code == 200:
345
- # request succeeded
346
- if logger:
347
- logger.debug(msg=f"POST success, status {response.status_code}")
348
- result = response.json()
349
- else:
350
- # request resulted in error
351
- err_msg = f"POST failure, status {response.status_code}, reason '{response.reason}'"
352
- if hasattr(response, "content") and response.content:
353
- err_msg += f", content '{response.content}'"
354
- if logger:
355
- logger.error(msg=err_msg)
356
- except Exception as e:
357
- # the operation raised an exception
358
- err_msg = exc_format(exc=e,
359
- exc_info=sys.exc_info())
360
- if logger:
361
- logger.error(msg=err_msg)
362
-
363
- if err_msg and isinstance(errors, list):
364
- errors.append(err_msg)
365
-
366
- return result
279
+ return registry["cache"]["users"] if registry else None