from typing import List from django.contrib.auth import get_user_model from ninja import Router, Schema, Field from ninja.errors import HttpError from ninja.pagination import paginate from ninja.security import HttpBearer from .logic import PackageManager from .models import User, Compound, APIToken class BearerTokenAuth(HttpBearer): def authenticate(self, request, token): for token_obj in APIToken.objects.select_related("user").all(): if token_obj.check_token(token) and token_obj.is_valid(): return token_obj.user raise HttpError(401, "Invalid or expired token") def _anonymous_or_real(request): if request.user.is_authenticated and not request.user.is_anonymous: return request.user return get_user_model().objects.get(username='anonymous') router = Router(auth=BearerTokenAuth()) class UserSchema(Schema): email: str username: str id: str = Field(None, alias="url") class PackageIn(Schema): name: str description: str class PackageOut(Schema): id: str = Field(None, alias="url") name: str reviewed: bool compound_links: str = None @staticmethod def resolve_compound_links(obj): return f"{obj.url}/compound" class Error(Schema): message: str class CompoundSchema(Schema): name: str = Field(None, alias="name") id: str = Field(None, alias="url") smiles: str = Field(None, alias="default_structure.smiles") reviewed: bool = Field(None, alias="package.reviewed") @router.get("/user", response={200: List[UserSchema], 403: Error}) def get_users(request): return User.objects.all() @router.get("/package", response={200: List[PackageOut], 403: Error}) def get_packages(request): return PackageManager.get_all_readable_packages(request.user, include_reviewed=True) @router.post("/package", response=PackageOut) def create_package(request, package: PackageIn): user = request.auth name = package.name.strip() description = package.description.strip() p = PackageManager.create_package(user, name, description=description) return p @router.get("/package/{uuid:package_uuid}", response={200: PackageOut, 403: Error}) def get_package(request, package_uuid): try: return PackageManager.get_package_by_id(request.auth, package_id=package_uuid) except ValueError: return 403, {'message': f'Getting Package with id {package_uuid} failed due to insufficient rights!'} @router.get("/compound", response={200: List[CompoundSchema], 403: Error}) @paginate def get_compounds(request): qs = Compound.objects.none() for p in PackageManager.get_reviewed_packages(): qs |= Compound.objects.filter(package=p) return qs @router.get("/package/{uuid:package_uuid}/compound", response={200: List[CompoundSchema], 403: Error}) @paginate def get_package_compounds(request, package_uuid): try: p = PackageManager.get_package_by_id(request.auth, package_uuid) return Compound.objects.filter(package=p) except ValueError: return 403, { 'message': f'Getting Compounds for Package with id {package_uuid} failed due to insufficient rights!'}