220 lines
6.8 KiB
Python
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!"}
|