Blorg-Backend/main.py

220 lines
6.8 KiB
Python

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,
""")
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/user/IDByAuthToken")
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/user/publicInfo/{userID}")
def getuserPublicInfo(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)
}
@app.get("/api/user/settings/account")
def getuserSettingsAccount(authToken: Annotated[str | None, Header()] = None):
try:
if tokenHandler.validateTokenExistence(dbConnection, authToken):
userID = userHandler.getIDByAuthToken(dbConnection, authToken)
return {
"success": True,
"username": userHandler.getUserInfoByID(dbConnection, userID, "username"),
"firstName": userHandler.getUserInfoByID(dbConnection, userID, "firstname"),
"lastName": userHandler.getUserInfoByID(dbConnection, userID, "lastname"),
"message": "Get user settings succeeded!"
}
else:
return {
"success": False,
"username": None,
"firstName": None,
"lastName": None,
"message": "Get user settings failed! authToken provided is not valid."
}
except Exception as error:
return {
"success": False,
"username": None,
"firstName": None,
"lastName": None,
"message": "Get user settings failed! Unexpected server error. " + repr(error)
}
# GET
# /api/user/ByAuthToken
# - userID
# /api/user/publicInfo/{userID}
# - username
# - firstname
# - lastname
# - profile picture
# - location
# - public email (For contact)
# /api/user/privateInfo/{userID}
# - private email (For authentication/login)
# /api/blog/title
# /api/blog/authorID
# /api/blog/categoryID
# /api/blog/pictureLocation
# /api/blog/description
# /api/blog/datePosted
# POST
# /api/user/changeInfo/{infotype}
@app.get("/api")
def getapi():
return {"Hello": "API!"}