Skip to content

Commit

Permalink
Adding in progress src and tests code
Browse files Browse the repository at this point in the history
  • Loading branch information
bergsalex committed Aug 14, 2023
1 parent fa8bb77 commit adbc0c1
Show file tree
Hide file tree
Showing 39 changed files with 1,298 additions and 0 deletions.
Empty file added src/geneweaver/api/__init__.py
Empty file.
Empty file.
32 changes: 32 additions & 0 deletions src/geneweaver/api/controller/api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"""The root API definition for the GeneWeaver API.
This file defines the root API for the GeneWeaver API. It is responsible for
defining the FastAPI application and including all other API routers.
"""
from fastapi import FastAPI, APIRouter, Security

from geneweaver.api.core import deps
from geneweaver.api.core.config import settings

from geneweaver.api.controller import batch
from geneweaver.api.controller import genesets

app = FastAPI(
title="GeneWeaver API",
docs_url=f"{settings.API_PREFIX}/docs",
redoc_url=f"{settings.API_PREFIX}/redoc",
openapi_url=f"{settings.API_PREFIX}/openapi.json",
swagger_ui_oauth2_redirect_url=f"{settings.API_PREFIX}/docs/oauth2-redirect",
swagger_ui_init_oauth={"clientId": settings.AUTH_CLIENT_ID},
)

api_router = APIRouter(
tags=["api"],
dependencies=[
Security(deps.auth.implicit_scheme),
],
)
api_router.include_router(batch.router)
api_router.include_router(genesets.router)

app.include_router(api_router, prefix=settings.API_PREFIX)
32 changes: 32 additions & 0 deletions src/geneweaver/api/controller/batch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"""API Controller definition for batch processing."""
from typing import Optional

from fastapi import APIRouter, UploadFile, Security

from geneweaver.api.core import deps
from geneweaver.api.schemas.auth import UserInternal
from geneweaver.api.schemas.batch import BatchResponse
from geneweaver.api.services.parse.batch import process_batch_file

router = APIRouter(prefix="/batch")


@router.post(path="")
async def batch(
batch_file: UploadFile,
curation_group_id: Optional[int] = None,
user: UserInternal = Security(deps.auth.get_user_strict),
) -> BatchResponse:
"""Submit a batch file for processing."""
user_id = 1 # TODO: Get user ID from session
genesets, user_messages, system_messages = await process_batch_file(
batch_file, user_id
)

return {
"genesets": genesets,
"messages": {
"user_messages": user_messages,
"system_messages": system_messages,
},
}
55 changes: 55 additions & 0 deletions src/geneweaver/api/controller/genesets.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
"""Endpoints related to genesets."""
from typing import Optional

from fastapi import APIRouter, Security, Depends, HTTPException

from geneweaver.api import dependencies as deps
from geneweaver.api.schemas.auth import UserInternal
from geneweaver.db import geneset_value as db_geneset_value
from geneweaver.db import geneset as db_geneset
from geneweaver.db import gene as db_gene
from geneweaver.db.geneset import by_id, by_user_id, is_readable
from geneweaver.db.geneset_value import by_geneset_id
from geneweaver.db.user import by_sso_id
from geneweaver.core.schema.geneset import GenesetUpload


router = APIRouter(prefix="/genesets")


@router.get("")
def get_visible_genesets(
user: UserInternal = Security(deps.full_user),
cursor: Optional[deps.Cursor] = Depends(deps.cursor),
):
"""Get all visible genesets."""
user_genesets = db_geneset.by_user_id(cursor, user.id)
return {"genesets": user_genesets}


@router.get("/{geneset_id}")
def get_geneset(
geneset_id: int,
user: UserInternal = Security(deps.full_user),
cursor: Optional[deps.Cursor] = Depends(deps.cursor),
):
"""Get a geneset by ID."""
if not is_readable(cursor, user.id, geneset_id):
raise HTTPException(status_code=403, detail="Forbidden")

geneset = db_geneset.by_id(cursor, geneset_id)
geneset_values = db_geneset_value.by_geneset_id(cursor, geneset_id)
return {"geneset": geneset, "geneset_values": geneset_values}


