@@ -184,7 +184,11 @@ def test_api_documents_link_configuration_update_role_restricted_forbidden():
184
184
document = document , user = user , role = models .RoleChoices .OWNER
185
185
)
186
186
187
- new_data = {"link_role" : models .LinkRoleChoices .EDITOR }
187
+ # Try to set a meaningful role on a restricted document
188
+ new_data = {
189
+ "link_reach" : models .LinkReachChoices .RESTRICTED ,
190
+ "link_role" : models .LinkRoleChoices .EDITOR ,
191
+ }
188
192
189
193
response = client .put (
190
194
f"/api/v1.0/documents/{ document .id !s} /link-configuration/" ,
@@ -198,3 +202,202 @@ def test_api_documents_link_configuration_update_role_restricted_forbidden():
198
202
"Cannot set link_role when link_reach is 'restricted'"
199
203
in response .json ()["link_role" ][0 ]
200
204
)
205
+
206
+
207
+ def test_api_documents_link_configuration_update_link_reach_required ():
208
+ """
209
+ Test that link_reach is required when updating link configuration.
210
+ """
211
+ user = factories .UserFactory ()
212
+ client = APIClient ()
213
+ client .force_login (user )
214
+
215
+ document = factories .DocumentFactory (
216
+ link_reach = models .LinkReachChoices .PUBLIC ,
217
+ link_role = models .LinkRoleChoices .READER ,
218
+ )
219
+
220
+ factories .UserDocumentAccessFactory (
221
+ document = document , user = user , role = models .RoleChoices .OWNER
222
+ )
223
+
224
+ # Try to update without providing link_reach
225
+ new_data = {"link_role" : models .LinkRoleChoices .EDITOR }
226
+
227
+ response = client .put (
228
+ f"/api/v1.0/documents/{ document .id !s} /link-configuration/" ,
229
+ new_data ,
230
+ format = "json" ,
231
+ )
232
+
233
+ assert response .status_code == 400
234
+ assert "link_reach" in response .json ()
235
+ assert "This field is required" in response .json ()["link_reach" ][0 ]
236
+
237
+
238
+ def test_api_documents_link_configuration_update_restricted_without_role_success (
239
+ mock_reset_connections , # pylint: disable=redefined-outer-name
240
+ ):
241
+ """
242
+ Test that setting link_reach to restricted without specifying link_role succeeds.
243
+ """
244
+ user = factories .UserFactory ()
245
+ client = APIClient ()
246
+ client .force_login (user )
247
+
248
+ document = factories .DocumentFactory (
249
+ link_reach = models .LinkReachChoices .PUBLIC ,
250
+ link_role = models .LinkRoleChoices .READER ,
251
+ )
252
+
253
+ factories .UserDocumentAccessFactory (
254
+ document = document , user = user , role = models .RoleChoices .OWNER
255
+ )
256
+
257
+ # Only specify link_reach, not link_role
258
+ new_data = {
259
+ "link_reach" : models .LinkReachChoices .RESTRICTED ,
260
+ }
261
+
262
+ with mock_reset_connections (document .id ):
263
+ response = client .put (
264
+ f"/api/v1.0/documents/{ document .id !s} /link-configuration/" ,
265
+ new_data ,
266
+ format = "json" ,
267
+ )
268
+
269
+ assert response .status_code == 200
270
+ document .refresh_from_db ()
271
+ assert document .link_reach == models .LinkReachChoices .RESTRICTED
272
+
273
+
274
+ @pytest .mark .parametrize (
275
+ "reach" , [models .LinkReachChoices .PUBLIC , models .LinkReachChoices .AUTHENTICATED ]
276
+ )
277
+ @pytest .mark .parametrize ("role" , models .LinkRoleChoices .values )
278
+ def test_api_documents_link_configuration_update_non_restricted_with_valid_role_success (
279
+ reach ,
280
+ role ,
281
+ mock_reset_connections , # pylint: disable=redefined-outer-name
282
+ ):
283
+ """
284
+ Test that setting non-restricted link_reach with valid link_role succeeds.
285
+ """
286
+ user = factories .UserFactory ()
287
+ client = APIClient ()
288
+ client .force_login (user )
289
+
290
+ document = factories .DocumentFactory (
291
+ link_reach = models .LinkReachChoices .RESTRICTED ,
292
+ link_role = models .LinkRoleChoices .READER ,
293
+ )
294
+
295
+ factories .UserDocumentAccessFactory (
296
+ document = document , user = user , role = models .RoleChoices .OWNER
297
+ )
298
+
299
+ new_data = {
300
+ "link_reach" : reach ,
301
+ "link_role" : role ,
302
+ }
303
+
304
+ with mock_reset_connections (document .id ):
305
+ response = client .put (
306
+ f"/api/v1.0/documents/{ document .id !s} /link-configuration/" ,
307
+ new_data ,
308
+ format = "json" ,
309
+ )
310
+
311
+ assert response .status_code == 200
312
+ document .refresh_from_db ()
313
+ assert document .link_reach == reach
314
+ assert document .link_role == role
315
+
316
+
317
+ def test_api_documents_link_configuration_update_with_ancestor_constraints ():
318
+ """
319
+ Test that link configuration respects ancestor constraints using get_select_options.
320
+ This test may need adjustment based on the actual get_select_options implementation.
321
+ """
322
+ user = factories .UserFactory ()
323
+ client = APIClient ()
324
+ client .force_login (user )
325
+
326
+ parent_document = factories .DocumentFactory (
327
+ link_reach = models .LinkReachChoices .PUBLIC ,
328
+ link_role = models .LinkRoleChoices .READER ,
329
+ )
330
+
331
+ child_document = factories .DocumentFactory (
332
+ parent = parent_document ,
333
+ link_reach = models .LinkReachChoices .PUBLIC ,
334
+ link_role = models .LinkRoleChoices .READER ,
335
+ )
336
+
337
+ factories .UserDocumentAccessFactory (
338
+ document = child_document , user = user , role = models .RoleChoices .OWNER
339
+ )
340
+
341
+ # Try to set child to PUBLIC when parent is RESTRICTED
342
+ new_data = {
343
+ "link_reach" : models .LinkReachChoices .RESTRICTED ,
344
+ "link_role" : models .LinkRoleChoices .READER ,
345
+ }
346
+
347
+ response = client .put (
348
+ f"/api/v1.0/documents/{ child_document .id !s} /link-configuration/" ,
349
+ new_data ,
350
+ format = "json" ,
351
+ )
352
+
353
+ assert response .status_code == 400
354
+ assert "link_reach" in response .json ()
355
+ assert (
356
+ "Link reach 'restricted' is not allowed based on parent"
357
+ in response .json ()["link_reach" ][0 ]
358
+ )
359
+
360
+
361
+ def test_api_documents_link_configuration_update_invalid_role_for_reach_validation ():
362
+ """
363
+ Test the specific validation logic that checks if link_role is allowed for link_reach.
364
+ This tests the code section that validates allowed_roles from get_select_options.
365
+ """
366
+ user = factories .UserFactory ()
367
+ client = APIClient ()
368
+ client .force_login (user )
369
+
370
+ parent_document = factories .DocumentFactory (
371
+ link_reach = models .LinkReachChoices .AUTHENTICATED ,
372
+ link_role = models .LinkRoleChoices .EDITOR ,
373
+ )
374
+
375
+ child_document = factories .DocumentFactory (
376
+ parent = parent_document ,
377
+ link_reach = models .LinkReachChoices .RESTRICTED ,
378
+ link_role = models .LinkRoleChoices .READER ,
379
+ )
380
+
381
+ factories .UserDocumentAccessFactory (
382
+ document = child_document , user = user , role = models .RoleChoices .OWNER
383
+ )
384
+
385
+ new_data = {
386
+ "link_reach" : models .LinkReachChoices .AUTHENTICATED ,
387
+ "link_role" : models .LinkRoleChoices .READER , # This should be rejected
388
+ }
389
+
390
+ response = client .put (
391
+ f"/api/v1.0/documents/{ child_document .id !s} /link-configuration/" ,
392
+ new_data ,
393
+ format = "json" ,
394
+ )
395
+
396
+ assert response .status_code == 400
397
+ assert "link_role" in response .json ()
398
+ error_message = response .json ()["link_role" ][0 ]
399
+ assert (
400
+ "Link role 'reader' is not allowed for link reach 'authenticated'"
401
+ in error_message
402
+ )
403
+ assert "Allowed roles: editor" in error_message
0 commit comments