elody 0.0.205__tar.gz → 0.0.207__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.
Files changed (51) hide show
  1. {elody-0.0.205 → elody-0.0.207}/PKG-INFO +1 -1
  2. {elody-0.0.205 → elody-0.0.207}/pyproject.toml +1 -1
  3. {elody-0.0.205 → elody-0.0.207}/src/elody/csv.py +1 -1
  4. {elody-0.0.205 → elody-0.0.207}/src/elody/object_configurations/elody_configuration.py +8 -1
  5. {elody-0.0.205 → elody-0.0.207}/src/elody/policies/authorization/filter_generic_objects_policy_v2.py +9 -19
  6. {elody-0.0.205 → elody-0.0.207}/src/elody/policies/authorization/generic_object_request_policy_v2.py +8 -22
  7. {elody-0.0.205 → elody-0.0.207}/src/elody/policies/permission_handler.py +11 -14
  8. {elody-0.0.205 → elody-0.0.207}/src/elody.egg-info/PKG-INFO +1 -1
  9. {elody-0.0.205 → elody-0.0.207}/LICENSE +0 -0
  10. {elody-0.0.205 → elody-0.0.207}/README.md +0 -0
  11. {elody-0.0.205 → elody-0.0.207}/setup.cfg +0 -0
  12. {elody-0.0.205 → elody-0.0.207}/src/__init__.py +0 -0
  13. {elody-0.0.205 → elody-0.0.207}/src/elody/__init__.py +0 -0
  14. {elody-0.0.205 → elody-0.0.207}/src/elody/client.py +0 -0
  15. {elody-0.0.205 → elody-0.0.207}/src/elody/error_codes.py +0 -0
  16. {elody-0.0.205 → elody-0.0.207}/src/elody/exceptions.py +0 -0
  17. {elody-0.0.205 → elody-0.0.207}/src/elody/job.py +0 -0
  18. {elody-0.0.205 → elody-0.0.207}/src/elody/loader.py +0 -0
  19. {elody-0.0.205 → elody-0.0.207}/src/elody/migration/__init__.py +0 -0
  20. {elody-0.0.205 → elody-0.0.207}/src/elody/migration/base_object_migrator.py +0 -0
  21. {elody-0.0.205 → elody-0.0.207}/src/elody/object_configurations/__init__.py +0 -0
  22. {elody-0.0.205 → elody-0.0.207}/src/elody/object_configurations/base_object_configuration.py +0 -0
  23. {elody-0.0.205 → elody-0.0.207}/src/elody/object_configurations/job_configuration.py +0 -0
  24. {elody-0.0.205 → elody-0.0.207}/src/elody/policies/__init__.py +0 -0
  25. {elody-0.0.205 → elody-0.0.207}/src/elody/policies/authentication/__init__.py +0 -0
  26. {elody-0.0.205 → elody-0.0.207}/src/elody/policies/authentication/base_user_tenant_validation_policy.py +0 -0
  27. {elody-0.0.205 → elody-0.0.207}/src/elody/policies/authentication/multi_tenant_policy.py +0 -0
  28. {elody-0.0.205 → elody-0.0.207}/src/elody/policies/authorization/__init__.py +0 -0
  29. {elody-0.0.205 → elody-0.0.207}/src/elody/policies/authorization/filter_generic_objects_policy.py +0 -0
  30. {elody-0.0.205 → elody-0.0.207}/src/elody/policies/authorization/generic_object_detail_policy.py +0 -0
  31. {elody-0.0.205 → elody-0.0.207}/src/elody/policies/authorization/generic_object_mediafiles_policy.py +0 -0
  32. {elody-0.0.205 → elody-0.0.207}/src/elody/policies/authorization/generic_object_metadata_policy.py +0 -0
  33. {elody-0.0.205 → elody-0.0.207}/src/elody/policies/authorization/generic_object_relations_policy.py +0 -0
  34. {elody-0.0.205 → elody-0.0.207}/src/elody/policies/authorization/generic_object_request_policy.py +0 -0
  35. {elody-0.0.205 → elody-0.0.207}/src/elody/policies/authorization/mediafile_derivatives_policy.py +0 -0
  36. {elody-0.0.205 → elody-0.0.207}/src/elody/policies/authorization/mediafile_download_policy.py +0 -0
  37. {elody-0.0.205 → elody-0.0.207}/src/elody/policies/authorization/multi_tenant_policy.py +0 -0
  38. {elody-0.0.205 → elody-0.0.207}/src/elody/policies/authorization/tenant_request_policy.py +0 -0
  39. {elody-0.0.205 → elody-0.0.207}/src/elody/policies/helpers.py +0 -0
  40. {elody-0.0.205 → elody-0.0.207}/src/elody/schemas.py +0 -0
  41. {elody-0.0.205 → elody-0.0.207}/src/elody/util.py +0 -0
  42. {elody-0.0.205 → elody-0.0.207}/src/elody/validator.py +0 -0
  43. {elody-0.0.205 → elody-0.0.207}/src/elody.egg-info/SOURCES.txt +0 -0
  44. {elody-0.0.205 → elody-0.0.207}/src/elody.egg-info/dependency_links.txt +0 -0
  45. {elody-0.0.205 → elody-0.0.207}/src/elody.egg-info/requires.txt +0 -0
  46. {elody-0.0.205 → elody-0.0.207}/src/elody.egg-info/top_level.txt +0 -0
  47. {elody-0.0.205 → elody-0.0.207}/src/tests/__init_.py +0 -0
  48. {elody-0.0.205 → elody-0.0.207}/src/tests/data.py +0 -0
  49. {elody-0.0.205 → elody-0.0.207}/src/tests/unit/__init__.py +0 -0
  50. {elody-0.0.205 → elody-0.0.207}/src/tests/unit/test_csv.py +0 -0
  51. {elody-0.0.205 → elody-0.0.207}/src/tests/unit/test_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: elody
