elody 0.0.63__py3-none-any.whl → 0.0.162__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.
Files changed (41) hide show
  1. elody/client.py +70 -23
  2. elody/csv.py +118 -21
  3. elody/error_codes.py +112 -0
  4. elody/exceptions.py +14 -0
  5. elody/job.py +95 -0
  6. elody/loader.py +33 -5
  7. elody/migration/__init__.py +0 -0
  8. elody/migration/base_object_migrator.py +18 -0
  9. elody/object_configurations/__init__.py +0 -0
  10. elody/object_configurations/base_object_configuration.py +174 -0
  11. elody/object_configurations/elody_configuration.py +144 -0
  12. elody/object_configurations/job_configuration.py +65 -0
  13. elody/policies/authentication/base_user_tenant_validation_policy.py +48 -15
  14. elody/policies/authorization/filter_generic_objects_policy.py +68 -22
  15. elody/policies/authorization/filter_generic_objects_policy_v2.py +166 -0
  16. elody/policies/authorization/generic_object_detail_policy.py +10 -27
  17. elody/policies/authorization/generic_object_mediafiles_policy.py +82 -0
  18. elody/policies/authorization/generic_object_metadata_policy.py +8 -27
  19. elody/policies/authorization/generic_object_relations_policy.py +12 -29
  20. elody/policies/authorization/generic_object_request_policy.py +56 -55
  21. elody/policies/authorization/generic_object_request_policy_v2.py +133 -0
  22. elody/policies/authorization/mediafile_derivatives_policy.py +92 -0
  23. elody/policies/authorization/mediafile_download_policy.py +71 -0
  24. elody/policies/authorization/multi_tenant_policy.py +14 -6
  25. elody/policies/authorization/tenant_request_policy.py +3 -1
  26. elody/policies/helpers.py +37 -0
  27. elody/policies/permission_handler.py +217 -199
  28. elody/policies/tenant_id_resolver.py +375 -0
  29. elody/schemas.py +0 -3
  30. elody/util.py +165 -11
  31. {elody-0.0.63.dist-info → elody-0.0.162.dist-info}/METADATA +16 -11
  32. elody-0.0.162.dist-info/RECORD +47 -0
  33. {elody-0.0.63.dist-info → elody-0.0.162.dist-info}/WHEEL +1 -1
  34. {elody-0.0.63.dist-info → elody-0.0.162.dist-info}/top_level.txt +1 -0
  35. tests/__init_.py +0 -0
  36. tests/data.py +74 -0
  37. tests/unit/__init__.py +0 -0
  38. tests/unit/test_csv.py +410 -0
  39. tests/unit/test_utils.py +293 -0
  40. elody-0.0.63.dist-info/RECORD +0 -27
  41. {elody-0.0.63.dist-info → elody-0.0.162.dist-info}/LICENSE +0 -0
@@ -3,7 +3,7 @@ import re as regex
3
3
  from copy import deepcopy
4
4
  from elody.policies.permission_handler import (
5
5
  get_permissions,
6
- get_mask_protected_content_post_request_hook,
6
+ mask_protected_content_post_request_hook,
7
7
  )
8
8
  from flask import Request # pyright: ignore
9
9
  from inuits_policy_based_auth import BaseAuthorizationPolicy # pyright: ignore
@@ -20,9 +20,7 @@ class FilterGenericObjectsPolicy(BaseAuthorizationPolicy):
20
20
  self, policy_context: PolicyContext, user_context: UserContext, request_context
21
21
  ):
22
22
  request: Request = request_context.http_request
23
- if not user_context.auth_objects.get("token") or not regex.match(
24
- "^/[^/]+/filter$", request.path
25
- ):
23
+ if not regex.match("^(/[^/]+/v[0-9]+)?/[^/]+/filter$", request.path):
26
24
  return policy_context
27
25
 
28
26
  if not isinstance(user_context.access_restrictions.filters, list):
@@ -32,6 +30,7 @@ class FilterGenericObjectsPolicy(BaseAuthorizationPolicy):
32
30
  policy_context.access_verdict = True
33
31
  return policy_context
34
32
 
33
+ policy_context.access_verdict = False
35
34
  for role in user_context.x_tenant.roles:
36
35
  permissions = get_permissions(role, user_context)
