from django.conf import settings from django.http import HttpRequest from ninja import Router, Schema from ninja.errors import HttpError from accounts.auth import AUTH from accounts.models import PushSubscription from tracker.push import notify_user, push_is_configured router = Router(auth=AUTH) class SubscriptionKeys(Schema): p256dh: str auth: str class SubscribeIn(Schema): """Exactly the shape of a browser PushSubscription, so the client can post it as-is.""" endpoint: str keys: SubscriptionKeys class UnsubscribeIn(Schema): endpoint: str @router.post("/subscribe") def subscribe(request: HttpRequest, payload: SubscribeIn): """Register this device for reminders. Re-subscribing the same endpoint is a no-op.""" if not push_is_configured(): raise HttpError(503, "Push is not configured on the server.") PushSubscription.objects.update_or_create( endpoint=payload.endpoint, defaults={ "user": request.user, "p256dh": payload.keys.p256dh, "auth": payload.keys.auth, "user_agent": request.headers.get("User-Agent", "")[:300], }, ) return {"detail": "Reminders enabled on this device."} @router.post("/unsubscribe") def unsubscribe(request: HttpRequest, payload: UnsubscribeIn): PushSubscription.objects.filter( user=request.user, endpoint=payload.endpoint ).delete() return {"detail": "Reminders disabled on this device."} @router.post("/test") def send_test(request: HttpRequest): """Push a notification right now, to prove the chain works end to end.""" if not request.user.push_subscriptions.exists(): raise HttpError(400, "No device has enabled reminders yet.") delivered = notify_user( request.user, { "title": "Osiris — test", "body": "Reminders are working. This is what a dose reminder looks like.", "url": "/admin/today/", "tag": "test", }, ) if not delivered: raise HttpError(502, "The push service rejected the message.") return {"detail": f"Sent to {delivered} device(s)."} @router.get("/public-key", auth=None) def public_key(request: HttpRequest): """The applicationServerKey the browser needs in order to subscribe.""" return {"public_key": settings.VAPID_PUBLIC_KEY}