feat(notify): convert email lists to NotifyEmailEntry struct with toggle support
- Change balance_notify_extra_emails and account_quota_notify_emails
from []string to []NotifyEmailEntry{email, disabled, verified}
- Add per-email enable/disable toggle for both user and admin notifications
- Add PUT /user/notify-email/toggle API endpoint
- Fix critical bug: API key auth cache snapshot missing balance notify
fields (Email, Username, BalanceNotifyEnabled, etc.), causing
notifications to never fire on cached request paths
- Bump cache snapshot version 3→4 to invalidate stale entries
- Add SQL migration 104 to convert old format data
- Backward compatible: parseNotifyEmails auto-detects old/new format
- User balance notify: max 3 emails (primary + 2 extra)
- Admin quota notify: unlimited emails, each with toggle
This commit is contained in:
@@ -3,7 +3,6 @@ package repository
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -667,12 +666,9 @@ func userEntityToService(u *dbent.User) *service.User {
|
||||
CreatedAt: u.CreatedAt,
|
||||
UpdatedAt: u.UpdatedAt,
|
||||
}
|
||||
// Parse extra emails JSON array
|
||||
// Parse extra emails JSON (supports both old []string and new []NotifyEmailEntry format)
|
||||
if u.BalanceNotifyExtraEmails != "" && u.BalanceNotifyExtraEmails != "[]" {
|
||||
var emails []string
|
||||
if err := json.Unmarshal([]byte(u.BalanceNotifyExtraEmails), &emails); err == nil {
|
||||
out.BalanceNotifyExtraEmails = emails
|
||||
}
|
||||
out.BalanceNotifyExtraEmails = service.ParseNotifyEmails(u.BalanceNotifyExtraEmails)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package repository
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sort"
|
||||
@@ -563,16 +562,9 @@ func applyUserEntityToService(dst *service.User, src *dbent.User) {
|
||||
dst.UpdatedAt = src.UpdatedAt
|
||||
}
|
||||
|
||||
// marshalExtraEmails serializes a string slice to JSON for storage.
|
||||
func marshalExtraEmails(emails []string) string {
|
||||
if len(emails) == 0 {
|
||||
return "[]"
|
||||
}
|
||||
data, err := json.Marshal(emails)
|
||||
if err != nil {
|
||||
return "[]"
|
||||
}
|
||||
return string(data)
|
||||
// marshalExtraEmails serializes notify email entries to JSON for storage.
|
||||
func marshalExtraEmails(entries []service.NotifyEmailEntry) string {
|
||||
return service.MarshalNotifyEmails(entries)
|
||||
}
|
||||
|
||||
// UpdateTotpSecret 更新用户的 TOTP 加密密钥
|
||||
|
||||
Reference in New Issue
Block a user