Files
enviPy-bayer/epapi/v1/dal.py
Tobias O d80dfb5ee3 [Feature] Dynamic additional information rendering in frontend (#282)
This implements a version of #274, relying on Pydantics built in JSON schema and JSON rendering.
Requires additional UI tagging in the ai model repo but will remove HTML tags.

Example scenario with filled information: 5882df9c-dae1-4d80-a40e-db4724271456/scenario/3a4d395a-6a6d-4154-8ce3-ced667fceec0

Reviewed-on: enviPath/enviPy#282
Co-authored-by: Tobias O <tobias.olenyi@envipath.com>
Co-committed-by: Tobias O <tobias.olenyi@envipath.com>
2026-01-31 00:44:03 +13:00

120 lines
4.4 KiB
Python

from django.db.models import Model
from epdb.logic import PackageManager
from epdb.models import CompoundStructure, User, Package, Compound, Scenario
from uuid import UUID
from .errors import EPAPINotFoundError, EPAPIPermissionDeniedError
def get_compound_for_read(user, compound_uuid: UUID):
"""
Get compound by UUID with permission check.
"""
try:
compound = Compound.objects.get(uuid=compound_uuid)
package = compound.package
except Compound.DoesNotExist:
raise EPAPINotFoundError(f"Compound with UUID {compound_uuid} not found")
# FIXME: optimize package manager to exclusively work with UUIDs
if not user or user.is_anonymous or not PackageManager.readable(user, package):
raise EPAPIPermissionDeniedError("Insufficient permissions to access this compound.")
return compound
def get_package_for_read(user, package_uuid: UUID):
"""
Get package by UUID with permission check.
"""
# FIXME: update package manager with custom exceptions to avoid manual checks here
try:
package = Package.objects.get(uuid=package_uuid)
except Package.DoesNotExist:
raise EPAPINotFoundError(f"Package with UUID {package_uuid} not found")
# FIXME: optimize package manager to exclusively work with UUIDs
if not user or user.is_anonymous or not PackageManager.readable(user, package):
raise EPAPIPermissionDeniedError("Insufficient permissions to access this package.")
return package
def get_scenario_for_read(user, scenario_uuid: UUID):
"""Get scenario by UUID with read permission check."""
try:
scenario = Scenario.objects.select_related("package").get(uuid=scenario_uuid)
except Scenario.DoesNotExist:
raise EPAPINotFoundError(f"Scenario with UUID {scenario_uuid} not found")
if not user or user.is_anonymous or not PackageManager.readable(user, scenario.package):
raise EPAPIPermissionDeniedError("Insufficient permissions to access this scenario.")
return scenario
def get_scenario_for_write(user, scenario_uuid: UUID):
"""Get scenario by UUID with write permission check."""
try:
scenario = Scenario.objects.select_related("package").get(uuid=scenario_uuid)
except Scenario.DoesNotExist:
raise EPAPINotFoundError(f"Scenario with UUID {scenario_uuid} not found")
if not user or user.is_anonymous or not PackageManager.writable(user, scenario.package):
raise EPAPIPermissionDeniedError("Insufficient permissions to modify this scenario.")
return scenario
def get_user_packages_for_read(user: User | None):
"""Get all packages readable by the user."""
if not user or user.is_anonymous:
return PackageManager.get_reviewed_packages()
return PackageManager.get_all_readable_packages(user, include_reviewed=True)
def get_user_entities_for_read(model_class: Model, user: User | None):
"""Build queryset for reviewed package entities."""
if not user or user.is_anonymous:
return model_class.objects.filter(package__reviewed=True).select_related("package")
qs = model_class.objects.filter(
package__in=PackageManager.get_all_readable_packages(user, include_reviewed=True)
).select_related("package")
return qs
def get_package_entities_for_read(model_class: Model, package_uuid: UUID, user: User | None = None):
"""Build queryset for specific package entities."""
package = get_package_for_read(user, package_uuid)
qs = model_class.objects.filter(package=package).select_related("package")
return qs
def get_user_structure_for_read(user: User | None):
"""Build queryset for structures accessible to the user (via compound->package)."""
if not user or user.is_anonymous:
return CompoundStructure.objects.filter(compound__package__reviewed=True).select_related(
"compound__package"
)
qs = CompoundStructure.objects.filter(
compound__package__in=PackageManager.get_all_readable_packages(user, include_reviewed=True)
).select_related("compound__package")
return qs
def get_package_compound_structure_for_read(
package_uuid: UUID, compound_uuid: UUID, user: User | None = None
):
"""Build queryset for specific package compound structures."""
get_package_for_read(user, package_uuid)
compound = get_compound_for_read(user, compound_uuid)
qs = CompoundStructure.objects.filter(compound=compound).select_related("compound__package")
return qs