37
36
  if not permissions:
@@ -46,7 +45,7 @@ class FilterGenericObjectsPolicy(BaseAuthorizationPolicy):
46
45
  if access_verdict != None:
47
46
  policy_context.access_verdict = access_verdict
48
47
  if not policy_context.access_verdict:
49
- return policy_context
48
+ break
50
49
 
51
50
  if policy_context.access_verdict:
52
51
  return policy_context
@@ -60,7 +59,7 @@ class FilterGenericObjectsPolicy(BaseAuthorizationPolicy):
60
59
  type_filter = filter
61
60
  elif (
62
61
  filter["type"] == "selection"
63
- and filter["parent_key"] == ""
62
+ and filter.get("parent_key", "") == ""
64
63
  and filter["key"] == "type"
65
64
  ):
66
65
  type_filter = filter
@@ -69,12 +68,26 @@ class FilterGenericObjectsPolicy(BaseAuthorizationPolicy):
69
68
  user_context.access_restrictions.filters.append( # pyright: ignore
70
69
  {
71
70
  "type": "selection",
72
- "parent_key": "relations",
73
- "key": user_context.bag["tenant_relation_type"],
71
+ "key": "type",
72
+ # TODO refactor this in a more generic way
74
73
  "value": [
75
- user_context.bag.get(
76
- "tenant_defining_entity_id", user_context.x_tenant.id
77
- )
74
+ "language",
75
+ "type",
76
+ "collectionForm",
77
+ "institution",
78
+ "tag",
79
+ "triple",
80
+ "person",
81
+ "externalRecord",
82
+ "verzameling",
83
+ "arches_record",
84
+ "photographer",
85
+ "creator",
86
+ "assetPart",
87
+ "set",
88
+ "license",
89
+ "mediafile",
90
+ "share_link",
78
91
  ],
79
92
  "match_exact": True,
80
93
  }
@@ -103,24 +116,57 @@ class PostRequestRules:
103
116
  type_filter_values.remove(type_filter_value)
104
117
  continue
105
118
 
106
- restrictions = permissions["read"][type_filter_value].get(
107
- "restrictions", {}
108
- )
109
- for parent_key in restrictions.keys():
110
- for restriction in restrictions[parent_key]:
119
+ restrictions_grouped_by_index = {}
120
+ schemas = permissions["read"][type_filter_value]
121
+ for schema in schemas.keys():
122
+ restrictions = schemas[schema].get("object_restrictions", {})
123
+ for restricted_key, restricting_value in restrictions.items():
124
+ index, restricted_key = restricted_key.split(":")
125
+ prefix = ""
126
+ if restricted_key[0] == "!":
127
+ restricted_key = restricted_key[1:]
128
+ prefix += "!"
129
+ if restricted_key[0] == "?":
130
+ restricted_key = restricted_key[1:]
131
+ prefix += "?"
132
+ key = f"{schema}|{restricted_key}"
133
+
134
+ if group := restrictions_grouped_by_index.get(index):
135
+ group["key"].append(key)
136
+ else:
137
+ restrictions_grouped_by_index.update(
138
+ {
139
+ index: {
140
+ "key": [key],
141
+ "value": restricting_value,
142
+ "prefix": prefix,
143
+ }
144
+ }
145
+ )
146
+
147
+ for restriction in restrictions_grouped_by_index.values():
148
+ user_context.access_restrictions.filters.append( # pyright: ignore
149
+ {
150
+ "type": "selection",
151
+ "key": restriction["key"],
152
+ "value": restriction["value"],
153
+ "match_exact": True,
154
+ "operator": "or" if restriction["prefix"] == "?" else "and",
155
+ }
156
+ )
157
+ if restriction["prefix"] == "?":
111
158
  user_context.access_restrictions.filters.append( # pyright: ignore
112
159
  {
113
- "type": "selection",
114
- "parent_key": parent_key if parent_key != "root" else "",
160
+ "type": "text",
115
161
  "key": restriction["key"],
116
- "value": restriction["value"],
117
- "match_exact": True,
162
+ "value": "",
163
+ "operator": "or",
118
164
  }
119
165
  )
120
166
 
121
167
  if len(type_filter_values) == 0:
122
- return None
168
+ return False
123
169
  user_context.access_restrictions.post_request_hook = (
124
- get_mask_protected_content_post_request_hook(user_context, permissions)
170
+ mask_protected_content_post_request_hook(user_context, permissions)
125
171
  )
126
172
  return True
@@ -0,0 +1,166 @@
1
+ import re as regex
2
+
3
+ from copy import deepcopy
4
+ from elody.policies.permission_handler import (
5
+ get_permissions,
6
+ mask_protected_content_post_request_hook,
7
+ )
8
+ from flask import Request # pyright: ignore
9
+ from inuits_policy_based_auth import BaseAuthorizationPolicy # pyright: ignore
10
+ from inuits_policy_based_auth.contexts.policy_context import ( # pyright: ignore
11
+ PolicyContext,
12
+ )
13
+ from inuits_policy_based_auth.contexts.user_context import ( # pyright: ignore
14
+ UserContext,
15
+ )
16
+
17
+
18
+ class FilterGenericObjectsPolicyV2(BaseAuthorizationPolicy):
19
+ def authorize(
20
+ self, policy_context: PolicyContext, user_context: UserContext, request_context
21
+ ):
22
+ request: Request = request_context.http_request
23
+ if not regex.match("^(/[^/]+/v[0-9]+)?/[^/]+/filter$", request.path):
24
+ return policy_context
25
+
26
+ if not isinstance(user_context.access_restrictions.filters, list):
27
+ user_context.access_restrictions.filters = []
28
+ type_filter, filters = self.__split_type_filter(
29
+ user_context, deepcopy(request.json or [])
30
+ )
31
+ if not type_filter:
32
+ policy_context.access_verdict = True
33
+ return policy_context
34
+
35
+ policy_context.access_verdict = False
36
+ for role in user_context.x_tenant.roles:
37
+ permissions = get_permissions(role, user_context)
38
+ if not permissions:
39
+ continue
40
+
41
+ rules = [PostRequestRules]
42
+ access_verdict = None
43
+ for rule in rules:
44
+ access_verdict = rule().apply(
45
+ type_filter["value"], filters, user_context, request, permissions
46
+ )
47
+ if access_verdict != None:
48
+ policy_context.access_verdict = access_verdict
49
+ if not policy_context.access_verdict:
50
+ break
51
+
52
+ if policy_context.access_verdict:
53
+ return policy_context
54
+
55
+ return policy_context
56
+
57
+ def __split_type_filter(self, user_context: UserContext, request_body: list):
58
+ type_filter = None
59
+ for filter in request_body:
60
+ if filter["type"] == "type":
61
+ type_filter = filter
62
+ elif filter["type"] == "selection" and filter["key"] == "type":
63
+ type_filter = filter
64
+ elif item_types := filter.get("item_types"):
65
+ type_filter = {
66
+ "type": "selection",
67
+ "key": "type",
68
+ "value": item_types,
69
+ "match_exact": True,
70
+ }
71
+
72
+ if not type_filter:
73
+ if tenant_relation_type := user_context.bag.get("tenant_relation_type"):
74
+ user_context.access_restrictions.filters.append( # pyright: ignore
75
+ {
76
+ "type": "selection",
77
+ "key": tenant_relation_type,
78
+ "value": [
79
+ user_context.bag.get(
80
+ "tenant_defining_entity_id", user_context.x_tenant.id
81
+ )
82
+ ],
83
+ "match_exact": True,
84
+ }
85
+ )
86
+ return None, request_body
87
+
88
+ try:
89
+ request_body.remove(type_filter)
90
+ except ValueError:
91
+ pass
92
+ return type_filter, request_body
93
+
94
+
95
+ class PostRequestRules:
96
+ def apply(
97
+ self,
98
+ type_filter_values: str | list[str],
99
+ filters: list[dict],
100
+ user_context: UserContext,
101
+ request: Request,
102
+ permissions,
103
+ ) -> bool | None:
104
+ if request.method != "POST":
105
+ return None
106
+
107
+ if isinstance(type_filter_values, str):
108
+ type_filter_values = [type_filter_values]
109
+
110
+ type_filter_values_copy = deepcopy(type_filter_values)
111
+ for type_filter_value in type_filter_values_copy:
112
+ if type_filter_value not in permissions["read"].keys():
113
+ type_filter_values.remove(type_filter_value)
114
+ continue
115
+
116
+ restrictions_grouped_by_index = {}
117
+ schemas = permissions["read"][type_filter_value]
118
+ for schema in schemas.keys():
119
+ restrictions = schemas[schema].get("object_restrictions", {})
120
+ for restricted_key, restricting_value in restrictions.items():
121
+ index, restricted_key = restricted_key.split(":")
122
+ key = f"{schema}|{restricted_key}"
123
+ if group := restrictions_grouped_by_index.get(index):
124
+ group["key"].append(key)
125
+ else:
126
+ restrictions_grouped_by_index.update(
127
+ {
128
+ index: {
129
+ "key": [key],
130
+ "value": restricting_value,
131
+ }
132
+ }
133
+ )
134
+
135
+ # support false soft call read responses
136
+ for filter in filters:
137
+ key = filter.get("key", "")
138
+ if isinstance(key, list):
139
+ key = ",".join(key)
140
+ for restriction in restrictions_grouped_by_index.values():
141
+ if key not in ",".join(restriction["key"]):
142
+ continue
143
+ values = (
144
+ filter["value"]
145
+ if isinstance(filter["value"], list)
146
+ else [filter["value"]]
147
+ )
148
+ if not any(value in restriction["value"] for value in values):
149
+ return False
150
+
151
+ for restriction in restrictions_grouped_by_index.values():
152
+ user_context.access_restrictions.filters.append( # pyright: ignore
153
+ {
154
+ "type": "selection",
155
+ "key": restriction["key"],
156
+ "value": restriction["value"],
157
+ "match_exact": True,
158
+ }
159
+ )
160
+
161
+ if len(type_filter_values) == 0:
162
+ return False
163
+ user_context.access_restrictions.post_request_hook = (
164
+ mask_protected_content_post_request_hook(user_context, permissions)
165
+ )
166
+ return True
@@ -1,12 +1,11 @@
1
1
  import re as regex
2
2
 
3
+ from elody.policies.helpers import get_content, get_item
3
4
  from elody.policies.permission_handler import (
4
- get_mask_protected_content_post_request_hook,
5
5
  get_permissions,
6
6
  handle_single_item_request,
7
7
  )
8
8
  from flask import Request # pyright: ignore
9
- from flask_restful import abort # pyright: ignore
10
9
  from inuits_policy_based_auth import BaseAuthorizationPolicy # pyright: ignore
11
10
  from inuits_policy_based_auth.contexts.policy_context import ( # pyright: ignore
12
11
  PolicyContext,
@@ -22,27 +21,10 @@ class GenericObjectDetailPolicy(BaseAuthorizationPolicy):
22
21
  self, policy_context: PolicyContext, user_context: UserContext, request_context
23
22
  ):
24
23
  request: Request = request_context.http_request
25
- if not user_context.auth_objects.get("token") or not regex.match(
26
- "^/[^/]+/[^/]+$|^/ngsi-ld/v1/entities/[^/]+$", request.path
27
- ):
24
+ if not regex.match("^(/[^/]+/v[0-9]+)?/[^/]+/[^/]+$", request.path):
28
25
  return policy_context
29
26
 
30
- view_args = request.view_args or {}
31
- collection = "entities"
32
- if not request.path.startswith("/ngsi-ld/v1/entities"):
33
- collection = request.path.split("/")[1]
34
- id = view_args.get("id")
35
- item = (
36
- StorageManager()
37
- .get_db_engine()
38
- .get_item_from_collection_by_id(view_args.get("collection", collection), id)
39
- )
40
- if not item:
41
- abort(
42
- 404,
43
- message=f"Item with id {id} doesn't exist in collection {collection}",
44
- )
45
-
27
+ item = get_item(StorageManager(), user_context.bag, request.view_args)
46
28
  for role in user_context.x_tenant.roles:
47
29
  permissions = get_permissions(role, user_context)
48
30
  if not permissions:
@@ -61,7 +43,7 @@ class GenericObjectDetailPolicy(BaseAuthorizationPolicy):
61
43
  if access_verdict != None:
62
44
  policy_context.access_verdict = access_verdict
63
45
  if not policy_context.access_verdict:
64
- return policy_context
46
+ break
65
47
 
66
48
  if policy_context.access_verdict:
67
49
  return policy_context
@@ -75,6 +57,7 @@ class PostRequestRules:
75
57
  ) -> bool | None:
