diff --git a/.env b/.env index c0b198a..ef3644a 100644 --- a/.env +++ b/.env @@ -7,3 +7,4 @@ POSTGRES_DB=postgres POSTGRES_HOST=postgres POSTGRES_PORT=5432 HASURAGRES_PORT=8000 +API_KEYS=my_key \ No newline at end of file diff --git a/app/helpers/auth.py b/app/helpers/auth.py new file mode 100644 index 0000000..4d9bf7a --- /dev/null +++ b/app/helpers/auth.py @@ -0,0 +1,13 @@ +import os +from typing import Annotated + +from dotenv import load_dotenv +from fastapi import Header, HTTPException + +load_dotenv() +API_KEYS = list(filter(None, os.environ.get("API_KEYS", "").split(";"))) + + +def validate_api_key(x_api_key: Annotated[str, Header()] = ""): + if x_api_key not in API_KEYS: + raise HTTPException(status_code=401, detail="X-API-Key invalid or missing") diff --git a/app/main.py b/app/main.py index 445f9fe..54884a6 100644 --- a/app/main.py +++ b/app/main.py @@ -3,12 +3,13 @@ import psycopg2 import uvicorn -from fastapi import FastAPI, HTTPException +from fastapi import FastAPI, HTTPException, Depends from fastapi.middleware.cors import CORSMiddleware from psycopg2 import Error from psycopg2.extensions import connection, cursor from pydantic import BaseModel, Field +from helpers.auth import validate_api_key from helpers.hasura import track_table @@ -20,6 +21,7 @@ class Metadata(BaseModel): sql_down: str # SQL to tear DOWN a table (should be the opp. of up) columns: list[str] # list of column names that require insertion write_mode: Literal['append', 'overwrite'] = Field('overwrite', description='mode in which to write to the database') + dryrun: bool = Field(False, description='if true, does not commit changes - useful for testing') conn: connection = None @@ -139,7 +141,7 @@ def execute_delete(metadata: Metadata, payload: list[Any]): cur.execute(cmd, (values,)) -@app.post("/insert") +@app.post("/insert", dependencies=[Depends(validate_api_key)]) def insert(metadata: Metadata, payload: list[Any]): try: created = create_table(metadata) @@ -166,11 +168,14 @@ def insert(metadata: Metadata, payload: list[Any]): conn.rollback() raise HTTPException(status_code=400, detail=err_msg) - conn.commit() + if not metadata.dryrun: + conn.commit() - # Run Hasura actions - must be done after transaction committed otherwise Hasura won't see the table - if created: - track_table(metadata.table_name.lower()) + # Run Hasura actions - must be done after transaction committed otherwise Hasura won't see the table + if created: + track_table(metadata.table_name.lower()) + else: + conn.rollback() return {} diff --git a/docker-compose.yaml b/docker-compose.yaml index 60b3fba..8892318 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -17,6 +17,7 @@ services: HASURA_GRAPHQL_HOST: ${HASURA_GRAPHQL_HOST} HASURA_GRAPHQL_PORT: ${HASURA_GRAPHQL_PORT} HASURAGRES_PORT: ${HASURAGRES_PORT} + API_KEYS: ${API_KEYS} depends_on: - graphql-engine - postgres