Files
sakhteman/core/utils/router.py
T
2024-02-15 00:17:51 +03:30

207 lines
6.0 KiB
Python

import time
from functools import wraps
from typing import Callable, TypeVar, Generic
from fastapi import APIRouter, Request, Response, Body
from fastapi import Security
from fastapi.routing import APIRoute
from starlette.background import BackgroundTasks
from auth.utils import get_current_active_user
from config import conf
from core.utils import to_http_res, http_exception
from core.utils.auth import get_current_active_user
class BaseRoute(APIRoute):
def get_route_handler(self) -> Callable:
original_route_handler = super().get_route_handler()
async def custom_route_handler(request: Request) -> Response:
before = time.time()
response: Response = await original_route_handler(request)
duration = time.time() - before
response.headers["X-Response-Time"] = str(duration)
return response
return custom_route_handler
def shrink(cal: Callable, name: str = None, bt: BackgroundTasks = None):
def can_inner(func):
@wraps(func)
async def wrapper(*args, **kwargs):
return await safe_route(name or cal.__name__, cal, *kwargs.values())
return wrapper
return can_inner
def back_task(cal: Callable, name: str = None):
print(cal)
def back_inner(func):
print(func)
@wraps(func)
async def wrapper(*args, **kwargs):
if cal.__name__ == 'create_salam':
print(cal.__name__)
return await safe_route(name or cal.__name__, cal, *kwargs.values())
return wrapper
return back_inner
def generate_router(
prefix,
dependencies=None,
auth_dependencies=False,
version='v1',
auth_scopes=['account']):
"""
Generate a router with a prefix and dependencies.
Args:
prefix: prefix of the router.
dependencies: dependencies of the router.
auth_dependencies: if router has auth dependencies is True.
version: version of the router.
auth_scopes: auth scopes of the router.
Returns: ApiRouter
"""
if auth_dependencies:
dependencies = dependencies or []
if 'customer' in auth_scopes:
dependencies.extend(
[Security(get_current_active_customer, scopes=auth_scopes)])
else:
dependencies.extend(
[Security(get_current_active_user, scopes=auth_scopes)])
_pre = conf.server.prefix_url.replace('v1', version)
return APIRouter(
prefix=f"{_pre}/{prefix}",
route_class=BaseRoute,
dependencies=dependencies if dependencies else []
)
async def safe_route(_type, fn, *args):
try:
return to_http_res(await fn(*args), _type)
except Exception as e:
return http_exception(e)
class CrudMethods:
create = True
read = True
update = True
delete = True
get_all = True
def __init__(self, create=True, read=True, update=True, delete=True, fetch=True):
self.create = create
self.read = read
self.update = update
self.delete = delete
self.fetch = fetch
def __iter__(self):
r = []
if self.create:
r.append('create')
if self.read:
r.append('read')
if self.update:
r.append('update')
if self.delete:
r.append('delete')
if self.fetch:
r.append('fetch')
return r
T = TypeVar("T")
class SetupCrud(Generic[T]):
_url_prefix = {
'create': '/create',
'get': '/{_id}',
'update': '/{_id}',
'delete': '/{_id}',
'fetch': ''
}
_methods = {
'create': 'post',
'fetch': 'post',
'get': 'get',
'update': 'put',
'delete': 'delete',
}
def __init__(self,
router: APIRouter,
repository,
model: T,
tags=[],
methods: CrudMethods = CrudMethods()
):
for i in ['create', 'update', 'get', 'delete', 'fetch']:
if i == 'create':
@router.post(
self._url_prefix[i],
response_model=model,
tags=tags
)
async def create(body=Body(...)):
b = T(**body)
return await safe_route(i, getattr(repository, 'create'), b)
# elif i == 'update':
# async def update(_id, body: T = Body(...)):
# return await safe_route(i, getattr(repository, i), _id, body)
#
# router.add_api_route(
# _url_prefix[i],
# update,
# methods=[_methods[i]],
# response_model=model,
# tags=tags
# )
# elif i == 'delete':
# async def delete(_id):
# return await safe_route(i, getattr(repository, i), _id)
#
# router.add_api_route(
# _url_prefix[i],
# delete,
# methods=[_methods[i]],
# response_model=model,
# tags=tags
# )
# elif i == 'get':
# async def get(_id):
# return await safe_route(i, getattr(repository, i), _id)
#
# router.add_api_route(
# _url_prefix[i],
# get,
# methods=[_methods[i]],
# response_model=model,
# tags=tags
# )
# elif i == 'fetch':
# async def fetch(_id, body: T = Body(...)):
# return await safe_route(i, getattr(repository, i), _id, body)
#
# router.add_api_route(
# _url_prefix[i],
# fetch,
# methods=[_methods[i]],
# response_model=model,
# tags=tags
# )