76
58
  if request.method != "POST":
77
59
  return None
60
+
78
61
  return handle_single_item_request(user_context, item, permissions, "create")
79
62
 
80
63
 
@@ -85,9 +68,6 @@ class GetRequestRules:
85
68
  if request.method != "GET":
86
69
  return None
87
70
 
88
- user_context.access_restrictions.post_request_hook = (
89
- get_mask_protected_content_post_request_hook(user_context, permissions)
90
- )
91
71
  return handle_single_item_request(user_context, item, permissions, "read")
92
72
 
93
73
 
@@ -98,8 +78,9 @@ class PutRequestRules:
98
78
  if request.method != "PUT":
99
79
  return None
100
80
 
81
+ content = get_content(item, request, request.json)
101
82
  return handle_single_item_request(
102
- user_context, item, permissions, "update", request.json
83
+ user_context, item, permissions, "update", content
103
84
  )
104
85
 
105
86
 
@@ -110,8 +91,9 @@ class PatchRequestRules:
110
91
  if request.method != "PATCH":
111
92
  return None
112
93
 
94
+ content = get_content(item, request, request.json)
113
95
  return handle_single_item_request(
114
- user_context, item, permissions, "update", request.json
96
+ user_context, item, permissions, "update", content
115
97
  )
116
98
 
