FIX(notifications): action_code accepts dots, PushMessage.stats actually updates #4
3 changed files with 38 additions and 4 deletions
|
|
@ -0,0 +1,24 @@
|
|||
# Generated by Django 5.2.6 on 2026-09-01 12:23
|
||||
|
||||
import django.core.validators
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('push_notifications', '0006_rename_code_notificationlink_action_code_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='notificationlink',
|
||||
name='action_code',
|
||||
field=models.CharField(db_index=True, max_length=100, unique=True, validators=[django.core.validators.RegexValidator(message='Enter a valid action code: letters, numbers, underscores, hyphens, or dots.', regex='^[-a-zA-Z0-9_.]+\\Z')]),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='pushmessage',
|
||||
name='action_code',
|
||||
field=models.CharField(blank=True, db_index=True, max_length=100, null=True, validators=[django.core.validators.RegexValidator(message='Enter a valid action code: letters, numbers, underscores, hyphens, or dots.', regex='^[-a-zA-Z0-9_.]+\\Z')]),
|
||||
),
|
||||
]
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
from django.core.validators import RegexValidator
|
||||
from django.db import models
|
||||
from oauth2_provider.settings import oauth2_settings
|
||||
|
||||
|
|
@ -6,6 +7,15 @@ from utils.models import BaseModel
|
|||
from utils.clients import gotify
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
# action_code values are dotted, e.g. "billboard.approved", "escrow.timeout"
|
||||
# (see docs/frontend-notification-click-actions.md) — a plain SlugField
|
||||
# rejects the dot, so every real call using the documented catalog gets a
|
||||
# 400 from the serializer. This mirrors slug's allowed charset but adds ".".
|
||||
validate_action_code = RegexValidator(
|
||||
regex=r'^[-a-zA-Z0-9_.]+\Z',
|
||||
message="Enter a valid action code: letters, numbers, underscores, hyphens, or dots.",
|
||||
)
|
||||
|
||||
|
||||
class PushUserQuerySet(models.QuerySet):
|
||||
def submit(self, user):
|
||||
|
|
@ -51,7 +61,7 @@ class NotificationLink(BaseModel):
|
|||
type) instead of a raw URL, so where a tap should navigate is a config
|
||||
change here, not a code deploy across every producer service.
|
||||
"""
|
||||
action_code = models.SlugField(max_length=100, unique=True, db_index=True)
|
||||
action_code = models.CharField(max_length=100, unique=True, db_index=True, validators=[validate_action_code])
|
||||
description = models.CharField(max_length=255, blank=True)
|
||||
url_template = models.CharField(
|
||||
max_length=1000,
|
||||
|
|
@ -93,7 +103,7 @@ class PushMessage(BaseModel):
|
|||
# action_code, resolved against NotificationLink at send time (see
|
||||
# get_gotify_extras). click_object_id_value is substituted into that
|
||||
# action_code's {object_id} placeholder.
|
||||
action_code = models.SlugField(max_length=100, null=True, blank=True, db_index=True)
|
||||
action_code = models.CharField(max_length=100, null=True, blank=True, db_index=True, validators=[validate_action_code])
|
||||
click_object_id_value = models.CharField(max_length=255, null=True, blank=True)
|
||||
stats = models.IntegerField(default=StateChoices.INIT, choices=StateChoices.choices)
|
||||
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@ def send_push_notification(push_message_uuid):
|
|||
message=push_message.message,
|
||||
priority=push_message.priority,
|
||||
extras=push_message.get_gotify_extras())
|
||||
push_message.state = push_message.StateChoices.DONE
|
||||
push_message.save()
|
||||
push_message.stats = push_message.StateChoices.DONE
|
||||
push_message.save(update_fields=["stats"])
|
||||
|
||||
|
||||
@celery_app.task
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue