80 lines
2.3 KiB
Python
80 lines
2.3 KiB
Python
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}
|