59 lines
2.1 KiB
Python
59 lines
2.1 KiB
Python
from django.db.models import Q
|
|
|
|
from .models import MainProduct, ProjectAccess, ProjectAccessPolicy, SubProduct
|
|
|
|
|
|
def _mode(user):
|
|
try:
|
|
return user.project_access_policy.mode
|
|
except ProjectAccessPolicy.DoesNotExist:
|
|
return ProjectAccessPolicy.OWN
|
|
|
|
|
|
def accessible_projects(user, model, *, edit=False):
|
|
"""Return projects visible/editable by a user; explicit overrides win."""
|
|
if model not in (MainProduct, SubProduct):
|
|
raise ValueError("Expected a main project or sub-project model")
|
|
if not user.is_authenticated or not user.is_active:
|
|
return model.objects.none()
|
|
if user.is_superuser:
|
|
return model.objects.all()
|
|
|
|
field = "main_product" if model is MainProduct else "sub_product"
|
|
overrides = ProjectAccess.objects.filter(user=user, **{f"{field}__isnull": False})
|
|
allowed_levels = (ProjectAccess.EDIT,) if edit else (ProjectAccess.VIEW, ProjectAccess.EDIT)
|
|
permitted = overrides.filter(level__in=allowed_levels)
|
|
excluded = overrides.exclude(level__in=allowed_levels)
|
|
|
|
mode = _mode(user)
|
|
base = Q(created_by=user) if mode != ProjectAccessPolicy.NONE else Q(pk__in=[])
|
|
if mode == ProjectAccessPolicy.ALL_EDIT or (mode == ProjectAccessPolicy.ALL_VIEW and not edit):
|
|
base = Q(pk__isnull=False)
|
|
return model.objects.filter(base | Q(pk__in=permitted.values_list(f"{field}_id", flat=True))).exclude(
|
|
pk__in=excluded.values_list(f"{field}_id", flat=True)
|
|
).distinct()
|
|
|
|
|
|
def can_access_project(user, project, *, edit=False):
|
|
if project is None:
|
|
return False
|
|
return accessible_projects(user, type(project), edit=edit).filter(pk=project.pk).exists()
|
|
|
|
|
|
def can_create_project(user):
|
|
return user.is_authenticated and user.is_active and (
|
|
user.is_superuser or _mode(user) != ProjectAccessPolicy.NONE
|
|
)
|
|
|
|
|
|
def project_for_related(obj):
|
|
if isinstance(obj, (MainProduct, SubProduct)):
|
|
return obj
|
|
if getattr(obj, "sub_product_id", None):
|
|
return obj.sub_product
|
|
if getattr(obj, "main_product_id", None):
|
|
return obj.main_product
|
|
if getattr(obj, "article_id", None):
|
|
return project_for_related(obj.article)
|
|
return None
|