kinto 23.2.1__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.
- kinto/__init__.py +92 -0
- kinto/__main__.py +249 -0
- kinto/authorization.py +134 -0
- kinto/config/__init__.py +94 -0
- kinto/config/kinto.tpl +270 -0
- kinto/contribute.json +27 -0
- kinto/core/__init__.py +246 -0
- kinto/core/authentication.py +48 -0
- kinto/core/authorization.py +311 -0
- kinto/core/cache/__init__.py +131 -0
- kinto/core/cache/memcached.py +112 -0
- kinto/core/cache/memory.py +104 -0
- kinto/core/cache/postgresql/__init__.py +178 -0
- kinto/core/cache/postgresql/schema.sql +23 -0
- kinto/core/cache/testing.py +208 -0
- kinto/core/cornice/__init__.py +93 -0
- kinto/core/cornice/cors.py +144 -0
- kinto/core/cornice/errors.py +40 -0
- kinto/core/cornice/pyramidhook.py +373 -0
- kinto/core/cornice/renderer.py +89 -0
- kinto/core/cornice/resource.py +205 -0
- kinto/core/cornice/service.py +641 -0
- kinto/core/cornice/util.py +138 -0
- kinto/core/cornice/validators/__init__.py +94 -0
- kinto/core/cornice/validators/_colander.py +142 -0
- kinto/core/cornice/validators/_marshmallow.py +182 -0
- kinto/core/cornice_swagger/__init__.py +92 -0
- kinto/core/cornice_swagger/converters/__init__.py +21 -0
- kinto/core/cornice_swagger/converters/exceptions.py +6 -0
- kinto/core/cornice_swagger/converters/parameters.py +90 -0
- kinto/core/cornice_swagger/converters/schema.py +249 -0
- kinto/core/cornice_swagger/swagger.py +725 -0
- kinto/core/cornice_swagger/templates/index.html +73 -0
- kinto/core/cornice_swagger/templates/index_script_template.html +21 -0
- kinto/core/cornice_swagger/util.py +42 -0
- kinto/core/cornice_swagger/views.py +78 -0
- kinto/core/decorators.py +74 -0
- kinto/core/errors.py +216 -0
- kinto/core/events.py +301 -0
- kinto/core/initialization.py +738 -0
- kinto/core/listeners/__init__.py +9 -0
- kinto/core/metrics.py +94 -0
- kinto/core/openapi.py +115 -0
- kinto/core/permission/__init__.py +202 -0
- kinto/core/permission/memory.py +167 -0
- kinto/core/permission/postgresql/__init__.py +489 -0
- kinto/core/permission/postgresql/migrations/migration_001_002.sql +18 -0
- kinto/core/permission/postgresql/schema.sql +41 -0
- kinto/core/permission/testing.py +487 -0
- kinto/core/resource/__init__.py +1311 -0
- kinto/core/resource/model.py +412 -0
- kinto/core/resource/schema.py +502 -0
- kinto/core/resource/viewset.py +230 -0
- kinto/core/schema.py +119 -0
- kinto/core/scripts.py +50 -0
- kinto/core/statsd.py +1 -0
- kinto/core/storage/__init__.py +436 -0
- kinto/core/storage/exceptions.py +53 -0
- kinto/core/storage/generators.py +58 -0
- kinto/core/storage/memory.py +651 -0
- kinto/core/storage/postgresql/__init__.py +1131 -0
- kinto/core/storage/postgresql/client.py +120 -0
- kinto/core/storage/postgresql/migrations/migration_001_002.sql +10 -0
- kinto/core/storage/postgresql/migrations/migration_002_003.sql +33 -0
- kinto/core/storage/postgresql/migrations/migration_003_004.sql +18 -0
- kinto/core/storage/postgresql/migrations/migration_004_005.sql +20 -0
- kinto/core/storage/postgresql/migrations/migration_005_006.sql +11 -0
- kinto/core/storage/postgresql/migrations/migration_006_007.sql +74 -0
- kinto/core/storage/postgresql/migrations/migration_007_008.sql +66 -0
- kinto/core/storage/postgresql/migrations/migration_008_009.sql +41 -0
- kinto/core/storage/postgresql/migrations/migration_009_010.sql +98 -0
- kinto/core/storage/postgresql/migrations/migration_010_011.sql +14 -0
- kinto/core/storage/postgresql/migrations/migration_011_012.sql +9 -0
- kinto/core/storage/postgresql/migrations/migration_012_013.sql +71 -0
- kinto/core/storage/postgresql/migrations/migration_013_014.sql +14 -0
- kinto/core/storage/postgresql/migrations/migration_014_015.sql +95 -0
- kinto/core/storage/postgresql/migrations/migration_015_016.sql +4 -0
- kinto/core/storage/postgresql/migrations/migration_016_017.sql +81 -0
- kinto/core/storage/postgresql/migrations/migration_017_018.sql +25 -0
- kinto/core/storage/postgresql/migrations/migration_018_019.sql +8 -0
- kinto/core/storage/postgresql/migrations/migration_019_020.sql +7 -0
- kinto/core/storage/postgresql/migrations/migration_020_021.sql +68 -0
- kinto/core/storage/postgresql/migrations/migration_021_022.sql +62 -0
- kinto/core/storage/postgresql/migrations/migration_022_023.sql +5 -0
- kinto/core/storage/postgresql/migrations/migration_023_024.sql +6 -0
- kinto/core/storage/postgresql/migrations/migration_024_025.sql +6 -0
- kinto/core/storage/postgresql/migrator.py +98 -0
- kinto/core/storage/postgresql/pool.py +55 -0
- kinto/core/storage/postgresql/schema.sql +143 -0
- kinto/core/storage/testing.py +1857 -0
- kinto/core/storage/utils.py +37 -0
- kinto/core/testing.py +182 -0
- kinto/core/utils.py +553 -0
- kinto/core/views/__init__.py +0 -0
- kinto/core/views/batch.py +163 -0
- kinto/core/views/errors.py +145 -0
- kinto/core/views/heartbeat.py +106 -0
- kinto/core/views/hello.py +69 -0
- kinto/core/views/openapi.py +35 -0
- kinto/core/views/version.py +50 -0
- kinto/events.py +3 -0
- kinto/plugins/__init__.py +0 -0
- kinto/plugins/accounts/__init__.py +94 -0
- kinto/plugins/accounts/authentication.py +63 -0
- kinto/plugins/accounts/scripts.py +61 -0
- kinto/plugins/accounts/utils.py +13 -0
- kinto/plugins/accounts/views.py +136 -0
- kinto/plugins/admin/README.md +3 -0
- kinto/plugins/admin/VERSION +1 -0
- kinto/plugins/admin/__init__.py +40 -0
- kinto/plugins/admin/build/VERSION +1 -0
- kinto/plugins/admin/build/assets/index-CYFwtKtL.css +6 -0
- kinto/plugins/admin/build/assets/index-DJ0m93zA.js +149 -0
- kinto/plugins/admin/build/assets/logo-VBRiKSPX.png +0 -0
- kinto/plugins/admin/build/index.html +18 -0
- kinto/plugins/admin/public/help.html +25 -0
- kinto/plugins/admin/views.py +42 -0
- kinto/plugins/default_bucket/__init__.py +191 -0
- kinto/plugins/flush.py +28 -0
- kinto/plugins/history/__init__.py +65 -0
- kinto/plugins/history/listener.py +181 -0
- kinto/plugins/history/views.py +66 -0
- kinto/plugins/openid/__init__.py +131 -0
- kinto/plugins/openid/utils.py +14 -0
- kinto/plugins/openid/views.py +193 -0
- kinto/plugins/prometheus.py +300 -0
- kinto/plugins/statsd.py +85 -0
- kinto/schema_validation.py +135 -0
- kinto/views/__init__.py +34 -0
- kinto/views/admin.py +195 -0
- kinto/views/buckets.py +45 -0
- kinto/views/collections.py +58 -0
- kinto/views/contribute.py +39 -0
- kinto/views/groups.py +90 -0
- kinto/views/permissions.py +235 -0
- kinto/views/records.py +133 -0
- kinto-23.2.1.dist-info/METADATA +232 -0
- kinto-23.2.1.dist-info/RECORD +142 -0
- kinto-23.2.1.dist-info/WHEEL +5 -0
- kinto-23.2.1.dist-info/entry_points.txt +5 -0
- kinto-23.2.1.dist-info/licenses/LICENSE +13 -0
- kinto-23.2.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
import warnings
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class Model:
|
|
5
|
+
"""A resource stores and manipulate objects in its attached storage.
|
|
6
|
+
|
|
7
|
+
It is not aware of HTTP environment nor HTTP API.
|
|
8
|
+
|
|
9
|
+
Objects are isolated according to the provided `name` and `parent_id`.
|
|
10
|
+
|
|
11
|
+
Those notions have no particular semantic and can represent anything.
|
|
12
|
+
For example, the resource `name` can be the *type* of objects stored, and
|
|
13
|
+
`parent_id` can be the current *user id* or *a group* where the resource
|
|
14
|
+
belongs. If left empty, the resource objects are not isolated.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
id_field = "id"
|
|
18
|
+
"""Name of `id` field in objects"""
|
|
19
|
+
|
|
20
|
+
modified_field = "last_modified"
|
|
21
|
+
"""Name of `last modified` field in objects"""
|
|
22
|
+
|
|
23
|
+
deleted_field = "deleted"
|
|
24
|
+
"""Name of `deleted` field in deleted objects"""
|
|
25
|
+
|
|
26
|
+
permissions_field = "__permissions__"
|
|
27
|
+
# Permissions field used to annotate data with permissions.
|
|
28
|
+
|
|
29
|
+
def __init__(
|
|
30
|
+
self,
|
|
31
|
+
storage,
|
|
32
|
+
permission,
|
|
33
|
+
id_generator=None,
|
|
34
|
+
resource_name="",
|
|
35
|
+
parent_id="",
|
|
36
|
+
current_principal=None,
|
|
37
|
+
prefixed_principals=None,
|
|
38
|
+
explicit_perm=True,
|
|
39
|
+
):
|
|
40
|
+
"""
|
|
41
|
+
:param storage: an instance of storage
|
|
42
|
+
:type storage: :class:`kinto.core.storage.Storage`
|
|
43
|
+
:param id_generator: an instance of id generator, used by storage
|
|
44
|
+
on object creation.
|
|
45
|
+
|
|
46
|
+
:param str resource_name: the resource name
|
|
47
|
+
:param str parent_id: the default parent id
|
|
48
|
+
:param bool explicit_perm:
|
|
49
|
+
Without explicit permissions, the ACLs on the object will
|
|
50
|
+
fully depend on the inherited permission tree (eg. read/write on parent).
|
|
51
|
+
This basically means that if user loose the permission on the
|
|
52
|
+
parent, they also loose the permission on children.
|
|
53
|
+
See https://github.com/Kinto/kinto/issues/893
|
|
54
|
+
"""
|
|
55
|
+
self.storage = storage
|
|
56
|
+
self.permission = permission
|
|
57
|
+
self.id_generator = id_generator
|
|
58
|
+
self.parent_id = parent_id
|
|
59
|
+
self.resource_name = resource_name
|
|
60
|
+
self.current_principal = current_principal
|
|
61
|
+
self.prefixed_principals = prefixed_principals
|
|
62
|
+
self.explicit_perm = explicit_perm
|
|
63
|
+
|
|
64
|
+
# Object permission id.
|
|
65
|
+
self.get_permission_object_id = None
|
|
66
|
+
|
|
67
|
+
def timestamp(self, parent_id=None):
|
|
68
|
+
"""Fetch the resource current timestamp.
|
|
69
|
+
|
|
70
|
+
:param str parent_id: optional filter for parent id
|
|
71
|
+
:rtype: int
|
|
72
|
+
|
|
73
|
+
"""
|
|
74
|
+
parent_id = parent_id or self.parent_id
|
|
75
|
+
return self.storage.resource_timestamp(
|
|
76
|
+
resource_name=self.resource_name, parent_id=parent_id
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
def _annotate(self, obj, perm_object_id):
|
|
80
|
+
permissions = self.permission.get_object_permissions(perm_object_id)
|
|
81
|
+
# Permissions are not returned if user only has read permission.
|
|
82
|
+
writers = permissions.get("write", [])
|
|
83
|
+
principals = self.prefixed_principals + [self.current_principal]
|
|
84
|
+
if len(set(writers) & set(principals)) == 0:
|
|
85
|
+
permissions = {}
|
|
86
|
+
# Insert the permissions values in the response.
|
|
87
|
+
annotated = {**obj, self.permissions_field: permissions}
|
|
88
|
+
return annotated
|
|
89
|
+
|
|
90
|
+
def _allow_write(self, perm_object_id):
|
|
91
|
+
"""Helper to give the ``write`` permission to the current user."""
|
|
92
|
+
if self.explicit_perm:
|
|
93
|
+
self.permission.add_principal_to_ace(perm_object_id, "write", self.current_principal)
|
|
94
|
+
|
|
95
|
+
def get_objects(
|
|
96
|
+
self,
|
|
97
|
+
filters=None,
|
|
98
|
+
sorting=None,
|
|
99
|
+
pagination_rules=None,
|
|
100
|
+
limit=None,
|
|
101
|
+
include_deleted=False,
|
|
102
|
+
parent_id=None,
|
|
103
|
+
):
|
|
104
|
+
"""Fetch the resource objects.
|
|
105
|
+
|
|
106
|
+
Override to post-process objects after feching them from storage.
|
|
107
|
+
|
|
108
|
+
:param filters: Optionally filter the objects by their attribute.
|
|
109
|
+
Each filter in this list is a tuple of a field, a value and a
|
|
110
|
+
comparison (see `kinto.core.utils.COMPARISON`). All filters
|
|
111
|
+
are combined using *AND*.
|
|
112
|
+
:type filters: list of :class:`kinto.core.storage.Filter`
|
|
113
|
+
|
|
114
|
+
:param sorting: Optionally sort the objects by attribute.
|
|
115
|
+
Each sort instruction in this list refers to a field and a
|
|
116
|
+
direction (negative means descending). All sort instructions are
|
|
117
|
+
cumulative.
|
|
118
|
+
:type sorting: list of :class:`kinto.core.storage.Sort`
|
|
119
|
+
|
|
120
|
+
:param pagination_rules: Optionally paginate the list of objects.
|
|
121
|
+
This list of rules aims to reduce the set of objects to the current
|
|
122
|
+
page. A rule is a list of filters (see `filters` parameter),
|
|
123
|
+
and all rules are combined using *OR*.
|
|
124
|
+
:type pagination_rules: list of list of
|
|
125
|
+
:class:`kinto.core.storage.Filter`
|
|
126
|
+
|
|
127
|
+
:param int limit: Optionally limit the number of objects to be
|
|
128
|
+
retrieved.
|
|
129
|
+
|
|
130
|
+
:param bool include_deleted: Optionally include the deleted objects
|
|
131
|
+
that match the filters.
|
|
132
|
+
|
|
133
|
+
:param str parent_id: optional filter for parent id
|
|
134
|
+
|
|
135
|
+
:returns: A list of objects in the current page.
|
|
136
|
+
:rtype: list
|
|
137
|
+
"""
|
|
138
|
+
parent_id = parent_id or self.parent_id
|
|
139
|
+
return self.storage.list_all(
|
|
140
|
+
resource_name=self.resource_name,
|
|
141
|
+
parent_id=parent_id,
|
|
142
|
+
filters=filters,
|
|
143
|
+
sorting=sorting,
|
|
144
|
+
pagination_rules=pagination_rules,
|
|
145
|
+
limit=limit,
|
|
146
|
+
include_deleted=include_deleted,
|
|
147
|
+
id_field=self.id_field,
|
|
148
|
+
modified_field=self.modified_field,
|
|
149
|
+
deleted_field=self.deleted_field,
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
def count_objects(self, filters=None, parent_id=None):
|
|
153
|
+
"""Fetch the total count of resource objects
|
|
154
|
+
|
|
155
|
+
Override to post-process objects after feching them from storage.
|
|
156
|
+
|
|
157
|
+
:param filters: Optionally filter the objects by their attribute.
|
|
158
|
+
Each filter in this list is a tuple of a field, a value and a
|
|
159
|
+
comparison (see `kinto.core.utils.COMPARISON`). All filters
|
|
160
|
+
are combined using *AND*.
|
|
161
|
+
:type filters: list of :class:`kinto.core.storage.Filter`
|
|
162
|
+
|
|
163
|
+
:param str parent_id: optional filter for parent id
|
|
164
|
+
|
|
165
|
+
:returns: An integer of the total number of objects in the result set.
|
|
166
|
+
:rtype: int
|
|
167
|
+
"""
|
|
168
|
+
parent_id = parent_id or self.parent_id
|
|
169
|
+
return self.storage.count_all(
|
|
170
|
+
resource_name=self.resource_name,
|
|
171
|
+
parent_id=parent_id,
|
|
172
|
+
filters=filters,
|
|
173
|
+
id_field=self.id_field,
|
|
174
|
+
modified_field=self.modified_field,
|
|
175
|
+
deleted_field=self.deleted_field,
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
def delete_objects(
|
|
179
|
+
self, filters=None, sorting=None, pagination_rules=None, limit=None, parent_id=None
|
|
180
|
+
):
|
|
181
|
+
"""Delete multiple resource objects.
|
|
182
|
+
|
|
183
|
+
Override to post-process objects after their deletion from storage.
|
|
184
|
+
|
|
185
|
+
:param filters: Optionally filter the objects by their attribute.
|
|
186
|
+
Each filter in this list is a tuple of a field, a value and a
|
|
187
|
+
comparison (see `kinto.core.utils.COMPARISON`). All filters
|
|
188
|
+
are combined using *AND*.
|
|
189
|
+
:type filters: list of :class:`kinto.core.storage.Filter`
|
|
190
|
+
|
|
191
|
+
:param sorting: Optionnally sort the objects by attribute.
|
|
192
|
+
Each sort instruction in this list refers to a field and a
|
|
193
|
+
direction (negative means descending). All sort instructions are
|
|
194
|
+
cumulative.
|
|
195
|
+
:type sorting: list of :class:`kinto.core.storage.Sort`
|
|
196
|
+
|
|
197
|
+
:param pagination_rules: Optionnally paginate the deletion of objects.
|
|
198
|
+
This list of rules aims to reduce the set of objects to the current
|
|
199
|
+
page. A rule is a list of filters (see `filters` parameter),
|
|
200
|
+
and all rules are combined using *OR*.
|
|
201
|
+
:type pagination_rules: list of list of
|
|
202
|
+
:class:`kinto.core.storage.Filter`
|
|
203
|
+
|
|
204
|
+
:param int limit: Optionnally limit the number of objects to be
|
|
205
|
+
deleted.
|
|
206
|
+
|
|
207
|
+
:param str parent_id: optional filter for parent id
|
|
208
|
+
|
|
209
|
+
:returns: The list of deleted objects from storage.
|
|
210
|
+
"""
|
|
211
|
+
parent_id = parent_id or self.parent_id
|
|
212
|
+
deleted = self.storage.delete_all(
|
|
213
|
+
resource_name=self.resource_name,
|
|
214
|
+
parent_id=parent_id,
|
|
215
|
+
filters=filters,
|
|
216
|
+
sorting=sorting,
|
|
217
|
+
pagination_rules=pagination_rules,
|
|
218
|
+
limit=limit,
|
|
219
|
+
id_field=self.id_field,
|
|
220
|
+
modified_field=self.modified_field,
|
|
221
|
+
deleted_field=self.deleted_field,
|
|
222
|
+
)
|
|
223
|
+
# Take a huge shortcut in case we want to delete everything.
|
|
224
|
+
if not filters:
|
|
225
|
+
perm_ids = [self.get_permission_object_id(object_id="*")]
|
|
226
|
+
else:
|
|
227
|
+
perm_ids = [self.get_permission_object_id(object_id=r[self.id_field]) for r in deleted]
|
|
228
|
+
self.permission.delete_object_permissions(*perm_ids)
|
|
229
|
+
return deleted
|
|
230
|
+
|
|
231
|
+
def get_object(self, object_id, parent_id=None):
|
|
232
|
+
"""Fetch current view related object, and raise 404 if missing.
|
|
233
|
+
|
|
234
|
+
:param str object_id: object identifier
|
|
235
|
+
:param str parent_id: optional filter for parent id
|
|
236
|
+
|
|
237
|
+
:returns: the object from storage
|
|
238
|
+
:rtype: dict
|
|
239
|
+
"""
|
|
240
|
+
parent_id = parent_id or self.parent_id
|
|
241
|
+
obj = self.storage.get(
|
|
242
|
+
resource_name=self.resource_name,
|
|
243
|
+
parent_id=parent_id,
|
|
244
|
+
object_id=object_id,
|
|
245
|
+
id_field=self.id_field,
|
|
246
|
+
modified_field=self.modified_field,
|
|
247
|
+
)
|
|
248
|
+
perm_object_id = self.get_permission_object_id(object_id)
|
|
249
|
+
return self._annotate(obj, perm_object_id)
|
|
250
|
+
|
|
251
|
+
def create_object(self, obj, parent_id=None):
|
|
252
|
+
"""Create an object in the resource.
|
|
253
|
+
|
|
254
|
+
The current principal is added to the owner (``write`` permission).
|
|
255
|
+
|
|
256
|
+
Override to perform actions or post-process objects after their
|
|
257
|
+
creation in storage.
|
|
258
|
+
|
|
259
|
+
.. code-block:: python
|
|
260
|
+
|
|
261
|
+
def create_object(self, obj):
|
|
262
|
+
obj = super().create_object(obj)
|
|
263
|
+
idx = index.store(obj)
|
|
264
|
+
object['index'] = idx
|
|
265
|
+
return object
|
|
266
|
+
|
|
267
|
+
:param dict obj: object to store
|
|
268
|
+
:param str parent_id: optional filter for parent id
|
|
269
|
+
|
|
270
|
+
:returns: the newly created object.
|
|
271
|
+
:rtype: dict
|
|
272
|
+
"""
|
|
273
|
+
parent_id = parent_id or self.parent_id
|
|
274
|
+
|
|
275
|
+
permissions = obj.pop(self.permissions_field, {})
|
|
276
|
+
|
|
277
|
+
created = self.storage.create(
|
|
278
|
+
resource_name=self.resource_name,
|
|
279
|
+
parent_id=parent_id,
|
|
280
|
+
obj=obj,
|
|
281
|
+
id_generator=self.id_generator,
|
|
282
|
+
id_field=self.id_field,
|
|
283
|
+
modified_field=self.modified_field,
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
object_id = created[self.id_field]
|
|
287
|
+
perm_object_id = self.get_permission_object_id(object_id)
|
|
288
|
+
self.permission.replace_object_permissions(perm_object_id, permissions)
|
|
289
|
+
self._allow_write(perm_object_id)
|
|
290
|
+
|
|
291
|
+
return self._annotate(created, perm_object_id)
|
|
292
|
+
|
|
293
|
+
def update_object(self, obj, parent_id=None):
|
|
294
|
+
"""Update object and the specified permissions.
|
|
295
|
+
|
|
296
|
+
If no permissions is specified, the current permissions are not
|
|
297
|
+
modified.
|
|
298
|
+
|
|
299
|
+
The current principal is added to the owner (``write`` permission).
|
|
300
|
+
|
|
301
|
+
Override to perform actions or post-process objects after their
|
|
302
|
+
modification in storage.
|
|
303
|
+
|
|
304
|
+
.. code-block:: python
|
|
305
|
+
|
|
306
|
+
def update_object(self, obj, parent_id=None):
|
|
307
|
+
obj = super().update_object(obj, parent_id)
|
|
308
|
+
subject = f'Object {record[self.id_field]} was changed'
|
|
309
|
+
send_email(subject)
|
|
310
|
+
return object
|
|
311
|
+
|
|
312
|
+
:param dict obj: object to store
|
|
313
|
+
:param str parent_id: optional filter for parent id
|
|
314
|
+
:returns: the updated object.
|
|
315
|
+
:rtype: dict
|
|
316
|
+
"""
|
|
317
|
+
parent_id = parent_id or self.parent_id
|
|
318
|
+
object_id = obj[self.id_field]
|
|
319
|
+
permissions = obj.pop(self.permissions_field, {})
|
|
320
|
+
|
|
321
|
+
updated = self.storage.update(
|
|
322
|
+
resource_name=self.resource_name,
|
|
323
|
+
parent_id=parent_id,
|
|
324
|
+
object_id=object_id,
|
|
325
|
+
obj=obj,
|
|
326
|
+
id_field=self.id_field,
|
|
327
|
+
modified_field=self.modified_field,
|
|
328
|
+
)
|
|
329
|
+
|
|
330
|
+
perm_object_id = self.get_permission_object_id(object_id)
|
|
331
|
+
self.permission.replace_object_permissions(perm_object_id, permissions)
|
|
332
|
+
self._allow_write(perm_object_id)
|
|
333
|
+
|
|
334
|
+
return self._annotate(updated, perm_object_id)
|
|
335
|
+
|
|
336
|
+
def delete_object(self, obj, parent_id=None, last_modified=None):
|
|
337
|
+
"""Delete an object and its associated permissions.
|
|
338
|
+
|
|
339
|
+
Override to perform actions or post-process objects after deletion
|
|
340
|
+
from storage for example:
|
|
341
|
+
|
|
342
|
+
.. code-block:: python
|
|
343
|
+
|
|
344
|
+
def delete_object(self, obj):
|
|
345
|
+
deleted = super().delete_object(obj)
|
|
346
|
+
erase_media(obj)
|
|
347
|
+
deleted['media'] = 0
|
|
348
|
+
return deleted
|
|
349
|
+
|
|
350
|
+
:param dict obj: the object to delete
|
|
351
|
+
:param str parent_id: optional filter for parent id
|
|
352
|
+
:returns: the deleted object.
|
|
353
|
+
:rtype: dict
|
|
354
|
+
"""
|
|
355
|
+
parent_id = parent_id or self.parent_id
|
|
356
|
+
object_id = obj[self.id_field]
|
|
357
|
+
perm_object_id = self.get_permission_object_id(object_id)
|
|
358
|
+
|
|
359
|
+
self.permission.delete_object_permissions(perm_object_id)
|
|
360
|
+
|
|
361
|
+
return self.storage.delete(
|
|
362
|
+
resource_name=self.resource_name,
|
|
363
|
+
parent_id=parent_id,
|
|
364
|
+
object_id=object_id,
|
|
365
|
+
id_field=self.id_field,
|
|
366
|
+
modified_field=self.modified_field,
|
|
367
|
+
deleted_field=self.deleted_field,
|
|
368
|
+
last_modified=last_modified,
|
|
369
|
+
)
|
|
370
|
+
|
|
371
|
+
@property
|
|
372
|
+
def collection_id(self):
|
|
373
|
+
message = "`collection_id` is deprecated, use `resource_name` instead."
|
|
374
|
+
warnings.warn(message, DeprecationWarning)
|
|
375
|
+
return self.resource_name
|
|
376
|
+
|
|
377
|
+
def get_records(self, *args, **kwargs):
|
|
378
|
+
message = "`get_records()` is deprecated, use `get_objects()` instead."
|
|
379
|
+
warnings.warn(message, DeprecationWarning)
|
|
380
|
+
return self.get_objects(*args, **kwargs)
|
|
381
|
+
|
|
382
|
+
def delete_records(self, *args, **kwargs):
|
|
383
|
+
message = "`delete_records()` is deprecated, use `delete_objects()` instead."
|
|
384
|
+
warnings.warn(message, DeprecationWarning)
|
|
385
|
+
return self.delete_objects(*args, **kwargs)
|
|
386
|
+
|
|
387
|
+
def get_record(self, record_id, parent_id=None):
|
|
388
|
+
message = "`get_record()` is deprecated, use `get_object()` instead."
|
|
389
|
+
warnings.warn(message, DeprecationWarning)
|
|
390
|
+
return self.get_object(object_id=record_id, parent_id=parent_id)
|
|
391
|
+
|
|
392
|
+
def create_record(self, record, parent_id=None):
|
|
393
|
+
message = "`create_record()` is deprecated, use `create_object()` instead."
|
|
394
|
+
warnings.warn(message, DeprecationWarning)
|
|
395
|
+
return self.create_object(obj=record, parent_id=parent_id)
|
|
396
|
+
|
|
397
|
+
def update_record(self, record, parent_id=None):
|
|
398
|
+
message = "`update_record()` is deprecated, use `update_object()` instead."
|
|
399
|
+
warnings.warn(message, DeprecationWarning)
|
|
400
|
+
return self.update_object(obj=record, parent_id=parent_id)
|
|
401
|
+
|
|
402
|
+
def delete_record(self, record, parent_id=None, last_modified=None):
|
|
403
|
+
message = "`delete_record()` is deprecated, use `delete_object()` instead."
|
|
404
|
+
warnings.warn(message, DeprecationWarning)
|
|
405
|
+
return self.delete_object(obj=record, parent_id=parent_id, last_modified=last_modified)
|
|
406
|
+
|
|
407
|
+
|
|
408
|
+
class ShareableModel(Model):
|
|
409
|
+
def __init__(self, *args, **kwargs):
|
|
410
|
+
message = "`ShareableModel` is deprecated, use `Model` instead."
|
|
411
|
+
warnings.warn(message, DeprecationWarning)
|
|
412
|
+
super().__init__(*args, **kwargs)
|