lib.itmens/common/api.py

80 lines
2.4 KiB
Python
Raw Normal View History

from typing import Any, Callable, List, Optional, Tuple, Type
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
from oauth2_provider.oauth2_backends import OAuthLibCore
from oauth2_provider.oauth2_validators import OAuth2Validator
from oauthlib.oauth2 import Server
PERMITTED_WRITE_METHODS = ["PUT", "POST", "DELETE", "PATCH"]
PERMITTED_READ_METHODS = ["GET", "HEAD", "OPTIONS"]
class OAuthAccessTokenAuth(HttpBearer):
def authenticate(self, request, token) -> bool:
if not token or not request.user.is_authenticated:
2024-05-25 23:38:11 -04:00
logger.debug("API auth: no access token or user not authenticated")
return False
request_scopes = []
request_method = request.method
if request_method in PERMITTED_READ_METHODS:
request_scopes = ["read"]
elif request_method in PERMITTED_WRITE_METHODS:
request_scopes = ["write"]
else:
return False
validator = OAuth2Validator()
core = OAuthLibCore(Server(validator))
valid, oauthlib_req = core.verify_request(request, scopes=request_scopes)
if not valid:
2024-05-25 23:38:11 -04:00
logger.debug(f"API auth: request scope {request_scopes} not verified")
return valid
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(),
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
)