Skip to content
Snippets Groups Projects
Commit d904ef24 authored by Jeremy M Fee's avatar Jeremy M Fee
Browse files

Merge branch 'issue-41' into 'master'

Custom OpenAPI Titles/Descriptions

Closes #41

See merge request !111
parents 5188102d 2135ba2a
No related branches found
No related tags found
2 merge requests!146Release CMO metadata to production,!111Custom OpenAPI Titles/Descriptions
Pipeline #57722 passed with warnings
......@@ -11,7 +11,11 @@ from .metadata import router as metadata_router
from .SessionMiddleware import SessionMiddleware
app = FastAPI(root_path="/ws/secure")
app = FastAPI(
description="Web service for interaction with operational metadata records",
root_path="/ws/secure",
title="Geomagnetism Metadata Web Service",
)
# NOTE: database used for sessions is started by ..app.app,
# which mounts this application at /ws/secure
......
......@@ -150,10 +150,11 @@ oauth.register(
router = APIRouter()
@router.get("/authorize")
@router.get(
"/authorize",
description="Authorize callback after authenticating using OpenID",
)
async def authorize(request: Request):
"""Authorize callback after authenticating using OpenID"""
# finish login
token = await oauth.openid.authorize_access_token(request)
......@@ -171,9 +172,11 @@ async def authorize(request: Request):
)
@router.get("/login")
@router.get(
"/login",
description="Redirect to OpenID provider.",
)
async def login(request: Request):
"""Redirect to OpenID provider."""
redirect_uri = request.url_for("authorize")
if "127.0.0.1" not in redirect_uri:
# 127.0.0.1 used for local dev, all others use https
......@@ -185,9 +188,11 @@ async def login(request: Request):
return await oauth.openid.authorize_redirect(request, redirect_uri)
@router.get("/logout")
@router.get(
"/logout",
description="Clear session and redirect to index page.",
)
async def logout(request: Request):
"""Clear session and redirect to index page."""
request.session.pop("token", None)
request.session.pop("user", None)
return RedirectResponse(
......@@ -199,7 +204,9 @@ async def logout(request: Request):
)
@router.get("/user")
@router.get(
"/user",
description="Get currently logged in user.",
)
async def user(request: Request, user: User = Depends(require_user())) -> User:
"""Get currently logged in user."""
return user
......@@ -59,7 +59,11 @@ def get_metadata_query(
)
@router.post("/metadata", response_model=Metadata)
@router.post(
"/metadata",
description="Save metadata in database",
response_model=Metadata,
)
async def create_metadata(
request: Request,
metadata: Metadata,
......@@ -71,13 +75,22 @@ async def create_metadata(
return Response(metadata.json(), status_code=201, media_type="application/json")
@router.get("/metadata", response_model=List[Metadata])
@router.get(
"/metadata",
description="Search metadata by query parameters",
name="Request metadata",
response_model=List[Metadata],
)
async def get_metadata(query: MetadataQuery = Depends(get_metadata_query)):
metas = await MetadataDatabaseFactory(database=database).get_metadata(params=query)
return metas
@router.get("/metadata/history", response_model=List[Metadata])
@router.get(
"/metadata/history",
description="Search historical metadata by query parameters",
response_model=List[Metadata],
)
async def get_metadata_history(query: MetadataQuery = Depends(get_metadata_query)):
metas = await MetadataDatabaseFactory(database=database).get_metadata(
params=query, history=True
......@@ -85,12 +98,20 @@ async def get_metadata_history(query: MetadataQuery = Depends(get_metadata_query
return metas
@router.get("/metadata/{id}", response_model=Metadata)
@router.get(
"/metadata/{id}",
description="Search metadata by database id",
response_model=Metadata,
)
async def get_metadata_by_id(id: int):
return await MetadataDatabaseFactory(database=database).get_metadata_by_id(id=id)
@router.get("/metadata/{metadata_id}/history", response_model=List[Metadata])
@router.get(
"/metadata/{metadata_id}/history",
description="Search metadata version history by database id",
response_model=List[Metadata],
)
async def get_metadata_history_by_metadata_id(
metadata_id: int,
):
......@@ -101,7 +122,11 @@ async def get_metadata_history_by_metadata_id(
)
@router.get("/metadata/history/{id}", response_model=Metadata)
@router.get(
"/metadata/history/{id}",
description="Search historical metadata by database id",
response_model=Metadata,
)
async def get_metadata_history_by_id(id: int):
metadata = await MetadataDatabaseFactory(
database=database
......@@ -111,7 +136,11 @@ async def get_metadata_history_by_id(id: int):
return metadata
@router.put("/metadata/{id}", response_model=Metadata)
@router.put(
"/metadata/{id}",
description="Edit metadata from older version",
response_model=Metadata,
)
async def update_metadata(
id: int,
metadata: Metadata = Body(...),
......
from os import name
from fastapi import APIRouter, Depends, HTTPException
from starlette.responses import Response
......@@ -14,7 +15,11 @@ from .data import format_timeseries, get_data_factory, get_data_query, get_times
router = APIRouter()
@router.get("/algorithms/dbdt/")
@router.get(
"/algorithms/dbdt/",
description="First order derivative at requested interval",
name="Dbdt Algorithm",
)
def get_dbdt(
query: DataApiQuery = Depends(get_data_query),
data_factory: TimeseriesFactory = Depends(get_data_factory),
......@@ -31,7 +36,12 @@ def get_dbdt(
)
@router.post("/algorithms/residual", response_model=Reading)
@router.post(
"/algorithms/residual",
description="Caclulates new absolutes and baselines from reading\n\n"
+ "Returns posted reading object with updated values",
response_model=Reading,
)
def calculate_residual(reading: Reading, adjust_reference: bool = True):
try:
return calculate(reading=reading, adjust_reference=adjust_reference)
......
......@@ -22,7 +22,13 @@ METADATA_ENDPOINT = bool(os.getenv("METADATA_ENDPOINT", False))
VERSION = os.getenv("GEOMAG_VERSION", "version")
app = FastAPI(docs_url="/docs", root_path="/ws")
app = FastAPI(
description="Web service for data access and observatory/element information\n\n"
+ "Supports realtime processing via algorithms",
docs_url="/docs",
root_path="/ws",
title="Geomagnetism Data Web Service",
)
app.include_router(algorithms.router)
app.include_router(data.router)
......
......@@ -158,7 +158,12 @@ def get_timeseries(data_factory: TimeseriesFactory, query: DataApiQuery) -> Stre
router = APIRouter()
@router.get("/data/")
@router.get(
"/data/",
name="Request data",
description="Returns timeseries depending on query parameters\n\n"
+ "Limited to 345600 data points",
)
def get_data(
query: DataApiQuery = Depends(get_data_query),
) -> Response:
......
......@@ -8,7 +8,10 @@ from .Element import ELEMENTS
router = APIRouter()
@router.get("/elements/")
@router.get(
"/elements/",
description="Information regarding available geomagnetic elements",
)
def get_elements() -> Dict:
features = []
for e in ELEMENTS:
......
......@@ -10,7 +10,11 @@ from ..db import MetadataDatabaseFactory
router = APIRouter()
@router.get("/metadata", response_model=List[Metadata])
@router.get(
"/metadata",
description="Search metadata records with query parameters(excludes id and metadata id)",
response_model=List[Metadata],
)
async def get_metadata(
category: MetadataCategory = None,
starttime: UTCDateTime = None,
......@@ -36,6 +40,6 @@ async def get_metadata(
status=status,
)
metas = await MetadataDatabaseFactory(database=database).get_metadata(
**query.datetime_dict(exclude={"id"})
**query.datetime_dict(exclude={"id", "metadata_id"})
)
return metas
......@@ -8,7 +8,10 @@ from .Observatory import OBSERVATORIES, OBSERVATORY_INDEX
router = APIRouter()
@router.get("/observatories/")
@router.get(
"/observatories/",
description="Information regarding available geomagnetic observatories",
)
def get_observatories() -> Dict:
return {
"type": "FeatureCollection",
......@@ -16,7 +19,10 @@ def get_observatories() -> Dict:
}
@router.get("/observatories/{id}")
@router.get(
"/observatories/{id}",
description="Search observatories by 3-letter observatory code",
)
async def get_observatory_by_id(id: str) -> Dict:
try:
return OBSERVATORY_INDEX[id].geojson()
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment