elody 0.0.195__py3-none-any.whl → 0.0.196__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.
@@ -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 get_content
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
@@ -4,6 +4,24 @@ from serialization.serialize import serialize # pyright: ignore
4
4
  from werkzeug.exceptions import NotFound
5
5
 
6
6
 
7
+ def generate_filter_key_and_lookup_from_restricted_key(key):
8
+ if (keys := key.split("@", 1)) and len(keys) == 1:
9
+ return key, {}
10
+
11
+ local_field = keys[0]
12
+ document_type, key = keys[1].split("-", 1)
13
+ collection = (
14
+ get_object_configuration_mapper().get(document_type).crud()["collection"]
15
+ )
16
+ lookup = {
17
+ "from": collection,
18
+ "local_field": local_field,
19
+ "foreign_field": "identifiers",
20
+ "as": f"__lookup.virtual_relations.{document_type}",
21
+ }
22
+ return f"{lookup['as']}.{key}", lookup
23
+
24
+
7
25
  def get_content(item, request, content):
8
26
  return serialize(
9
27
  content,
@@ -3,9 +3,11 @@ import re as regex
3
3
  from configuration import get_object_configuration_mapper # pyright: ignore
4
4
  from copy import deepcopy
5
5
  from elody.error_codes import ErrorCode, get_error_code, get_read
6
+ from elody.policies.helpers import get_item
6
7
  from elody.util import flatten_dict, interpret_flat_key
7
8
  from inuits_policy_based_auth.contexts.user_context import UserContext
8
9
  from logging_elody.log import log # pyright: ignore
10
+ from storage.storagemanager import StorageManager # pyright: ignore
9
11
 
10
12
 
11
13
  _permissions = {}
@@ -63,7 +65,7 @@ def handle_single_item_request(
63
65
  )
64
66
 
65
67
  is_allowed_to_crud_item = (
66
- __is_allowed_to_crud_item(flat_item, restrictions_schema)
68
+ __is_allowed_to_crud_item(flat_item, restrictions_schema, user_context)
67
69
  if flat_item
68
70
  else None
69
71
  )
@@ -131,10 +133,7 @@ def __prepare_item_for_permission_check(item, permissions, crud):
131
133
  if item.get("type", "") not in permissions[crud].keys():
132
134
  return item, None, None, None
133
135
 
134
- config = get_object_configuration_mapper().get(item["type"])
135
- object_lists = config.document_info().get("object_lists", {})
136
- flat_item = flatten_dict(object_lists, item)
137
-
136
+ flat_item, object_lists = __get_flat_item_and_object_lists(item)
138
137
  return (
139
138
  item,
140
139
  flat_item,
@@ -159,13 +158,15 @@ def __get_restrictions_schema(flat_item, permissions, crud):
159
158
  return schemas[schema] if schemas and schema else {}
160
159
 
161
160
 
162
- def __is_allowed_to_crud_item(flat_item, restrictions_schema):
161
+ def __is_allowed_to_crud_item(
162
+ flat_item, restrictions_schema, user_context: UserContext
163
+ ):
163
164
  restrictions = restrictions_schema.get("object_restrictions", {})
164
165
 
165
166
  for restricted_key, restricting_values in restrictions.items():
166
167
  restricted_key = restricted_key.split(":")[1]
167
168
  item_value_in_restricting_values = __item_value_in_values(
168
- flat_item, restricted_key, restricting_values
169
+ flat_item, restricted_key, restricting_values, {}, user_context
169
170
  )
170
171
  if not item_value_in_restricting_values:
171
172
  return None
@@ -192,7 +193,11 @@ def __is_allowed_to_crud_item_keys(
192
193
  condition_match = True
193
194
  for condition_key, condition_values in restricting_conditions.items():
194
195
  condition_match = __item_value_in_values(
195
- flat_item, condition_key, condition_values, flat_request_body
196
+ flat_item,
197
+ condition_key,
198
+ condition_values,
199
+ flat_request_body,
200
+ user_context,
196
201
  )
197
202
  if not condition_match:
198
203
  break
@@ -228,7 +233,9 @@ def __is_allowed_to_crud_item_keys(
228
233
  return len(user_context.bag["restricted_keys"]) == 0
229
234
 
230
235
 
231
- def __item_value_in_values(flat_item, key, values: list, flat_request_body: dict = {}):
236
+ def __item_value_in_values(
237
+ flat_item, key, values: list, flat_request_body, user_context: UserContext
238
+ ):
232
239
  negate_condition = False
233
240
  is_optional = False
234
241
 
@@ -239,6 +246,10 @@ def __item_value_in_values(flat_item, key, values: list, flat_request_body: dict
239
246
  key = key[1:]
240
247
  is_optional = True
241
248
 
249
+ key_of_relation = None
250
+ if (keys := key.split("@", 1)) and len(keys) == 2:
251
+ key = keys[0]
252
+ key_of_relation = keys[1].split("-", 1)[1]
242
253
  try:
243
254
  item_value = flat_request_body.get(key, flat_item[key])
244
255
  if is_optional:
@@ -249,6 +260,15 @@ def __item_value_in_values(flat_item, key, values: list, flat_request_body: dict
249
260
  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
261
  )
251
262
  return not negate_condition
263
+ else:
264
+ if key_of_relation:
265
+ if isinstance(item_value, list):
266
+ item_value = item_value[0]
267
+ item = get_item(StorageManager(), user_context.bag, {"id": item_value})
268
+ flat_item, _ = __get_flat_item_and_object_lists(item)
269
+ return __item_value_in_values(
270
+ flat_item, key_of_relation, values, flat_request_body, user_context
271
+ )
252
272
 
253
273
  expected_values = []
254
274
  for value in values:
@@ -280,3 +300,9 @@ def __get_element_from_object_list_of_item(
280
300
  if element[object_lists[object_list]] == key:
281
301
  return element
282
302
  return {}
303
+
304
+
305
+ def __get_flat_item_and_object_lists(item):
306
+ config = get_object_configuration_mapper().get(item["type"])
307
+ object_lists = config.document_info().get("object_lists", {})
308
+ return flatten_dict(object_lists, item), object_lists
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: elody
3
- Version: 0.0.195
3
+ Version: 0.0.196
4
4
  Summary: elody SDK for Python
5
5
  Author-email: Inuits <developers@inuits.eu>
6
6
  License: GNU GENERAL PUBLIC LICENSE
@@ -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=FFpCRNITO-Y9yzTBJEV70FeFwx6xTG93ddYHL5QAl10,1215
20
- elody/policies/permission_handler.py,sha256=C5wwgAplxmrkrseA-oNjX_Ff1PfVGP5NIvpx0F5PYho,9869
19
+ elody/policies/helpers.py,sha256=I0ctnQ0ilcbzlIfDTcgzGzAWVrrH0GoLZsB1d6sAf6I,1766
20
+ elody/policies/permission_handler.py,sha256=a9kiHRINdQpkmDgrcLYZl4FplkpsURO42FMZ3Vzmdv4,10843
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=RrGFARQJnIQUvUSN8i9PvhNxzEVpNInkLGf5mK1Ch0Y,6474
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=zaoCdV7KVAcMYNNXHYTi8Vtjkw_E8_w8aMqxJ62QqBE,5099
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.195.dist-info/licenses/LICENSE,sha256=gXf5dRMhNSbfLPYYTY_5hsZ1r7UU1OaKQEAQUhuIBkM,18092
37
+ elody-0.0.196.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.195.dist-info/METADATA,sha256=ryafZPjxZIEOt-tgv23aB6yqYkXrP1MtBztr4AxsrVI,23358
44
- elody-0.0.195.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
45
- elody-0.0.195.dist-info/top_level.txt,sha256=E0mImupLj0KmtUUCXRYEoLDRaSkuiGaOIIseAa0oQ-M,21
46
- elody-0.0.195.dist-info/RECORD,,
43
+ elody-0.0.196.dist-info/METADATA,sha256=1m1zQRz7y_tJ05tOOMfPCD69nzUNSFdW6ADucbpHITs,23358
44
+ elody-0.0.196.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
45
+ elody-0.0.196.dist-info/top_level.txt,sha256=E0mImupLj0KmtUUCXRYEoLDRaSkuiGaOIIseAa0oQ-M,21
46
+ elody-0.0.196.dist-info/RECORD,,