From a7c25076d16bde9ec928b9ef01bce952406ea7b1 Mon Sep 17 00:00:00 2001 From: Christian Cleberg Date: Wed, 8 Apr 2026 14:29:21 -0500 Subject: initial commit --- app/routers/devices.py | 20 ++++++++++++++++++++ app/routers/health.py | 8 ++++++++ app/routers/subscriptions.py | 14 ++++++++++++++ app/routers/test.py | 33 +++++++++++++++++++++++++++++++++ 4 files changed, 75 insertions(+) create mode 100644 app/routers/devices.py create mode 100644 app/routers/health.py create mode 100644 app/routers/subscriptions.py create mode 100644 app/routers/test.py (limited to 'app/routers') diff --git a/app/routers/devices.py b/app/routers/devices.py new file mode 100644 index 0000000..882c474 --- /dev/null +++ b/app/routers/devices.py @@ -0,0 +1,20 @@ +from fastapi import APIRouter, Depends +from sqlalchemy.ext.asyncio import AsyncSession +from app.db import get_db +from app.schemas import DeviceRegisterIn +from app.crud import upsert_device +from app.security import require_api_key + +router = APIRouter(prefix="/v1/devices", tags=["devices"], dependencies=[Depends(require_api_key)]) + + +@router.post("/register") +async def register_device(payload: DeviceRegisterIn, db: AsyncSession = Depends(get_db)) -> dict: + device = await upsert_device(db, payload) + return { + "id": device.id, + "user_id": device.user_id, + "bundle_id": device.bundle_id, + "apns_env": device.apns_env, + "is_enabled": device.is_enabled, + } diff --git a/app/routers/health.py b/app/routers/health.py new file mode 100644 index 0000000..794a09f --- /dev/null +++ b/app/routers/health.py @@ -0,0 +1,8 @@ +from fastapi import APIRouter + +router = APIRouter(tags=["health"]) + + +@router.get("/health") +async def health() -> dict: + return {"status": "ok"} diff --git a/app/routers/subscriptions.py b/app/routers/subscriptions.py new file mode 100644 index 0000000..81585a1 --- /dev/null +++ b/app/routers/subscriptions.py @@ -0,0 +1,14 @@ +from fastapi import APIRouter, Depends +from sqlalchemy.ext.asyncio import AsyncSession +from app.db import get_db +from app.schemas import SubscriptionUpsertIn +from app.crud import replace_subscriptions +from app.security import require_api_key + +router = APIRouter(prefix="/v1/subscriptions", tags=["subscriptions"], dependencies=[Depends(require_api_key)]) + + +@router.post("/upsert") +async def upsert_subscriptions(payload: SubscriptionUpsertIn, db: AsyncSession = Depends(get_db)) -> dict: + await replace_subscriptions(db, payload) + return {"status": "ok"} diff --git a/app/routers/test.py b/app/routers/test.py new file mode 100644 index 0000000..70a5d4e --- /dev/null +++ b/app/routers/test.py @@ -0,0 +1,33 @@ +from fastapi import APIRouter, Depends, HTTPException +from sqlalchemy import select +from sqlalchemy.ext.asyncio import AsyncSession + +from app.apns import APNSClient +from app.db import get_db +from app.models import Device +from app.security import require_api_key + +router = APIRouter(prefix="/v1/test", tags=["test"], dependencies=[Depends(require_api_key)]) + + +@router.post("/push/{device_id}") +async def test_push(device_id: int, db: AsyncSession = Depends(get_db)) -> dict: + result = await db.execute(select(Device).where(Device.id == device_id)) + device = result.scalar_one_or_none() + if device is None: + raise HTTPException(status_code=404, detail="device not found") + + client = APNSClient() + try: + ok, apns_id, error = await client.send_alert( + device_token=device.apns_token, + apns_env=device.apns_env, + topic=device.bundle_id, + title="Hutch test", + body="Test push from hutch-notify", + payload={"event_type": "test", "deep_link": "hutch://home"}, + ) + finally: + await client.aclose() + + return {"ok": ok, "apns_id": apns_id, "error": error} -- cgit v1.2.3