feat: pwa notifications
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
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}
|
||||
Reference in New Issue
Block a user