felicity-lims/backend/felicity_lims/felicity/main.py

118 lines
4.2 KiB
Python
Raw Normal View History

2021-01-06 19:52:14 +08:00
from felicity.init import initialize_felicity
if initialize_felicity():
2021-04-18 18:37:49 +08:00
import logging
from typing import List
from fastapi import FastAPI, WebSocket
2021-01-06 19:52:14 +08:00
from starlette.middleware.cors import CORSMiddleware
from graphql.execution.executors.asyncio import AsyncioExecutor
2021-04-18 18:37:49 +08:00
from starlette.middleware.authentication import AuthenticationMiddleware
from starlette.authentication import (
AuthenticationBackend,
AuthenticationError,
SimpleUser,
# UnauthenticatedUser,
2021-04-18 18:37:49 +08:00
AuthCredentials
)
import base64
import binascii
2021-01-06 19:52:14 +08:00
from felicity.database.session import database # noqa
from felicity.api.api_v1.api import api_router # noqa
from felicity.core.config import settings # noqa
from starlette.graphql import GraphQLApp
from felicity.gql.schema import gql_schema # noqa
2021-04-18 18:37:49 +08:00
from felicity.gql.deps import get_current_active_user
2021-01-06 19:52:14 +08:00
from felicity.apps.job.sched import felicity_workforce_init, felicity_halt_workforce
2021-04-18 18:37:49 +08:00
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
class FelicityAuthBackend(AuthenticationBackend):
async def authenticate(self, request):
# logger.info(f"trial middle ware: {request}")
# logger.info(f"trial middle ware: {dir(request)}")
if "Authorization" not in request.headers:
2021-07-03 22:41:46 +08:00
logger.info(f"No Authorization Data")
2021-04-18 18:37:49 +08:00
return
# logger.info(f"Authorization checking: {request.headers}")
auth = request.headers["Authorization"]
try:
scheme, credentials = auth.split()
if scheme.lower() == 'basic':
decoded = base64.b64decode(credentials).decode("ascii")
username, _, password = decoded.partition(":")
2021-07-03 22:41:46 +08:00
# TODO: You'd want to verify the username and password here if needed
2021-04-18 18:37:49 +08:00
elif scheme.lower() == 'bearer':
""""get is active user from token"""
logger.info(f"credentials bearer: {credentials}")
user = get_current_active_user(credentials)
2021-07-03 22:41:46 +08:00
logger.info(f"User from token: {user.auth.user_name}")
2021-04-18 18:37:49 +08:00
username, _, password = user.auth.user_name, None, None
else:
2021-07-03 22:41:46 +08:00
raise AuthenticationError(f'UnKnown Authentication Backend: {scheme.lower()}')
return AuthCredentials(["authenticated"]), SimpleUser(username)
2021-04-18 18:37:49 +08:00
except (ValueError, UnicodeDecodeError, binascii.Error) as exc:
raise AuthenticationError(f'Invalid auth credentials: {exc}')
2021-04-18 18:37:49 +08:00
2021-01-06 19:52:14 +08:00
flims = FastAPI(
title=settings.PROJECT_NAME, openapi_url=f"{settings.API_V1_STR}/openapi.json"
)
@flims.on_event("startup")
async def startup():
await database.connect()
felicity_workforce_init()
2021-01-06 19:52:14 +08:00
@flims.on_event("shutdown")
async def shutdown():
felicity_halt_workforce()
2021-01-06 19:52:14 +08:00
await database.disconnect()
# Set all CORS enabled origins
if settings.BACKEND_CORS_ORIGINS:
flims.add_middleware(
CORSMiddleware,
allow_origins=[str(origin) for origin in settings.BACKEND_CORS_ORIGINS],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
2021-04-18 18:37:49 +08:00
flims.add_middleware(
AuthenticationMiddleware,
backend=FelicityAuthBackend()
)
2021-01-06 19:52:14 +08:00
flims.include_router(api_router, prefix=settings.API_V1_STR)
flims.add_route("/felicity-gql", GraphQLApp(schema=gql_schema, executor_class=AsyncioExecutor))
2021-04-18 18:37:49 +08:00
class ConnectionManager:
def __init__(self):
self.connections: List[WebSocket] = []
async def connect(self, websocket: WebSocket):
await websocket.accept()
self.connections.append(websocket)
async def broadcast(self, data: str):
for connection in self.connections:
await connection.send_text(data)
manager = ConnectionManager()
@flims.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
await manager.connect(websocket)
while True:
data = await websocket.receive_text()
await manager.broadcast(f"Client {data}")