Skip to content

Commit

Permalink
Add SQL databases for CLEM workflow to Murfey (#321)
Browse files Browse the repository at this point in the history
* Added SQLModel tables to record CLEM data
* Added FastAPI endpoints to facilitate registration of CLEM data into the Murfey database
* Refactored API endpoint files to move towards increased modularity
  • Loading branch information
tieneupin authored Aug 23, 2024
1 parent b8eb968 commit 557c1ea
Show file tree
Hide file tree
Showing 18 changed files with 1,015 additions and 139 deletions.
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ server = [
"pillow",
"prometheus_client",
"python-jose[cryptography]",
"sqlalchemy[postgresql]", # Add as explicit dependency
"sqlmodel",
"stomp-py<=8.1.0", # 8.1.1 (released 2024-04-06) doesn't work with our project
"uvicorn[standard]",
Expand Down
2 changes: 1 addition & 1 deletion src/murfey/cli/add_user.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from sqlmodel import Session, create_engine

from murfey.server.auth import hash_password
from murfey.server.api.auth import hash_password
from murfey.server.config import get_machine_config
from murfey.server.murfey_db import url
from murfey.util.db import MurfeyUser as User
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@
sanitise,
templates,
)
from murfey.server.auth import validate_token
from murfey.server.api.auth import validate_token
from murfey.server.api.spa import _cryolo_model_path
from murfey.server.config import from_file, settings
from murfey.server.gain import Camera, prepare_eer_gain, prepare_gain
from murfey.server.murfey_db import murfey_db
from murfey.server.spa.api import _cryolo_model_path
from murfey.util.db import (
AutoProcProgram,
ClientEnvironment,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,39 @@
from __future__ import annotations

import secrets
from logging import getLogger
from typing import Annotated

from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
from fastapi import APIRouter, Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from jose import JWTError, jwt
from passlib.context import CryptContext
from pydantic import BaseModel
from sqlmodel import Session, create_engine, select

from murfey.server.config import get_machine_config
from murfey.server.murfey_db import url
from murfey.util.db import MurfeyUser as User

# Set up logger
logger = getLogger("murfey.server.api.auth")

# Set up router
router = APIRouter()

# Set up variables used for authentication
machine_config = get_machine_config()
ALGORITHM = machine_config.auth_algorithm or "HS256"
SECRET_KEY = machine_config.auth_key or secrets.token_hex(32)

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")


"""
HELPER FUNCTIONS
"""


def verify_password(plain_password: str, hashed_password: str) -> bool:
return pwd_context.verify(plain_password, hashed_password)

Expand All @@ -28,6 +42,7 @@ def hash_password(password: str) -> str:
return pwd_context.hash(password)


# Set up database engine
try:
_url = url(get_machine_config())
engine = create_engine(_url)
Expand Down Expand Up @@ -65,3 +80,37 @@ async def validate_token(token: Annotated[str, Depends(oauth2_scheme)]):
headers={"WWW-Authenticate": "Bearer"},
)
return None


class Token(BaseModel):
access_token: str
token_type: str


def create_access_token(data: dict):
to_encode = data.copy()

encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
return encoded_jwt


"""
API ENDPOINTS
"""


@router.post("/token")
def generate_token(
form_data: Annotated[OAuth2PasswordRequestForm, Depends()],
) -> Token:
validated = validate_user(form_data.username, form_data.password)
if not validated:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Incorrect username or password",
headers={"WWW-Authenticate": "Bearer"},
)
access_token = create_access_token(
data={"user": form_data.username},
)
return Token(access_token=access_token, token_type="bearer")
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
cygwin = APIRouter(prefix="/cygwin", tags=["bootstrap"])
version = APIRouter(prefix="/version", tags=["bootstrap"])

log = logging.getLogger("murfey.server.bootstrap")
log = logging.getLogger("murfey.server.api.bootstrap")


def _validate_package_name(package: str) -> bool:
Expand Down
Loading

0 comments on commit 557c1ea

Please sign in to comment.