@router.post("")
def upload_geneset(
geneset: GenesetUpload,
user: UserInternal = Security(deps.full_user),
cursor: Optional[deps.Cursor] = Depends(deps.cursor),
):
"""Upload a geneset."""
formatted_geneset_values = db_geneset_value.format_geneset_values_for_file_insert(
geneset.gene_list
)
return {"geneset_id": 0}
1 change: 1 addition & 0 deletions src/geneweaver/api/controller/search.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Endpoints related to searching."""
Empty file.
8 changes: 8 additions & 0 deletions src/geneweaver/api/core/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
"""A namespace for the initialized Geneweaver API configuration."""
from geneweaver.db.core.settings_class import Settings as DBSettings

from geneweaver.api.core.config_class import GeneweaverAPIConfig

settings = GeneweaverAPIConfig()

db_settings = DBSettings()
45 changes: 45 additions & 0 deletions src/geneweaver/api/core/config_class.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
"""Namespace for the config class for the Geneweaver API."""
from typing import Any, Dict, Optional, List

from pydantic import BaseSettings, PostgresDsn, validator
from geneweaver.db.core.settings_class import Settings


class GeneweaverAPIConfig(BaseSettings):
"""Config class for the Geneweaver API."""

API_PREFIX: str = ""

POSTGRES_SERVER: str
POSTGRES_USER: str
POSTGRES_PASSWORD: str
POSTGRES_DB: str
SQLALCHEMY_DATABASE_URI: Optional[PostgresDsn] = None

@validator("SQLALCHEMY_DATABASE_URI", pre=True)
def assemble_db_connection(cls, v: Optional[str], values: Dict[str, Any]) -> Any:
if isinstance(v, str):
return v
return PostgresDsn.build(
scheme="postgresql",
user=values.get("POSTGRES_USER"),
password=values.get("POSTGRES_PASSWORD"),
host=values.get("POSTGRES_SERVER"),
path=f"/{values.get('POSTGRES_DB') or ''}",
)

AUTH_DOMAIN: str = "geneweaver.auth0.com"
AUTH_AUDIENCE: str = "https://api.geneweaver.org"
AUTH_ALGORITHMS: List[str] = ["RS256"]
AUTH_EMAIL_NAMESPACE: str = AUTH_AUDIENCE
AUTH_SCOPES = {
"openid profile email": "read",
}
JWT_PERMISSION_PREFIX: str = "approle"
AUTH_CLIENT_ID: str = "oVm9omUtLBpVyL7YfJA8gp3hHaHwyVt8"

class Config:
"""Configuration for the BaseSettings class."""

env_file = ".env"
case_sensitive = True
Empty file added src/geneweaver/api/core/db.py
Empty file.
12 changes: 12 additions & 0 deletions src/geneweaver/api/core/deps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
"""A module to keep track of injectable dependencies for FastAPI endpoints.
- https://fastapi.tiangolo.com/tutorial/dependencies/
"""
from geneweaver.api.core.config import settings
from geneweaver.api.core.security import Auth0

auth = Auth0(
domain=settings.AUTH_DOMAIN,
api_audience=settings.AUTH_AUDIENCE,
scopes=settings.AUTH_SCOPES,
auto_error=False,
)
36 changes: 36 additions & 0 deletions src/geneweaver/api/core/exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
""""""
from fastapi import HTTPException


class Auth0UnauthenticatedException(HTTPException):
def __init__(self, **kwargs):
super().__init__(401, **kwargs)


class Auth0UnauthorizedException(HTTPException):
def __init__(self, **kwargs):
super().__init__(403, **kwargs)


class NotAHeaderRowError(Exception):
pass


class InvalidBatchValueLine(Exception):
pass


class MultiLineStringError(Exception):
pass


class IgnoreLineError(Exception):
pass


class MissingRequiredHeaderError(Exception):
pass


class InvalidScoreThresholdException(Exception):
pass
Loading

0 comments on commit adbc0c1

Please sign in to comment.