Skip to content

fix(notification): the badge congratulations dialog can always be dismissed - #1633

Open
rstrzelecki-inne-projekty wants to merge 1 commit into
apache:mainfrom
rstrzelecki-inne-projekty:fix/badge-alert-cannot-be-dismissed
Open

rstrzelecki-inne-projekty wants to merge 1 commit into
apache:mainfrom
rstrzelecki-inne-projekty:fix/badge-alert-cannot-be-dismissed

Conversation

@rstrzelecki-inne-projekty

Copy link
Copy Markdown

Problem

The "congratulations, you earned a badge" dialog reads its content from the red dot cache (GET /notification/status → badge_award). Closing it calls PUT /answer/api/v1/notification/read/state, and NotificationService.ClearIDUnRead does this:

notificationInfo, exist, err := ns.notificationRepo.GetById(ctx, id)
...
if !exist || notificationInfo.UserID != userID {
    return nil            // <- returns success, and the alert stays in the cache
}
...
err = ns.notificationCommon.RemoveBadgeAwardAlertCache(ctx, userID, id)

When the notification row behind the alert is missing, the method returns nil, the endpoint answers 200, and the alert is never removed. /notification/status keeps returning the same badge_award, so the dialog comes back on the next page load — and there is no way to close it, because every attempt takes the same early return.

The rows do go missing in practice: revoking a badge deletes its notification while the alert stays in the cache. The same early return also skips the cleanup when the notification is already read or belongs to another user.

Observed on a live instance: PUT /notification/read/state answered {"code":200} repeatedly while /notification/status kept serving the same badge_award, whose notification_id no longer appeared in /notification/page.

Change

The alert is removed from the cache before the notification row is looked up. The cache key is built from the caller's own user id (RedDotCacheKey + the login user), so a request can only ever clear the caller's own alert — passing somebody else's notification id does nothing to them.

Tests

internal/service/notification/badge_alert_test.go puts an alert in the cache, has the repository report the notification as missing, dismisses it and asserts the alert is gone. It fails on the current code ("the badge alert is still there, the dialog would come back") and passes with the fix.

…missed

Closing the dialog calls PUT /notification/read/state, which returned success
while doing nothing whenever the notification row behind the alert was gone or
belonged to somebody else: the guard returned early and the alert stayed in the
red dot cache, so /notification/status kept serving the same badge_award and the
dialog came back on every page load with no way to close it.

A revoked badge deletes its notification, which is exactly how the rows go
missing.

The alert now leaves the cache before the notification row is looked up. The
cache key is built from the caller's own user id, so a request can only ever
clear the caller's own alert.

The test fails on the current code and passes with the fix.
rstrzelecki-inne-projekty pushed a commit to rstrzelecki-inne-projekty/answer that referenced this pull request Sep 22, 2026
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants