2023-06-02 21:54:48 -04:00
|
|
|
from typing import Any, Callable, List, Optional, Tuple, Type
|
2023-08-10 11:27:31 -04:00
|
|
|
|
|
|
|
from django.conf import settings
|
2023-06-02 21:54:48 -04:00
|
|
|
from django.db.models import QuerySet
|
2024-05-25 23:38:11 -04:00
|
|
|
from loguru import logger
|
2023-08-10 11:27:31 -04:00
|
|
|
from ninja import NinjaAPI, Schema
|
|
|
|
from ninja.pagination import PageNumberPagination as NinjaPageNumberPagination
|
2023-06-02 21:54:48 -04:00
|
|
|
from ninja.security import HttpBearer
|
2024-06-10 17:28:20 -04:00
|
|
|
|
|
|
|
from takahe.utils import Takahe
|
|
|
|
from users.models.apidentity import APIdentity
|
2023-06-02 21:54:48 -04:00
|
|
|
|
2023-11-02 21:28:11 +01:00
|
|
|
PERMITTED_WRITE_METHODS = ["PUT", "POST", "DELETE", "PATCH"]
|
|
|
|
PERMITTED_READ_METHODS = ["GET", "HEAD", "OPTIONS"]
|
|
|
|
|
|
|
|
|
2023-06-02 21:54:48 -04:00
|
|
|
class OAuthAccessTokenAuth(HttpBearer):
|
2023-11-02 21:28:11 +01:00
|
|
|
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")
|
2023-06-02 21:54:48 -04:00
|
|
|
return False
|
2024-06-10 17:28:20 -04:00
|
|
|
request_scope = ""
|
2023-11-02 21:28:11 +01:00
|
|
|
request_method = request.method
|
|
|
|
if request_method in PERMITTED_READ_METHODS:
|
2024-06-10 17:28:20 -04:00
|
|
|
request_scope = "read"
|
2023-11-02 21:28:11 +01:00
|
|
|
elif request_method in PERMITTED_WRITE_METHODS:
|
2024-06-10 17:28:20 -04:00
|
|
|
request_scope = "write"
|
2023-11-02 21:28:11 +01:00
|
|
|
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")
|
2023-11-02 21:28:11 +01:00
|
|
|
return False
|
2024-06-10 17:28:20 -04:00
|
|
|
request.user = user
|
|
|
|
return True
|
2023-06-02 21:54:48 -04:00
|
|
|
|
|
|
|
|
|
|
|
class EmptyResult(Schema):
|
|
|
|
pass
|
2023-02-15 15:45:57 -05:00
|
|
|
|
2023-02-15 16:22:32 -05:00
|
|
|
|
|
|
|
class Result(Schema):
|
2023-06-02 21:54:48 -04:00
|
|
|
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"
|
|
|
|
|
2023-06-02 21:54:48 -04:00
|
|
|
class Output(Schema):
|
2023-06-03 01:22:19 -04:00
|
|
|
data: List[Any]
|
2023-06-02 21:54:48 -04:00
|
|
|
pages: int
|
|
|
|
count: int
|
|
|
|
|
|
|
|
def paginate_queryset(
|
|
|
|
self,
|
|
|
|
queryset: QuerySet,
|
|
|
|
pagination: NinjaPageNumberPagination.Input,
|
|
|
|
**params: Any,
|
2023-06-03 11:10:48 -04:00
|
|
|
):
|
2023-06-02 21:54: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(
|
2023-06-02 21:54:48 -04:00
|
|
|
auth=OAuthAccessTokenAuth(),
|
2023-08-10 17:15:00 -04:00
|
|
|
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
|
|
|
)
|