117
99
 
@@ -121,4 +103,5 @@ class DeleteRequestRules:
121
103
  ) -> bool | None:
122
104
  if request.method != "DELETE":
123
105
  return None
106
+
124
107
  return handle_single_item_request(user_context, item, permissions, "delete")
@@ -0,0 +1,82 @@
1
+ import re as regex
2
+
3
+ from elody.error_codes import ErrorCode, get_error_code, get_read, get_write
4
+ from elody.policies.permission_handler import (
5
+ get_permissions,
6
+ handle_single_item_request,
7
+ )
8
+ from flask import Request # pyright: ignore
9
+ from flask_restful import abort # pyright: ignore
10
+ from inuits_policy_based_auth import BaseAuthorizationPolicy # pyright: ignore
11
+ from inuits_policy_based_auth.contexts.policy_context import ( # pyright: ignore
12
+ PolicyContext,
13
+ )
14
+ from inuits_policy_based_auth.contexts.user_context import ( # pyright: ignore
15
+ UserContext,
16
+ )
17
+ from storage.storagemanager import StorageManager # pyright: ignore
18
+
19
+
20
+ class GenericObjectMediafilesPolicy(BaseAuthorizationPolicy):
21
+ def authorize(
22
+ self, policy_context: PolicyContext, user_context: UserContext, request_context
23
+ ):
24
+ request: Request = request_context.http_request
25
+ if not regex.match("^(/[^/]+/v[0-9]+)?/[^/]+/[^/]+/mediafiles$", request.path):
26
+ return policy_context
27
+
28
+ view_args = request.view_args or {}
29
+ collection = view_args.get("collection", request.path.split("/")[-3])
30
+ id = view_args.get("id")
31
+ item = (
32
+ StorageManager()
33
+ .get_db_engine()
34
+ .get_item_from_collection_by_id(collection, id)
35
+ )
36
+ if not item:
37
+ abort(
38
+ 404,
39
+ message=f"{get_error_code(ErrorCode.ITEM_NOT_FOUND_IN_COLLECTION, get_read())} | id:{id} | collection:{collection} - Item with id {id} doesn't exist in collection {collection}",
40
+ )
41
+
42
+ for role in user_context.x_tenant.roles:
43
+ permissions = get_permissions(role, user_context)
44
+ if not permissions:
45
+ continue
46
+
47
+ rules = [
48
+ PostRequestRules,
49
+ GetRequestRules,
50
+ ]
51
+ access_verdict = None
52
+ for rule in rules:
53
+ access_verdict = rule().apply(item, user_context, request, permissions)
54
+ if access_verdict != None:
55
+ policy_context.access_verdict = access_verdict
56
+ if not policy_context.access_verdict:
57
+ break
58
+
59
+ if policy_context.access_verdict:
60
+ return policy_context
61
+
62
+ return policy_context
63
+
64
+
65
+ class PostRequestRules:
66
+ def apply(
67
+ self, item, user_context: UserContext, request: Request, permissions
68
+ ) -> bool | None:
69
+ if request.method != "POST":
70
+ return None
71
+
72
+ return handle_single_item_request(user_context, item, permissions, "create")
73
+
74
+
75
+ class GetRequestRules:
76
+ def apply(
77
+ self, item, user_context: UserContext, request: Request, permissions
78
+ ) -> bool | None:
79
+ if request.method != "GET":
80
+ return None
81
+
82
+ return handle_single_item_request(user_context, item, permissions, "read")
@@ -1,12 +1,11 @@
1
1
  import re as regex
