feat: add test notif button on admin
This commit is contained in:
+75
-1
@@ -1,8 +1,50 @@
|
||||
from django.contrib import admin
|
||||
from django.contrib import admin, messages
|
||||
from django.contrib.auth.admin import UserAdmin
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.urls import reverse
|
||||
|
||||
from accounts.models import ApiToken, PushSubscription, User
|
||||
|
||||
TEST_PAYLOAD = {
|
||||
"title": "Osiris — test",
|
||||
"body": "Reminders are working. This is what a dose reminder looks like.",
|
||||
"url": "/admin/today/",
|
||||
"tag": "test",
|
||||
}
|
||||
|
||||
|
||||
def send_test_push(request, subscription: PushSubscription) -> bool:
|
||||
"""Push a test notification and report the outcome as an admin message."""
|
||||
# Imported here rather than at module scope: tracker.push imports this module's
|
||||
# models, so a top-level import would be circular.
|
||||
from tracker.push import push_is_configured, send_to_subscription
|
||||
|
||||
if not push_is_configured():
|
||||
messages.error(
|
||||
request,
|
||||
"VAPID keys are not set on the server — run manage.py generate_vapid_keys.",
|
||||
)
|
||||
return False
|
||||
|
||||
pk = subscription.pk
|
||||
if send_to_subscription(subscription, TEST_PAYLOAD):
|
||||
messages.success(request, f"Test notification sent to {subscription}.")
|
||||
return True
|
||||
|
||||
# send_to_subscription deletes the row on a 404/410, which is the single most
|
||||
# useful thing to know here: the device is gone, not merely unreachable.
|
||||
if not PushSubscription.objects.filter(pk=pk).exists():
|
||||
messages.warning(
|
||||
request,
|
||||
"That device had discarded its subscription (the push service returned "
|
||||
"404/410), so it has been removed. Re-enable reminders on the device.",
|
||||
)
|
||||
else:
|
||||
messages.error(
|
||||
request, "The push service rejected the message. See the server log."
|
||||
)
|
||||
return False
|
||||
|
||||
|
||||
@admin.register(User)
|
||||
class OsirisUserAdmin(UserAdmin):
|
||||
@@ -15,6 +57,38 @@ class PushSubscriptionAdmin(admin.ModelAdmin):
|
||||
|
||||
list_display = ["user", "user_agent", "created_at", "last_success_at"]
|
||||
readonly_fields = ["endpoint", "p256dh", "auth", "created_at", "last_success_at"]
|
||||
actions = ["send_test_notification"]
|
||||
change_form_template = "admin/accounts/pushsubscription/change_form.html"
|
||||
|
||||
@admin.action(description="Send a test notification to the selected devices")
|
||||
def send_test_notification(self, request, queryset):
|
||||
for subscription in queryset:
|
||||
send_test_push(request, subscription)
|
||||
|
||||
def change_view(self, request, object_id, form_url="", extra_context=None):
|
||||
"""Handle the 'Send test notification' button.
|
||||
|
||||
Intercepted before the form is validated or saved: sending a test is not an
|
||||
edit, and it should not be blocked by an unrelated validation error.
|
||||
"""
|
||||
if request.method == "POST" and "_send_test" in request.POST:
|
||||
subscription = self.get_object(request, object_id)
|
||||
if subscription is None:
|
||||
return self._get_obj_does_not_exist_redirect(
|
||||
request, self.opts, object_id
|
||||
)
|
||||
|
||||
send_test_push(request, subscription)
|
||||
|
||||
# Back to this object so the message is read in context — unless the push
|
||||
# came back 404/410, in which case the row was deleted as dead.
|
||||
if PushSubscription.objects.filter(pk=subscription.pk).exists():
|
||||
return HttpResponseRedirect(request.get_full_path())
|
||||
return HttpResponseRedirect(
|
||||
reverse("admin:accounts_pushsubscription_changelist")
|
||||
)
|
||||
|
||||
return super().change_view(request, object_id, form_url, extra_context)
|
||||
|
||||
|
||||
@admin.register(ApiToken)
|
||||
|
||||
Reference in New Issue
Block a user