Brushed up the backend, added writing task 1 academic prompt gen and grading ENCOA-274
This commit is contained in:
9
ielts_be/middlewares/__init__.py
Normal file
9
ielts_be/middlewares/__init__.py
Normal file
@@ -0,0 +1,9 @@
|
||||
from .authentication import AuthBackend, AuthenticationMiddleware
|
||||
from .authorization import Authorized, IsAuthenticatedViaBearerToken
|
||||
|
||||
__all__ = [
|
||||
"AuthBackend",
|
||||
"AuthenticationMiddleware",
|
||||
"Authorized",
|
||||
"IsAuthenticatedViaBearerToken"
|
||||
]
|
||||
48
ielts_be/middlewares/authentication.py
Normal file
48
ielts_be/middlewares/authentication.py
Normal file
@@ -0,0 +1,48 @@
|
||||
import os
|
||||
from typing import Tuple
|
||||
|
||||
import jwt
|
||||
from jwt import InvalidTokenError
|
||||
from pydantic import BaseModel, Field
|
||||
from starlette.authentication import AuthenticationBackend
|
||||
from starlette.middleware.authentication import (
|
||||
AuthenticationMiddleware as BaseAuthenticationMiddleware,
|
||||
)
|
||||
from starlette.requests import HTTPConnection
|
||||
|
||||
|
||||
class Session(BaseModel):
|
||||
authenticated: bool = Field(False, description="Is user authenticated?")
|
||||
|
||||
|
||||
class AuthBackend(AuthenticationBackend):
|
||||
async def authenticate(
|
||||
self, conn: HTTPConnection
|
||||
) -> Tuple[bool, Session]:
|
||||
session = Session()
|
||||
authorization: str = conn.headers.get("Authorization")
|
||||
if not authorization:
|
||||
return False, session
|
||||
|
||||
try:
|
||||
scheme, token = authorization.split(" ")
|
||||
if scheme.lower() != "bearer":
|
||||
return False, session
|
||||
except ValueError:
|
||||
return False, session
|
||||
|
||||
jwt_secret_key = os.getenv("JWT_SECRET_KEY")
|
||||
if not jwt_secret_key:
|
||||
return False, session
|
||||
|
||||
try:
|
||||
jwt.decode(token, jwt_secret_key, algorithms=["HS256"])
|
||||
except InvalidTokenError:
|
||||
return False, session
|
||||
|
||||
session.authenticated = True
|
||||
return True, session
|
||||
|
||||
|
||||
class AuthenticationMiddleware(BaseAuthenticationMiddleware):
|
||||
pass
|
||||
36
ielts_be/middlewares/authorization.py
Normal file
36
ielts_be/middlewares/authorization.py
Normal file
@@ -0,0 +1,36 @@
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import List, Type
|
||||
|
||||
from fastapi import Request
|
||||
from fastapi.openapi.models import APIKey, APIKeyIn
|
||||
from fastapi.security.base import SecurityBase
|
||||
|
||||
from ielts_be.exceptions import CustomException, UnauthorizedException
|
||||
|
||||
|
||||
class BaseAuthorization(ABC):
|
||||
exception = CustomException
|
||||
|
||||
@abstractmethod
|
||||
async def has_permission(self, request: Request) -> bool:
|
||||
pass
|
||||
|
||||
|
||||
class IsAuthenticatedViaBearerToken(BaseAuthorization):
|
||||
exception = UnauthorizedException
|
||||
|
||||
async def has_permission(self, request: Request) -> bool:
|
||||
return request.user.authenticated
|
||||
|
||||
|
||||
class Authorized(SecurityBase):
|
||||
def __init__(self, permissions: List[Type[BaseAuthorization]]):
|
||||
self.permissions = permissions
|
||||
self.model: APIKey = APIKey(**{"in": APIKeyIn.header}, name="Authorization")
|
||||
self.scheme_name = self.__class__.__name__
|
||||
|
||||
async def __call__(self, request: Request):
|
||||
for permission in self.permissions:
|
||||
cls = permission()
|
||||
if not await cls.has_permission(request=request):
|
||||
raise cls.exception
|
||||
Reference in New Issue
Block a user