@@ -418,3 +418,231 @@ def test_stop_recording_follows_mode_permission_authenticated(
418418 # Any authenticated user should be able to stop
419419 response = client .post (f"/api/v1.0/rooms/{ room .id } /stop-recording/" )
420420 assert response .status_code == 200
421+
422+
423+ # =============================================================================
424+ # Tests for per-room recording permission overrides via room.configuration
425+ # =============================================================================
426+
427+
428+ def test_room_config_overrides_global_screen_recording_permission (
429+ mock_worker_service_factory , mock_worker_manager , settings
430+ ):
431+ """Room configuration should override global screen recording permission."""
432+ settings .RECORDING_ENABLE = True
433+ settings .RECORDING_SCREEN_PERMISSION = "admin_owner"
434+
435+ room = RoomFactory (configuration = {"screen_recording_permission" : "authenticated" })
436+ user = UserFactory ()
437+ client = APIClient ()
438+ client .force_login (user )
439+
440+ # Global is admin_owner, but room overrides to authenticated
441+ response = client .post (
442+ f"/api/v1.0/rooms/{ room .id } /start-recording/" ,
443+ {"mode" : "screen_recording" },
444+ )
445+ assert response .status_code == 201
446+ assert Recording .objects .count () == 1
447+
448+
449+ def test_room_config_overrides_global_transcript_permission (
450+ mock_worker_service_factory , mock_worker_manager , settings
451+ ):
452+ """Room configuration should override global transcript permission."""
453+ settings .RECORDING_ENABLE = True
454+ settings .RECORDING_TRANSCRIPT_PERMISSION = "admin_owner"
455+
456+ room = RoomFactory (configuration = {"transcript_permission" : "authenticated" })
457+ user = UserFactory ()
458+ client = APIClient ()
459+ client .force_login (user )
460+
461+ # Global is admin_owner, but room overrides to authenticated
462+ response = client .post (
463+ f"/api/v1.0/rooms/{ room .id } /start-recording/" ,
464+ {"mode" : "transcript" },
465+ )
466+ assert response .status_code == 201
467+ assert Recording .objects .count () == 1
468+
469+
470+ def test_room_config_restricts_when_global_is_permissive (settings ):
471+ """Room configuration can restrict permissions even when global is permissive."""
472+ settings .RECORDING_ENABLE = True
473+ settings .RECORDING_SCREEN_PERMISSION = "authenticated"
474+
475+ room = RoomFactory (configuration = {"screen_recording_permission" : "admin_owner" })
476+ user = UserFactory ()
477+ client = APIClient ()
478+ client .force_login (user )
479+
480+ # Global is authenticated, but room overrides to admin_owner
481+ response = client .post (
482+ f"/api/v1.0/rooms/{ room .id } /start-recording/" ,
483+ {"mode" : "screen_recording" },
484+ )
485+ assert response .status_code == 403
486+ assert Recording .objects .count () == 0
487+
488+
489+ def test_room_config_empty_falls_back_to_global (settings ):
490+ """Without room configuration override, global permission applies."""
491+ settings .RECORDING_ENABLE = True
492+ settings .RECORDING_SCREEN_PERMISSION = "admin_owner"
493+
494+ room = RoomFactory (configuration = {})
495+ user = UserFactory ()
496+ client = APIClient ()
497+ client .force_login (user )
498+
499+ # No room override, global admin_owner applies
500+ response = client .post (
501+ f"/api/v1.0/rooms/{ room .id } /start-recording/" ,
502+ {"mode" : "screen_recording" },
503+ )
504+ assert response .status_code == 403
505+ assert Recording .objects .count () == 0
506+
507+
508+ def test_recording_permissions_in_room_response_for_admin (settings ):
509+ """recording_permissions should be present in room response for admin users."""
510+ settings .RECORDING_SCREEN_PERMISSION = "admin_owner"
511+ settings .RECORDING_TRANSCRIPT_PERMISSION = "authenticated"
512+
513+ room = RoomFactory ()
514+ user = UserFactory ()
515+ room .accesses .create (user = user , role = "administrator" )
516+
517+ client = APIClient ()
518+ client .force_login (user )
519+
520+ response = client .get (f"/api/v1.0/rooms/{ room .id } /" )
521+ assert response .status_code == 200
522+ assert "recording_permissions" in response .json ()
523+ assert (
524+ response .json ()["recording_permissions" ]["screen_recording_permission" ]
525+ == "admin_owner"
526+ )
527+ assert (
528+ response .json ()["recording_permissions" ]["transcript_permission" ]
529+ == "authenticated"
530+ )
531+
532+
533+ def test_recording_permissions_in_room_response_for_non_admin (settings ):
534+ """recording_permissions should be present in room response for non-admin users."""
535+ settings .RECORDING_SCREEN_PERMISSION = "authenticated"
536+ settings .RECORDING_TRANSCRIPT_PERMISSION = "admin_owner"
537+
538+ room = RoomFactory ()
539+ user = UserFactory ()
540+ room .accesses .create (user = user , role = "member" )
541+
542+ client = APIClient ()
543+ client .force_login (user )
544+
545+ response = client .get (f"/api/v1.0/rooms/{ room .id } /" )
546+ assert response .status_code == 200
547+ assert "recording_permissions" in response .json ()
548+ assert (
549+ response .json ()["recording_permissions" ]["screen_recording_permission" ]
550+ == "authenticated"
551+ )
552+ assert (
553+ response .json ()["recording_permissions" ]["transcript_permission" ]
554+ == "admin_owner"
555+ )
556+ # configuration should NOT be visible to non-admin
557+ assert "configuration" not in response .json ()
558+
559+
560+ def test_recording_permissions_reflect_room_override (settings ):
561+ """recording_permissions should reflect room configuration override."""
562+ settings .RECORDING_SCREEN_PERMISSION = "admin_owner"
563+ settings .RECORDING_TRANSCRIPT_PERMISSION = "admin_owner"
564+
565+ room = RoomFactory (
566+ configuration = {
567+ "screen_recording_permission" : "authenticated" ,
568+ "transcript_permission" : "authenticated" ,
569+ }
570+ )
571+ user = UserFactory ()
572+ room .accesses .create (user = user , role = "member" )
573+
574+ client = APIClient ()
575+ client .force_login (user )
576+
577+ response = client .get (f"/api/v1.0/rooms/{ room .id } /" )
578+ assert response .status_code == 200
579+ assert (
580+ response .json ()["recording_permissions" ]["screen_recording_permission" ]
581+ == "authenticated"
582+ )
583+ assert (
584+ response .json ()["recording_permissions" ]["transcript_permission" ]
585+ == "authenticated"
586+ )
587+
588+
589+ def test_admin_can_patch_room_recording_config (settings ):
590+ """Admin should be able to patch room configuration with recording permissions."""
591+ settings .RECORDING_ENABLE = True
592+ settings .RECORDING_SCREEN_PERMISSION = "admin_owner"
593+
594+ room = RoomFactory ()
595+ user = UserFactory ()
596+ room .accesses .create (user = user , role = "administrator" )
597+
598+ client = APIClient ()
599+ client .force_login (user )
600+
601+ response = client .patch (
602+ f"/api/v1.0/rooms/{ room .id } /" ,
603+ {"configuration" : {"screen_recording_permission" : "authenticated" }},
604+ format = "json" ,
605+ )
606+ assert response .status_code == 200
607+ assert (
608+ response .json ()["recording_permissions" ]["screen_recording_permission" ]
609+ == "authenticated"
610+ )
611+
612+
613+ def test_patch_room_rejects_invalid_recording_permission (settings ):
614+ """Invalid recording permission values should be rejected with 400."""
615+ settings .RECORDING_ENABLE = True
616+
617+ room = RoomFactory ()
618+ user = UserFactory ()
619+ room .accesses .create (user = user , role = "administrator" )
620+
621+ client = APIClient ()
622+ client .force_login (user )
623+
624+ response = client .patch (
625+ f"/api/v1.0/rooms/{ room .id } /" ,
626+ {"configuration" : {"screen_recording_permission" : "everyone" }},
627+ format = "json" ,
628+ )
629+ assert response .status_code == 400
630+
631+
632+ def test_patch_room_rejects_invalid_transcript_permission (settings ):
633+ """Invalid transcript permission values should be rejected with 400."""
634+ settings .RECORDING_ENABLE = True
635+
636+ room = RoomFactory ()
637+ user = UserFactory ()
638+ room .accesses .create (user = user , role = "administrator" )
639+
640+ client = APIClient ()
641+ client .force_login (user )
642+
643+ response = client .patch (
644+ f"/api/v1.0/rooms/{ room .id } /" ,
645+ {"configuration" : {"transcript_permission" : "foobar" }},
646+ format = "json" ,
647+ )
648+ assert response .status_code == 400
0 commit comments