first commit
This commit is contained in:
commit
b54624be96
226 files changed
+108840
No files matched your search
@@ -0,0 +1,177 @@
|
||||
"""Visibility scoping for HQ executives.
|
||||
|
||||
- director / director_admin: all sites / city sites / GMs
|
||||
- buh / bu_admin: only GMs (and gm_admins) they manage, plus those GMs' sites
|
||||
- gm / gm_admin: only their own sites / city sites they registered
|
||||
|
||||
Farm Site rows are only visible to non-directors when linked to an active
|
||||
CitySite 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 / CitySite.registered_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_city_site_ids(user: User) -> list[int] | None:
|
||||
"""
|
||||
Active CitySite pks in this viewer's Pengaturan registry.
|
||||
|
||||
Returns None for directors (no restriction). Empty list means no farm sites.
|
||||
"""
|
||||
from apps.sync.models import CitySite
|
||||
|
||||
owners = visible_owner_ids(user)
|
||||
if owners is None:
|
||||
return None
|
||||
if not owners:
|
||||
return []
|
||||
return list(
|
||||
CitySite.objects.filter(
|
||||
registered_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()
|
||||
city_ids = visible_active_city_site_ids(viewer)
|
||||
if not city_ids:
|
||||
return qs.none()
|
||||
return qs.filter(user_id__in=owners, city_site_id__in=city_ids)
|
||||
|
||||
|
||||
def filter_city_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(registered_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()
|
||||
city_ids = visible_active_city_site_ids(viewer)
|
||||
if not city_ids:
|
||||
return qs.none()
|
||||
return qs.filter(site__user_id__in=owners, site__city_site_id__in=city_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()
|
||||
city_ids = visible_active_city_site_ids(viewer)
|
||||
if not city_ids:
|
||||
return qs.none()
|
||||
return qs.filter(
|
||||
kandang__site__user_id__in=owners,
|
||||
kandang__site__city_site_id__in=city_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()
|
||||
city_ids = visible_active_city_site_ids(viewer)
|
||||
if not city_ids:
|
||||
return qs.none()
|
||||
return qs.filter(
|
||||
kandang__site__user_id__in=owners,
|
||||
kandang__site__city_site_id__in=city_ids,
|
||||
)
|
||||
Reference in new issue
Block a user