@@ -224,12 +224,7 @@ def test_api_document_accesses_list_authenticated_related_privileged(
224
224
other_access = factories .UserDocumentAccessFactory (user = user )
225
225
factories .UserDocumentAccessFactory (document = other_access .document )
226
226
227
- nb_queries = 3
228
- if role == "owner" :
229
- # Queries that secure the owner status
230
- nb_queries += sum (acc .role == "owner" for acc in document_accesses )
231
-
232
- with django_assert_num_queries (nb_queries ):
227
+ with django_assert_num_queries (3 ):
233
228
response = client .get (f"/api/v1.0/documents/{ document .id !s} /accesses/" )
234
229
235
230
assert response .status_code == 200
@@ -335,7 +330,12 @@ def test_api_document_accesses_retrieve_set_role_to_child():
335
330
],
336
331
[
337
332
["owner" , "reader" , "reader" , "reader" ],
338
- [[], [], [], ["reader" , "editor" , "administrator" , "owner" ]],
333
+ [
334
+ ["reader" , "editor" , "administrator" , "owner" ],
335
+ [],
336
+ [],
337
+ ["reader" , "editor" , "administrator" , "owner" ],
338
+ ],
339
339
],
340
340
[
341
341
["owner" , "reader" , "reader" , "owner" ],
@@ -412,7 +412,12 @@ def test_api_document_accesses_list_authenticated_related_same_user(roles, resul
412
412
],
413
413
[
414
414
["owner" , "reader" , "reader" , "reader" ],
415
- [[], [], [], ["reader" , "editor" , "administrator" , "owner" ]],
415
+ [
416
+ ["reader" , "editor" , "administrator" , "owner" ],
417
+ [],
418
+ [],
419
+ ["reader" , "editor" , "administrator" , "owner" ],
420
+ ],
416
421
],
417
422
[
418
423
["owner" , "reader" , "reader" , "owner" ],
@@ -425,7 +430,12 @@ def test_api_document_accesses_list_authenticated_related_same_user(roles, resul
425
430
],
426
431
[
427
432
["reader" , "reader" , "reader" , "owner" ],
428
- [["reader" , "editor" , "administrator" , "owner" ], [], [], []],
433
+ [
434
+ ["reader" , "editor" , "administrator" , "owner" ],
435
+ [],
436
+ [],
437
+ ["reader" , "editor" , "administrator" , "owner" ],
438
+ ],
429
439
],
430
440
[
431
441
["reader" , "administrator" , "reader" , "editor" ],
@@ -929,7 +939,7 @@ def test_api_document_accesses_update_owner(
929
939
930
940
931
941
@pytest .mark .parametrize ("via" , VIA )
932
- def test_api_document_accesses_update_owner_self (
942
+ def test_api_document_accesses_update_owner_self_root (
933
943
via ,
934
944
mock_user_teams ,
935
945
mock_reset_connections , # pylint: disable=redefined-outer-name
@@ -990,6 +1000,51 @@ def test_api_document_accesses_update_owner_self(
990
1000
assert access .role == new_role
991
1001
992
1002
1003
+ @pytest .mark .parametrize ("via" , VIA )
1004
+ def test_api_document_accesses_update_owner_self_child (
1005
+ via ,
1006
+ mock_user_teams ,
1007
+ mock_reset_connections , # pylint: disable=redefined-outer-name
1008
+ ):
1009
+ """
1010
+ A user who is owner of a document should be allowed to update
1011
+ their own user access even if they are the only owner in the document,
1012
+ provided the document is not a root.
1013
+ """
1014
+ user = factories .UserFactory (with_owned_document = True )
1015
+
1016
+ client = APIClient ()
1017
+ client .force_login (user )
1018
+
1019
+ parent = factories .DocumentFactory ()
1020
+ document = factories .DocumentFactory (parent = parent )
1021
+ access = None
1022
+ if via == USER :
1023
+ access = factories .UserDocumentAccessFactory (
1024
+ document = document , user = user , role = "owner"
1025
+ )
1026
+ elif via == TEAM :
1027
+ mock_user_teams .return_value = ["lasuite" , "unknown" ]
1028
+ access = factories .TeamDocumentAccessFactory (
1029
+ document = document , team = "lasuite" , role = "owner"
1030
+ )
1031
+
1032
+ old_values = serializers .DocumentAccessSerializer (instance = access ).data
1033
+ new_role = random .choice (["administrator" , "editor" , "reader" ])
1034
+
1035
+ user_id = str (access .user_id ) if via == USER else None
1036
+ with mock_reset_connections (document .id , user_id ):
1037
+ response = client .put (
1038
+ f"/api/v1.0/documents/{ document .id !s} /accesses/{ access .id !s} /" ,
1039
+ data = {** old_values , "role" : new_role },
1040
+ format = "json" ,
1041
+ )
1042
+
1043
+ assert response .status_code == 200
1044
+ access .refresh_from_db ()
1045
+ assert access .role == new_role
1046
+
1047
+
993
1048
# Delete
994
1049
995
1050
@@ -1170,17 +1225,16 @@ def test_api_document_accesses_delete_owners(
1170
1225
f"/api/v1.0/documents/{ document .id !s} /accesses/{ access .id !s} /" ,
1171
1226
)
1172
1227
1173
- assert response .status_code == 204
1174
- assert models .DocumentAccess .objects .count () == 1
1228
+ assert response .status_code == 204
1229
+ assert models .DocumentAccess .objects .count () == 1
1175
1230
1176
1231
1177
1232
@pytest .mark .parametrize ("via" , VIA )
1178
- def test_api_document_accesses_delete_owners_last_owner (via , mock_user_teams ):
1233
+ def test_api_document_accesses_delete_owners_last_owner_root (via , mock_user_teams ):
1179
1234
"""
1180
- It should not be possible to delete the last owner access from a document
1235
+ It should not be possible to delete the last owner access from a root document
1181
1236
"""
1182
1237
user = factories .UserFactory (with_owned_document = True )
1183
-
1184
1238
client = APIClient ()
1185
1239
client .force_login (user )
1186
1240
@@ -1203,3 +1257,63 @@ def test_api_document_accesses_delete_owners_last_owner(via, mock_user_teams):
1203
1257
1204
1258
assert response .status_code == 403
1205
1259
assert models .DocumentAccess .objects .count () == 2
1260
+
1261
+
1262
+ def test_api_document_accesses_delete_owners_last_owner_child_user (
1263
+ mock_reset_connections , # pylint: disable=redefined-outer-name
1264
+ ):
1265
+ """
1266
+ It should be possible to delete the last owner access from a document that is not a root.
1267
+ """
1268
+ user = factories .UserFactory (with_owned_document = True )
1269
+ client = APIClient ()
1270
+ client .force_login (user )
1271
+
1272
+ parent = factories .DocumentFactory ()
1273
+ document = factories .DocumentFactory (parent = parent )
1274
+ access = None
1275
+ access = factories .UserDocumentAccessFactory (
1276
+ document = document , user = user , role = "owner"
1277
+ )
1278
+
1279
+ assert models .DocumentAccess .objects .count () == 2
1280
+ with mock_reset_connections (document .id , str (access .user_id )):
1281
+ response = client .delete (
1282
+ f"/api/v1.0/documents/{ document .id !s} /accesses/{ access .id !s} /" ,
1283
+ )
1284
+
1285
+ assert response .status_code == 204
1286
+ assert models .DocumentAccess .objects .count () == 1
1287
+
1288
+
1289
+ @pytest .mark .skip (
1290
+ reason = "Pending fix on https://github.com/suitenumerique/docs/issues/969"
1291
+ )
1292
+ def test_api_document_accesses_delete_owners_last_owner_child_team (
1293
+ mock_user_teams ,
1294
+ mock_reset_connections , # pylint: disable=redefined-outer-name
1295
+ ):
1296
+ """
1297
+ It should be possible to delete the last owner access from a document that
1298
+ is not a root.
1299
+ """
1300
+ user = factories .UserFactory (with_owned_document = True )
1301
+ client = APIClient ()
1302
+ client .force_login (user )
1303
+
1304
+ parent = factories .DocumentFactory ()
1305
+ document = factories .DocumentFactory (parent = parent )
1306
+ access = None
1307
+ mock_user_teams .return_value = ["lasuite" , "unknown" ]
1308
+ access = factories .TeamDocumentAccessFactory (
1309
+ document = document , team = "lasuite" , role = "owner"
1310
+ )
1311
+
1312
+ assert models .DocumentAccess .objects .count () == 2
1313
+ with mock_reset_connections (document .id , str (access .user_id )):
1314
+ response = client .delete (
1315
+ f"/api/v1.0/documents/{ document .id !s} /accesses/{ access .id !s} /" ,
1316
+ )
1317
+
1318
+ assert response .status_code == 204
1319
+ assert models .DocumentAccess .objects .count () == 1
0 commit comments