elody 0.0.195__py3-none-any.whl → 0.0.197__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.
- elody/policies/authorization/filter_generic_objects_policy_v2.py +8 -0
- elody/policies/authorization/generic_object_request_policy_v2.py +12 -3
- elody/policies/helpers.py +25 -0
- elody/policies/permission_handler.py +29 -10
- {elody-0.0.195.dist-info → elody-0.0.197.dist-info}/METADATA +1 -1
- {elody-0.0.195.dist-info → elody-0.0.197.dist-info}/RECORD +9 -9
- {elody-0.0.195.dist-info → elody-0.0.197.dist-info}/WHEEL +0 -0
- {elody-0.0.195.dist-info → elody-0.0.197.dist-info}/licenses/LICENSE +0 -0
- {elody-0.0.195.dist-info → elody-0.0.197.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import re as regex
|
|
2
2
|
|
|
3
3
|
from copy import deepcopy
|
|
4
|
+
from elody.policies.helpers import generate_filter_key_and_lookup_from_restricted_key
|
|
4
5
|
from elody.policies.permission_handler import (
|
|
5
6
|
get_permissions,
|
|
6
7
|
mask_protected_content_post_request_hook,
|
|
@@ -123,6 +124,11 @@ class PostRequestRules:
|
|
|
123
124
|
restrictions = schemas[schema].get("object_restrictions", {})
|
|
124
125
|
for restricted_key, restricting_value in restrictions.items():
|
|
125
126
|
index, restricted_key = restricted_key.split(":")
|
|
127
|
+
restricted_key, lookup = (
|
|
128
|
+
generate_filter_key_and_lookup_from_restricted_key(
|
|
129
|
+
restricted_key
|
|
130
|
+
)
|
|
131
|
+
)
|
|
126
132
|
key = f"{schema}|{restricted_key}"
|
|
127
133
|
if group := restrictions_grouped_by_index.get(index):
|
|
128
134
|
group["key"].append(key)
|
|
@@ -130,6 +136,7 @@ class PostRequestRules:
|
|
|
130
136
|
restrictions_grouped_by_index.update(
|
|
131
137
|
{
|
|
132
138
|
index: {
|
|
139
|
+
"lookup": lookup,
|
|
133
140
|
"key": [key],
|
|
134
141
|
"value": restricting_value,
|
|
135
142
|
}
|
|
@@ -155,6 +162,7 @@ class PostRequestRules:
|
|
|
155
162
|
for restriction in restrictions_grouped_by_index.values():
|
|
156
163
|
user_context.access_restrictions.filters.append( # pyright: ignore
|
|
157
164
|
{
|
|
165
|
+
"lookup": restriction["lookup"],
|
|
158
166
|
"type": "selection",
|
|
159
167
|
"key": restriction["key"],
|
|
160
168
|
"value": restriction["value"],
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import re as regex
|
|
2
2
|
|
|
3
3
|
from configuration import get_object_configuration_mapper # pyright: ignore
|
|
4
|
-
from elody.policies.helpers import
|
|
4
|
+
from elody.policies.helpers import (
|
|
5
|
+
generate_filter_key_and_lookup_from_restricted_key,
|
|
6
|
+
get_content,
|
|
7
|
+
)
|
|
5
8
|
from elody.policies.permission_handler import (
|
|
6
9
|
get_permissions,
|
|
7
10
|
handle_single_item_request,
|
|
@@ -82,7 +85,7 @@ class GetRequestRules:
|
|
|
82
85
|
type_permissions[schemas[0]].get("object_restrictions", {}).keys()
|
|
83
86
|
)
|
|
84
87
|
for i in range(number_of_object_restrictions):
|
|
85
|
-
keys, values = [], []
|
|
88
|
+
lookup, keys, values = {}, [], []
|
|
86
89
|
for schema in schemas:
|
|
87
90
|
object_restrictions = type_permissions[schema].get(
|
|
88
91
|
"object_restrictions", {}
|
|
@@ -92,10 +95,16 @@ class GetRequestRules:
|
|
|
92
95
|
for key in object_restrictions.keys()
|
|
93
96
|
if key.startswith(f"{i}:")
|
|
94
97
|
][0]
|
|
95
|
-
keys.append(f"{schema}|{key.split(':')[1]}")
|
|
96
98
|
values = object_restrictions[key]
|
|
99
|
+
key, lookup = (
|
|
100
|
+
generate_filter_key_and_lookup_from_restricted_key(
|
|
101
|
+
key.split(":")[1]
|
|
102
|
+
)
|
|
103
|
+
)
|
|
104
|
+
keys.append(f"{schema}|{key}")
|
|
97
105
|
filters.append(
|
|
98
106
|
{
|
|
107
|
+
"lookup": lookup,
|
|
99
108
|
"type": "selection",
|
|
100
109
|
"key": keys,
|
|
101
110
|
"value": values,
|
elody/policies/helpers.py
CHANGED
|
@@ -1,9 +1,28 @@
|
|
|
1
1
|
from configuration import get_object_configuration_mapper # pyright: ignore
|
|
2
2
|
from elody.error_codes import ErrorCode, get_error_code, get_read
|
|
3
|
+
from elody.util import flatten_dict
|
|
3
4
|
from serialization.serialize import serialize # pyright: ignore
|
|
4
5
|
from werkzeug.exceptions import NotFound
|
|
5
6
|
|
|
6
7
|
|
|
8
|
+
def generate_filter_key_and_lookup_from_restricted_key(key):
|
|
9
|
+
if (keys := key.split("@", 1)) and len(keys) == 1:
|
|
10
|
+
return key, {}
|
|
11
|
+
|
|
12
|
+
local_field = keys[0]
|
|
13
|
+
document_type, key = keys[1].split("-", 1)
|
|
14
|
+
collection = (
|
|
15
|
+
get_object_configuration_mapper().get(document_type).crud()["collection"]
|
|
16
|
+
)
|
|
17
|
+
lookup = {
|
|
18
|
+
"from": collection,
|
|
19
|
+
"local_field": local_field,
|
|
20
|
+
"foreign_field": "identifiers",
|
|
21
|
+
"as": f"__lookup.virtual_relations.{document_type}",
|
|
22
|
+
}
|
|
23
|
+
return f"{lookup['as']}.{key}", lookup
|
|
24
|
+
|
|
25
|
+
|
|
7
26
|
def get_content(item, request, content):
|
|
8
27
|
return serialize(
|
|
9
28
|
content,
|
|
@@ -15,6 +34,12 @@ def get_content(item, request, content):
|
|
|
15
34
|
)
|
|
16
35
|
|
|
17
36
|
|
|
37
|
+
def get_flat_item_and_object_lists(item):
|
|
38
|
+
config = get_object_configuration_mapper().get(item["type"])
|
|
39
|
+
object_lists = config.document_info().get("object_lists", {})
|
|
40
|
+
return flatten_dict(object_lists, item), object_lists
|
|
41
|
+
|
|
42
|
+
|
|
18
43
|
def get_item(storage_manager, user_context_bag, view_args) -> dict:
|
|
19
44
|
view_args = view_args or {}
|
|
20
45
|
if id := view_args.get("id"):
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import re as regex
|
|
2
2
|
|
|
3
|
-
from configuration import get_object_configuration_mapper # pyright: ignore
|
|
4
3
|
from copy import deepcopy
|
|
5
4
|
from elody.error_codes import ErrorCode, get_error_code, get_read
|
|
5
|
+
from elody.policies.helpers import get_flat_item_and_object_lists, get_item
|
|
6
6
|
from elody.util import flatten_dict, interpret_flat_key
|
|
7
7
|
from inuits_policy_based_auth.contexts.user_context import UserContext
|
|
8
8
|
from logging_elody.log import log # pyright: ignore
|
|
9
|
+
from storage.storagemanager import StorageManager # pyright: ignore
|
|
9
10
|
|
|
10
11
|
|
|
11
12
|
_permissions = {}
|
|
@@ -63,7 +64,7 @@ def handle_single_item_request(
|
|
|
63
64
|
)
|
|
64
65
|
|
|
65
66
|
is_allowed_to_crud_item = (
|
|
66
|
-
__is_allowed_to_crud_item(flat_item, restrictions_schema)
|
|
67
|
+
__is_allowed_to_crud_item(flat_item, restrictions_schema, user_context)
|
|
67
68
|
if flat_item
|
|
68
69
|
else None
|
|
69
70
|
)
|
|
@@ -131,10 +132,7 @@ def __prepare_item_for_permission_check(item, permissions, crud):
|
|
|
131
132
|
if item.get("type", "") not in permissions[crud].keys():
|
|
132
133
|
return item, None, None, None
|
|
133
134
|
|
|
134
|
-
|
|
135
|
-
object_lists = config.document_info().get("object_lists", {})
|
|
136
|
-
flat_item = flatten_dict(object_lists, item)
|
|
137
|
-
|
|
135
|
+
flat_item, object_lists = get_flat_item_and_object_lists(item)
|
|
138
136
|
return (
|
|
139
137
|
item,
|
|
140
138
|
flat_item,
|
|
@@ -159,13 +157,15 @@ def __get_restrictions_schema(flat_item, permissions, crud):
|
|
|
159
157
|
return schemas[schema] if schemas and schema else {}
|
|
160
158
|
|
|
161
159
|
|
|
162
|
-
def __is_allowed_to_crud_item(
|
|
160
|
+
def __is_allowed_to_crud_item(
|
|
161
|
+
flat_item, restrictions_schema, user_context: UserContext
|
|
162
|
+
):
|
|
163
163
|
restrictions = restrictions_schema.get("object_restrictions", {})
|
|
164
164
|
|
|
165
165
|
for restricted_key, restricting_values in restrictions.items():
|
|
166
166
|
restricted_key = restricted_key.split(":")[1]
|
|
167
167
|
item_value_in_restricting_values = __item_value_in_values(
|
|
168
|
-
flat_item, restricted_key, restricting_values
|
|
168
|
+
flat_item, restricted_key, restricting_values, {}, user_context
|
|
169
169
|
)
|
|
170
170
|
if not item_value_in_restricting_values:
|
|
171
171
|
return None
|
|
@@ -192,7 +192,11 @@ def __is_allowed_to_crud_item_keys(
|
|
|
192
192
|
condition_match = True
|
|
193
193
|
for condition_key, condition_values in restricting_conditions.items():
|
|
194
194
|
condition_match = __item_value_in_values(
|
|
195
|
-
flat_item,
|
|
195
|
+
flat_item,
|
|
196
|
+
condition_key,
|
|
197
|
+
condition_values,
|
|
198
|
+
flat_request_body,
|
|
199
|
+
user_context,
|
|
196
200
|
)
|
|
197
201
|
if not condition_match:
|
|
198
202
|
break
|
|
@@ -228,7 +232,9 @@ def __is_allowed_to_crud_item_keys(
|
|
|
228
232
|
return len(user_context.bag["restricted_keys"]) == 0
|
|
229
233
|
|
|
230
234
|
|
|
231
|
-
def __item_value_in_values(
|
|
235
|
+
def __item_value_in_values(
|
|
236
|
+
flat_item, key, values: list, flat_request_body, user_context: UserContext
|
|
237
|
+
):
|
|
232
238
|
negate_condition = False
|
|
233
239
|
is_optional = False
|
|
234
240
|
|
|
@@ -239,6 +245,10 @@ def __item_value_in_values(flat_item, key, values: list, flat_request_body: dict
|
|
|
239
245
|
key = key[1:]
|
|
240
246
|
is_optional = True
|
|
241
247
|
|
|
248
|
+
key_of_relation = None
|
|
249
|
+
if (keys := key.split("@", 1)) and len(keys) == 2:
|
|
250
|
+
key = keys[0]
|
|
251
|
+
key_of_relation = keys[1].split("-", 1)[1]
|
|
242
252
|
try:
|
|
243
253
|
item_value = flat_request_body.get(key, flat_item[key])
|
|
244
254
|
if is_optional:
|
|
@@ -249,6 +259,15 @@ def __item_value_in_values(flat_item, key, values: list, flat_request_body: dict
|
|
|
249
259
|
f"{get_error_code(ErrorCode.METADATA_KEY_UNDEFINED, get_read())} | key:{key} | document:{flat_item.get('_id', flat_item["type"])} - Key {key} not found in document {flat_item.get('_id', flat_item["type"])}. Either prefix the key with '?' in your permission configuration to make it an optional restriction, or patch the document to include the key. '?' will allow access if key does not exist, '!?' will deny access if key does not exist."
|
|
250
260
|
)
|
|
251
261
|
return not negate_condition
|
|
262
|
+
else:
|
|
263
|
+
if key_of_relation:
|
|
264
|
+
if isinstance(item_value, list):
|
|
265
|
+
item_value = item_value[0]
|
|
266
|
+
item = get_item(StorageManager(), user_context.bag, {"id": item_value})
|
|
267
|
+
flat_item, _ = get_flat_item_and_object_lists(item)
|
|
268
|
+
return __item_value_in_values(
|
|
269
|
+
flat_item, key_of_relation, values, flat_request_body, user_context
|
|
270
|
+
)
|
|
252
271
|
|
|
253
272
|
expected_values = []
|
|
254
273
|
for value in values:
|
|
@@ -16,31 +16,31 @@ elody/object_configurations/base_object_configuration.py,sha256=8wyUq_zqRkGb4Mp1
|
|
|
16
16
|
elody/object_configurations/elody_configuration.py,sha256=H3iqNXPhYX6scR7C57L_hCWQH2MnWKwnH3vegLg-UGw,7645
|
|
17
17
|
elody/object_configurations/job_configuration.py,sha256=HMDxaRUyfqhIy0q3yQDDMH9uW5iCd7VCmqknQofXNt0,2039
|
|
18
18
|
elody/policies/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
19
|
-
elody/policies/helpers.py,sha256=
|
|
20
|
-
elody/policies/permission_handler.py,sha256=
|
|
19
|
+
elody/policies/helpers.py,sha256=LTV_Hmg8AN64e6t4glpKhZMsRNYCLN8FC-KQ0-7EmR8,2035
|
|
20
|
+
elody/policies/permission_handler.py,sha256=dWNGzcfGoJrJjMS80-7egXzHFNaLr0UBrzXB6jwyktg,10559
|
|
21
21
|
elody/policies/authentication/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
22
22
|
elody/policies/authentication/base_user_tenant_validation_policy.py,sha256=yyGiYy-MM63itQYwUc99FPeXt6TBW5B95FeLMfjMEok,5368
|
|
23
23
|
elody/policies/authentication/multi_tenant_policy.py,sha256=g4ZYUQMmCjgLg09wj0-0lGKsJsRt7h4ppI25o1VdZHw,4039
|
|
24
24
|
elody/policies/authorization/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
25
25
|
elody/policies/authorization/filter_generic_objects_policy.py,sha256=mF32moh8hRetBgG8vQW-rz4xjoRQD2yOxdI740SFSUo,6522
|
|
26
|
-
elody/policies/authorization/filter_generic_objects_policy_v2.py,sha256=
|
|
26
|
+
elody/policies/authorization/filter_generic_objects_policy_v2.py,sha256=_imNTxEa21DOxfn3KwCBsEIUUVkx-IAn25rpZd5gG58,6885
|
|
27
27
|
elody/policies/authorization/generic_object_detail_policy.py,sha256=y6g1i3vdKMKY4xS4H2m0e1DRztrivMEomx6NkDqA0Pk,3672
|
|
28
28
|
elody/policies/authorization/generic_object_mediafiles_policy.py,sha256=1-DMsV-FDkcrQCE4KL-SGlVHjTZSMPwYq1bWln2nXE4,2887
|
|
29
29
|
elody/policies/authorization/generic_object_metadata_policy.py,sha256=xwtOVYmiCKgf75CydfWnV7DLI9X1yVfXPQ4-Ux0Htqk,2787
|
|
30
30
|
elody/policies/authorization/generic_object_relations_policy.py,sha256=hRLeA5gXB44ufiVVaxWtAuwnXBRY1U4bLWgIadzKtmw,3712
|
|
31
31
|
elody/policies/authorization/generic_object_request_policy.py,sha256=kuLczjnK5omMF2Gw5ViY_Z9MNPx_w6bNwexiMzvLiUU,4867
|
|
32
|
-
elody/policies/authorization/generic_object_request_policy_v2.py,sha256=
|
|
32
|
+
elody/policies/authorization/generic_object_request_policy_v2.py,sha256=bD7X9zFt0AysbyVljOcvbdmbJNRQsMZRGfqs3jjHuxY,5434
|
|
33
33
|
elody/policies/authorization/mediafile_derivatives_policy.py,sha256=OwNpbS8i7-LzcQDPddMWTrXk_Y4wqZxrB12Lw1dhkr0,2671
|
|
34
34
|
elody/policies/authorization/mediafile_download_policy.py,sha256=XMsKavBucmTh4W1kWOzpFWxJ_ZXgHVK1RS7JB4HjtQo,1979
|
|
35
35
|
elody/policies/authorization/multi_tenant_policy.py,sha256=SA9H7SBjzuh8mY3gYN7pDG8TV7hdI3GEUtNeiZeNL3M,3164
|
|
36
36
|
elody/policies/authorization/tenant_request_policy.py,sha256=dEgblwRAqwWVcE-O7Jn8hVL3OnwDlQhDEOcPlcElBrk,1185
|
|
37
|
-
elody-0.0.
|
|
37
|
+
elody-0.0.197.dist-info/licenses/LICENSE,sha256=gXf5dRMhNSbfLPYYTY_5hsZ1r7UU1OaKQEAQUhuIBkM,18092
|
|
38
38
|
tests/__init_.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
39
39
|
tests/data.py,sha256=Q3oxduf-E3m-Z5G_p3fcs8jVy6g10I7zXKL1m94UVMI,2906
|
|
40
40
|
tests/unit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
41
41
|
tests/unit/test_csv.py,sha256=NQaOhehfQ4GuXku0Y1SA8DYjJeqqidbF50zEHAi8RZA,15923
|
|
42
42
|
tests/unit/test_utils.py,sha256=g63szcEZyHhCOtrW4BnNbcgVca3oYPIOLjBdIzNwwN0,8784
|
|
43
|
-
elody-0.0.
|
|
44
|
-
elody-0.0.
|
|
45
|
-
elody-0.0.
|
|
46
|
-
elody-0.0.
|
|
43
|
+
elody-0.0.197.dist-info/METADATA,sha256=L8aD51TwE-M6C-b8YfpJVljODpuCw5rN0HIsQKEnjVA,23358
|
|
44
|
+
elody-0.0.197.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
45
|
+
elody-0.0.197.dist-info/top_level.txt,sha256=E0mImupLj0KmtUUCXRYEoLDRaSkuiGaOIIseAa0oQ-M,21
|
|
46
|
+
elody-0.0.197.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|