2
2
 
3
+ from elody.policies.helpers import get_content, get_item
3
4
  from elody.policies.permission_handler import (
4
- get_mask_protected_content_post_request_hook,
5
5
  get_permissions,
6
6
  handle_single_item_request,
7
7
  )
8
8
  from flask import Request # pyright: ignore
9
- from flask_restful import abort # pyright: ignore
10
9
  from inuits_policy_based_auth import BaseAuthorizationPolicy # pyright: ignore
11
10
  from inuits_policy_based_auth.contexts.policy_context import ( # pyright: ignore
12
11
  PolicyContext,
@@ -22,25 +21,10 @@ class GenericObjectMetadataPolicy(BaseAuthorizationPolicy):
22
21
  self, policy_context: PolicyContext, user_context: UserContext, request_context
23
22
  ):
24
23
  request: Request = request_context.http_request
25
- if not user_context.auth_objects.get("token") or not regex.match(
26
- "^/[^/]+/[^/]+/metadata$", request.path
27
- ):
24
+ if not regex.match("^(/elody/v[0-9]+)?/[^/]+/[^/]+/metadata$", request.path):
28
25
  return policy_context
29
26
 
30
- view_args = request.view_args or {}
31
- collection = view_args.get("collection", request.path.split("/")[1])
32
- id = view_args.get("id")
33
- item = (
34
- StorageManager()
35
- .get_db_engine()
36
- .get_item_from_collection_by_id(collection, id)
37
- )
38
- if not item:
39
- abort(
40
- 404,
41
- message=f"Item with id {id} doesn't exist in collection {collection}",
42
- )
43
-
27
+ item = get_item(StorageManager(), user_context.bag, request.view_args)
44
28
  for role in user_context.x_tenant.roles:
