[FEATURE] add notification mail event#886
Open
acapai wants to merge 10 commits intoClub-Alpin-Annecy:masterfrom
Open
[FEATURE] add notification mail event#886acapai wants to merge 10 commits intoClub-Alpin-Annecy:masterfrom
acapai wants to merge 10 commits intoClub-Alpin-Annecy:masterfrom
Conversation
17 tasks
Add the first functional part of the new collective-notification system. Users can now configure notification preferences from their profile: - enable or disable notifications - choose a daily or weekly digest frequency - filter by event types - filter by activity types - restrict notifications to selected weekdays The commit adds the backing user fields, enum, ORM relations, form, profile route, template entry point and migrations, plus test coverage for updating preferences. Reviewed-by: andriacap
…ribers immediately Change the new collective notification flow so subscriber notifications are no longer sent immediately at event creation time. This commit introduces a dedicated new_event_notifications persistence table and its ORM model to store newly created events that should later appear in notification digests. The existing send_new_event_notification() flow is updated to: - enqueue the created event for later subscriber digest processing - keep the immediate operational email to configured activity addresses - stop sending direct subscriber emails at creation time A focused event test is added to verify the new behavior: - a matching subscribed user no longer receives an immediate email - a non-matching subscribed user also receives nothing immediately - the event is persisted in the notification queue - the operational activity email is still sent Reviewed-by: andriacap
…enance Add the operational part of the new collective notification system on top of the previously introduced preference and queue layers. This commit introduces: - digest selection logic that resolves pending queued events per user - filtering of digest recipients at send time, including an active-license check - plain-text digest message generation with event links and unsubscribe instructions - one-click public routes to track digest link clicks and disable notifications without authentication - inactivity handling that warns users after one year without email link usage, then disables the subscription after a grace period - Flask CLI commands to send digests and maintain inactive subscriptions - serializer registration in the application factory for signed notification links - cleanup of notification preferences when a user account is anonymized/deleted Focused tests are added for: - skipping expired licenses at digest send time - click tracking and one-click unsubscribe links - warning then disabling inactive notification subscriptions Reviewed-by: andriacap
Add documentation for the new digest-based collective notification system and the scheduled jobs required to operate it in production. This commit documents: - the new notification behavior introduced in this branch - the difference between queued user digests and immediate operational activity emails - the two Flask CLI commands used to send digests and maintain inactive subscriptions - the inactivity policy applied to stale notification subscriptions - the one-click unsubscribe behavior available from notification emails - a sample cron file showing how to schedule the maintenance commands - deployment guidance and a link from the main documentation index Reviewed-by: andriacap
Improve the digest notification flow for production usage and larger recipient volumes. This commit hardens the public mail actions by switching notification link signing to timed tokens and enforcing an explicit expiration window for: - click tracking links - one-click unsubscribe links This prevents archived or forwarded mail links from remaining valid indefinitely. It also reduces the database cost of digest delivery: - due subscribers are resolved once per batch - candidate queued notifications are loaded once and reused across users - per-user matching is performed from a shared in-memory candidate set - obsolete queue rows are purged once they are no longer needed by active subscribers This matters because the previous implementation reloaded the queued notification set for each subscribed user, which does not scale well when the recipient population grows. The commit also makes the transaction boundary explicit for event creation: - queue_new_event_notification() now only adds the queue entry to the SQLAlchemy session - manage_event() commits after send_new_event_notification(event), so persistence remains guaranteed without hiding a commit inside the helper Additional tests cover: - expiration of public notification links - purge of delivered queued notifications - existing digest behaviors remain validateddocker compose -f docker-compose.dev.yml up -d --build
- add an inline, collapsible notification preferences section on the user profile page - improve the notification summary header with compact metadata, icons, and horizontal overflow handling - route admin user creation through a dedicated form variant to avoid exposing raw notification internals - add user-facing French labels for notification-related fields in admin edit views - adjust notification digest scheduling logic for fixed daily and weekly send slots - update profile notification handling and related redirects - extend tests to cover the new scheduling and notification flows Reviewed-by: andriacap
- update digest sending to persist sent state only after SMTP success - add mail headers support for List-Unsubscribe on notification emails - fix HTML digest links so href values stay valid - replace unsubscribe-on-GET with confirmation GET + state-changing POST - add a dedicated RFC 8058 one-click unsubscribe endpoint - add confirmation template for unsubscribe flow - extend notification tests for token expiry, safe unsubscribe, one-click flow and SMTP failure handling - update fake SMTP to match the new mailer contract in tests Reviewed-by: andriacap
- switch notification filters to checkbox-based multi-selects - add dedicated notification preferences page and reusable form partial - add dropdown multi-selects with tags, quick unselect and clear-all actions - prevent impossible event-type/activity combinations when saving preferences - improve notification summary layout in profile - add profile tests for rendering and preference normalization Reviewed-by: andriacap
Reviewed-by: andriacap
Reviewed-by: acapai
775d46d to
766366a
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Système de notifications digest pour les nouvelles collectives
Ce que propose cette branche
Cette PR introduit un système de notifications email groupées (digest) pour alerter les membres de la création de nouvelles collectives. Les utilisateurs s'abonnent via leur profil, choisissent leur fréquence, et reçoivent un email synthétique (quotidien ou hebdomadaire) listant uniquement les collectives qui correspondent à leurs filtres.
Les notifications de supervision vers les boîtes activité (comportement existant) sont préservées et non modifiées.
Fonctionnalités livrées
flask send-new-event-digestsetflask maintain-new-event-notifications2f4d0f7a9c3b— 6 colonnes surusers, 2 tables de jonction, 1 table queueArchitecture — schéma de flux
Travail de comparaison avec la PR #877
Les deux PR convergent vers le même objectif : permettre aux membres d'être informés des nouvelles collectives correspondant à leurs intérêts, avec abonnement via le profil, filtrage par activité, et lien de désabonnement dans les emails.
Cett PR répond à ces mêmes besoins et apporte en plus :
Envoi asynchrone par digest — les emails ne sont pas envoyés dans la requête web mais mis en queue, puis expédiés en lot par un cron. Cela évite la contention SMTP et les timeouts lors de la création d'une collective.
Désabonnement one-click sans login — les routes
/click/et/unsubscribe/sont explicitement exemptées d'authentification. Le token signé suffit. Dans l'autre branche, la route reste derrière@valid_user(), ce qui impose en pratique d'être connecté pour se désabonner depuis un email.Pas de doublon d'envoi possible — un watermark
last_sent_atpar utilisateur et une purge de la queue garantissent qu'une même collective n'est jamais envoyée deux fois.Qualification des destinataires à l'envoi — licence valide, compte actif et filtres métier sont vérifiés au moment de l'envoi du digest, pas seulement à la souscription.
Politique d'inactivité RGPD — après 365 jours sans clic sur un lien de notification, un préavis est envoyé. Sans réaction sous 14 jours, l'abonnement est automatiquement coupé.
Filtrage fin par jour de semaine — en plus des types d'activités et d'événements, l'utilisateur peut restreindre ses notifications aux collectives débutant certains jours de la semaine.
Outillage opérationnel complet — deux commandes CLI dédiées (
flask send-new-event-digests,flask maintain-new-event-notifications), un exemple de fichier cron, et une documentation Sphinx.Couverture de tests d'intégration — queue, scheduling, tokens publics, rendering HTML, purge, inactivité, préférences profil. L'autre branche couvre uniquement les méthodes modèles en tests unitaires, sans couverture des routes de notification ni de l'envoi email.
Fichiers modifiés / créés
collectives/new_event_notifications.pycollectives/models/new_event_notification.pycollectives/models/user/model.pycollectives/models/user/misc.pycollectives/models/user/enum.pyNotificationFrequencycollectives/routes/profile.pycollectives/forms/user.pyNotificationPreferencesFormcollectives/templates/profile/notification_preferences.htmlcollectives/email_templates.pycollectives/__init__.pymigrations/versions/2f4d0f7a9c3b_add_user_new_event_notifications.pytests/test_new_event_notifications.pydoc/cron/collectives-notifications.crondoc/source/notifications_digest.rstPoints d'attention pour la review
/profile/user/notifications/click/<token>et/profile/user/notifications/unsubscribe/<token>sont volontairement exemptes d'authentification — elles sont accessibles depuis un email. La sécurité repose sur le token signéitsdangerous.URLSafeTimedSerializer.collectives/models/user/misc.py— non configurable viaapp.configniConfiguration.doc/cron/collectives-notifications.cron.Refs #877
Closes #873