3
- Version: 0.0.205
3
+ Version: 0.0.207
4
4
  Summary: elody SDK for Python
5
5
  Author-email: Inuits <developers@inuits.eu>
6
6
  License: GNU GENERAL PUBLIC LICENSE
@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
6
6
 
7
7
  [project]
8
8
  name = "elody"
9
- version = "0.0.205"
9
+ version = "0.0.207"
10
10
  description = "elody SDK for Python"
11
11
  readme = "README.md"
12
12
  authors = [{ name = "Inuits", email = "developers@inuits.eu" }]
@@ -275,7 +275,7 @@ class CSVMultiObject(CSVParser):
275
275
  if not value:
276
276
  continue
277
277
  if not key or isinstance(value, list):
278
- if len(value) == 1 and value[0] == '':
278
+ if len(value) == 1 and value[0] == "":
279
279
  continue
280
280
  if "invalid_value" not in self.get_errors():
281
281
  self.set_error("invalid_value", list())
@@ -60,7 +60,14 @@ class ElodyConfiguration(BaseObjectConfiguration):
60
60
  template = {
61
61
  "_id": _id,
62
62
  "identifiers": list(
63
- set([_id, *identifiers, *document_defaults.pop("identifiers", [])])
63
+ set(
64
+ [
65
+ _id,
66
+ *identifiers,
67
+ *document_defaults.pop("identifiers", []),
68
+ *post_body.pop("identifiers", []),
69
+ ]
70
+ )
64
71
  ),
65
72
  "metadata": [],
66
73
  "relations": [],
@@ -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
- user_context, deepcopy(g.get("content") or request.json or [])
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, user_context: UserContext, request_body: list):
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
- if tenant_relation_type := user_context.bag.get("tenant_relation_type"):
79
- user_context.access_restrictions.filters.append( # pyright: ignore
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)
@@ -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
- filters.append(
117
- {
118
- "type": "selection",
119
- "key": "type",
120
- "value": allowed_item_types,
121
- "match_exact": True,
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
- item_in_storage_format, flat_item, object_lists, restrictions_schema = (
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
- item_in_storage_format,
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.get("storage_format", 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
- item_in_storage_format,
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
- item_in_storage_format,
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.get("storage_format", 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
- item_in_storage_format,
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
- item_in_storage_format,
209
+ item,
211
210
  info["key"],
212
211
  info["object_key"],
213
212
  object_lists,
214
213
  )
215
214
  if element:
216
- item_in_storage_format[info["key"]].remove(element)
215
+ item[info["key"]].remove(element)
217
216
  break
218
217
  else:
219
218
  try:
220
- del item_in_storage_format[keys_info[0]["key"]][
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"] = item_in_storage_format
228
+ user_context.bag["requested_item"] = item
232
229
  return len(user_context.bag["restricted_keys"]) == 0
233
230
 
234
231
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: elody
3
- Version: 0.0.205
3
+ Version: 0.0.207
4
4
  Summary: elody SDK for Python
5
5
  Author-email: Inuits <developers@inuits.eu>
6
6
  License: GNU GENERAL PUBLIC LICENSE
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