Keep platform bootstrap permissions additive

This commit is contained in:
kcar 2026-05-28 15:10:54 +01:00
parent 4f6634e088
commit 88a3193e01
2 changed files with 20 additions and 2 deletions

View File

@ -261,7 +261,12 @@ class BootstrapService:
permissions = dict(BASE_PERMISSIONS)
permissions["platform_admin"] = platform_admin
permissions["platform_super_admin"] = super_admin
role_permissions = ROLE_PERMISSIONS.get(active.get("role") or "", {})
permissions.update(role_permissions)
if platform_admin:
# Platform authority is additive and must not be reduced by a user's
# school membership role (for example a platform admin who also has
# a teacher/student membership).
permissions.update({
"can_create_school": True,
"can_manage_school": True,
@ -271,8 +276,6 @@ class BootstrapService:
"can_manage_classes": True,
"can_view_student_data": True,
})
role_permissions = ROLE_PERMISSIONS.get(active.get("role") or "", {})
permissions.update(role_permissions)
return permissions
def _school_status(self, active: MembershipRow, memberships: List[MembershipRow], admin_profile: Optional[Dict[str, Any]]) -> str:

View File

@ -218,6 +218,21 @@ def test_platform_admin_uses_admin_profiles_without_relying_on_profile_super_adm
assert payload["permissions"]["can_create_school"] is True
def test_platform_admin_membership_role_does_not_reduce_platform_permissions():
payload = build(credentials={"sub": USER_ID, "email": "admin@example.test"}, tables={
"profiles": [profile(user_type="student")],
"admin_profiles": [{"id": USER_ID, "admin_role": "owner", "is_super_admin": True}],
"institute_memberships": [membership(INST_A, "student")],
"institutes": [institute()],
})
assert payload["school_status"] == "platform_admin"
assert payload["permissions"]["platform_admin"] is True
assert payload["permissions"]["can_manage_school"] is True
assert payload["permissions"]["can_manage_calendar"] is True
assert payload["permissions"]["can_view_student_data"] is True
def test_neo4j_probe_failure_does_not_block_supabase_bootstrap_state():
def failing_probe(**_kwargs):
raise RuntimeError("connection refused with host details that must not leak")