Skip to content

Commit

Permalink
Added bearer token checking to restricted API calls - Protein upload,…
Browse files Browse the repository at this point in the history
… delete, and edit.
  • Loading branch information
ansengarvin committed Feb 26, 2024
1 parent fb0b3ff commit a308e71
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 7 deletions.
13 changes: 9 additions & 4 deletions backend/src/api/protein.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()

Expand Down Expand Up @@ -179,7 +181,9 @@ 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):
print("DELETING")
requiresAuthentication(req)
# Todo, have a meaningful error if the delete fails
with Database() as db:
# remove protein
Expand Down Expand Up @@ -207,7 +211,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
Expand Down Expand Up @@ -262,10 +267,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))
Expand Down
26 changes: 23 additions & 3 deletions backend/src/auth.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import jwt
from datetime import datetime, timezone, timedelta
from fastapi.requests import Request
from fastapi import HTTPException

# TODO: This method of secret key generation is, obviously, extremely unsafe.
# This needs to be changed.
Expand All @@ -15,13 +17,31 @@ 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:]
print(sliced_token)
decoded = jwt.decode(sliced_token, secret_key, algorithms="HS256")
print("Valid token")
print(decoded)
return decoded

# If the token is invalid, return None.
except Exception:
except Exception as err:
print("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")):
print("Unauthorized User")
raise HTTPException(
status_code=403,
detail="Unauthorized"
)
else:
print("User authorized.")

0 comments on commit a308e71

Please sign in to comment.