lib.itmens/common/api.py

101 lines
2.9 KiB
Python
Raw Normal View History

from typing import Any, List
from django.conf import settings
from django.db.models import QuerySet
2024-05-25 23:38:11 -04:00
from loguru import logger
from ninja import NinjaAPI, Schema
from ninja.pagination import PageNumberPagination as NinjaPageNumberPagination
from ninja.security import HttpBearer
2024-06-10 17:28:20 -04:00
from takahe.utils import Takahe
from users.models.apidentity import APIdentity
PERMITTED_WRITE_METHODS = ["PUT", "POST", "DELETE", "PATCH"]
PERMITTED_READ_METHODS = ["GET", "HEAD", "OPTIONS"]
class OAuthAccessTokenAuth(HttpBearer):
def authenticate(self, request, token) -> bool:
2024-06-10 17:28:20 -04:00
if not token:
logger.debug("API auth: no access token provided")
return False
tk = Takahe.get_token(token)
if not tk:
logger.debug("API auth: access token not found")
return False
2024-06-10 17:40:04 -04:00
if tk.revoked:
logger.debug("API auth: access token revoked")
return False
2024-06-10 17:28:20 -04:00
request_scope = ""
request_method = request.method
if request_method in PERMITTED_READ_METHODS:
2024-06-10 17:28:20 -04:00
request_scope = "read"
elif request_method in PERMITTED_WRITE_METHODS:
2024-06-10 17:28:20 -04:00
request_scope = "write"
else:
2024-06-10 17:28:20 -04:00
logger.debug("API auth: unsupported HTTP method")
return False
if request_scope not in tk.scopes:
logger.debug("API auth: scope not allowed")
return False
identity = APIdentity.objects.filter(pk=tk.identity_id).first()
if not identity:
logger.debug("API auth: identity not found")
return False
if identity.deleted:
logger.debug("API auth: identity deleted")
return False
user = identity.user
if not user:
logger.debug("API auth: user not found")
return False
2024-06-10 17:28:20 -04:00
request.user = user
return True
class EmptyResult(Schema):
pass
2023-02-15 15:45:57 -05:00
2023-02-15 16:22:32 -05:00
class Result(Schema):
message: str | None
# error: Optional[str]
class RedirectedResult(Schema):
message: str | None
url: str
class PageNumberPagination(NinjaPageNumberPagination):
2023-06-03 01:22:19 -04:00
items_attribute = "data"
class Output(Schema):
2023-06-03 01:22:19 -04:00
data: List[Any]
pages: int
count: int
def paginate_queryset(
self,
queryset: QuerySet,
pagination: NinjaPageNumberPagination.Input,
**params: Any,
2023-06-03 11:10:48 -04:00
):
val = super().paginate_queryset(queryset, pagination, **params)
2023-06-03 11:10:48 -04:00
return {
"data": val["items"],
"count": val["count"],
"pages": (val["count"] + self.page_size - 1) // self.page_size,
}
2023-02-15 16:22:32 -05:00
2023-02-15 15:45:57 -05:00
api = NinjaAPI(
auth=OAuthAccessTokenAuth(),
title=f"{settings.SITE_INFO['site_name']} API",
2023-02-15 15:45:57 -05:00
version="1.0.0",
2023-07-10 15:29:29 -04:00
description=f"{settings.SITE_INFO['site_name']} API <hr/><a href='{settings.SITE_INFO['site_url']}'>Learn more</a>",
2023-02-15 15:45:57 -05:00
)
2025-01-19 16:04:22 -05:00
NOT_FOUND = 404, {"message": "Note not found"}
OK = 200, {"message": "OK"}