from fastapi_pagination import add_pagination from fastapi.responses import PlainTextResponse from fastapi.exceptions import RequestValidationError, ValidationError from datetime import timedelta from fastapi import FastAPI, HTTPException, Depends, Request, status from fastapi_jwt_auth import AuthJWT from fastapi_jwt_auth.exceptions import AuthJWTException from fastapi.responses import JSONResponse from typing import List from tortoise.contrib.pydantic import pydantic_model_creator from fastapi import FastAPI, HTTPException from tortoise import Tortoise from database.exercices.models import Exercice from fastapi.middleware.cors import CORSMiddleware from tortoise.contrib.fastapi import register_tortoise from pydantic import BaseModel import apis.base import config from redis import Redis from fastapi.encoders import jsonable_encoder app = FastAPI(title="Tortoise ORM FastAPI example") origins = [ "http://localhost:8000", "https://localhost:8001", "http://localhost", "http://localhost:8080", ] app.add_middleware( CORSMiddleware, allow_origins=['*'], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) @app.exception_handler(RequestValidationError) @app.exception_handler(ValidationError) async def validation_exception_handler(request, exc: RequestValidationError): errors = {} for e in exc.errors(): errors[e['loc'][-1] + "_error"] = e['msg'] return JSONResponse( status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, content=jsonable_encoder({"detail": errors}), ) class Settings(BaseModel): authjwt_secret_key: str = config.SECRET_KEY authjwt_denylist_enabled: bool = True authjwt_denylist_token_checks: set = {"access", "refresh"} access_expires: int = timedelta(minutes=15 ) refresh_expires: int = timedelta(days=30) # callback to get your configuration settings = Settings() @AuthJWT.load_config def get_config(): return settings # exception handler for authjwt # in production, you can tweak performance using orjson response @app.exception_handler(AuthJWTException) def authjwt_exception_handler(request: Request, exc: AuthJWTException): return JSONResponse( status_code=exc.status_code, content={"detail": exc.message} ) redis_conn = Redis(host='localhost', port=6379, db=0, decode_responses=True) @AuthJWT.token_in_denylist_loader def check_if_token_in_denylist(decrypted_token): jti = decrypted_token['jti'] entry = redis_conn.get(jti) return entry and entry == 'true' app.include_router(apis.base.api_router) @app.delete('/access-revoke') def access_revoke(Authorize: AuthJWT = Depends()): Authorize.jwt_required() # Store the tokens in redis with the value true for revoked. # We can also set an expires time on these tokens in redis, # so they will get automatically removed after they expired. jti = Authorize.get_raw_jwt()['jti'] redis_conn.setex(jti, settings.access_expires, 'true') return {"detail": "Access token has been revoke"} @app.delete('/refresh-revoke') def refresh_revoke(Authorize: AuthJWT = Depends()): Authorize.jwt_refresh_token_required() jti = Authorize.get_raw_jwt()['jti'] redis_conn.setex(jti, settings.refresh_expires, 'true') return {"detail": "Refresh token has been revoke"} add_pagination(app) TORTOISE_ORM = { "connections": {"default": "sqlite://database/db.sqlite3"}, "apps": { "models": { "models": ["database.exercices.models", 'database.auth.models', "database.room.models","aerich.models"], "default_connection": "default", }, }, } register_tortoise( app, config=TORTOISE_ORM, #db_url="sqlite://database/db.sqlite3", modules={"models": ["database.exercices.models", 'database.auth.models']}, generate_schemas=True, add_exception_handlers=True, )