Coverage for src / lexigram / admin / rbac / policies.py: 48%

21 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-08-13 22:14 +0800

1"""Standard RBAC policies.""" 

2 

3from __future__ import annotations 

4 

5from lexigram.admin.rbac.types import Policy, PolicyContext 

6 

7_registry: dict[str, Policy] = {} 

8 

9 

10def register_policy(name: str, policy: Policy) -> None: 

11 """Register a policy by name.""" 

12 _registry[name] = policy 

13 

14 

15def get_policy(name: str) -> Policy | None: 

16 """Get a policy by name.""" 

17 return _registry.get(name) 

18 

19 

20# --- Standard Implementation Helpers --- 

21 

22 

23def owner_only(context: PolicyContext) -> bool: 

24 """Check if the user is the owner of the record.""" 

25 if not context.record or not context.user: 

26 return False 

27 

28 user_id = getattr(context.user, "id", getattr(context.user, "user_id", None)) 

29 # Check common owner field names 

30 owner_id = ( 

31 getattr(context.record, "user_id", None) 

32 or getattr(context.record, "owner_id", None) 

33 or getattr(context.record, "creator_id", None) 

34 ) 

35 return user_id is not None and user_id == owner_id 

36 

37 

38def team_scoped(context: PolicyContext) -> bool: 

39 """Check if the user belongs to the same team as the record.""" 

40 if not context.record or not context.user: 

41 return False 

42 

43 user_team = getattr(context.user, "team_id", None) 

44 record_team = getattr(context.record, "team_id", None) 

45 

46 return user_team is not None and user_team == record_team 

47 

48 

49# Register standard policies 

50register_policy("owner_only", owner_only) 

51register_policy("team_scoped", team_scoped)