0
0
mirror of https://github.com/go-gitea/gitea.git synced 2026-04-14 15:50:44 +02:00
gitea/services/websocket/notifier.go
Epid b47686ce32 fix(websocket): auth via IsSigned check instead of reqSignIn middleware
reqSignIn sends a 303 redirect which breaks WebSocket upgrade; use the
same pattern as /user/events: register the route without middleware and
return 401 inside the handler when the user is not signed in.

Also fix copyright year to 2026 in all three new Go files and add a
console.warn for malformed JSON in the SharedWorker.
2026-03-30 06:37:53 +03:00

83 lines
2.0 KiB
Go

// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package websocket
import (
"context"
"time"
activities_model "code.gitea.io/gitea/models/activities"
"code.gitea.io/gitea/modules/graceful"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/process"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/services/pubsub"
)
// nowTS returns the current time as a TimeStamp using the real wall clock,
// avoiding data races with timeutil.MockUnset during tests.
func nowTS() timeutil.TimeStamp {
return timeutil.TimeStamp(time.Now().Unix())
}
type notificationCountEvent struct {
Type string `json:"type"`
Count int64 `json:"count"`
}
// Init starts the background goroutine that polls notification counts
// and pushes updates to connected WebSocket clients.
func Init() error {
go graceful.GetManager().RunWithShutdownContext(run)
return nil
}
func run(ctx context.Context) {
ctx, _, finished := process.GetManager().AddTypedContext(ctx, "Service: WebSocket", process.SystemProcessType, true)
defer finished()
if setting.UI.Notification.EventSourceUpdateTime <= 0 {
return
}
then := nowTS().Add(-2)
timer := time.NewTicker(setting.UI.Notification.EventSourceUpdateTime)
defer timer.Stop()
for {
select {
case <-ctx.Done():
return
case <-timer.C:
if !pubsub.DefaultBroker.HasSubscribers() {
then = nowTS().Add(-2)
continue
}
now := nowTS().Add(-2)
uidCounts, err := activities_model.GetUIDsAndNotificationCounts(ctx, then, now)
if err != nil {
log.Error("websocket: GetUIDsAndNotificationCounts: %v", err)
continue
}
for _, uidCount := range uidCounts {
msg, err := json.Marshal(notificationCountEvent{
Type: "notification-count",
Count: uidCount.Count,
})
if err != nil {
continue
}
pubsub.DefaultBroker.Publish(pubsub.UserTopic(uidCount.UserID), msg)
}
then = now
}
}
}