pypomes-iam 0.6.2__py3-none-any.whl → 0.8.2__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-iam might be problematic. Click here for more details.
- pypomes_iam/__init__.py +20 -12
- pypomes_iam/iam_actions.py +343 -122
- pypomes_iam/iam_common.py +71 -29
- pypomes_iam/iam_pomes.py +123 -100
- pypomes_iam/iam_services.py +330 -126
- pypomes_iam/provider_pomes.py +197 -30
- pypomes_iam/token_pomes.py +27 -0
- {pypomes_iam-0.6.2.dist-info → pypomes_iam-0.8.2.dist-info}/METADATA +2 -2
- pypomes_iam-0.8.2.dist-info/RECORD +11 -0
- pypomes_iam-0.6.2.dist-info/RECORD +0 -11
- {pypomes_iam-0.6.2.dist-info → pypomes_iam-0.8.2.dist-info}/WHEEL +0 -0
- {pypomes_iam-0.6.2.dist-info → pypomes_iam-0.8.2.dist-info}/licenses/LICENSE +0 -0
pypomes_iam/provider_pomes.py
CHANGED
|
@@ -4,8 +4,13 @@ import sys
|
|
|
4
4
|
from base64 import b64encode
|
|
5
5
|
from datetime import datetime
|
|
6
6
|
from enum import StrEnum
|
|
7
|
+
from flask import Flask, Response, request, jsonify
|
|
7
8
|
from logging import Logger
|
|
8
|
-
from pypomes_core import
|
|
9
|
+
from pypomes_core import (
|
|
10
|
+
APP_PREFIX, TZ_LOCAL,
|
|
11
|
+
env_get_str, env_get_strs, env_get_obj, exc_format,
|
|
12
|
+
func_capture_params, func_defaulted_params
|
|
13
|
+
)
|
|
9
14
|
from threading import Lock
|
|
10
15
|
from typing import Any, Final
|
|
11
16
|
|
|
@@ -14,16 +19,67 @@ class ProviderParam(StrEnum):
|
|
|
14
19
|
"""
|
|
15
20
|
Parameters for configuring a *JWT* token provider.
|
|
16
21
|
"""
|
|
17
|
-
|
|
18
|
-
USER = "user"
|
|
19
|
-
PWD = "pwd"
|
|
22
|
+
BODY_DATA = "body-data"
|
|
20
23
|
CUSTOM_AUTH = "custom-auth"
|
|
21
24
|
HEADER_DATA = "headers-data"
|
|
22
|
-
|
|
25
|
+
USER_ID = "user-id"
|
|
26
|
+
USER_SECRET = "user-secret"
|
|
23
27
|
ACCESS_TOKEN = "access-token"
|
|
24
28
|
ACCESS_EXPIRATION = "access-expiration"
|
|
25
29
|
REFRESH_TOKEN = "refresh-token"
|
|
26
30
|
REFRESH_EXPIRATION = "refresh-expiration"
|
|
31
|
+
URL_AUTH = "url-auth"
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
# the logger for IAM service operations
|
|
35
|
+
# (used exclusively at the HTTP endpoints - all other functions receive the logger as parameter)
|
|
36
|
+
__JWT_LOGGER: Logger | None = None
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def __get_provider_data() -> dict[str, dict[ProviderParam, Any]]:
|
|
40
|
+
"""
|
|
41
|
+
Obtain the configuration data for select *JWT* providers.
|
|
42
|
+
|
|
43
|
+
The configuration parameters for the JWT providers are specified with environment variables,
|
|
44
|
+
or dynamically with *provider_setup_server()*. Specifying configuration parameters with
|
|
45
|
+
environment variables can be done by following these steps:
|
|
46
|
+
|
|
47
|
+
1. Specify *<APP_PREFIX>_IAM_PROVIDERS* with a list of names (typically, in lower-case), and the data set
|
|
48
|
+
below for each providers, where *<JWT>* stands for the provider's name in upper-case:
|
|
49
|
+
- *<APP_PREFIX>_<JWT>_BODY_DATA* (optional)
|
|
50
|
+
- *<APP_PREFIX>_<JWT>_CUSTOM_AUTH* (optional)
|
|
51
|
+
- *<APP_PREFIX>_<JWT>_HEADER_DATA* (optional)
|
|
52
|
+
- *<APP_PREFIX>_<JWT>_USER_ID* (required)
|
|
53
|
+
- *<APP_PREFIX>_<JWT>_USER_SECRET* (required)
|
|
54
|
+
- *<APP_PREFIX>_<JWT>_URL_TOKEN* (required)
|
|
55
|
+
|
|
56
|
+
2. The special environment variable *<APP_PREFIX>_IAM_PROVIDER_ENDPOINT_TOKEN* identifies the endpoint
|
|
57
|
+
from which to obtain JWT tokens. It is not part of the *JWT* providers' setup, but is meant to be
|
|
58
|
+
used by function *provider_setup_endpoint()*, wherein the value in that variable would represent
|
|
59
|
+
the default value for its parameter.
|
|
60
|
+
|
|
61
|
+
:return: the configuration data for the select *JWT* providers.
|
|
62
|
+
"""
|
|
63
|
+
# initialize the return variable
|
|
64
|
+
result: dict[str, dict[ProviderParam, Any]] = {}
|
|
65
|
+
|
|
66
|
+
servers: list[str] = env_get_strs(key=f"{APP_PREFIX}_IAM_PROVIDERS") or []
|
|
67
|
+
for server in servers:
|
|
68
|
+
prefix = server.upper()
|
|
69
|
+
result[server] = {
|
|
70
|
+
ProviderParam.BODY_DATA: env_get_obj(key=f"{APP_PREFIX}_{prefix}_BODY_DATA"),
|
|
71
|
+
ProviderParam.CUSTOM_AUTH: env_get_strs(key=f"{APP_PREFIX}_{prefix}_CUSTOM_AUTH"),
|
|
72
|
+
ProviderParam.HEADER_DATA: env_get_obj(key=f"{APP_PREFIX}_{prefix}_HEADER_DATA"),
|
|
73
|
+
ProviderParam.USER_ID: env_get_str(key=f"{APP_PREFIX}_{prefix}_USER_ID"),
|
|
74
|
+
ProviderParam.USER_SECRET: env_get_str(key=f"{APP_PREFIX}_{prefix}_USER_SECRET"),
|
|
75
|
+
ProviderParam.URL_AUTH: env_get_str(key=f"{APP_PREFIX}_{prefix}_URL_AUTH"),
|
|
76
|
+
ProviderParam.ACCESS_TOKEN: None,
|
|
77
|
+
ProviderParam.ACCESS_EXPIRATION: 0,
|
|
78
|
+
ProviderParam.REFRESH_TOKEN: None,
|
|
79
|
+
ProviderParam.REFRESH_EXPIRATION: 0
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return result
|
|
27
83
|
|
|
28
84
|
|
|
29
85
|
# structure:
|
|
@@ -32,7 +88,7 @@ class ProviderParam(StrEnum):
|
|
|
32
88
|
# "url": <strl>,
|
|
33
89
|
# "user": <str>,
|
|
34
90
|
# "pwd": <str>,
|
|
35
|
-
# "custom-auth": <
|
|
91
|
+
# "custom-auth": <tuple[str, str]>,
|
|
36
92
|
# "headers-data": <dict[str, str]>,
|
|
37
93
|
# "body-data": <dict[str, str],
|
|
38
94
|
# "access-token": <str>,
|
|
@@ -41,22 +97,26 @@ class ProviderParam(StrEnum):
|
|
|
41
97
|
# "refresh-expiration": <timestamp>
|
|
42
98
|
# }
|
|
43
99
|
# }
|
|
44
|
-
_provider_registry: Final[dict[str, dict[str, Any]]] =
|
|
100
|
+
_provider_registry: Final[dict[str, dict[str, Any]]] = __get_provider_data()
|
|
45
101
|
|
|
46
102
|
# the lock protecting the data in '_provider_registry'
|
|
47
103
|
# (because it is 'Final' and set at declaration time, it can be accessed through simple imports)
|
|
48
104
|
_provider_lock: Final[Lock] = Lock()
|
|
49
105
|
|
|
50
106
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
107
|
+
@func_capture_params
|
|
108
|
+
def provider_setup_server(provider_id: str,
|
|
109
|
+
user_id: str = None,
|
|
110
|
+
user_secret: str = None,
|
|
111
|
+
custom_auth: tuple[str, str] = None,
|
|
112
|
+
header_data: dict[str, str] = None,
|
|
113
|
+
body_data: dict[str, str] = None,
|
|
114
|
+
url_auth: str = None) -> None:
|
|
58
115
|
"""
|
|
59
|
-
|
|
116
|
+
Setup the *JWT* provider *provider_id*.
|
|
117
|
+
|
|
118
|
+
For the parameters not effectively passed, an attempt is made to obtain a value from the corresponding
|
|
119
|
+
environment variable.
|
|
60
120
|
|
|
61
121
|
If specified, *custom_auth* provides key names for sending credentials (username and password, in this order)
|
|
62
122
|
as key-value pairs in the body of the request. Otherwise, the external provider *provider_id* uses the standard
|
|
@@ -67,23 +127,42 @@ def provider_register(provider_id: str,
|
|
|
67
127
|
(such as ['grant_type', 'client_credentials']), to be added to the request body, may be specified in *body_data*.
|
|
68
128
|
|
|
69
129
|
:param provider_id: the provider's identification
|
|
70
|
-
:param
|
|
71
|
-
:param
|
|
72
|
-
:param auth_pwd: the basic authorization password
|
|
130
|
+
:param user_id: the basic authorization user
|
|
131
|
+
:param user_secret: the basic authorization password
|
|
73
132
|
:param custom_auth: optional key names for sending the credentials as key-value pairs in the body of the request
|
|
74
|
-
:param
|
|
133
|
+
:param header_data: optional key-value pairs to be added to the request headers
|
|
75
134
|
:param body_data: optional key-value pairs to be added to the request body
|
|
135
|
+
:param url_auth: the url to request *JWT* tokens with
|
|
76
136
|
"""
|
|
77
137
|
global _provider_registry
|
|
78
138
|
|
|
139
|
+
# obtain the defaulted parameters
|
|
140
|
+
defaulted_params: list[str] = func_defaulted_params.get()
|
|
141
|
+
|
|
142
|
+
# read from the environment variables
|
|
143
|
+
prefix: str = provider_id.upper()
|
|
144
|
+
if "user_id" in defaulted_params:
|
|
145
|
+
user_id = env_get_str(key=f"{APP_PREFIX}_{prefix}_USER_ID")
|
|
146
|
+
if "user_secret" in defaulted_params:
|
|
147
|
+
user_secret = env_get_str(key=f"{APP_PREFIX}_{prefix}_USER_SECRET")
|
|
148
|
+
if "custom_auth" in defaulted_params:
|
|
149
|
+
custom_auth = env_get_strs(key=f"{APP_PREFIX}_{prefix}_CUSTOM_AUTH")
|
|
150
|
+
if "header_data" in defaulted_params:
|
|
151
|
+
header_data = env_get_obj(key=f"{APP_PREFIX}_{prefix}_HEADER_DATA")
|
|
152
|
+
if "body_data" in defaulted_params:
|
|
153
|
+
body_data = env_get_obj(key=f"{APP_PREFIX}_{prefix}_BODY_DATA")
|
|
154
|
+
if "url_auth" in defaulted_params:
|
|
155
|
+
url_auth = env_get_str(key=f"{APP_PREFIX}_{prefix}_URL_AUTH")
|
|
156
|
+
|
|
79
157
|
with _provider_lock:
|
|
80
158
|
_provider_registry[provider_id] = {
|
|
81
|
-
ProviderParam.
|
|
82
|
-
ProviderParam.
|
|
83
|
-
ProviderParam.
|
|
159
|
+
ProviderParam.URL_AUTH: url_auth,
|
|
160
|
+
ProviderParam.USER_ID: user_id,
|
|
161
|
+
ProviderParam.USER_SECRET: user_secret,
|
|
84
162
|
ProviderParam.CUSTOM_AUTH: custom_auth,
|
|
85
|
-
ProviderParam.HEADER_DATA:
|
|
163
|
+
ProviderParam.HEADER_DATA: header_data,
|
|
86
164
|
ProviderParam.BODY_DATA: body_data,
|
|
165
|
+
# dynamically set
|
|
87
166
|
ProviderParam.ACCESS_TOKEN: None,
|
|
88
167
|
ProviderParam.ACCESS_EXPIRATION: 0,
|
|
89
168
|
ProviderParam.REFRESH_TOKEN: None,
|
|
@@ -91,17 +170,105 @@ def provider_register(provider_id: str,
|
|
|
91
170
|
}
|
|
92
171
|
|
|
93
172
|
|
|
173
|
+
@func_capture_params
|
|
174
|
+
def provider_setup_endpoint(flask_app: Flask,
|
|
175
|
+
provider_endpoint: str = None) -> None:
|
|
176
|
+
"""
|
|
177
|
+
Setup the endpoint for requesting token from the registered *JWT* providers.
|
|
178
|
+
|
|
179
|
+
if *provider_endpoint* is not effectively passed, an attempt is made to obtain a value from the corresponding
|
|
180
|
+
environment variable.
|
|
181
|
+
|
|
182
|
+
:param flask_app: the Flask application
|
|
183
|
+
:param provider_endpoint: endpoint for requenting tokens to provider
|
|
184
|
+
"""
|
|
185
|
+
# obtain the defaulted parameters
|
|
186
|
+
defaulted_params: list[str] = func_defaulted_params.get()
|
|
187
|
+
|
|
188
|
+
# read from the environment variable
|
|
189
|
+
if "provider_endpoint" in defaulted_params:
|
|
190
|
+
provider_endpoint = env_get_str(key=f"{APP_PREFIX}_IAM_PROVIDER_ENDPOINT_TOKEN")
|
|
191
|
+
|
|
192
|
+
# establish the endpoints
|
|
193
|
+
if provider_endpoint:
|
|
194
|
+
flask_app.add_url_rule(rule=provider_endpoint,
|
|
195
|
+
endpoint=f"jwt-callback",
|
|
196
|
+
view_func=service_get_token,
|
|
197
|
+
methods=["GET"])
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def provider_setup_logger(logger: Logger) -> None:
|
|
201
|
+
"""
|
|
202
|
+
Register the logger for HTTP services.
|
|
203
|
+
|
|
204
|
+
:param logger: the logger to be registered
|
|
205
|
+
"""
|
|
206
|
+
global __JWT_LOGGER
|
|
207
|
+
__JWT_LOGGER = logger
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
# @flask_app.route(rule=<token_endpoint>, # IAM_PROVIDER_ENDPOINT_TOKEN
|
|
211
|
+
# methods=["GET"])
|
|
212
|
+
def service_get_token() -> Response:
|
|
213
|
+
"""
|
|
214
|
+
Entry point for retrieving a token from the *JWT* provider.
|
|
215
|
+
|
|
216
|
+
The provider is identified by the request parameter *jwt-provider*.
|
|
217
|
+
|
|
218
|
+
On success, the returned *Response* will contain the following JSON:
|
|
219
|
+
{
|
|
220
|
+
"access-token": <token>
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
:return: *Response* containing the JWT token, or *BAD REQUEST*
|
|
224
|
+
"""
|
|
225
|
+
# log the request
|
|
226
|
+
if __JWT_LOGGER:
|
|
227
|
+
params: str = json.dumps(obj=request.args,
|
|
228
|
+
ensure_ascii=False)
|
|
229
|
+
__JWT_LOGGER.debug(msg=f"Request {request.method}:{request.path}, params {params}")
|
|
230
|
+
|
|
231
|
+
# obtain the provider JWT
|
|
232
|
+
provider_id: str = request.args.get("jwt-provider")
|
|
233
|
+
|
|
234
|
+
# retrieve the token
|
|
235
|
+
token: str | None = None
|
|
236
|
+
errors: list[str] = []
|
|
237
|
+
if provider_id:
|
|
238
|
+
token: str = provider_get_token(provider_id=provider_id,
|
|
239
|
+
errors=errors,
|
|
240
|
+
logger=__JWT_LOGGER)
|
|
241
|
+
else:
|
|
242
|
+
msg: str = "JWT provider not informed"
|
|
243
|
+
errors.append(msg)
|
|
244
|
+
if __JWT_LOGGER:
|
|
245
|
+
__JWT_LOGGER.error(msg=msg)
|
|
246
|
+
|
|
247
|
+
result: Response
|
|
248
|
+
if errors:
|
|
249
|
+
result = Response(response="; ".join(errors),
|
|
250
|
+
status=400)
|
|
251
|
+
else:
|
|
252
|
+
result = jsonify({"access-token": token})
|
|
253
|
+
if __JWT_LOGGER:
|
|
254
|
+
# log the response (the returned data is not logged, as it contains the token)
|
|
255
|
+
__JWT_LOGGER.debug(msg=f"Response {result}")
|
|
256
|
+
|
|
257
|
+
return result
|
|
258
|
+
|
|
259
|
+
|
|
94
260
|
def provider_get_token(provider_id: str,
|
|
95
261
|
errors: list[str] = None,
|
|
96
262
|
logger: Logger = None) -> str | None:
|
|
97
263
|
"""
|
|
98
|
-
Obtain an
|
|
264
|
+
Obtain an JWT token from the external provider *provider_id*.
|
|
99
265
|
|
|
100
266
|
:param provider_id: the provider's identification
|
|
101
267
|
:param errors: incidental error messages
|
|
102
268
|
:param logger: optional logger
|
|
269
|
+
:return: the JWT token, or *None* if error
|
|
103
270
|
"""
|
|
104
|
-
global _provider_registry
|
|
271
|
+
global _provider_registry
|
|
105
272
|
|
|
106
273
|
# initialize the return variable
|
|
107
274
|
result: str | None = None
|
|
@@ -117,7 +284,7 @@ def provider_get_token(provider_id: str,
|
|
|
117
284
|
# access token has expired
|
|
118
285
|
header_data: dict[str, str] | None = None
|
|
119
286
|
body_data: dict[str, str] | None = None
|
|
120
|
-
url: str = provider.get(ProviderParam.
|
|
287
|
+
url: str = provider.get(ProviderParam.URL_AUTH)
|
|
121
288
|
refresh_token: str = provider.get(ProviderParam.REFRESH_TOKEN)
|
|
122
289
|
if refresh_token:
|
|
123
290
|
# refresh token exists
|
|
@@ -133,9 +300,9 @@ def provider_get_token(provider_id: str,
|
|
|
133
300
|
}
|
|
134
301
|
if not body_data:
|
|
135
302
|
# refresh token does not exist or has expired
|
|
136
|
-
user: str = provider.get(ProviderParam.
|
|
137
|
-
pwd: str = provider.get(ProviderParam.
|
|
138
|
-
|
|
303
|
+
user: str = provider.get(ProviderParam.USER_ID)
|
|
304
|
+
pwd: str = provider.get(ProviderParam.USER_SECRET)
|
|
305
|
+
header_data: dict[str, str] = provider.get(ProviderParam.HEADER_DATA) or {}
|
|
139
306
|
body_data: dict[str, str] = provider.get(ProviderParam.BODY_DATA) or {}
|
|
140
307
|
custom_auth: tuple[str, str] = provider.get(ProviderParam.CUSTOM_AUTH)
|
|
141
308
|
if custom_auth:
|
|
@@ -143,7 +310,7 @@ def provider_get_token(provider_id: str,
|
|
|
143
310
|
body_data[custom_auth[1]] = pwd
|
|
144
311
|
else:
|
|
145
312
|
enc_bytes: bytes = b64encode(f"{user}:{pwd}".encode())
|
|
146
|
-
|
|
313
|
+
header_data["Authorization"] = f"Basic {enc_bytes.decode()}"
|
|
147
314
|
|
|
148
315
|
# obtain the token
|
|
149
316
|
token_data: dict[str, Any] = __post_for_token(url=url,
|
pypomes_iam/token_pomes.py
CHANGED
|
@@ -46,6 +46,33 @@ def token_get_claims(token: str,
|
|
|
46
46
|
return result
|
|
47
47
|
|
|
48
48
|
|
|
49
|
+
def token_get_values(token: str,
|
|
50
|
+
keys: tuple[str, ...],
|
|
51
|
+
errors: list[str] = None,
|
|
52
|
+
logger: Logger = None) -> tuple:
|
|
53
|
+
"""
|
|
54
|
+
Retrieve the values of *keys* in the token's payload.
|
|
55
|
+
|
|
56
|
+
Ther values are returned in the same order as requested in *keys*.
|
|
57
|
+
For a claim not found, *None* is returned in its position.
|
|
58
|
+
|
|
59
|
+
:param token: the reference token
|
|
60
|
+
:param keys: the names of the claims whose values are to be returned
|
|
61
|
+
:param errors: incidental errors
|
|
62
|
+
:param logger: optiona logger
|
|
63
|
+
:return: a tuple containing the respective values of *claims* in *token*.
|
|
64
|
+
"""
|
|
65
|
+
token_claims: dict[str, dict[str, Any]] = token_get_claims(token=token,
|
|
66
|
+
errors=errors,
|
|
67
|
+
logger=logger)
|
|
68
|
+
payload: dict[str, Any] = token_claims["payload"]
|
|
69
|
+
values: list[Any] = []
|
|
70
|
+
for key in keys:
|
|
71
|
+
values.append(payload.get(key))
|
|
72
|
+
|
|
73
|
+
return tuple(values)
|
|
74
|
+
|
|
75
|
+
|
|
49
76
|
def token_validate(token: str,
|
|
50
77
|
issuer: str = None,
|
|
51
78
|
recipient_id: str = None,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pypomes_iam
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.8.2
|
|
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
|
|
@@ -12,6 +12,6 @@ Classifier: Programming Language :: Python :: 3
|
|
|
12
12
|
Requires-Python: >=3.12
|
|
13
13
|
Requires-Dist: flask>=3.1.2
|
|
14
14
|
Requires-Dist: pyjwt>=2.10.1
|
|
15
|
-
Requires-Dist: pypomes-core>=2.8.
|
|
15
|
+
Requires-Dist: pypomes-core>=2.8.6
|
|
16
16
|
Requires-Dist: pypomes-crypto>=0.4.8
|
|
17
17
|
Requires-Dist: requests>=2.32.5
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
pypomes_iam/__init__.py,sha256=kkHvF3P79h21dNBmJ566Mp-L27oejhBcJa2VquyVsdg,1619
|
|
2
|
+
pypomes_iam/iam_actions.py,sha256=ORuHoiuMPnrMabvnCUcMeqHI4xfqbTErED1LydOPBCg,51191
|
|
3
|
+
pypomes_iam/iam_common.py,sha256=f8MGez9Eyia30FAXdNiHjeHnljnMQOOERr_BOxtoirY,17575
|
|
4
|
+
pypomes_iam/iam_pomes.py,sha256=VwqK3FoGj76SHKLARuBmIhziYnd_hoMWoUteMGRjuSc,8963
|
|
5
|
+
pypomes_iam/iam_services.py,sha256=NIU-pRuCzY8TOdGLzMngKn6rzy4sOM6SyPdPMeJQZQI,26815
|
|
6
|
+
pypomes_iam/provider_pomes.py,sha256=BP2fzuRSOFq7iN3e1tvX06Q1PhvbS-MM3M8i0TPtLg8,17546
|
|
7
|
+
pypomes_iam/token_pomes.py,sha256=KiTlBNj3HURbZS_Rmti2RC6hny8VFPpbXeIO--HZ-fI,7703
|
|
8
|
+
pypomes_iam-0.8.2.dist-info/METADATA,sha256=EkjqtV-n1LhJo9i6jM__IpgLLFhgUEBhXFP62XLdwpM,661
|
|
9
|
+
pypomes_iam-0.8.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
10
|
+
pypomes_iam-0.8.2.dist-info/licenses/LICENSE,sha256=YvUELgV8qvXlaYsy9hXG5EW3Bmsrkw-OJmmILZnonAc,1086
|
|
11
|
+
pypomes_iam-0.8.2.dist-info/RECORD,,
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
pypomes_iam/__init__.py,sha256=_6tSFfjuU-5p6TAMqNLHSL6IQmaJMSYuEW-TG3ybhTI,1044
|
|
2
|
-
pypomes_iam/iam_actions.py,sha256=DhDZcY6j3uSWnm5Q5SrA5jriTUCatLqJKd9K7IjA2i8,39283
|
|
3
|
-
pypomes_iam/iam_common.py,sha256=ki_-m6fqJqUbGjgTD41r9zaE-FOXgA_c_tLisIYYTfU,15457
|
|
4
|
-
pypomes_iam/iam_pomes.py,sha256=XkxpwwGivUR3Y1TKR6McrqLUnpFJhRvIrsEn9T_Ut9A,7351
|
|
5
|
-
pypomes_iam/iam_services.py,sha256=IkCjrKDX1Ix7BiHh-BL3VKz5xogcNC8prXkHyJzQoZ8,15862
|
|
6
|
-
pypomes_iam/provider_pomes.py,sha256=3mMj5LQs53YEINUEOfFBAxOwOP3aOR_szlE4daEBLK0,10523
|
|
7
|
-
pypomes_iam/token_pomes.py,sha256=K4nSAotKUoHIE2s3ltc_nVimlNeKS9tnD-IlslkAvkk,6626
|
|
8
|
-
pypomes_iam-0.6.2.dist-info/METADATA,sha256=XeUm7yxjoWFURVvoHDSoYkF5iROCC696PPuHydJ1UIs,661
|
|
9
|
-
pypomes_iam-0.6.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
10
|
-
pypomes_iam-0.6.2.dist-info/licenses/LICENSE,sha256=YvUELgV8qvXlaYsy9hXG5EW3Bmsrkw-OJmmILZnonAc,1086
|
|
11
|
-
pypomes_iam-0.6.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|