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.
@@ -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
@@ -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
- 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
-
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(flat_item, restrictions_schema):
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, condition_key, condition_values, flat_request_body
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(flat_item, key, values: list, flat_request_body: dict = {}):
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:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: elody
3
- Version: 0.0.195
3
+ Version: 0.0.197
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=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=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.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.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.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,,