import sys import atexit import signal from typing import Union, Annotated from contextlib import asynccontextmanager from fastapi import FastAPI, Request, Header from fastapi.middleware.cors import CORSMiddleware from pydantic import BaseModel import dbHandler import userHandler import securityHandler import tokenHandler dbConnection = dbHandler.connect("blorgdb", "172.20.0.10", "dev", "dev", "5432") def apiInit(): dbHandler.initTable(dbConnection, "Users", """ ID SERIAL PRIMARY KEY, Username VARCHAR(255), Email VARCHAR(255), FirstName VARCHAR(255), LastName VARCHAR(255), Description VARCHAR(255), Country VARCHAR(255), Theme VARCHAR(255), AccentColor VARCHAR(255), PasswordHash VARCHAR(255) """) dbHandler.initTable(dbConnection, "SignOns", """ ID SERIAL PRIMARY KEY, UserID INTEGER, LoginSuccess BOOLEAN, DateAttempted TIMESTAMP, IPLocationAttempted VARCHAR(255) """) dbHandler.initTable(dbConnection, "AuthTokens", """ ID SERIAL PRIMARY KEY, Token VARCHAR(2048), OwnerID INTEGER, DateCreated TIMESTAMP, DateExpiry TIMESTAMP, IPLocationCreated VARCHAR(255) """) dbHandler.initTable(dbConnection, "Blogs", """ ID SERIAL PRIMARY KEY, AuthorID INTEGER, CategoryID INTEGER, DatePosted TIMESTAMP, Description VARCHAR(255) """) dbHandler.initTable(dbConnection, "Categories", """ ID SERIAL PRIMARY KEY, Name VARCHAR(255) """) # userHandler.createUser(dbConnection, "testuser", "Test", "User", "A test user", "TestCountry", "TestTheme", "TestColor", "testuser") def apiCleanup(): dbHandler.disconnect(dbConnection) @asynccontextmanager async def apiLifespan(app: FastAPI): # API Init apiInit() # API Clean up yield apiCleanup() app = FastAPI(lifespan=apiLifespan) origins = [ "http://localhost", "http://localhost:8080", ] app.add_middleware( CORSMiddleware, allow_origins=origins, allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) @app.get("/") def getroot(): return {"Hello": "World"} class ApiBody(BaseModel): username: str password: str @app.post("/api") def postapi(body: ApiBody): print(body.username) print(body.password) return body class loginBody(BaseModel): username: str password: str rememberMe: bool @app.post("/api/login") def postlogin(body: loginBody, request: Request): try: if userHandler.checkUserExistence(dbConnection, body.username): userID = userHandler.getIDByUsername(dbConnection, body.username) if securityHandler.handlePasswordVerification(dbConnection, body.password, userID): return {"success": True, "authToken": tokenHandler.createToken(dbConnection, userID, body.rememberMe, request.client.host), "message": "User login success!"} else: return {"success": False, "authToken": None, "message": "User login failed! Please check your password."} else: return {"success": False, "authToken": None, "message": "User login failed! User does not exist."} except Exception as error: msg = "User login failed! Unexpected server error. " + repr(error) print(msg) return {"success": False, "authToken": None, "message": msg} @app.get("/api/userIDByAuthToken") def getuserIDByAuthToken(authToken: Annotated[str | None, Header()] = None): try: if tokenHandler.validateTokenExistence(dbConnection, authToken): userID = userHandler.getIDByAuthToken(dbConnection, authToken) return {"success": True, "userID": userID, "message": "Get userID by authToken succeeded!"} else: return {"success": False, "userID": None, "message": "Get userID by authToken failed! authToken provided is not valid."} except Exception as error: msg = "Get userID by authToken failed! Unexpected server error. " + repr(error) print(msg) return {"success": False, "authToken": None, "message": msg} @app.get("/api/publicInfo/{userID}") def getpublicInfo(userID: int): try: if userHandler.checkIDExistence(dbConnection, userID): return { "success": True, "username": userHandler.getUserInfoByID(dbConnection, userID, "username"), "firstName": userHandler.getUserInfoByID(dbConnection, userID, "firstname"), "lastName": userHandler.getUserInfoByID(dbConnection, userID, "lastname"), "message": "Get public info succeeded!" } else: return { "success": False, "username": None, "firstName": None, "lastName": None, "message": "Get public info failed! UserID provided does not exist." } except Exception as error: return { "success": False, "username": None, "firstName": None, "lastName": None, "message": "Get public info failed! Unexpected server error. " + repr(error) } # GET # /api/userByAuthToken # - userID # /api/publicInfo/{userID} # - username # - firstname # - lastname # - profile picture # - location # - public email (For contact) # /api/privateInfo/{userID} # - private email (For authentication/login) # POST # /api/changeInfo/{infotype} @app.get("/api") def getapi(): return {"Hello": "API!"}