Coverage for sm/utils_permissions.py: 80%
25 statements
« prev ^ index » next coverage.py v7.17.0, created at 2026-10-24 19:06 +0000
« prev ^ index » next coverage.py v7.17.0, created at 2026-10-24 19:06 +0000
1from django.contrib.auth.models import Group, Permission
2from django.contrib.contenttypes.models import ContentType
3from typing import List, Tuple
4import logging
6logger = logging.getLogger(__name__)
9# All core tenant models that can be permission-managed per group.
10APP_MODELS: List[Tuple[str, str]] = [
11 ("server", "model"),
12 ("cluster", "model"),
13 ("domain", "model"),
14 ("vendor", "model"),
15 ("operatingsystem", "model"),
16 ("status", "model"),
17 ("location", "model"),
18 ("patchtime", "model"),
19 ("servermodel", "model"),
20 ("clusterpackage", "model"),
21 ("clustersoftware", "model"),
22 ("clusterpackagetype", "model"),
23]
25# Human-readable labels for the permission management UI, keyed by app_label.
26MODEL_LABELS: dict = {
27 "server": "Servers",
28 "cluster": "Clusters",
29 "domain": "Domains",
30 "vendor": "Vendors",
31 "operatingsystem": "Operating Systems",
32 "status": "Statuses",
33 "location": "Locations",
34 "patchtime": "Patch Times",
35 "servermodel": "Server Models",
36 "clusterpackage": "Cluster Packages",
37 "clustersoftware": "Cluster Software",
38 "clusterpackagetype": "Package Types",
39}
42def get_group_permissions_for_model(
43 app_label: str, model_name: str = "model"
44) -> List[Permission]:
45 """
46 Returns the standard permissions (view, add, change, delete) for a model.
47 """
48 try:
49 ct = ContentType.objects.get(app_label=app_label, model=model_name)
50 return list(Permission.objects.filter(content_type=ct))
51 except ContentType.DoesNotExist:
52 logger.warning(f"ContentType for {app_label}.{model_name} not found.")
53 return []
56def assign_group_permissions(group: Group, permissions: List[Permission]) -> None:
57 """
58 Assigns a list of permissions to a group.
59 """
60 group.permissions.add(*permissions)
63def sync_group_permissions(group: Group, grant_all: bool = False) -> None:
64 """
65 Ensures a group has at least basic view permissions for the core models
66 so multi-tenancy works as expected.
67 If grant_all is True, also grants add, change, and delete permissions.
68 """
69 for app, model in APP_MODELS:
70 perms = get_group_permissions_for_model(app, model)
71 if grant_all:
72 # Grant all permissions for this model
73 group.permissions.add(*perms)
74 else:
75 # By default, give view permission to every group
76 view_perm = next((p for p in perms if p.codename.startswith("view_")), None)
77 if view_perm:
78 group.permissions.add(view_perm)
79 else:
80 logger.debug(f"View permission for {app}.{model} not found.")