aws-python-helper 1.6.0__tar.gz → 1.7.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.
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/PKG-INFO +1 -1
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/api/base.py +21 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/api/fetcher.py +29 -24
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/permissions/catalog.py +38 -1
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper.egg-info/PKG-INFO +1 -1
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/pyproject.toml +1 -1
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/README.md +0 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/__init__.py +0 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/api/__init__.py +0 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/api/auth_middleware.py +0 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/api/auth_validators.py +0 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/api/dispatcher.py +0 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/api/exceptions.py +0 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/api/handler.py +0 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/context/__init__.py +0 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/context/session.py +0 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/context/state_validator.py +0 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/database/__init__.py +0 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/database/database_proxy.py +0 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/database/external_database_proxy.py +0 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/database/external_mongo_manager.py +0 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/database/mongo_manager.py +0 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/fargate/__init__.py +0 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/fargate/executor.py +0 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/fargate/fetcher.py +0 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/fargate/handler.py +0 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/fargate/task_base.py +0 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/invoker/__init__.py +0 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/invoker/api_client.py +0 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/invoker/exceptions.py +0 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/invoker/lambda_invoker.py +0 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/lambda_standalone/__init__.py +0 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/lambda_standalone/base.py +0 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/lambda_standalone/fetcher.py +0 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/lambda_standalone/handler.py +0 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/model_index_sync/__init__.py +0 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/model_index_sync/base.py +0 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/model_query/__init__.py +0 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/model_query/base.py +0 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/permissions/__init__.py +0 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/repository/__init__.py +0 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/repository/audit.py +0 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/repository/base.py +0 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/sns/__init__.py +0 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/sns/publisher.py +0 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/sqs/__init__.py +0 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/sqs/consumer_base.py +0 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/sqs/fetcher.py +0 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/sqs/handler.py +0 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/utils/__init__.py +0 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/utils/json_encoder.py +0 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/utils/response.py +0 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/utils/serializer.py +0 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper.egg-info/SOURCES.txt +0 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper.egg-info/dependency_links.txt +0 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper.egg-info/requires.txt +0 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper.egg-info/top_level.txt +0 -0
- {aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/setup.cfg +0 -0
|
@@ -288,6 +288,27 @@ class API(ABC):
|
|
|
288
288
|
'headers': self._response_headers
|
|
289
289
|
}
|
|
290
290
|
|
|
291
|
+
@property
|
|
292
|
+
def public(self) -> bool:
|
|
293
|
+
"""
|
|
294
|
+
Whether this endpoint answers without a token.
|
|
295
|
+
|
|
296
|
+
Declared here, next to the code, so the permission catalog can leave it
|
|
297
|
+
out: a permission for something nobody needs permission for is noise in
|
|
298
|
+
every role screen, and an administrator ticking it would be granting
|
|
299
|
+
nothing.
|
|
300
|
+
|
|
301
|
+
This does not make an endpoint public — terraform does, by leaving
|
|
302
|
+
`authorization` unset on its lambda. This says so, so the rest of the
|
|
303
|
+
framework can act on it.
|
|
304
|
+
|
|
305
|
+
class AuthLoginAPI(API):
|
|
306
|
+
@property
|
|
307
|
+
def public(self):
|
|
308
|
+
return True
|
|
309
|
+
"""
|
|
310
|
+
return False
|
|
311
|
+
|
|
291
312
|
@property
|
|
292
313
|
def schema(self):
|
|
293
314
|
"""
|
|
@@ -7,6 +7,34 @@ import importlib.util
|
|
|
7
7
|
from pathlib import Path
|
|
8
8
|
from typing import List
|
|
9
9
|
|
|
10
|
+
def load_controller_class(file_path: str):
|
|
11
|
+
"""The API class a controller file defines.
|
|
12
|
+
|
|
13
|
+
Shared so the permission catalog asks the class the same questions the
|
|
14
|
+
dispatcher does — a second way of finding it would answer differently the
|
|
15
|
+
day one of them changes.
|
|
16
|
+
"""
|
|
17
|
+
spec = importlib.util.spec_from_file_location("api_module", file_path)
|
|
18
|
+
if not spec or not spec.loader:
|
|
19
|
+
raise ImportError(f"Could not load module spec from: {file_path}")
|
|
20
|
+
|
|
21
|
+
module = importlib.util.module_from_spec(spec)
|
|
22
|
+
spec.loader.exec_module(module)
|
|
23
|
+
|
|
24
|
+
for item_name in dir(module):
|
|
25
|
+
item = getattr(module, item_name)
|
|
26
|
+
if (isinstance(item, type) and
|
|
27
|
+
hasattr(item, 'process') and
|
|
28
|
+
item.__name__ not in ['API', 'ABC'] and
|
|
29
|
+
item.__module__ == module.__name__):
|
|
30
|
+
return item
|
|
31
|
+
|
|
32
|
+
raise ValueError(
|
|
33
|
+
f"No API class found in {file_path}\n"
|
|
34
|
+
f"Make sure your file exports a class that inherits from API"
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
|
|
10
38
|
class Fetcher:
|
|
11
39
|
"""
|
|
12
40
|
Dynamically load API controllers
|
|
@@ -187,30 +215,7 @@ class Fetcher:
|
|
|
187
215
|
f"Expected file for endpoint '{self.endpoint}' with method '{self.method}'"
|
|
188
216
|
)
|
|
189
217
|
|
|
190
|
-
|
|
191
|
-
spec = importlib.util.spec_from_file_location("api_module", file_path)
|
|
192
|
-
if not spec or not spec.loader:
|
|
193
|
-
raise ImportError(f"Could not load module spec from: {file_path}")
|
|
194
|
-
|
|
195
|
-
module = importlib.util.module_from_spec(spec)
|
|
196
|
-
spec.loader.exec_module(module)
|
|
197
|
-
|
|
198
|
-
# Search for a class that inherits from API
|
|
199
|
-
controller_class = None
|
|
200
|
-
for item_name in dir(module):
|
|
201
|
-
item = getattr(module, item_name)
|
|
202
|
-
if (isinstance(item, type) and
|
|
203
|
-
hasattr(item, 'process') and
|
|
204
|
-
item.__name__ not in ['API', 'ABC'] and
|
|
205
|
-
item.__module__ == module.__name__):
|
|
206
|
-
controller_class = item
|
|
207
|
-
break
|
|
208
|
-
|
|
209
|
-
if not controller_class:
|
|
210
|
-
raise ValueError(
|
|
211
|
-
f"No API class found in {file_path}\n"
|
|
212
|
-
f"Make sure your file exports a class that inherits from API"
|
|
213
|
-
)
|
|
218
|
+
controller_class = load_controller_class(file_path)
|
|
214
219
|
|
|
215
220
|
# Cache the class (not the instance)
|
|
216
221
|
self._cache[file_path] = controller_class
|
{aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/permissions/catalog.py
RENAMED
|
@@ -12,10 +12,14 @@ otherwise silently stop matching in the other, and an access check that never
|
|
|
12
12
|
matches fails open or shut without anyone noticing.
|
|
13
13
|
"""
|
|
14
14
|
|
|
15
|
+
import logging
|
|
15
16
|
import os
|
|
17
|
+
import re
|
|
16
18
|
from typing import Dict, List
|
|
17
19
|
|
|
18
|
-
from ..api.fetcher import Fetcher
|
|
20
|
+
from ..api.fetcher import Fetcher, load_controller_class
|
|
21
|
+
|
|
22
|
+
logger = logging.getLogger(__name__)
|
|
19
23
|
|
|
20
24
|
# Cómo se llama el archivo según el método. `list` y `get` son ambos GET: uno
|
|
21
25
|
# responde la colección, el otro un elemento.
|
|
@@ -46,6 +50,10 @@ def discover(api_root: str, service: str) -> List[Dict[str, str]]:
|
|
|
46
50
|
if extension != ".py" or stem not in FILE_METHODS:
|
|
47
51
|
continue
|
|
48
52
|
|
|
53
|
+
controller = _controller(os.path.join(current, filename))
|
|
54
|
+
if controller and getattr(controller(), "public", False):
|
|
55
|
+
continue
|
|
56
|
+
|
|
49
57
|
relative = os.path.relpath(current, api_root)
|
|
50
58
|
parts = [] if relative == "." else relative.split(os.sep)
|
|
51
59
|
path = "/" + "/".join(parts)
|
|
@@ -62,11 +70,40 @@ def discover(api_root: str, service: str) -> List[Dict[str, str]]:
|
|
|
62
70
|
"method": method,
|
|
63
71
|
"path": path,
|
|
64
72
|
"scope": "item" if stem == "get" else "collection",
|
|
73
|
+
"name": _readable(controller),
|
|
65
74
|
})
|
|
66
75
|
|
|
67
76
|
return sorted(found, key=lambda item: item["code"])
|
|
68
77
|
|
|
69
78
|
|
|
79
|
+
def _controller(file_path: str):
|
|
80
|
+
"""The controller class, or None if it cannot be read.
|
|
81
|
+
|
|
82
|
+
None errs towards listing the endpoint. A permission that appears for a
|
|
83
|
+
public endpoint is noise; one that disappears for a protected endpoint
|
|
84
|
+
leaves the check with nothing to match and locks everybody out of it.
|
|
85
|
+
"""
|
|
86
|
+
try:
|
|
87
|
+
return load_controller_class(file_path)
|
|
88
|
+
except Exception as exc:
|
|
89
|
+
logger.warning("Could not read %s, listing it anyway: %s", file_path, exc)
|
|
90
|
+
return None
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def _readable(controller) -> str:
|
|
94
|
+
"""The class name as words: `UsersInviteAPI` -> `Users Invite`.
|
|
95
|
+
|
|
96
|
+
A panel showing raw paths makes people read routing to answer "what does
|
|
97
|
+
this let someone do". The class already names the thing; this only spaces it
|
|
98
|
+
out. Empty when the class could not be read, so the panel falls back to the
|
|
99
|
+
path rather than inventing a name.
|
|
100
|
+
"""
|
|
101
|
+
if controller is None:
|
|
102
|
+
return ""
|
|
103
|
+
name = re.sub(r"(API|Api)$", "", controller.__name__)
|
|
104
|
+
return re.sub(r"(?<=[a-z0-9])(?=[A-Z])", " ", name).strip()
|
|
105
|
+
|
|
106
|
+
|
|
70
107
|
def service_wildcard(service: str) -> str:
|
|
71
108
|
return f"{service}:*"
|
|
72
109
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/api/auth_middleware.py
RENAMED
|
File without changes
|
{aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/api/auth_validators.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/context/state_validator.py
RENAMED
|
File without changes
|
|
File without changes
|
{aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/database/database_proxy.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/database/mongo_manager.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/invoker/lambda_invoker.py
RENAMED
|
File without changes
|
{aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/lambda_standalone/__init__.py
RENAMED
|
File without changes
|
{aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/lambda_standalone/base.py
RENAMED
|
File without changes
|
{aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/lambda_standalone/fetcher.py
RENAMED
|
File without changes
|
{aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/lambda_standalone/handler.py
RENAMED
|
File without changes
|
{aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/model_index_sync/__init__.py
RENAMED
|
File without changes
|
{aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/model_index_sync/base.py
RENAMED
|
File without changes
|
{aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/model_query/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/permissions/__init__.py
RENAMED
|
File without changes
|
{aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper/repository/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
{aws_python_helper-1.6.0 → aws_python_helper-1.7.0}/aws_python_helper.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|