diff --git a/backend/src/api/protein.py b/backend/src/api/protein.py index 84cf640e..51053ec0 100644 --- a/backend/src/api/protein.py +++ b/backend/src/api/protein.py @@ -7,9 +7,11 @@ from ..db import Database, bytea_to_str, str_to_bytea from ..api_types import ProteinEntry, UploadBody, UploadError, EditBody, CamelModel +from ..auth import requiresAuthentication from io import BytesIO from fastapi import APIRouter from fastapi.responses import FileResponse, StreamingResponse +from fastapi.requests import Request router = APIRouter() @@ -179,7 +181,8 @@ def get_protein_entry(protein_name: str): # TODO: add permissions so only the creator can delete not just anyone @router.delete("/protein/entry/{protein_name:str}", response_model=None) -def delete_protein_entry(protein_name: str): +def delete_protein_entry(protein_name: str, req: Request): + requiresAuthentication(req) # Todo, have a meaningful error if the delete fails with Database() as db: # remove protein @@ -207,7 +210,8 @@ def upload_protein_png(body: UploadPNGBody): # None return means success @router.post("/protein/upload", response_model=UploadError | None) -def upload_protein_entry(body: UploadBody): +def upload_protein_entry(body: UploadBody, req: Request): + requiresAuthentication(req) # check that the name is not already taken in the DB if protein_name_found(body.name): return UploadError.NAME_NOT_UNIQUE @@ -262,10 +266,10 @@ def upload_protein_entry(body: UploadBody): # TODO: add more edits, now only does name and content edits @router.put("/protein/edit", response_model=UploadError | None) -def edit_protein_entry(body: EditBody): +def edit_protein_entry(body: EditBody, req: Request): # check that the name is not already taken in the DB # TODO: check if permission so we don't have people overriding other people's names - + requiresAuthentication(req) try: if body.new_name != body.old_name: os.rename(pdb_file_name(body.old_name), pdb_file_name(body.new_name)) diff --git a/backend/src/auth.py b/backend/src/auth.py index 2a1437cd..9d491449 100644 --- a/backend/src/auth.py +++ b/backend/src/auth.py @@ -1,5 +1,8 @@ import jwt from datetime import datetime, timezone, timedelta +from fastapi.requests import Request +from fastapi import HTTPException +import logging as log # TODO: This method of secret key generation is, obviously, extremely unsafe. # This needs to be changed. @@ -15,13 +18,28 @@ def generateAuthToken(userId, admin): return jwt.encode(payload, secret_key, algorithm="HS256") -# TODO: Find out how FastAPI handles middleware functions, and turn this into one. def authenticateToken(token): # Return the decoded token if it's valid. try: - decoded = jwt.decode(token, secret_key, algorithms="HS256") + # Valid token is always is in the form "Bearer [token]", so we need to slice off the "Bearer" portion. + sliced_token = token[7:] + log.warn(sliced_token) + decoded = jwt.decode(sliced_token, secret_key, algorithms="HS256") + log.warn("Valid token") + log.warn(decoded) return decoded # If the token is invalid, return None. - except Exception: + except Exception as err: + log.error("Invalid token:", err) return None + + +# Use this function with a request if you want. +def requiresAuthentication(req: Request): + userInfo = authenticateToken(req.headers["authorization"]) + if not userInfo or not userInfo.get("admin"): + log.error("Unauthorized User") + raise HTTPException(status_code=403, detail="Unauthorized") + else: + log.warn("User authorized.") diff --git a/frontend/src/lib/backend.ts b/frontend/src/lib/backend.ts index a9fc598d..ec2f25bd 100644 --- a/frontend/src/lib/backend.ts +++ b/frontend/src/lib/backend.ts @@ -1,6 +1,19 @@ export * from "./openapi"; export { DefaultService as Backend } from "./openapi"; import { OpenAPI } from "./openapi"; +import Cookies from "js-cookie"; export const BACKEND_URL = "http://localhost:8000"; OpenAPI.BASE = BACKEND_URL; + +// Sets the token header to the stored authentication token from the cookie +export function setToken() { + console.log("Setting Token") + OpenAPI.TOKEN = Cookies.get("auth") +} + +// Sets the token header to nothing. +export function clearToken() { + console.log("Clearing token.") + OpenAPI.TOKEN = undefined +} diff --git a/frontend/src/routes/Edit.svelte b/frontend/src/routes/Edit.svelte index 0a23cfad..0c22fee9 100644 --- a/frontend/src/routes/Edit.svelte +++ b/frontend/src/routes/Edit.svelte @@ -1,5 +1,5 @@