45
29
  permissions = get_permissions(role, user_context)
46
30
  if not permissions:
@@ -53,7 +37,7 @@ class GenericObjectMetadataPolicy(BaseAuthorizationPolicy):
53
37
  if access_verdict != None:
54
38
  policy_context.access_verdict = access_verdict
55
39
  if not policy_context.access_verdict:
56
- return policy_context
40
+ break
57
41
 
58
42
  if policy_context.access_verdict:
59
43
  return policy_context
@@ -68,11 +52,6 @@ class GetRequestRules:
68
52
  if request.method != "GET":
69
53
  return None
70
54
 
71
- user_context.access_restrictions.post_request_hook = (
72
- get_mask_protected_content_post_request_hook(
73
- user_context, permissions, item["type"]
74
- )
75
- )
76
55
  return handle_single_item_request(user_context, item, permissions, "read")
77
56
 
78
57
 
@@ -83,8 +62,9 @@ class PutRequestRules:
83
62
  if request.method != "PUT":
84
63
  return None
85
64
 
65
+ content = get_content(item, request, {"metadata": request.json})
86
66
  return handle_single_item_request(
87
- user_context, item, permissions, "update", {"metadata": request.json}
67
+ user_context, item, permissions, "update", content
88
68
  )
89
69
 
90
70
 
@@ -95,6 +75,7 @@ class PatchRequestRules:
95
75
  if request.method != "PATCH":
96
76
  return None
97
77
 
78
+ content = get_content(item, request, {"metadata": request.json})
98
79
  return handle_single_item_request(
99
- user_context, item, permissions, "update", {"metadata": request.json}
80
+ user_context, item, permissions, "update", content
100
81
  )
@@ -1,12 +1,11 @@
1
1
  import re as regex
