Fix bootstrap meeting unread counts
This commit is contained in:
@@ -75,6 +75,10 @@ func (s testSecurityStore) CountUnreadSystemNotifications(types.TenantID, types.
|
||||
return 0, s.err
|
||||
}
|
||||
|
||||
func (s testSecurityStore) CountUnreadSystemNotificationsByEventPrefix(types.TenantID, types.Uid, string) (int, error) {
|
||||
return 0, s.err
|
||||
}
|
||||
|
||||
func (s testSecurityStore) MarkSystemNotificationRead(types.TenantID, types.Uid, string, time.Time) error {
|
||||
return s.err
|
||||
}
|
||||
|
||||
@@ -490,6 +490,7 @@ type TenantBusinessAdapter interface {
|
||||
TenantSystemNotificationCreate(t.TenantID, *t.SystemNotification) error
|
||||
TenantSystemNotificationList(t.TenantID, t.Uid, string, int) ([]t.SystemNotification, string, error)
|
||||
TenantSystemNotificationUnreadCount(t.TenantID, t.Uid) (int, error)
|
||||
TenantSystemNotificationUnreadCountByEventPrefix(t.TenantID, t.Uid, string) (int, error)
|
||||
TenantSystemNotificationMarkRead(t.TenantID, t.Uid, string, time.Time) error
|
||||
|
||||
TenantFriendRequestCreate(t.TenantID, *t.FriendRequest) (*t.FriendRequest, error)
|
||||
|
||||
@@ -8793,6 +8793,33 @@ func (a *adapter) TenantSystemNotificationUnreadCount(id t.TenantID, uid t.Uid)
|
||||
return count, nil
|
||||
}
|
||||
|
||||
func (a *adapter) TenantSystemNotificationUnreadCountByEventPrefix(id t.TenantID, uid t.Uid, eventPrefix string) (int, error) {
|
||||
if !a.tenantScopedDB {
|
||||
tenantAdp, err := a.routedTenantAdapter(id)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if tenantAdp != a {
|
||||
return tenantAdp.TenantSystemNotificationUnreadCountByEventPrefix(id, uid, eventPrefix)
|
||||
}
|
||||
}
|
||||
eventPrefix = strings.TrimSpace(eventPrefix)
|
||||
if err := validTenant(id); err != nil || uid.IsZero() || eventPrefix == "" {
|
||||
return 0, t.ErrMalformed
|
||||
}
|
||||
ctx, cancel := a.getContext()
|
||||
if cancel != nil {
|
||||
defer cancel()
|
||||
}
|
||||
var count int
|
||||
if err := a.db.GetContext(ctx, &count,
|
||||
`SELECT COUNT(*) FROM im_system_notifications WHERE user_id=? AND read_at IS NULL AND event_type LIKE ?`,
|
||||
decodeUID(uid), eventPrefix+"%"); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
func (a *adapter) TenantSystemNotificationMarkRead(id t.TenantID, uid t.Uid, eventID string, readAt time.Time) error {
|
||||
if !a.tenantScopedDB {
|
||||
tenantAdp, err := a.routedTenantAdapter(id)
|
||||
|
||||
@@ -1711,6 +1711,10 @@ func serveIMBootstrap(wrt http.ResponseWriter, req *http.Request) {
|
||||
}
|
||||
}
|
||||
modulePayloads := workbenchModulePayloads(modules)
|
||||
if err := populateWorkbenchModuleUnreadCounts(principal.TenantID, principal.Uid, modulePayloads); err != nil {
|
||||
writeIMRelationError(wrt, req, err)
|
||||
return
|
||||
}
|
||||
entryBadges, entries, err := bootstrapEntryPayloads(principal.TenantID, principal.Uid, modulePayloads)
|
||||
if err != nil {
|
||||
writeIMRelationError(wrt, req, err)
|
||||
@@ -7855,6 +7859,26 @@ func workbenchModulePayloads(modules []types.WorkbenchModule) []map[string]any {
|
||||
return items
|
||||
}
|
||||
|
||||
func populateWorkbenchModuleUnreadCounts(tenantID types.TenantID, uid types.Uid, modules []map[string]any) error {
|
||||
if store.Security == nil {
|
||||
return nil
|
||||
}
|
||||
for _, module := range modules {
|
||||
code, _ := module["code"].(string)
|
||||
switch code {
|
||||
case "meetings":
|
||||
count, err := store.Security.CountUnreadSystemNotificationsByEventPrefix(tenantID, uid, "meeting.")
|
||||
if err != nil && !errors.Is(err, types.ErrNotFound) && !errors.Is(err, types.ErrUnsupported) {
|
||||
return err
|
||||
}
|
||||
if err == nil {
|
||||
module["unread_count"] = count
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func bootstrapEntryPayloads(tenantID types.TenantID, uid types.Uid, modules []map[string]any) (map[string]any, map[string]any, error) {
|
||||
newFriendsPending := 0
|
||||
if store.Relations != nil {
|
||||
|
||||
+14
-4
@@ -2406,14 +2406,21 @@ func TestServeIMBootstrapIncludesHomeCapabilities(t *testing.T) {
|
||||
oldWorkbench := store.Workbench
|
||||
oldRelations := store.Relations
|
||||
oldThirdParty := store.ThirdPartyConfig
|
||||
readAt := time.Now().UTC()
|
||||
security := &testSecurityStore{
|
||||
realName: &types.RealNameVerification{Status: "verified"},
|
||||
unreadNotifications: 4,
|
||||
realName: &types.RealNameVerification{Status: "verified"},
|
||||
notifications: []types.SystemNotification{
|
||||
{EventID: "evt-meeting-created", EventType: "meeting.created"},
|
||||
{EventID: "evt-meeting-updated", EventType: "meeting.updated"},
|
||||
{EventID: "evt-friend-request", EventType: "friend.request.created"},
|
||||
{EventID: "evt-daily-report", EventType: "daily_report.reminded"},
|
||||
{EventID: "evt-meeting-read", EventType: "meeting.created", ReadAt: &readAt},
|
||||
},
|
||||
}
|
||||
relations := &testRelationsStore{pendingCount: 2}
|
||||
workbench := &testWorkbenchStore{version: 9, modules: []types.WorkbenchModule{
|
||||
{Code: "organization", Name: "组织架构", Route: "/organization", UnreadCount: 3, Enabled: true, Permission: "enabled"},
|
||||
{Code: "meetings", Name: "会议通知", Route: "/meetings", UnreadCount: 5, Enabled: false, Permission: "enabled"},
|
||||
{Code: "meetings", Name: "会议通知", Route: "/meetings", UnreadCount: 0, Enabled: true, Permission: "enabled"},
|
||||
{Code: "external", Name: "外链", Route: "https://example.com", UnreadCount: 9, Enabled: true, Permission: "enabled"},
|
||||
}}
|
||||
store.Security = security
|
||||
@@ -2473,11 +2480,14 @@ func TestServeIMBootstrapIncludesHomeCapabilities(t *testing.T) {
|
||||
if modules[0].(map[string]any)["unread_count"].(float64) != 3 {
|
||||
t.Fatalf("unexpected bootstrap module unread: %#v", modules[0])
|
||||
}
|
||||
if modules[1].(map[string]any)["unread_count"].(float64) != 2 {
|
||||
t.Fatalf("unexpected bootstrap meetings unread: %#v", modules[1])
|
||||
}
|
||||
badges := data["entry_badges"].(map[string]any)
|
||||
if badges["new_friends_pending_count"].(float64) != 2 ||
|
||||
badges["contacts_total_unread"].(float64) != 2 ||
|
||||
badges["system_unread_count"].(float64) != 4 ||
|
||||
badges["workbench_total_unread"].(float64) != 3 {
|
||||
badges["workbench_total_unread"].(float64) != 5 {
|
||||
t.Fatalf("unexpected bootstrap badges: %#v", badges)
|
||||
}
|
||||
entries := data["entries"].(map[string]any)
|
||||
|
||||
@@ -4258,6 +4258,7 @@ type UserSecurityPersistenceInterface interface {
|
||||
CreateSystemNotification(tenantID types.TenantID, notification *types.SystemNotification) error
|
||||
ListSystemNotifications(tenantID types.TenantID, uid types.Uid, cursor string, limit int) ([]types.SystemNotification, string, error)
|
||||
CountUnreadSystemNotifications(tenantID types.TenantID, uid types.Uid) (int, error)
|
||||
CountUnreadSystemNotificationsByEventPrefix(tenantID types.TenantID, uid types.Uid, eventPrefix string) (int, error)
|
||||
MarkSystemNotificationRead(tenantID types.TenantID, uid types.Uid, eventID string, readAt time.Time) error
|
||||
}
|
||||
|
||||
@@ -4421,6 +4422,17 @@ func (userSecurityMapper) CountUnreadSystemNotifications(tenantID types.TenantID
|
||||
return tenantAdp.TenantSystemNotificationUnreadCount(tenantID, uid)
|
||||
}
|
||||
|
||||
func (userSecurityMapper) CountUnreadSystemNotificationsByEventPrefix(tenantID types.TenantID, uid types.Uid, eventPrefix string) (int, error) {
|
||||
if uid.IsZero() || strings.TrimSpace(eventPrefix) == "" {
|
||||
return 0, types.ErrMalformed
|
||||
}
|
||||
tenantAdp, err := tenantBusinessAdapter(tenantID)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return tenantAdp.TenantSystemNotificationUnreadCountByEventPrefix(tenantID, uid, eventPrefix)
|
||||
}
|
||||
|
||||
func (userSecurityMapper) MarkSystemNotificationRead(tenantID types.TenantID, uid types.Uid, eventID string, readAt time.Time) error {
|
||||
tenantAdp, err := tenantBusinessAdapter(tenantID)
|
||||
if err != nil {
|
||||
|
||||
@@ -241,6 +241,7 @@ type testSecurityStore struct {
|
||||
nextCursor string
|
||||
unreadTenant types.TenantID
|
||||
unreadUser types.Uid
|
||||
unreadEventPrefix string
|
||||
readTenant types.TenantID
|
||||
readUser types.Uid
|
||||
}
|
||||
@@ -402,6 +403,19 @@ func (s *testSecurityStore) CountUnreadSystemNotifications(tenantID types.Tenant
|
||||
return count, s.err
|
||||
}
|
||||
|
||||
func (s *testSecurityStore) CountUnreadSystemNotificationsByEventPrefix(tenantID types.TenantID, uid types.Uid, eventPrefix string) (int, error) {
|
||||
s.unreadTenant = tenantID
|
||||
s.unreadUser = uid
|
||||
s.unreadEventPrefix = eventPrefix
|
||||
count := 0
|
||||
for _, notification := range s.notifications {
|
||||
if notification.ReadAt == nil && strings.HasPrefix(notification.EventType, eventPrefix) {
|
||||
count++
|
||||
}
|
||||
}
|
||||
return count, s.err
|
||||
}
|
||||
|
||||
func (s *testSecurityStore) MarkSystemNotificationRead(tenantID types.TenantID, uid types.Uid, eventID string, readAt time.Time) error {
|
||||
s.readTenant = tenantID
|
||||
s.readUser = uid
|
||||
|
||||
Reference in New Issue
Block a user