Migrated to fastapi router from subapps

pull/268/head
kompotkot 2021-09-21 12:56:56 +00:00
rodzic d23313c9d1
commit 79dab82972
6 zmienionych plików z 100 dodań i 208 usunięć

Wyświetl plik

@ -3,24 +3,46 @@ The Moonstream HTTP API
""" """
import logging import logging
import time import time
from typing import Dict
from fastapi import FastAPI from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware from fastapi.middleware.cors import CORSMiddleware
from . import data from . import data
from .routes.subscriptions import app as subscriptions_api from .routes.address_info import router as addressinfo_router
from .routes.users import app as users_api from .routes.streams import router as streams_router
from .routes.txinfo import app as txinfo_api from .routes.subscriptions import router as subscriptions_router
from .routes.streams import app as streams_api from .routes.txinfo import router as txinfo_router
from .routes.address_info import app as addressinfo_api from .routes.users import router as users_router
from .settings import ORIGINS from .middleware import BroodAuthMiddleware
from .settings import DOCS_PATHS, DOCS_TARGET_PATH, ORIGINS
from .version import MOONSTREAM_VERSION from .version import MOONSTREAM_VERSION
logging.basicConfig(level=logging.INFO) logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
app = FastAPI(openapi_url=None)
tags_metadata = [
{"name": "addressinfo", "description": "Address public information."},
{"name": "labels", "description": "Addresses label information."},
{"name": "streams", "description": "Operations with data stream and filters."},
{"name": "subscriptions", "description": "Operations with subscriptions."},
{"name": "time", "description": "Timestamp endpoints."},
{"name": "tokens", "description": "Operations with user tokens."},
{"name": "txinfo", "description": "Ethereum transactions info."},
{"name": "users", "description": "Operations with users."},
]
app = FastAPI(
title=f"Moonstream API",
description="Moonstream API endpoints.",
version=MOONSTREAM_VERSION,
openapi_tags=tags_metadata,
openapi_url="/openapi.json",
docs_url=None,
redoc_url=f"/{DOCS_TARGET_PATH}",
)
app.add_middleware( app.add_middleware(
CORSMiddleware, CORSMiddleware,
@ -29,6 +51,24 @@ app.add_middleware(
allow_methods=["*"], allow_methods=["*"],
allow_headers=["*"], allow_headers=["*"],
) )
whitelist_paths: Dict[str, str] = {}
whitelist_paths.update(DOCS_PATHS)
whitelist_paths.update(
{
"/ping": "GET",
"/version": "GET",
"/now": "GET",
"/docs": "GET",
"/openapi.json": "GET",
"/streams/info": "GET",
"/subscriptions/types": "GET",
"/users": "POST",
"/users/token": "POST",
"/users/password/reset_initiate": "POST",
"/users/password/reset_complete": "POST",
}
)
app.add_middleware(BroodAuthMiddleware, whitelist=whitelist_paths)
@app.get("/ping", response_model=data.PingResponse) @app.get("/ping", response_model=data.PingResponse)
@ -46,8 +86,10 @@ async def now_handler() -> data.NowResponse:
return data.NowResponse(epoch_time=time.time()) return data.NowResponse(epoch_time=time.time())
app.mount("/subscriptions", subscriptions_api) app.include_router(addressinfo_router)
app.mount("/users", users_api) app.include_router(streams_router)
app.mount("/streams", streams_api) app.include_router(subscriptions_router)
app.mount("/txinfo", txinfo_api) app.include_router(txinfo_router)
app.mount("/address_info", addressinfo_api) app.include_router(users_router)
# app.mount("/address_info", addressinfo_api)

Wyświetl plik

@ -1,50 +1,22 @@
import logging import logging
from typing import Dict, List, Optional from typing import Optional
from sqlalchemy.sql.expression import true from fastapi import APIRouter, Depends, Query
from fastapi import FastAPI, Depends, Query
from fastapi.middleware.cors import CORSMiddleware
from moonstreamdb.db import yield_db_session from moonstreamdb.db import yield_db_session
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from .. import actions from .. import actions
from .. import data from .. import data
from ..middleware import BroodAuthMiddleware, MoonstreamHTTPException from ..middleware import MoonstreamHTTPException
from ..settings import DOCS_TARGET_PATH, ORIGINS, DOCS_PATHS
from ..version import MOONSTREAM_VERSION
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
tags_metadata = [ router = APIRouter(
{"name": "addressinfo", "description": "Address public information."}, prefix="/users",
{"name": "labels", "description": "Addresses label information."},
]
app = FastAPI(
title=f"Moonstream users API.",
description="User, token and password handlers.",
version=MOONSTREAM_VERSION,
openapi_tags=tags_metadata,
openapi_url="/openapi.json",
docs_url=None,
redoc_url=f"/{DOCS_TARGET_PATH}",
) )
app.add_middleware(
CORSMiddleware,
allow_origins=ORIGINS,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
whitelist_paths: Dict[str, str] = {} @router.get(
whitelist_paths.update(DOCS_PATHS)
app.add_middleware(BroodAuthMiddleware, whitelist=whitelist_paths)
@app.get(
"/ethereum_blockchain", "/ethereum_blockchain",
tags=["addressinfo"], tags=["addressinfo"],
response_model=data.EthereumAddressInfo, response_model=data.EthereumAddressInfo,
@ -57,9 +29,9 @@ async def addressinfo_handler(
return response return response
@app.get( @router.get(
"/labels/ethereum_blockchain", "/labels/ethereum_blockchain",
tags=["labels bul"], tags=["labels"],
response_model=data.AddressListLabelsResponse, response_model=data.AddressListLabelsResponse,
) )
async def addresses_labels_bulk_handler( async def addresses_labels_bulk_handler(

Wyświetl plik

@ -5,14 +5,12 @@ import logging
from typing import Any, Dict, List, Optional from typing import Any, Dict, List, Optional
from bugout.data import BugoutResource from bugout.data import BugoutResource
from fastapi import FastAPI, Request, Query, Depends from fastapi import APIRouter, Request, Query, Depends
from fastapi.middleware.cors import CORSMiddleware
from moonstreamdb import db from moonstreamdb import db
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from .. import data from .. import data
from ..middleware import BroodAuthMiddleware, MoonstreamHTTPException from ..middleware import MoonstreamHTTPException
from ..providers import ( from ..providers import (
ReceivingEventsException, ReceivingEventsException,
event_providers, event_providers,
@ -22,47 +20,20 @@ from ..providers import (
previous_event, previous_event,
) )
from ..settings import ( from ..settings import (
DOCS_TARGET_PATH,
MOONSTREAM_ADMIN_ACCESS_TOKEN, MOONSTREAM_ADMIN_ACCESS_TOKEN,
MOONSTREAM_DATA_JOURNAL_ID, MOONSTREAM_DATA_JOURNAL_ID,
ORIGINS,
DOCS_PATHS,
bugout_client as bc, bugout_client as bc,
BUGOUT_REQUEST_TIMEOUT_SECONDS, BUGOUT_REQUEST_TIMEOUT_SECONDS,
) )
from .. import stream_queries from .. import stream_queries
from .subscriptions import BUGOUT_RESOURCE_TYPE_SUBSCRIPTION from .subscriptions import BUGOUT_RESOURCE_TYPE_SUBSCRIPTION
from ..version import MOONSTREAM_VERSION
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
tags_metadata = [ router = APIRouter(
{"name": "streams", "description": "Operations with data stream and filters."}, prefix="/streams",
]
app = FastAPI(
title=f"Moonstream streams API.",
description="Streams endpoints.",
version=MOONSTREAM_VERSION,
openapi_tags=tags_metadata,
openapi_url="/openapi.json",
docs_url=None,
redoc_url=f"/{DOCS_TARGET_PATH}",
) )
app.add_middleware(
CORSMiddleware,
allow_origins=ORIGINS,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
whitelist_paths: Dict[str, str] = {"/streams/info": "GET"}
whitelist_paths.update(DOCS_PATHS)
whitelist_paths.update()
app.add_middleware(BroodAuthMiddleware, whitelist=whitelist_paths)
def get_user_subscriptions(token: str) -> Dict[str, List[BugoutResource]]: def get_user_subscriptions(token: str) -> Dict[str, List[BugoutResource]]:
""" """
@ -89,7 +60,7 @@ def get_user_subscriptions(token: str) -> Dict[str, List[BugoutResource]]:
return user_subscriptions return user_subscriptions
@app.get("/info", tags=["streams"]) @router.get("/info", tags=["streams"])
async def info_handler() -> Dict[str, Any]: async def info_handler() -> Dict[str, Any]:
info = { info = {
event_type: { event_type: {
@ -102,7 +73,7 @@ async def info_handler() -> Dict[str, Any]:
return info return info
@app.get("/", tags=["streams"], response_model=data.GetEventsResponse) @router.get("/", tags=["streams"], response_model=data.GetEventsResponse)
async def stream_handler( async def stream_handler(
request: Request, request: Request,
q: str = Query(""), q: str = Query(""),
@ -159,7 +130,7 @@ async def stream_handler(
return response return response
@app.get("/latest", tags=["streams"]) @router.get("/latest", tags=["streams"])
async def latest_events_handler( async def latest_events_handler(
request: Request, q=Query(""), db_session: Session = Depends(db.yield_db_session) request: Request, q=Query(""), db_session: Session = Depends(db.yield_db_session)
) -> List[data.Event]: ) -> List[data.Event]:
@ -201,7 +172,7 @@ async def latest_events_handler(
return events return events
@app.get("/next", tags=["stream"]) @router.get("/next", tags=["stream"])
async def next_event_handler( async def next_event_handler(
request: Request, request: Request,
q: str = Query(""), q: str = Query(""),
@ -256,7 +227,7 @@ async def next_event_handler(
return event return event
@app.get("/previous", tags=["stream"]) @router.get("/previous", tags=["stream"])
async def previous_event_handler( async def previous_event_handler(
request: Request, request: Request,
q: str = Query(""), q: str = Query(""),

Wyświetl plik

@ -2,60 +2,31 @@
The Moonstream subscriptions HTTP API The Moonstream subscriptions HTTP API
""" """
import logging import logging
from typing import Dict, List, Optional from typing import List, Optional
from bugout.data import BugoutResource, BugoutResources from bugout.data import BugoutResource, BugoutResources
from bugout.exceptions import BugoutResponseException from bugout.exceptions import BugoutResponseException
from fastapi import FastAPI, Request, Form from fastapi import APIRouter, Request, Form
from fastapi.middleware.cors import CORSMiddleware
from ..admin import subscription_types from ..admin import subscription_types
from .. import data from .. import data
from ..middleware import BroodAuthMiddleware, MoonstreamHTTPException from ..middleware import MoonstreamHTTPException
from ..reporter import reporter from ..reporter import reporter
from ..settings import ( from ..settings import (
DOCS_TARGET_PATH,
DOCS_PATHS,
MOONSTREAM_APPLICATION_ID, MOONSTREAM_APPLICATION_ID,
ORIGINS,
bugout_client as bc, bugout_client as bc,
) )
from ..version import MOONSTREAM_VERSION
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
tags_metadata = [ router = APIRouter(
{"name": "subscriptions", "description": "Operations with subscriptions."}, prefix="/subscriptions",
]
app = FastAPI(
title=f"Moonstream subscriptions API.",
description="User subscriptions endpoints.",
version=MOONSTREAM_VERSION,
openapi_tags=tags_metadata,
openapi_url="/openapi.json",
docs_url=None,
redoc_url=f"/{DOCS_TARGET_PATH}",
) )
app.add_middleware(
CORSMiddleware,
allow_origins=ORIGINS,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
whitelist_paths: Dict[str, str] = {}
whitelist_paths.update(DOCS_PATHS)
whitelist_paths.update({"/subscriptions/types": "GET"})
app.add_middleware(BroodAuthMiddleware, whitelist=whitelist_paths)
BUGOUT_RESOURCE_TYPE_SUBSCRIPTION = "subscription" BUGOUT_RESOURCE_TYPE_SUBSCRIPTION = "subscription"
@app.post("/", tags=["subscriptions"], response_model=data.SubscriptionResourceData) @router.post("/", tags=["subscriptions"], response_model=data.SubscriptionResourceData)
async def add_subscription_handler( async def add_subscription_handler(
request: Request, # subscription_data: data.CreateSubscriptionRequest = Body(...) request: Request, # subscription_data: data.CreateSubscriptionRequest = Body(...)
address: str = Form(...), address: str = Form(...),
@ -118,7 +89,7 @@ async def add_subscription_handler(
) )
@app.delete( @router.delete(
"/{subscription_id}", "/{subscription_id}",
tags=["subscriptions"], tags=["subscriptions"],
response_model=data.SubscriptionResourceData, response_model=data.SubscriptionResourceData,
@ -148,7 +119,7 @@ async def delete_subscription_handler(request: Request, subscription_id: str):
) )
@app.get("/", tags=["subscriptions"], response_model=data.SubscriptionsListResponse) @router.get("/", tags=["subscriptions"], response_model=data.SubscriptionsListResponse)
async def get_subscriptions_handler(request: Request) -> data.SubscriptionsListResponse: async def get_subscriptions_handler(request: Request) -> data.SubscriptionsListResponse:
""" """
Get user's subscriptions. Get user's subscriptions.
@ -186,7 +157,7 @@ async def get_subscriptions_handler(request: Request) -> data.SubscriptionsListR
) )
@app.put( @router.put(
"/{subscription_id}", "/{subscription_id}",
tags=["subscriptions"], tags=["subscriptions"],
response_model=data.SubscriptionResourceData, response_model=data.SubscriptionResourceData,
@ -236,7 +207,7 @@ async def update_subscriptions_handler(
) )
@app.get( @router.get(
"/types", tags=["subscriptions"], response_model=data.SubscriptionTypesListResponse "/types", tags=["subscriptions"], response_model=data.SubscriptionTypesListResponse
) )
async def list_subscription_types() -> data.SubscriptionTypesListResponse: async def list_subscription_types() -> data.SubscriptionTypesListResponse:

Wyświetl plik

@ -6,10 +6,8 @@ transactions, etc.) with side information and return objects that are better sui
end users. end users.
""" """
import logging import logging
from typing import Dict
from fastapi import FastAPI, Depends from fastapi import APIRouter, Depends
from fastapi.middleware.cors import CORSMiddleware
from moonstreamdb.db import yield_db_session from moonstreamdb.db import yield_db_session
from moonstreamdb.models import EthereumAddress from moonstreamdb.models import EthereumAddress
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
@ -17,43 +15,18 @@ from sqlalchemy.orm import Session
from ..abi_decoder import decode_abi from ..abi_decoder import decode_abi
from .. import actions from .. import actions
from .. import data from .. import data
from ..middleware import BroodAuthMiddleware
from ..settings import DOCS_TARGET_PATH, ORIGINS, DOCS_PATHS
from ..version import MOONSTREAM_VERSION
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
tags_metadata = [ router = APIRouter(
{"name": "txinfo", "description": "Ethereum transactions info."}, prefix="/txinfo",
]
app = FastAPI(
title=f"Moonstream users API.",
description="User, token and password handlers.",
version=MOONSTREAM_VERSION,
openapi_tags=tags_metadata,
openapi_url="/openapi.json",
docs_url=None,
redoc_url=f"/{DOCS_TARGET_PATH}",
) )
app.add_middleware(
CORSMiddleware,
allow_origins=ORIGINS,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
whitelist_paths: Dict[str, str] = {}
whitelist_paths.update(DOCS_PATHS)
app.add_middleware(BroodAuthMiddleware, whitelist=whitelist_paths)
# TODO(zomglings): Factor out the enrichment logic into a separate action, because it may be useful # TODO(zomglings): Factor out the enrichment logic into a separate action, because it may be useful
# independently from serving API calls (e.g. data processing). # independently from serving API calls (e.g. data processing).
# TODO(kompotkot): Re-organize function to be able handle each steps with exceptions. # TODO(kompotkot): Re-organize function to be able handle each steps with exceptions.
@app.post( @router.post(
"/ethereum_blockchain", "/ethereum_blockchain",
tags=["txinfo"], tags=["txinfo"],
response_model=data.TxinfoEthereumBlockchainResponse, response_model=data.TxinfoEthereumBlockchainResponse,

Wyświetl plik

@ -7,68 +7,31 @@ import uuid
from bugout.data import BugoutToken, BugoutUser, BugoutResource from bugout.data import BugoutToken, BugoutUser, BugoutResource
from bugout.exceptions import BugoutResponseException from bugout.exceptions import BugoutResponseException
from fastapi import ( from fastapi import (
APIRouter,
Body, Body,
FastAPI,
Form, Form,
Request, Request,
) )
from fastapi.middleware.cors import CORSMiddleware
from .. import data from .. import data
from ..middleware import BroodAuthMiddleware, MoonstreamHTTPException from ..middleware import MoonstreamHTTPException
from ..settings import ( from ..settings import (
MOONSTREAM_APPLICATION_ID, MOONSTREAM_APPLICATION_ID,
DOCS_TARGET_PATH,
ORIGINS,
DOCS_PATHS,
bugout_client as bc, bugout_client as bc,
BUGOUT_REQUEST_TIMEOUT_SECONDS, BUGOUT_REQUEST_TIMEOUT_SECONDS,
) )
from ..version import MOONSTREAM_VERSION
from ..actions import create_onboarding_resource from ..actions import create_onboarding_resource
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
tags_metadata = [ router = APIRouter(
{"name": "users", "description": "Operations with users."}, prefix="/users",
{"name": "tokens", "description": "Operations with user tokens."},
]
app = FastAPI(
title=f"Moonstream users API.",
description="User, token and password handlers.",
version=MOONSTREAM_VERSION,
openapi_tags=tags_metadata,
openapi_url="/openapi.json",
docs_url=None,
redoc_url=f"/{DOCS_TARGET_PATH}",
) )
app.add_middleware(
CORSMiddleware,
allow_origins=ORIGINS,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
whitelist_paths: Dict[str, str] = {} @router.post("/", tags=["users"], response_model=BugoutUser)
whitelist_paths.update(DOCS_PATHS)
whitelist_paths.update(
{
"/users": "POST",
"/users/token": "POST",
"/users/password/reset_initiate": "POST",
"/users/password/reset_complete": "POST",
}
)
app.add_middleware(BroodAuthMiddleware, whitelist=whitelist_paths)
@app.post("/", tags=["users"], response_model=BugoutUser)
async def create_user_handler( async def create_user_handler(
username: str = Form(...), email: str = Form(...), password: str = Form(...) username: str = Form(...), email: str = Form(...), password: str = Form(...)
) -> BugoutUser: ) -> BugoutUser:
@ -86,13 +49,13 @@ async def create_user_handler(
return user return user
@app.get("/", tags=["users"], response_model=BugoutUser) @router.get("/", tags=["users"], response_model=BugoutUser)
async def get_user_handler(request: Request) -> BugoutUser: async def get_user_handler(request: Request) -> BugoutUser:
user: BugoutUser = request.state.user user: BugoutUser = request.state.user
return user return user
@app.post("/password/reset_initiate", tags=["users"], response_model=Dict[str, Any]) @router.post("/password/reset_initiate", tags=["users"], response_model=Dict[str, Any])
async def restore_password_handler(email: str = Form(...)) -> Dict[str, Any]: async def restore_password_handler(email: str = Form(...)) -> Dict[str, Any]:
try: try:
response = bc.restore_password(email=email) response = bc.restore_password(email=email)
@ -103,7 +66,7 @@ async def restore_password_handler(email: str = Form(...)) -> Dict[str, Any]:
return response return response
@app.post("/password/reset_complete", tags=["users"], response_model=BugoutUser) @router.post("/password/reset_complete", tags=["users"], response_model=BugoutUser)
async def reset_password_handler( async def reset_password_handler(
reset_id: str = Form(...), new_password: str = Form(...) reset_id: str = Form(...), new_password: str = Form(...)
) -> BugoutUser: ) -> BugoutUser:
@ -116,7 +79,7 @@ async def reset_password_handler(
return response return response
@app.post("/password/change", tags=["users"], response_model=BugoutUser) @router.post("/password/change", tags=["users"], response_model=BugoutUser)
async def change_password_handler( async def change_password_handler(
request: Request, current_password: str = Form(...), new_password: str = Form(...) request: Request, current_password: str = Form(...), new_password: str = Form(...)
) -> BugoutUser: ) -> BugoutUser:
@ -132,7 +95,7 @@ async def change_password_handler(
return user return user
@app.delete("/", tags=["users"], response_model=BugoutUser) @router.delete("/", tags=["users"], response_model=BugoutUser)
async def delete_user_handler( async def delete_user_handler(
request: Request, password: str = Form(...) request: Request, password: str = Form(...)
) -> BugoutUser: ) -> BugoutUser:
@ -147,7 +110,7 @@ async def delete_user_handler(
return user return user
@app.post("/token", tags=["tokens"], response_model=BugoutToken) @router.post("/token", tags=["tokens"], response_model=BugoutToken)
async def login_handler( async def login_handler(
username: str = Form(...), password: str = Form(...) username: str = Form(...), password: str = Form(...)
) -> BugoutToken: ) -> BugoutToken:
@ -166,7 +129,7 @@ async def login_handler(
return token return token
@app.delete("/token", tags=["tokens"], response_model=uuid.UUID) @router.delete("/token", tags=["tokens"], response_model=uuid.UUID)
async def logout_handler(request: Request) -> uuid.UUID: async def logout_handler(request: Request) -> uuid.UUID:
token = request.state.token token = request.state.token
try: try:
@ -178,7 +141,7 @@ async def logout_handler(request: Request) -> uuid.UUID:
return token_id return token_id
@app.post("/onboarding", tags=["users"], response_model=data.OnboardingState) @router.post("/onboarding", tags=["users"], response_model=data.OnboardingState)
async def set_onboarding_state( async def set_onboarding_state(
request: Request, request: Request,
onboarding_data: data.OnboardingState = Body(...), onboarding_data: data.OnboardingState = Body(...),
@ -224,7 +187,7 @@ async def set_onboarding_state(
return result return result
@app.get("/onboarding", tags=["users"], response_model=data.OnboardingState) @router.get("/onboarding", tags=["users"], response_model=data.OnboardingState)
async def get_onboarding_state(request: Request) -> data.OnboardingState: async def get_onboarding_state(request: Request) -> data.OnboardingState:
token = request.state.token token = request.state.token
try: try:
@ -259,7 +222,7 @@ async def get_onboarding_state(request: Request) -> data.OnboardingState:
return result return result
@app.delete("/onboarding", tags=["users"], response_model=data.OnboardingState) @router.delete("/onboarding", tags=["users"], response_model=data.OnboardingState)
async def delete_onboarding_state(request: Request) -> data.OnboardingState: async def delete_onboarding_state(request: Request) -> data.OnboardingState:
token = request.state.token token = request.state.token
try: try: