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.
Files changed (142) hide show
  1. kinto/__init__.py +92 -0
  2. kinto/__main__.py +249 -0
  3. kinto/authorization.py +134 -0
  4. kinto/config/__init__.py +94 -0
  5. kinto/config/kinto.tpl +270 -0
  6. kinto/contribute.json +27 -0
  7. kinto/core/__init__.py +246 -0
  8. kinto/core/authentication.py +48 -0
  9. kinto/core/authorization.py +311 -0
  10. kinto/core/cache/__init__.py +131 -0
  11. kinto/core/cache/memcached.py +112 -0
  12. kinto/core/cache/memory.py +104 -0
  13. kinto/core/cache/postgresql/__init__.py +178 -0
  14. kinto/core/cache/postgresql/schema.sql +23 -0
  15. kinto/core/cache/testing.py +208 -0
  16. kinto/core/cornice/__init__.py +93 -0
  17. kinto/core/cornice/cors.py +144 -0
  18. kinto/core/cornice/errors.py +40 -0
  19. kinto/core/cornice/pyramidhook.py +373 -0
  20. kinto/core/cornice/renderer.py +89 -0
  21. kinto/core/cornice/resource.py +205 -0
  22. kinto/core/cornice/service.py +641 -0
  23. kinto/core/cornice/util.py +138 -0
  24. kinto/core/cornice/validators/__init__.py +94 -0
  25. kinto/core/cornice/validators/_colander.py +142 -0
  26. kinto/core/cornice/validators/_marshmallow.py +182 -0
  27. kinto/core/cornice_swagger/__init__.py +92 -0
  28. kinto/core/cornice_swagger/converters/__init__.py +21 -0
  29. kinto/core/cornice_swagger/converters/exceptions.py +6 -0
  30. kinto/core/cornice_swagger/converters/parameters.py +90 -0
  31. kinto/core/cornice_swagger/converters/schema.py +249 -0
  32. kinto/core/cornice_swagger/swagger.py +725 -0
  33. kinto/core/cornice_swagger/templates/index.html +73 -0
  34. kinto/core/cornice_swagger/templates/index_script_template.html +21 -0
  35. kinto/core/cornice_swagger/util.py +42 -0
  36. kinto/core/cornice_swagger/views.py +78 -0
  37. kinto/core/decorators.py +74 -0
  38. kinto/core/errors.py +216 -0
  39. kinto/core/events.py +301 -0
  40. kinto/core/initialization.py +738 -0
  41. kinto/core/listeners/__init__.py +9 -0
  42. kinto/core/metrics.py +94 -0
  43. kinto/core/openapi.py +115 -0
  44. kinto/core/permission/__init__.py +202 -0
  45. kinto/core/permission/memory.py +167 -0
  46. kinto/core/permission/postgresql/__init__.py +489 -0
  47. kinto/core/permission/postgresql/migrations/migration_001_002.sql +18 -0
  48. kinto/core/permission/postgresql/schema.sql +41 -0
  49. kinto/core/permission/testing.py +487 -0
  50. kinto/core/resource/__init__.py +1311 -0
  51. kinto/core/resource/model.py +412 -0
  52. kinto/core/resource/schema.py +502 -0
  53. kinto/core/resource/viewset.py +230 -0
  54. kinto/core/schema.py +119 -0
  55. kinto/core/scripts.py +50 -0
  56. kinto/core/statsd.py +1 -0
  57. kinto/core/storage/__init__.py +436 -0
  58. kinto/core/storage/exceptions.py +53 -0
  59. kinto/core/storage/generators.py +58 -0
  60. kinto/core/storage/memory.py +651 -0
  61. kinto/core/storage/postgresql/__init__.py +1131 -0
  62. kinto/core/storage/postgresql/client.py +120 -0
  63. kinto/core/storage/postgresql/migrations/migration_001_002.sql +10 -0
  64. kinto/core/storage/postgresql/migrations/migration_002_003.sql +33 -0
  65. kinto/core/storage/postgresql/migrations/migration_003_004.sql +18 -0
  66. kinto/core/storage/postgresql/migrations/migration_004_005.sql +20 -0
  67. kinto/core/storage/postgresql/migrations/migration_005_006.sql +11 -0
  68. kinto/core/storage/postgresql/migrations/migration_006_007.sql +74 -0
  69. kinto/core/storage/postgresql/migrations/migration_007_008.sql +66 -0
  70. kinto/core/storage/postgresql/migrations/migration_008_009.sql +41 -0
  71. kinto/core/storage/postgresql/migrations/migration_009_010.sql +98 -0
  72. kinto/core/storage/postgresql/migrations/migration_010_011.sql +14 -0
  73. kinto/core/storage/postgresql/migrations/migration_011_012.sql +9 -0
  74. kinto/core/storage/postgresql/migrations/migration_012_013.sql +71 -0
  75. kinto/core/storage/postgresql/migrations/migration_013_014.sql +14 -0
  76. kinto/core/storage/postgresql/migrations/migration_014_015.sql +95 -0
  77. kinto/core/storage/postgresql/migrations/migration_015_016.sql +4 -0
  78. kinto/core/storage/postgresql/migrations/migration_016_017.sql +81 -0
  79. kinto/core/storage/postgresql/migrations/migration_017_018.sql +25 -0
  80. kinto/core/storage/postgresql/migrations/migration_018_019.sql +8 -0
  81. kinto/core/storage/postgresql/migrations/migration_019_020.sql +7 -0
  82. kinto/core/storage/postgresql/migrations/migration_020_021.sql +68 -0
  83. kinto/core/storage/postgresql/migrations/migration_021_022.sql +62 -0
  84. kinto/core/storage/postgresql/migrations/migration_022_023.sql +5 -0
  85. kinto/core/storage/postgresql/migrations/migration_023_024.sql +6 -0
  86. kinto/core/storage/postgresql/migrations/migration_024_025.sql +6 -0
  87. kinto/core/storage/postgresql/migrator.py +98 -0
  88. kinto/core/storage/postgresql/pool.py +55 -0
  89. kinto/core/storage/postgresql/schema.sql +143 -0
  90. kinto/core/storage/testing.py +1857 -0
  91. kinto/core/storage/utils.py +37 -0
  92. kinto/core/testing.py +182 -0
  93. kinto/core/utils.py +553 -0
  94. kinto/core/views/__init__.py +0 -0
  95. kinto/core/views/batch.py +163 -0
  96. kinto/core/views/errors.py +145 -0
  97. kinto/core/views/heartbeat.py +106 -0
  98. kinto/core/views/hello.py +69 -0
  99. kinto/core/views/openapi.py +35 -0
  100. kinto/core/views/version.py +50 -0
  101. kinto/events.py +3 -0
  102. kinto/plugins/__init__.py +0 -0
  103. kinto/plugins/accounts/__init__.py +94 -0
  104. kinto/plugins/accounts/authentication.py +63 -0
  105. kinto/plugins/accounts/scripts.py +61 -0
  106. kinto/plugins/accounts/utils.py +13 -0
  107. kinto/plugins/accounts/views.py +136 -0
  108. kinto/plugins/admin/README.md +3 -0
  109. kinto/plugins/admin/VERSION +1 -0
  110. kinto/plugins/admin/__init__.py +40 -0
  111. kinto/plugins/admin/build/VERSION +1 -0
  112. kinto/plugins/admin/build/assets/index-CYFwtKtL.css +6 -0
  113. kinto/plugins/admin/build/assets/index-DJ0m93zA.js +149 -0
  114. kinto/plugins/admin/build/assets/logo-VBRiKSPX.png +0 -0
  115. kinto/plugins/admin/build/index.html +18 -0
  116. kinto/plugins/admin/public/help.html +25 -0
  117. kinto/plugins/admin/views.py +42 -0
  118. kinto/plugins/default_bucket/__init__.py +191 -0
  119. kinto/plugins/flush.py +28 -0
  120. kinto/plugins/history/__init__.py +65 -0
  121. kinto/plugins/history/listener.py +181 -0
  122. kinto/plugins/history/views.py +66 -0
  123. kinto/plugins/openid/__init__.py +131 -0
  124. kinto/plugins/openid/utils.py +14 -0
  125. kinto/plugins/openid/views.py +193 -0
  126. kinto/plugins/prometheus.py +300 -0
  127. kinto/plugins/statsd.py +85 -0
  128. kinto/schema_validation.py +135 -0
  129. kinto/views/__init__.py +34 -0
  130. kinto/views/admin.py +195 -0
  131. kinto/views/buckets.py +45 -0
  132. kinto/views/collections.py +58 -0
  133. kinto/views/contribute.py +39 -0
  134. kinto/views/groups.py +90 -0
  135. kinto/views/permissions.py +235 -0
  136. kinto/views/records.py +133 -0
  137. kinto-23.2.1.dist-info/METADATA +232 -0
  138. kinto-23.2.1.dist-info/RECORD +142 -0
  139. kinto-23.2.1.dist-info/WHEEL +5 -0
  140. kinto-23.2.1.dist-info/entry_points.txt +5 -0
  141. kinto-23.2.1.dist-info/licenses/LICENSE +13 -0
  142. kinto-23.2.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,487 @@
1
+ from unittest import mock
2
+
3
+ from pyramid import testing
4
+
5
+ from kinto.core.permission import heartbeat
6
+ from kinto.core.storage import exceptions
7
+ from kinto.core.testing import DummyRequest
8
+
9
+
10
+ class PermissionTest:
11
+ backend = None
12
+ settings = {}
13
+
14
+ def setUp(self):
15
+ super().setUp()
16
+ self.permission = self.backend.load_from_config(self._get_config())
17
+ self.permission.initialize_schema()
18
+ self.request = DummyRequest()
19
+ self.client_error_patcher = []
20
+
21
+ def _get_config(self):
22
+ """Mock Pyramid config object."""
23
+ config = testing.setUp()
24
+ config.add_settings(self.settings)
25
+ return config
26
+
27
+ def tearDown(self):
28
+ mock.patch.stopall()
29
+ super().tearDown()
30
+ self.permission.flush()
31
+
32
+ def test_backend_error_is_raised_anywhere(self):
33
+ for patch in self.client_error_patcher:
34
+ patch.start()
35
+ calls = [
36
+ (self.permission.flush,),
37
+ (self.permission.add_user_principal, "", ""),
38
+ (self.permission.remove_user_principal, "", ""),
39
+ (self.permission.get_user_principals, ""),
40
+ (self.permission.add_principal_to_ace, "", "", ""),
41
+ (self.permission.remove_principal_from_ace, "", "", ""),
42
+ (self.permission.get_object_permission_principals, "", ""),
43
+ (self.permission.get_object_permissions, ""),
44
+ (self.permission.replace_object_permissions, "", {"write": []}),
45
+ (self.permission.delete_object_permissions, ""),
46
+ (self.permission.get_accessible_objects, []),
47
+ (self.permission.get_authorized_principals, [("*", "read")]),
48
+ ]
49
+ for call in calls:
50
+ self.assertRaises(exceptions.BackendError, *call)
51
+
52
+ def test_initialize_schema_is_idempotent(self):
53
+ self.permission.initialize_schema()
54
+ self.permission.initialize_schema() # not raising.
55
+
56
+ def test_ping_returns_false_if_unavailable(self):
57
+ ping = heartbeat(self.permission)
58
+ for patch in self.client_error_patcher:
59
+ patch.start()
60
+ self.assertFalse(ping(self.request))
61
+
62
+ def test_ping_returns_true_if_available(self):
63
+ ping = heartbeat(self.permission)
64
+ self.assertTrue(ping(self.request))
65
+
66
+ def test_ping_returns_false_if_unavailable_in_readonly_mode(self):
67
+ self.request.registry.settings["readonly"] = "true"
68
+ ping = heartbeat(self.permission)
69
+ with mock.patch.object(
70
+ self.permission, "get_user_principals", side_effect=exceptions.BackendError("Boom!")
71
+ ):
72
+ self.assertFalse(ping(self.request))
73
+
74
+ def test_ping_returns_true_if_available_in_readonly_mode(self):
75
+ self.request.registry.settings["readonly"] = "true"
76
+ ping = heartbeat(self.permission)
77
+ self.assertTrue(ping(self.request))
78
+
79
+ def test_ping_logs_error_if_unavailable(self):
80
+ for patch in self.client_error_patcher:
81
+ patch.start()
82
+ ping = heartbeat(self.permission)
83
+
84
+ with mock.patch("kinto.core.permission.logger.exception") as exc_handler:
85
+ self.assertFalse(ping(self.request))
86
+
87
+ self.assertTrue(exc_handler.called)
88
+
89
+ def test_can_add_a_principal_to_a_user(self):
90
+ user_id = "foo"
91
+ principal = "bar"
92
+ self.permission.add_user_principal(user_id, principal)
93
+ retrieved = self.permission.get_user_principals(user_id)
94
+ self.assertEqual(retrieved, {principal})
95
+
96
+ def test_add_twice_a_principal_to_a_user_add_it_once(self):
97
+ user_id = "foo"
98
+ principal = "bar"
99
+ self.permission.add_user_principal(user_id, principal)
100
+ self.permission.add_user_principal(user_id, principal)
101
+ retrieved = self.permission.get_user_principals(user_id)
102
+ self.assertEqual(retrieved, {principal})
103
+
104
+ def test_can_remove_a_principal_for_an_unknown_user(self):
105
+ self.permission.remove_user_principal("foo", "bar")
106
+
107
+ def test_can_remove_a_principal_for_a_user(self):
108
+ user_id = "foo"
109
+ principal = "bar"
110
+ principal2 = "foobar"
111
+ self.permission.add_user_principal(user_id, principal)
112
+ self.permission.add_user_principal(user_id, principal2)
113
+ self.permission.remove_user_principal(user_id, principal)
114
+ retrieved = self.permission.get_user_principals(user_id)
115
+ self.assertEqual(retrieved, {principal2})
116
+
117
+ def test_can_remove_a_unexisting_principal_to_a_user(self):
118
+ user_id = "foo"
119
+ principal = "bar"
120
+ principal2 = "foobar"
121
+ self.permission.add_user_principal(user_id, principal2)
122
+ self.permission.remove_user_principal(user_id, principal)
123
+ self.permission.remove_user_principal(user_id, principal2)
124
+ retrieved = self.permission.get_user_principals(user_id)
125
+ self.assertEqual(retrieved, set())
126
+
127
+ def test_can_remove_principal_from_every_users(self):
128
+ user_id1 = "foo1"
129
+ user_id2 = "foo2"
130
+ principal1 = "bar"
131
+ principal2 = "foobar"
132
+ self.permission.add_user_principal(user_id1, principal1)
133
+ self.permission.add_user_principal(user_id2, principal1)
134
+ self.permission.add_user_principal(user_id2, principal2)
135
+ self.permission.remove_principal(principal1)
136
+ self.permission.remove_principal("unknown")
137
+
138
+ retrieved = self.permission.get_user_principals(user_id1)
139
+ self.assertEqual(retrieved, set())
140
+ retrieved = self.permission.get_user_principals(user_id2)
141
+ self.assertEqual(retrieved, {principal2})
142
+
143
+ def test_cannot_remove_principal_from_objects(self):
144
+ object_id = "/buckets/some-bucket"
145
+ user_id = "user"
146
+ principal = "readers-group"
147
+ self.permission.add_principal_to_ace(object_id, "read", principal)
148
+ self.permission.add_user_principal(user_id, principal)
149
+ self.permission.remove_principal(principal)
150
+
151
+ retrieved = self.permission.get_object_permissions(object_id)
152
+ self.assertEqual(retrieved, {"read": set([principal])})
153
+
154
+ def test_authenticated_is_returned_for_everybody(self):
155
+ user_id = "foo"
156
+ principal = "bar"
157
+ self.permission.add_user_principal("system.Authenticated", principal)
158
+ retrieved = self.permission.get_user_principals(user_id)
159
+ self.assertEqual(retrieved, {principal})
160
+
161
+ #
162
+ # get_object_permission_principals()
163
+ #
164
+
165
+ def test_can_add_a_principal_to_an_object_permission(self):
166
+ object_id = "foo"
167
+ permission = "write"
168
+ principal = "bar"
169
+ self.permission.add_principal_to_ace(object_id, permission, principal)
170
+ retrieved = self.permission.get_object_permission_principals(object_id, permission)
171
+ self.assertEqual(retrieved, {principal})
172
+
173
+ def test_add_twice_a_principal_to_an_object_permission_add_it_once(self):
174
+ object_id = "foo"
175
+ permission = "write"
176
+ principal = "bar"
177
+ self.permission.add_principal_to_ace(object_id, permission, principal)
178
+ self.permission.add_principal_to_ace(object_id, permission, principal)
179
+ retrieved = self.permission.get_object_permission_principals(object_id, permission)
180
+ self.assertEqual(retrieved, {principal})
181
+
182
+ def test_can_remove_a_principal_from_an_object_permission(self):
183
+ object_id = "foo"
184
+ permission = "write"
185
+ principal = "bar"
186
+ principal2 = "foobar"
187
+ self.permission.add_principal_to_ace(object_id, permission, principal)
188
+ self.permission.add_principal_to_ace(object_id, permission, principal2)
189
+ self.permission.remove_principal_from_ace(object_id, permission, principal)
190
+ retrieved = self.permission.get_object_permission_principals(object_id, permission)
191
+ self.assertEqual(retrieved, {principal2})
192
+
193
+ def test_principals_is_empty_if_no_permission(self):
194
+ object_id = "foo"
195
+ permission = "write"
196
+ principal = "bar"
197
+ self.permission.add_principal_to_ace(object_id, permission, principal)
198
+ self.permission.remove_principal_from_ace(object_id, permission, principal)
199
+ retrieved = self.permission.get_object_permission_principals(object_id, permission)
200
+ self.assertEqual(retrieved, set())
201
+
202
+ def test_can_remove_an_unexisting_principal_to_an_object_permission(self):
203
+ object_id = "foo"
204
+ permission = "write"
205
+ principal = "bar"
206
+ principal2 = "foobar"
207
+ self.permission.add_principal_to_ace(object_id, permission, principal2)
208
+ self.permission.remove_principal_from_ace(object_id, permission, principal)
209
+ retrieved = self.permission.get_object_permission_principals(object_id, permission)
210
+ self.assertEqual(retrieved, {principal2})
211
+
212
+ #
213
+ # check_permission()
214
+ #
215
+
216
+ def test_check_permission_returns_true_for_userid(self):
217
+ object_id = "foo"
218
+ permission = "write"
219
+ principal = "bar"
220
+ self.permission.add_principal_to_ace(object_id, permission, principal)
221
+ check_permission = self.permission.check_permission({principal}, [(object_id, permission)])
222
+ self.assertTrue(check_permission)
223
+
224
+ def test_check_permission_returns_true_for_userid_group(self):
225
+ object_id = "foo"
226
+ permission = "write"
227
+ group_id = "bar"
228
+ user_id = "foobar"
229
+ self.permission.add_user_principal(user_id, group_id)
230
+ self.permission.add_principal_to_ace(object_id, permission, group_id)
231
+ check_permission = self.permission.check_permission(
232
+ {user_id, group_id}, [(object_id, permission)]
233
+ )
234
+ self.assertTrue(check_permission)
235
+
236
+ def test_check_permission_returns_true_for_object_inherited(self):
237
+ object_id = "foo"
238
+ user_id = "bar"
239
+ self.permission.add_principal_to_ace(object_id, "write", user_id)
240
+ check_permission = self.permission.check_permission(
241
+ {user_id}, [(object_id, "write"), (object_id, "read")]
242
+ )
243
+ self.assertTrue(check_permission)
244
+
245
+ def test_check_permissions_handles_empty_set(self):
246
+ principal = "bar"
247
+ permits = self.permission.check_permission({principal}, [])
248
+ self.assertFalse(permits)
249
+
250
+ def test_check_permission_return_false_for_unknown_principal(self):
251
+ object_id = "foo"
252
+ permission = "write"
253
+ principal = "bar"
254
+ check_permission = self.permission.check_permission({principal}, [(object_id, permission)])
255
+ self.assertFalse(check_permission)
256
+
257
+ #
258
+ # get_authorized_principals()
259
+ #
260
+
261
+ def test_get_authorized_principals_inherit_principals(self):
262
+ object_id = "foo"
263
+ user_id = "bar"
264
+ self.permission.add_principal_to_ace(object_id, "write", user_id)
265
+ principals = self.permission.get_authorized_principals(
266
+ [(object_id, "write"), (object_id, "read")]
267
+ )
268
+ self.assertEqual(principals, {user_id})
269
+
270
+ def test_get_authorized_principals_handles_empty_set(self):
271
+ principals = self.permission.get_authorized_principals([])
272
+ self.assertEqual(principals, set())
273
+
274
+ #
275
+ # get_accessible_objects()
276
+ #
277
+
278
+ def test_accessible_objects(self):
279
+ self.permission.add_principal_to_ace("id1", "write", "user1")
280
+ self.permission.add_principal_to_ace("id1", "object:create", "group")
281
+ self.permission.add_principal_to_ace("id2", "read", "user1")
282
+ self.permission.add_principal_to_ace("id2", "read", "user2")
283
+ self.permission.add_principal_to_ace("id3", "write", "user2")
284
+ per_object_ids = self.permission.get_accessible_objects(["user1", "group"])
285
+ self.assertEqual(sorted(per_object_ids.keys()), ["id1", "id2"])
286
+ self.assertEqual(per_object_ids["id1"], set(["write", "object:create"]))
287
+ self.assertEqual(per_object_ids["id2"], set(["read"]))
288
+
289
+ def test_accessible_objects_supports_empty_list(self):
290
+ per_object_ids = self.permission.get_accessible_objects(["user1", "group"], [])
291
+ self.assertEqual(per_object_ids, {})
292
+
293
+ def test_accessible_objects_from_permission(self):
294
+ self.permission.add_principal_to_ace("id1", "write", "user1")
295
+ self.permission.add_principal_to_ace("id1", "read", "user1")
296
+ self.permission.add_principal_to_ace("id1", "read", "group")
297
+ self.permission.add_principal_to_ace("id2", "write", "user1")
298
+ self.permission.add_principal_to_ace("id2", "read", "user2")
299
+ self.permission.add_principal_to_ace("id2", "read", "group")
300
+ self.permission.add_principal_to_ace("id3", "read", "user2")
301
+ per_object_ids = self.permission.get_accessible_objects(
302
+ ["user1", "group"], [("*", "read")]
303
+ )
304
+ self.assertEqual(sorted(per_object_ids.keys()), ["id1", "id2"])
305
+
306
+ def test_accessible_objects_with_pattern(self):
307
+ self.permission.add_principal_to_ace("/url1/id", "write", "user1")
308
+ self.permission.add_principal_to_ace("/url2/id", "write", "user1")
309
+ per_object_ids = self.permission.get_accessible_objects(["user1"], [("*url1*", "write")])
310
+ self.assertEqual(sorted(per_object_ids.keys()), ["/url1/id"])
311
+
312
+ def test_accessible_objects_with_pattern_matches_whole_id(self):
313
+ self.permission.add_principal_to_ace("/url1/id", "write", "user1")
314
+ self.permission.add_principal_to_ace("/url1/id/sub", "write", "user1")
315
+ self.permission.add_principal_to_ace("/a/url1/id", "write", "user1")
316
+ per_object_ids = self.permission.get_accessible_objects(
317
+ ["user1"], [("/url1/*", "write")], with_children=False
318
+ )
319
+ self.assertEqual(sorted(per_object_ids.keys()), ["/url1/id"])
320
+
321
+ def test_accessible_objects_several_bound_permissions(self):
322
+ self.permission.add_principal_to_ace("/url/a/id/1", "write", "user1")
323
+ self.permission.add_principal_to_ace("/url/a/id/2", "read", "user1")
324
+ self.permission.add_principal_to_ace("/url/_/id/2", "read", "user1")
325
+ per_object_ids = self.permission.get_accessible_objects(
326
+ ["user1"], [("/url/a/id/*", "read"), ("/url/a/id/*", "write")]
327
+ )
328
+ self.assertEqual(sorted(per_object_ids.keys()), ["/url/a/id/1", "/url/a/id/2"])
329
+
330
+ def test_accessible_objects_without_match(self):
331
+ self.permission.add_principal_to_ace("/url/a", "write", "user1")
332
+ self.permission.add_principal_to_ace("/url/a/id/1", "write", "user1")
333
+ self.permission.add_principal_to_ace("/url/b/id/1", "write", "user1")
334
+ self.permission.add_principal_to_ace("/url/a/id/2", "read", "user1")
335
+ self.permission.add_principal_to_ace("/url/b/id/2", "read", "user1")
336
+ per_object_ids = self.permission.get_accessible_objects(
337
+ ["user1"],
338
+ [
339
+ ("/url/a", "write"),
340
+ ("/url/a", "read"),
341
+ ("/url/a/id/*", "write"),
342
+ ("/url/a/id/*", "read"),
343
+ ],
344
+ )
345
+ self.assertEqual(sorted(per_object_ids.keys()), ["/url/a", "/url/a/id/1", "/url/a/id/2"])
346
+
347
+ def test_accessible_objects_with_user_principle(self):
348
+ self.permission.add_user_principal("user1", "group")
349
+ self.permission.add_principal_to_ace("id1", "write", "user1")
350
+ per_object_ids = self.permission.get_accessible_objects(["user1"])
351
+ self.assertEqual(sorted(per_object_ids.keys()), ["id1"])
352
+
353
+ #
354
+ # get_object_permissions()
355
+ #
356
+
357
+ def test_object_permissions_return_all_object_acls(self):
358
+ self.permission.add_principal_to_ace("/url/a/id/1", "write", "user1")
359
+ self.permission.add_principal_to_ace("/url/a/id/1", "write", "user2")
360
+ self.permission.add_principal_to_ace("/url/a/id/1", "read", "user3")
361
+ self.permission.add_principal_to_ace("/url/a/id/1", "obj:del", "user1")
362
+ self.permission.add_principal_to_ace("/url/a/id/1/sub", "create", "me")
363
+ permissions = self.permission.get_object_permissions("/url/a/id/1")
364
+ self.assertDictEqual(
365
+ permissions, {"write": {"user1", "user2"}, "read": {"user3"}, "obj:del": {"user1"}}
366
+ )
367
+
368
+ def test_object_permissions_return_listed_object_acls(self):
369
+ self.permission.add_principal_to_ace("/url/a/id/1", "write", "user1")
370
+ self.permission.add_principal_to_ace("/url/a/id/1", "write", "user2")
371
+ self.permission.add_principal_to_ace("/url/a/id/1", "read", "user3")
372
+ self.permission.add_principal_to_ace("/url/a/id/1", "create", "user1")
373
+ object_permissions = self.permission.get_object_permissions(
374
+ "/url/a/id/1", ["write", "read"]
375
+ )
376
+ self.assertDictEqual(object_permissions, {"write": {"user1", "user2"}, "read": {"user3"}})
377
+
378
+ def test_objects_permissions_returns_empty_if_unknown(self):
379
+ self.permission.add_principal_to_ace("/url/a/id/1", "write", "user1")
380
+ self.permission.add_principal_to_ace("/url/a/id/3", "read", "user3")
381
+ objects_permissions = self.permission.get_objects_permissions(
382
+ ["/url/a/id/1", "/abc", "/url/a/id/3"]
383
+ )
384
+ self.assertEqual(objects_permissions, [{"write": {"user1"}}, {}, {"read": {"user3"}}])
385
+
386
+ def test_object_permissions_return_empty_dict(self):
387
+ self.assertDictEqual(self.permission.get_object_permissions("abc"), {})
388
+
389
+ def test_replace_object_permission_replace_all_given_sets(self):
390
+ self.permission.add_principal_to_ace("/url/a/id/1", "write", "user1")
391
+ self.permission.add_principal_to_ace("/url/a/id/1", "write", "user2")
392
+ self.permission.add_principal_to_ace("/url/a/id/1", "read", "user3")
393
+ self.permission.add_principal_to_ace("/url/a/id/1", "update", "user1")
394
+ self.permission.add_principal_to_ace("/url/a/id/1", "obj:del", "user1")
395
+
396
+ self.permission.replace_object_permissions(
397
+ "/url/a/id/1",
398
+ {
399
+ "write": ["user1"],
400
+ "read": ["user2"],
401
+ "update": [],
402
+ "obj:del": ["user1"],
403
+ "new": ["user3"],
404
+ },
405
+ )
406
+
407
+ permissions = self.permission.get_object_permissions("/url/a/id/1")
408
+ self.assertDictEqual(
409
+ permissions,
410
+ {"write": {"user1"}, "read": {"user2"}, "obj:del": {"user1"}, "new": {"user3"}},
411
+ )
412
+
413
+ def test_replace_object_permission_only_replace_given_sets(self):
414
+ self.permission.add_principal_to_ace("/url/a/id/1", "write", "user1")
415
+ self.permission.add_principal_to_ace("/url/a/id/1", "write", "user2")
416
+ self.permission.add_principal_to_ace("/url/a/id/1", "read", "user3")
417
+ self.permission.add_principal_to_ace("/url/a/id/1", "obj:del", "user1")
418
+
419
+ self.permission.replace_object_permissions(
420
+ "/url/a/id/1", {"write": ["user1"], "new": set(["user2"])}
421
+ )
422
+
423
+ permissions = self.permission.get_object_permissions("/url/a/id/1")
424
+ self.assertDictEqual(
425
+ permissions,
426
+ {"write": {"user1"}, "read": {"user3"}, "new": {"user2"}, "obj:del": {"user1"}},
427
+ )
428
+
429
+ def test_replace_object_permission_supports_empty_existing_entries(self):
430
+ self.permission.replace_object_permissions("/url/a/id/1", {"write": ["user1"]})
431
+ permissions = self.permission.get_object_permissions("/url/a/id/1")
432
+ self.assertDictEqual(permissions, {"write": {"user1"}})
433
+
434
+ def test_replace_object_permission_supports_empty_input(self):
435
+ self.permission.add_principal_to_ace("/url/a/id/1", "write", "user1")
436
+ self.permission.replace_object_permissions("/url/a/id/1", {})
437
+ permissions = self.permission.get_object_permissions("/url/a/id/1")
438
+ self.assertDictEqual(permissions, {"write": {"user1"}})
439
+
440
+ def test_replace_object_permission_supports_duplicated_entries(self):
441
+ self.permission.add_principal_to_ace("/url/a/id/1", "write", "user1")
442
+ self.permission.replace_object_permissions("/url/a/id/1", {"write": ["user1", "user1"]})
443
+ permissions = self.permission.get_object_permissions("/url/a/id/1")
444
+ self.assertDictEqual(permissions, {"write": {"user1"}})
445
+
446
+ def test_replace_object_permission_supports_empty_list(self):
447
+ self.permission.add_principal_to_ace("/url/a/id/1", "write", "user1")
448
+ self.permission.replace_object_permissions("/url/a/id/1", {"write": set()})
449
+ permissions = self.permission.get_object_permissions("/url/a/id/1")
450
+ self.assertEqual(len(permissions), 0)
451
+
452
+ def test_replace_object_permission_supports_empty_list_to_new_object(self):
453
+ self.permission.replace_object_permissions("/url/a/id/1", {"write": set()})
454
+ permissions = self.permission.get_object_permissions("/url/a/id/1")
455
+ self.assertEqual(len(permissions), 0)
456
+
457
+ def test_delete_object_permissions_remove_all_given_objects_acls(self):
458
+ self.permission.add_principal_to_ace("/url/a/id/1", "write", "user1")
459
+ self.permission.add_principal_to_ace("/url/a/id/1", "write", "user2")
460
+ self.permission.add_principal_to_ace("/url/a/id/1", "read", "user3")
461
+ self.permission.add_principal_to_ace("/url/a/id/1", "create", "user1")
462
+ self.permission.add_principal_to_ace("/url/a/id/2", "create", "user3")
463
+ self.permission.add_principal_to_ace("/url/a/id/3", "create", "user4")
464
+
465
+ self.permission.delete_object_permissions("/url/a/id/1", "/url/a/id/2")
466
+
467
+ self.assertDictEqual(self.permission.get_object_permissions("/url/a/id/1"), {})
468
+ self.assertDictEqual(self.permission.get_object_permissions("/url/a/id/2"), {})
469
+ self.assertDictEqual(
470
+ self.permission.get_object_permissions("/url/a/id/3"), {"create": {"user4"}}
471
+ )
472
+
473
+ def test_delete_object_permissions_supports_empty_list(self):
474
+ self.permission.delete_object_permissions() # Not failing
475
+
476
+ def test_delete_object_permissions_supports_pattern_matching(self):
477
+ self.permission.add_principal_to_ace("/url/b/id/1", "write", "user1")
478
+ self.permission.add_principal_to_ace("/url/a/id/1", "write", "user2")
479
+ self.permission.add_principal_to_ace("/url/a/id/1", "read", "user3")
480
+ self.permission.add_principal_to_ace("/url/a/id/3", "create", "user4")
481
+
482
+ self.permission.delete_object_permissions("/url/a*")
483
+
484
+ self.assertDictEqual(self.permission.get_object_permissions("/url/a/id/1"), {})
485
+ self.assertDictEqual(
486
+ self.permission.get_object_permissions("/url/b/id/1"), {"write": {"user1"}}
487
+ )