elody 0.0.204__tar.gz → 0.0.206__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.
- {elody-0.0.204 → elody-0.0.206}/PKG-INFO +1 -1
- {elody-0.0.204 → elody-0.0.206}/pyproject.toml +1 -1
- {elody-0.0.204 → elody-0.0.206}/src/elody/csv.py +7 -0
- {elody-0.0.204 → elody-0.0.206}/src/elody/error_codes.py +1 -0
- {elody-0.0.204 → elody-0.0.206}/src/elody/policies/authorization/filter_generic_objects_policy_v2.py +9 -19
- {elody-0.0.204 → elody-0.0.206}/src/elody/policies/authorization/generic_object_request_policy_v2.py +8 -22
- {elody-0.0.204 → elody-0.0.206}/src/elody/policies/permission_handler.py +11 -14
- {elody-0.0.204 → elody-0.0.206}/src/elody.egg-info/PKG-INFO +1 -1
- {elody-0.0.204 → elody-0.0.206}/LICENSE +0 -0
- {elody-0.0.204 → elody-0.0.206}/README.md +0 -0
- {elody-0.0.204 → elody-0.0.206}/setup.cfg +0 -0
- {elody-0.0.204 → elody-0.0.206}/src/__init__.py +0 -0
- {elody-0.0.204 → elody-0.0.206}/src/elody/__init__.py +0 -0
- {elody-0.0.204 → elody-0.0.206}/src/elody/client.py +0 -0
- {elody-0.0.204 → elody-0.0.206}/src/elody/exceptions.py +0 -0
- {elody-0.0.204 → elody-0.0.206}/src/elody/job.py +0 -0
- {elody-0.0.204 → elody-0.0.206}/src/elody/loader.py +0 -0
- {elody-0.0.204 → elody-0.0.206}/src/elody/migration/__init__.py +0 -0
- {elody-0.0.204 → elody-0.0.206}/src/elody/migration/base_object_migrator.py +0 -0
- {elody-0.0.204 → elody-0.0.206}/src/elody/object_configurations/__init__.py +0 -0
- {elody-0.0.204 → elody-0.0.206}/src/elody/object_configurations/base_object_configuration.py +0 -0
- {elody-0.0.204 → elody-0.0.206}/src/elody/object_configurations/elody_configuration.py +0 -0
- {elody-0.0.204 → elody-0.0.206}/src/elody/object_configurations/job_configuration.py +0 -0
- {elody-0.0.204 → elody-0.0.206}/src/elody/policies/__init__.py +0 -0
- {elody-0.0.204 → elody-0.0.206}/src/elody/policies/authentication/__init__.py +0 -0
- {elody-0.0.204 → elody-0.0.206}/src/elody/policies/authentication/base_user_tenant_validation_policy.py +0 -0
- {elody-0.0.204 → elody-0.0.206}/src/elody/policies/authentication/multi_tenant_policy.py +0 -0
- {elody-0.0.204 → elody-0.0.206}/src/elody/policies/authorization/__init__.py +0 -0
- {elody-0.0.204 → elody-0.0.206}/src/elody/policies/authorization/filter_generic_objects_policy.py +0 -0
- {elody-0.0.204 → elody-0.0.206}/src/elody/policies/authorization/generic_object_detail_policy.py +0 -0
- {elody-0.0.204 → elody-0.0.206}/src/elody/policies/authorization/generic_object_mediafiles_policy.py +0 -0
- {elody-0.0.204 → elody-0.0.206}/src/elody/policies/authorization/generic_object_metadata_policy.py +0 -0
- {elody-0.0.204 → elody-0.0.206}/src/elody/policies/authorization/generic_object_relations_policy.py +0 -0
- {elody-0.0.204 → elody-0.0.206}/src/elody/policies/authorization/generic_object_request_policy.py +0 -0
- {elody-0.0.204 → elody-0.0.206}/src/elody/policies/authorization/mediafile_derivatives_policy.py +0 -0
- {elody-0.0.204 → elody-0.0.206}/src/elody/policies/authorization/mediafile_download_policy.py +0 -0
- {elody-0.0.204 → elody-0.0.206}/src/elody/policies/authorization/multi_tenant_policy.py +0 -0
- {elody-0.0.204 → elody-0.0.206}/src/elody/policies/authorization/tenant_request_policy.py +0 -0
- {elody-0.0.204 → elody-0.0.206}/src/elody/policies/helpers.py +0 -0
- {elody-0.0.204 → elody-0.0.206}/src/elody/schemas.py +0 -0
- {elody-0.0.204 → elody-0.0.206}/src/elody/util.py +0 -0
- {elody-0.0.204 → elody-0.0.206}/src/elody/validator.py +0 -0
- {elody-0.0.204 → elody-0.0.206}/src/elody.egg-info/SOURCES.txt +0 -0
- {elody-0.0.204 → elody-0.0.206}/src/elody.egg-info/dependency_links.txt +0 -0
- {elody-0.0.204 → elody-0.0.206}/src/elody.egg-info/requires.txt +0 -0
- {elody-0.0.204 → elody-0.0.206}/src/elody.egg-info/top_level.txt +0 -0
- {elody-0.0.204 → elody-0.0.206}/src/tests/__init_.py +0 -0
- {elody-0.0.204 → elody-0.0.206}/src/tests/data.py +0 -0
- {elody-0.0.204 → elody-0.0.206}/src/tests/unit/__init__.py +0 -0
- {elody-0.0.204 → elody-0.0.206}/src/tests/unit/test_csv.py +0 -0
- {elody-0.0.204 → elody-0.0.206}/src/tests/unit/test_utils.py +0 -0
|
@@ -274,6 +274,13 @@ class CSVMultiObject(CSVParser):
|
|
|
274
274
|
for key, value in row.items():
|
|
275
275
|
if not value:
|
|
276
276
|
continue
|
|
277
|
+
if not key or isinstance(value, list):
|
|
278
|
+
if len(value) == 1 and value[0] == "":
|
|
279
|
+
continue
|
|
280
|
+
if "invalid_value" not in self.get_errors():
|
|
281
|
+
self.set_error("invalid_value", list())
|
|
282
|
+
message = f'{get_error_code(ErrorCode.INVALID_VALUE, get_write())} | value:{value} | line_number:{row_number} - The value "{value}" is invalid, most likely caused by exceeding allowed columns.'
|
|
283
|
+
self.get_errors()["invalid_value"].append(message)
|
|
277
284
|
original_value = value
|
|
278
285
|
if key != identifying_column:
|
|
279
286
|
value = value.lower()
|
|
@@ -75,6 +75,7 @@ class ErrorCode(Enum):
|
|
|
75
75
|
INVALID_ACCEPT_HEADER = ("5015", [])
|
|
76
76
|
INVALID_VALUE = ("5016", ["value", "options", "line_number"])
|
|
77
77
|
ITEM_WITH_VALUE_FOR_KEY_NOT_FOUND = ("5017", ["key", "value", "line_number"])
|
|
78
|
+
ITEM_WITH_VALUE_FOR_KEY_NOT_UNIQUE = ("5018", ["key", "value", "line_number"])
|
|
78
79
|
|
|
79
80
|
# Filter error codes
|
|
80
81
|
NO_MATCHER_FOR_FILTER_REQUEST = ("6001", [])
|
{elody-0.0.204 → elody-0.0.206}/src/elody/policies/authorization/filter_generic_objects_policy_v2.py
RENAMED
|
@@ -14,6 +14,7 @@ from inuits_policy_based_auth.contexts.policy_context import ( # pyright: ignor
|
|
|
14
14
|
from inuits_policy_based_auth.contexts.user_context import ( # pyright: ignore
|
|
15
15
|
UserContext,
|
|
16
16
|
)
|
|
17
|
+
from werkzeug.exceptions import BadRequest
|
|
17
18
|
|
|
18
19
|
|
|
19
20
|
class FilterGenericObjectsPolicyV2(BaseAuthorizationPolicy):
|
|
@@ -27,11 +28,8 @@ class FilterGenericObjectsPolicyV2(BaseAuthorizationPolicy):
|
|
|
27
28
|
if not isinstance(user_context.access_restrictions.filters, list):
|
|
28
29
|
user_context.access_restrictions.filters = []
|
|
29
30
|
type_filter, filters = self.__split_type_filter(
|
|
30
|
-
|
|
31
|
+
deepcopy(g.get("content") or request.json or [])
|
|
31
32
|
)
|
|
32
|
-
if not type_filter:
|
|
33
|
-
policy_context.access_verdict = True
|
|
34
|
-
return policy_context
|
|
35
33
|
|
|
36
34
|
policy_context.access_verdict = False
|
|
37
35
|
for role in user_context.x_tenant.roles:
|
|
@@ -59,13 +57,15 @@ class FilterGenericObjectsPolicyV2(BaseAuthorizationPolicy):
|
|
|
59
57
|
|
|
60
58
|
return policy_context
|
|
61
59
|
|
|
62
|
-
def __split_type_filter(self,
|
|
60
|
+
def __split_type_filter(self, request_body: list):
|
|
63
61
|
type_filter = None
|
|
64
62
|
for filter in request_body:
|
|
65
63
|
if filter["type"] == "type":
|
|
66
64
|
type_filter = filter
|
|
65
|
+
break
|
|
67
66
|
elif filter["type"] == "selection" and filter["key"] == "type":
|
|
68
67
|
type_filter = filter
|
|
68
|
+
break
|
|
69
69
|
elif item_types := filter.get("item_types"):
|
|
70
70
|
type_filter = {
|
|
71
71
|
"type": "selection",
|
|
@@ -73,22 +73,12 @@ class FilterGenericObjectsPolicyV2(BaseAuthorizationPolicy):
|
|
|
73
73
|
"value": item_types,
|
|
74
74
|
"match_exact": True,
|
|
75
75
|
}
|
|
76
|
+
break
|
|
76
77
|
|
|
77
78
|
if not type_filter:
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
"type": "selection",
|
|
82
|
-
"key": tenant_relation_type,
|
|
83
|
-
"value": [
|
|
84
|
-
user_context.bag.get(
|
|
85
|
-
"tenant_defining_entity_id", user_context.x_tenant.id
|
|
86
|
-
)
|
|
87
|
-
],
|
|
88
|
-
"match_exact": True,
|
|
89
|
-
}
|
|
90
|
-
)
|
|
91
|
-
return None, request_body
|
|
79
|
+
raise BadRequest(
|
|
80
|
+
"Filter with type 'type', or a filter with type 'selection' and 'key' equal to 'type' is required"
|
|
81
|
+
)
|
|
92
82
|
|
|
93
83
|
try:
|
|
94
84
|
request_body.remove(type_filter)
|
{elody-0.0.204 → elody-0.0.206}/src/elody/policies/authorization/generic_object_request_policy_v2.py
RENAMED
|
@@ -18,6 +18,7 @@ from inuits_policy_based_auth.contexts.policy_context import ( # pyright: ignor
|
|
|
18
18
|
from inuits_policy_based_auth.contexts.user_context import ( # pyright: ignore
|
|
19
19
|
UserContext,
|
|
20
20
|
)
|
|
21
|
+
from werkzeug.exceptions import BadRequest
|
|
21
22
|
|
|
22
23
|
|
|
23
24
|
class GenericObjectRequestPolicyV2(BaseAuthorizationPolicy):
|
|
@@ -113,28 +114,13 @@ class GetRequestRules:
|
|
|
113
114
|
)
|
|
114
115
|
filters.insert(0, {"type": "type", "value": type_query_parameter})
|
|
115
116
|
else:
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
)
|
|
124
|
-
if tenant_relation_type := user_context.bag.get("tenant_relation_type"):
|
|
125
|
-
filters.append(
|
|
126
|
-
{
|
|
127
|
-
"type": "selection",
|
|
128
|
-
"key": tenant_relation_type,
|
|
129
|
-
"value": [
|
|
130
|
-
"tenant:super",
|
|
131
|
-
user_context.bag.get(
|
|
132
|
-
"tenant_defining_entity_id", user_context.x_tenant.id
|
|
133
|
-
),
|
|
134
|
-
],
|
|
135
|
-
"match_exact": True,
|
|
136
|
-
}
|
|
137
|
-
)
|
|
117
|
+
"""
|
|
118
|
+
Allowing no type_query_parameter will expose following security risks:
|
|
119
|
+
- object_restrictions not being applied
|
|
120
|
+
- inability to determine collection to execute filters
|
|
121
|
+
=> if no type_query_parameter is a business requirement, override this policy for that specific client and consider the security risks
|
|
122
|
+
"""
|
|
123
|
+
raise BadRequest("Query parameter 'type' is required")
|
|
138
124
|
|
|
139
125
|
user_context.access_restrictions.filters = filters
|
|
140
126
|
user_context.access_restrictions.post_request_hook = (
|
|
@@ -59,7 +59,7 @@ def handle_single_item_request(
|
|
|
59
59
|
key_to_check=None,
|
|
60
60
|
):
|
|
61
61
|
try:
|
|
62
|
-
|
|
62
|
+
item, flat_item, object_lists, restrictions_schema = (
|
|
63
63
|
__prepare_item_for_permission_check(item, permissions, crud)
|
|
64
64
|
)
|
|
65
65
|
|
|
@@ -73,7 +73,7 @@ def handle_single_item_request(
|
|
|
73
73
|
|
|
74
74
|
return __is_allowed_to_crud_item_keys(
|
|
75
75
|
user_context,
|
|
76
|
-
|
|
76
|
+
item,
|
|
77
77
|
flat_item,
|
|
78
78
|
restrictions_schema,
|
|
79
79
|
crud,
|
|
@@ -84,7 +84,7 @@ def handle_single_item_request(
|
|
|
84
84
|
except Exception as exception:
|
|
85
85
|
log.debug(
|
|
86
86
|
f"{exception.__class__.__name__}: {str(exception)}",
|
|
87
|
-
item
|
|
87
|
+
item,
|
|
88
88
|
)
|
|
89
89
|
if crud != "read":
|
|
90
90
|
log.debug(f"Request body: {request_body}", {})
|
|
@@ -97,7 +97,7 @@ def mask_protected_content_post_request_hook(user_context: UserContext, permissi
|
|
|
97
97
|
for item in response["results"]:
|
|
98
98
|
try:
|
|
99
99
|
(
|
|
100
|
-
|
|
100
|
+
item,
|
|
101
101
|
flat_item,
|
|
102
102
|
object_lists,
|
|
103
103
|
restrictions_schema,
|
|
@@ -107,7 +107,7 @@ def mask_protected_content_post_request_hook(user_context: UserContext, permissi
|
|
|
107
107
|
|
|
108
108
|
__is_allowed_to_crud_item_keys(
|
|
109
109
|
user_context,
|
|
110
|
-
|
|
110
|
+
item,
|
|
111
111
|
flat_item,
|
|
112
112
|
restrictions_schema,
|
|
113
113
|
"read",
|
|
@@ -117,7 +117,7 @@ def mask_protected_content_post_request_hook(user_context: UserContext, permissi
|
|
|
117
117
|
except Exception as exception:
|
|
118
118
|
log.debug(
|
|
119
119
|
f"{exception.__class__.__name__}: {str(exception)}",
|
|
120
|
-
item
|
|
120
|
+
item,
|
|
121
121
|
)
|
|
122
122
|
raise exception
|
|
123
123
|
|
|
@@ -128,7 +128,6 @@ def mask_protected_content_post_request_hook(user_context: UserContext, permissi
|
|
|
128
128
|
|
|
129
129
|
|
|
130
130
|
def __prepare_item_for_permission_check(item, permissions, crud):
|
|
131
|
-
item = deepcopy(item.get("storage_format", item))
|
|
132
131
|
if item.get("type", "") not in permissions[crud].keys():
|
|
133
132
|
return item, None, None, None
|
|
134
133
|
|
|
@@ -175,7 +174,7 @@ def __is_allowed_to_crud_item(
|
|
|
175
174
|
|
|
176
175
|
def __is_allowed_to_crud_item_keys(
|
|
177
176
|
user_context: UserContext,
|
|
178
|
-
|
|
177
|
+
item,
|
|
179
178
|
flat_item,
|
|
180
179
|
restrictions_schema,
|
|
181
180
|
crud,
|
|
@@ -207,19 +206,17 @@ def __is_allowed_to_crud_item_keys(
|
|
|
207
206
|
for info in keys_info:
|
|
208
207
|
if info["object_list"]:
|
|
209
208
|
element = __get_element_from_object_list_of_item(
|
|
210
|
-
|
|
209
|
+
item,
|
|
211
210
|
info["key"],
|
|
212
211
|
info["object_key"],
|
|
213
212
|
object_lists,
|
|
214
213
|
)
|
|
215
214
|
if element:
|
|
216
|
-
|
|
215
|
+
item[info["key"]].remove(element)
|
|
217
216
|
break
|
|
218
217
|
else:
|
|
219
218
|
try:
|
|
220
|
-
del
|
|
221
|
-
keys_info[1]["key"]
|
|
222
|
-
]
|
|
219
|
+
del item[keys_info[0]["key"]][keys_info[1]["key"]]
|
|
223
220
|
except KeyError:
|
|
224
221
|
pass
|
|
225
222
|
if key_to_check and key_to_check == restricted_key:
|
|
@@ -228,7 +225,7 @@ def __is_allowed_to_crud_item_keys(
|
|
|
228
225
|
if flat_request_body.get(restricted_key):
|
|
229
226
|
user_context.bag["restricted_keys"].append(restricted_key)
|
|
230
227
|
|
|
231
|
-
user_context.bag["requested_item"] =
|
|
228
|
+
user_context.bag["requested_item"] = item
|
|
232
229
|
return len(user_context.bag["restricted_keys"]) == 0
|
|
233
230
|
|
|
234
231
|
|
|
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
|
{elody-0.0.204 → elody-0.0.206}/src/elody/object_configurations/base_object_configuration.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
|
{elody-0.0.204 → elody-0.0.206}/src/elody/policies/authorization/filter_generic_objects_policy.py
RENAMED
|
File without changes
|
{elody-0.0.204 → elody-0.0.206}/src/elody/policies/authorization/generic_object_detail_policy.py
RENAMED
|
File without changes
|
{elody-0.0.204 → elody-0.0.206}/src/elody/policies/authorization/generic_object_mediafiles_policy.py
RENAMED
|
File without changes
|
{elody-0.0.204 → elody-0.0.206}/src/elody/policies/authorization/generic_object_metadata_policy.py
RENAMED
|
File without changes
|
{elody-0.0.204 → elody-0.0.206}/src/elody/policies/authorization/generic_object_relations_policy.py
RENAMED
|
File without changes
|
{elody-0.0.204 → elody-0.0.206}/src/elody/policies/authorization/generic_object_request_policy.py
RENAMED
|
File without changes
|
{elody-0.0.204 → elody-0.0.206}/src/elody/policies/authorization/mediafile_derivatives_policy.py
RENAMED
|
File without changes
|
{elody-0.0.204 → elody-0.0.206}/src/elody/policies/authorization/mediafile_download_policy.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
|
|
File without changes
|
|
File without changes
|