From f4abef1ed67f430c69924fc2b5483244ac226908 Mon Sep 17 00:00:00 2001 From: n Date: Thu, 1 May 2025 05:01:35 +0100 Subject: [PATCH] initial commit --- .env.example | 3 +++ .gitignore | 3 +++ Dockerfile | 14 ++++++++++++++ app/__init__.py | 0 app/main.py | 50 ++++++++++++++++++++++++++++++++++++++++++++++++ requirements.txt | 3 +++ 6 files changed, 73 insertions(+) create mode 100644 .env.example create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 app/__init__.py create mode 100644 app/main.py create mode 100644 requirements.txt diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..9ddc45b --- /dev/null +++ b/.env.example @@ -0,0 +1,3 @@ +MONZO_CLIENT_ID=oauth2client_xxx +MONZO_CLIENT_SECRET=mnzconf.base64-string +MONZO_CALLBACK_URI=http://localhost:8000/callback diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8820971 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.env +.env.public +.env.private diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..2b2a0e0 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,14 @@ +FROM ghcr.io/astral-sh/uv:alpine + +RUN uv venv /code/.venv +WORKDIR /code + +COPY ./requirements.txt /code/requirements.txt + +RUN uv pip install --no-cache-dir --upgrade -r /code/requirements.txt + +COPY ./app /code/app + +# If running behind a proxy like Nginx or Traefik add --proxy-headers +# CMD ["uv", "run", "fastapi", "run", "app/main.py", "--port", "80", "--proxy-headers"] +CMD ["uv", "run", "fastapi", "run", "app/main.py", "--port", "80"] diff --git a/app/__init__.py b/app/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/main.py b/app/main.py new file mode 100644 index 0000000..5f76f5b --- /dev/null +++ b/app/main.py @@ -0,0 +1,50 @@ +from collections import OrderedDict +from dotenv import load_dotenv +from fastapi import FastAPI +from fastapi.responses import RedirectResponse +from uuid import uuid4 +from urllib.parse import urlencode +from typing import Union +import requests +import os + +load_dotenv() +client_id = os.environ['MONZO_CLIENT_ID'] +client_secret = os.environ['MONZO_CLIENT_SECRET'] +callback_uri = os.environ['MONZO_CALLBACK_URI'] + +app = FastAPI() + +@app.get("/") +def read_root(): return {"version": "v0.0.4"} + + +@app.get("/redirect", response_class=RedirectResponse) +def read_redirect(): + state = uuid4() + # TODO: store state in a cookie to check it later + query = urlencode(OrderedDict( + client_id=client_id, + redirect_uri=callback_uri, + state=state, + response_type="code", + )) + return f"https://auth.monzo.com/?{query}" + + +@app.get("/callback") +def read_callback(code: str, state: str): + # TODO: check the state with the user's cookie + data = { + 'grant_type': 'authorization_code', + 'client_id': client_id, + 'client_secret': client_secret, + 'redirect_uri': callback_uri, + 'code': code, + } + response = requests.post("https://api.monzo.com/oauth2/token", data=data) + return response.json() + +@app.get("/items/{item_id}") +def read_item(item_id: int, q: Union[str, None] = None): + return {"item_id": item_id, "q": q} diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..1b3223d --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +fastapi[standard]>=0.113.0,<0.114.0 +pydantic>=2.7.0,<3.0.0 +requests>=2.32.3