180 lines
4.7 KiB
Python
180 lines
4.7 KiB
Python
"""Visibility scoping for HQ executives.
|
|
|
|
- director / director_admin: all sites / active sites / GMs
|
|
- buh / bu_admin: only GMs (and gm_admins) they manage, plus those GMs' sites
|
|
- gm / gm_admin: only their own sites / active sites they manage
|
|
|
|
Farm Site rows are only visible to non-directors when linked to an enabled
|
|
ActiveSite in the viewer's Pengaturan registry.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from django.db.models import QuerySet
|
|
|
|
from apps.accounts.models import User
|
|
|
|
DIRECTOR_STATUSES = frozenset(
|
|
{
|
|
User.STATUS_DIRECTOR,
|
|
User.STATUS_DIRECTOR_ADMIN,
|
|
User.STATUS_SUPERUSER,
|
|
}
|
|
)
|
|
|
|
BUH_STATUSES = frozenset(
|
|
{
|
|
User.STATUS_BUH,
|
|
User.STATUS_BU_ADMIN,
|
|
}
|
|
)
|
|
|
|
GM_STATUSES = frozenset(
|
|
{
|
|
User.STATUS_GM,
|
|
User.STATUS_GM_ADMIN,
|
|
}
|
|
)
|
|
|
|
|
|
def is_director_scope(user: User) -> bool:
|
|
return bool(user and user.status in DIRECTOR_STATUSES)
|
|
|
|
|
|
def is_buh_scope(user: User) -> bool:
|
|
return bool(user and user.status in BUH_STATUSES)
|
|
|
|
|
|
def is_gm_scope(user: User) -> bool:
|
|
return bool(user and user.status in GM_STATUSES)
|
|
|
|
|
|
def managed_gm_ids(buh: User) -> list[int]:
|
|
"""User pks for GMs / GM Admins reporting to this BUH."""
|
|
return list(
|
|
User.objects.filter(
|
|
managed_by=buh,
|
|
status__in=GM_STATUSES,
|
|
).values_list("pk", flat=True)
|
|
)
|
|
|
|
|
|
def visible_owner_ids(user: User) -> list[int] | None:
|
|
"""
|
|
Site.user / ActiveSite.managed_by ids this viewer may see.
|
|
|
|
Returns None when there is no restriction (director / superuser).
|
|
"""
|
|
if is_director_scope(user):
|
|
return None
|
|
if is_buh_scope(user):
|
|
return managed_gm_ids(user)
|
|
if is_gm_scope(user):
|
|
return [user.pk]
|
|
return []
|
|
|
|
|
|
def visible_active_site_ids(user: User) -> list[int] | None:
|
|
"""
|
|
Enabled ActiveSite pks in this viewer's Pengaturan registry.
|
|
|
|
Returns None for directors (no restriction). Empty list means no farm sites.
|
|
"""
|
|
from apps.sync.models import ActiveSite
|
|
|
|
owners = visible_owner_ids(user)
|
|
if owners is None:
|
|
return None
|
|
if not owners:
|
|
return []
|
|
return list(
|
|
ActiveSite.objects.filter(
|
|
managed_by_id__in=owners,
|
|
is_active=True,
|
|
).values_list("pk", flat=True)
|
|
)
|
|
|
|
|
|
def is_account_admin_scope(user: User) -> bool:
|
|
return bool(user and user.status == User.STATUS_ACCOUNT_ADMIN)
|
|
|
|
|
|
def filter_users_queryset(qs: QuerySet, viewer: User) -> QuerySet:
|
|
"""BUH sees managed GMs; director / account_admin see product users.
|
|
|
|
Break-glass status=superuser is never listed in the user directory.
|
|
"""
|
|
qs = qs.exclude(status=User.STATUS_SUPERUSER)
|
|
if is_director_scope(viewer) or is_account_admin_scope(viewer):
|
|
return qs
|
|
if is_buh_scope(viewer):
|
|
return qs.filter(pk__in=managed_gm_ids(viewer))
|
|
if is_gm_scope(viewer):
|
|
return qs.filter(pk=viewer.pk)
|
|
return qs.none()
|
|
|
|
|
|
def filter_sites_queryset(qs: QuerySet, viewer: User) -> QuerySet:
|
|
owners = visible_owner_ids(viewer)
|
|
if owners is None:
|
|
return qs
|
|
if not owners:
|
|
return qs.none()
|
|
active_ids = visible_active_site_ids(viewer)
|
|
if not active_ids:
|
|
return qs.none()
|
|
return qs.filter(user_id__in=owners, active_site_id__in=active_ids)
|
|
|
|
|
|
def filter_active_sites_queryset(qs: QuerySet, viewer: User) -> QuerySet:
|
|
owners = visible_owner_ids(viewer)
|
|
if owners is None:
|
|
return qs
|
|
if not owners:
|
|
return qs.none()
|
|
return qs.filter(managed_by_id__in=owners)
|
|
|
|
|
|
def filter_kandangs_queryset(qs: QuerySet, viewer: User) -> QuerySet:
|
|
owners = visible_owner_ids(viewer)
|
|
if owners is None:
|
|
return qs
|
|
if not owners:
|
|
return qs.none()
|
|
active_ids = visible_active_site_ids(viewer)
|
|
if not active_ids:
|
|
return qs.none()
|
|
return qs.filter(
|
|
site__user_id__in=owners, site__active_site_id__in=active_ids
|
|
)
|
|
|
|
|
|
def filter_flocks_queryset(qs: QuerySet, viewer: User) -> QuerySet:
|
|
owners = visible_owner_ids(viewer)
|
|
if owners is None:
|
|
return qs
|
|
if not owners:
|
|
return qs.none()
|
|
active_ids = visible_active_site_ids(viewer)
|
|
if not active_ids:
|
|
return qs.none()
|
|
return qs.filter(
|
|
kandang__site__user_id__in=owners,
|
|
kandang__site__active_site_id__in=active_ids,
|
|
)
|
|
|
|
|
|
def filter_cycles_queryset(qs: QuerySet, viewer: User) -> QuerySet:
|
|
owners = visible_owner_ids(viewer)
|
|
if owners is None:
|
|
return qs
|
|
if not owners:
|
|
return qs.none()
|
|
active_ids = visible_active_site_ids(viewer)
|
|
if not active_ids:
|
|
return qs.none()
|
|
return qs.filter(
|
|
kandang__site__user_id__in=owners,
|
|
kandang__site__active_site_id__in=active_ids,
|
|
)
|