diff --git a/.github/cspell.json b/.github/cspell.json new file mode 100644 index 0000000..20891be --- /dev/null +++ b/.github/cspell.json @@ -0,0 +1,17 @@ +{ + "version": "0.2", + "ignorepaths": [ + ".github/", + ".git/" + ], + "ignorewords": [], + "useGitignore": true, + "language": "en", + "import": [], + "dictionarydefinitions": [], + "dictionaries": [], + "words": [ + "cnap", + "Dockerfile" + ] +} \ No newline at end of file diff --git a/.github/workflows/doclint.yml b/.github/workflows/doclint.yml new file mode 100644 index 0000000..20e75e2 --- /dev/null +++ b/.github/workflows/doclint.yml @@ -0,0 +1,29 @@ +name: Document Scan + +on: + push: + branches: + - main + paths: + - '**/*.md' + pull_request: + paths: + - '**/*.md' + workflow_dispatch: + +permissions: + contents: read + +jobs: + scan_doc: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: streetsidesoftware/cspell-action@v2 + with: + files: | + **/*.md + *.md + config: .github/cspell.json + verbose: true + incremental_files_only: false diff --git a/.github/workflows/pylint.yml b/.github/workflows/pylint.yml new file mode 100644 index 0000000..b93f3db --- /dev/null +++ b/.github/workflows/pylint.yml @@ -0,0 +1,33 @@ +name: Pylint Scan + +on: + pull_request: + paths: + - 'src/**/*.py' + push: + branches: + - main + paths: + - 'src/**/*.py' + workflow_dispatch: + +jobs: + codescan: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + with: + python-version: 3.11 + - name: Install dependencies + run: | + pip3 install --upgrade pip + pip3 install pylint + for f in $(find -type f -name "requirements.txt"); do + pip3 install -r $f + done + - name: Analyzing the python code + run: | + set -ex + export PYTHONPATH=$PWD/src/tia/ + find . -type f -name "*.py" | xargs pylint diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ed8ebf5 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +__pycache__ \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..5f7436d --- /dev/null +++ b/README.md @@ -0,0 +1,11 @@ +# GenTrade Server + + +## Quick Start + +- Run from source + +```shell +export PYTHONPATH=/src +uvicorn gentrade-server.main:app --reload +``` \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..0195b38 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +fastapi[standard] +uvicorn \ No newline at end of file diff --git a/src/gentrade-server/__init__.py b/src/gentrade-server/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/gentrade-server/auth.py b/src/gentrade-server/auth.py new file mode 100644 index 0000000..70e6804 --- /dev/null +++ b/src/gentrade-server/auth.py @@ -0,0 +1,14 @@ +from fastapi import Security, HTTPException, status +from fastapi.security import APIKeyHeader +from .db import check_api_key, get_user_from_api_key + +api_key_header = APIKeyHeader(name="X-API-Key") + +def get_user(api_key_header: str = Security(api_key_header)): + if check_api_key(api_key_header): + user = get_user_from_api_key(api_key_header) + return user + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail="Missing or invalid API key" + ) diff --git a/src/gentrade-server/db.py b/src/gentrade-server/db.py new file mode 100644 index 0000000..7266790 --- /dev/null +++ b/src/gentrade-server/db.py @@ -0,0 +1,19 @@ +api_keys = { + "e54d4431-5dab-474e-b71a-0db1fcb9e659": "7oDYjo3d9r58EJKYi5x4E8", + "5f0c7127-3be9-4488-b801-c7b6415b45e9": "mUP7PpTHmFAkxcQLWKMY8t" +} + +users = { + "7oDYjo3d9r58EJKYi5x4E8": { + "name": "Bob" + }, + "mUP7PpTHmFAkxcQLWKMY8t": { + "name": "Alice" + }, +} + +def check_api_key(api_key: str): + return api_key in api_keys + +def get_user_from_api_key(api_key: str): + return users[api_keys[api_key]] diff --git a/src/gentrade-server/main.py b/src/gentrade-server/main.py new file mode 100644 index 0000000..9a67f98 --- /dev/null +++ b/src/gentrade-server/main.py @@ -0,0 +1,15 @@ +from fastapi import FastAPI, Depends +from .routers import secure, public +from .auth import get_user + +app = FastAPI() + +app.include_router( + public.router, + prefix="/api/v1/public" +) +app.include_router( + secure.router, + prefix="/api/v1/secure", + dependencies=[Depends(get_user)] +) diff --git a/src/gentrade-server/routers/__init__.py b/src/gentrade-server/routers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/gentrade-server/routers/public.py b/src/gentrade-server/routers/public.py new file mode 100644 index 0000000..88373eb --- /dev/null +++ b/src/gentrade-server/routers/public.py @@ -0,0 +1,8 @@ +from fastapi import APIRouter + + +router = APIRouter() + +@router.get("/") +async def get_testroute(): + return "OK" \ No newline at end of file diff --git a/src/gentrade-server/routers/secure.py b/src/gentrade-server/routers/secure.py new file mode 100644 index 0000000..4633323 --- /dev/null +++ b/src/gentrade-server/routers/secure.py @@ -0,0 +1,8 @@ +from fastapi import APIRouter, Depends +from ..auth import get_user + +router = APIRouter() + +@router.get("/") +async def get_testroute(user: dict = Depends(get_user)): + return user \ No newline at end of file