2
2
 
3
+ from elody.policies.helpers import get_content, get_item
3
4
  from elody.policies.permission_handler import (
4
- get_mask_protected_content_post_request_hook,
5
5
  get_permissions,
6
6
  handle_single_item_request,
7
7
  )
8
8
  from flask import Request # pyright: ignore
9
- from flask_restful import abort # pyright: ignore
10
9
  from inuits_policy_based_auth import BaseAuthorizationPolicy # pyright: ignore
11
10
  from inuits_policy_based_auth.contexts.policy_context import ( # pyright: ignore
12
11
  PolicyContext,
@@ -22,25 +21,10 @@ class GenericObjectRelationsPolicy(BaseAuthorizationPolicy):
22
21
  self, policy_context: PolicyContext, user_context: UserContext, request_context
23
22
  ):
24
23
  request: Request = request_context.http_request
25
- if not user_context.auth_objects.get("token") or not regex.match(
26
- "^/[^/]+/[^/]+/relations$", request.path
27
- ):
24
+ if not regex.match("^(/elody/v[0-9]+)?/[^/]+/[^/]+/relations$", request.path):
28
25
  return policy_context
29
26
 
30
- view_args = request.view_args or {}
31
- collection = view_args.get("collection", request.path.split("/")[1])
32
- id = view_args.get("id")
33
- item = (
34
- StorageManager()
35
- .get_db_engine()
36
- .get_item_from_collection_by_id(collection, id)
37
- )
38
- if not item:
39
- abort(
40
- 404,
41
- message=f"Item with id {id} doesn't exist in collection {collection}",
42
- )
43
-
27
+ item = get_item(StorageManager(), user_context.bag, request.view_args)
44
28
  for role in user_context.x_tenant.roles:
45
29
  permissions = get_permissions(role, user_context)
46
30
  if not permissions:
@@ -59,7 +43,7 @@ class GenericObjectRelationsPolicy(BaseAuthorizationPolicy):
59
43
  if access_verdict != None:
60
44
  policy_context.access_verdict = access_verdict
61
45
  if not policy_context.access_verdict:
62
- return policy_context
46
+ break
63
47
 
64
48
  if policy_context.access_verdict:
65
49
  return policy_context
@@ -74,8 +58,9 @@ class PostRequestRules:
74
58
  if request.method != "POST":
75
59
  return None
76
60
 
61
+ content = get_content(item, request, {"relations": request.json})
77
62
  return handle_single_item_request(
78
- user_context, item, permissions, "create", {"relations": request.json}
63
+ user_context, item, permissions, "create", content
79
64
  )
80
65
 
81
66
 
@@ -86,11 +71,6 @@ class GetRequestRules:
86
71
  if request.method != "GET":
87
72
  return None
88
73
 
89
- user_context.access_restrictions.post_request_hook = (
90
- get_mask_protected_content_post_request_hook(
91
- user_context, permissions, item["type"]
92
- )
93
- )
94
74
  return handle_single_item_request(user_context, item, permissions, "read")
95
75
 
96
76
 
@@ -101,8 +81,9 @@ class PutRequestRules:
101
81
  if request.method != "PUT":
102
82
  return None
103
83
 
84
+ content = get_content(item, request, {"relations": request.json})
104
85
  return handle_single_item_request(
105
- user_context, item, permissions, "update", {"relations": request.json}
86
+ user_context, item, permissions, "update", content
106
87
  )
107
88
 
108
89
 
@@ -113,8 +94,9 @@ class PatchRequestRules:
113
94
  if request.method != "PATCH":
114
95
  return None
115
96
 
97
+ content = get_content(item, request, {"relations": request.json})
116
98
  return handle_single_item_request(
117
- user_context, item, permissions, "update", {"relations": request.json}
99
+ user_context, item, permissions, "update", content
118
100
  )
119
101
 
120
102
 
@@ -125,6 +107,7 @@ class DeleteRequestRules:
125
107
  if request.method != "DELETE":
126
108
  return None
127
109
 
110
+ content = get_content(item, request, {"relations": request.json})
128
111
  return handle_single_item_request(
129
- user_context, item, permissions, "delete", {"relations": request.json}
112
+ user_context, item, permissions, "delete", content
130
113
  )