0
0
Fork 0
mirror of https://github.com/discourse/discourse.git synced 2026-08-12 05:37:26 +08:00
discourse/app/jobs
Régis Hanol fa0cabddbe
FIX: Notification counts not matching displayed notifications
Notification badge counts could get "stuck" — showing a number higher
than the actual visible notifications. This happened because count
queries used lightweight SQL (only filtering deleted topics), while
display queries applied full access control via Guardian. When a user
lost access to a topic — removed from a group/PM, or category
permissions changed — the notification persisted in counts but was
filtered from the displayed list.

Additionally, the `visible` scope had a logic error: the LEFT JOIN
condition `topics.id IS NULL OR topics.deleted_at IS NULL` incorrectly
included notifications for hard-deleted topics.

The fix introduces `NotificationQuery` (following the `BookmarkQuery`
pattern) — a centralized class that handles all notification filtering
at the SQL level, ensuring counts always match displayed notifications.

Access control uses a CASE on topic archetype: PMs check
topic_allowed_users + topic_allowed_groups; regular topics check
category read_restricted against the user's secure_category_ids. Shared
drafts are excluded when the user lacks access. Admins without
suppress_secured_categories_from_admin skip all checks. Badge
notifications are handled via Ruby post-processing when enable_badges
is false.

To prevent DB bloat from orphaned notifications, model callbacks
enqueue DeleteInaccessibleNotifications when access is revoked:

- TopicAllowedUser after_destroy — enqueues with topic_id
- TopicAllowedGroup after_destroy — enqueues with topic_id
- GroupUser after_destroy — enqueues with user_id + group_id
- Category after_update — enqueues with category_id when permissions change

The job supports three modes: topic_id (checks each user via Guardian),
category_id (iterates topics, delegates to topic_id mode), and
user_id + group_id (finds affected topics, bulk-deletes where user
lost access).

Redo of #27589
Ref - t/121464
2026-06-17 10:32:53 +02:00
..
concerns DEV: Enable Style/RedundantParentheses rubocop rule (#40095) 2026-05-19 15:48:09 +02:00
onceoff DEV: Enable Style/RedundantSelf rubocop rule (#40098) 2026-05-19 19:27:45 +02:00
regular FIX: Notification counts not matching displayed notifications 2026-06-17 10:32:53 +02:00
scheduled FIX: Do not send notifications for upcoming changes not displayed (#40933) 2026-06-17 09:10:49 +10:00
base.rb DEV: Enable Style/RedundantSelf rubocop rule (#40098) 2026-05-19 19:27:45 +02:00