mirror of
https://github.com/J3vb/OwnCord.git
synced 2026-09-03 03:50:00 +03:00
fix: security hardening, DM auth, LiveKit stability, and voice call timer
Security fixes (from multi-reviewer code review): - Add DM participant auth checks to channel_focus, typing, and REST message endpoints — prevents unauthorized access to DM channels - Fix TOCTOU race in GetOrCreateDMChannel using IMMEDIATE transaction - Validate YAML credentials before LiveKit config interpolation - Add CSS variable injection prevention in custom theme loader - Validate localStorage JSON before unsafe type casts LiveKit stability: - Track remote mic audio elements for cleanup on abnormal disconnect - Remove duplicate token refresh timer scheduling - Add .catch() to all floating applyMicMuteState promises - Clear reconnectAc after async post-connect work completes - Fix double cmd.Wait() race in LiveKit process Stop() - Reorder voice_join guards: validate channel before livekit==nil check - Add startup warning for external LiveKit webhook CIDR mismatch DM system fixes: - Emit dm_channel_close WebSocket event from REST close handler - Re-open DM for caller when channel already exists - Fix unread count incrementing for own messages and active DMs - Reset channelBeforeDm after Back navigation (stale state bug) New feature: - Voice call duration timer in VoiceWidget (MM:SS / HH:MM:SS elapsed) - Accent color restored on app startup (was only applied in settings) Test infrastructure: - Add DM tables to all test schemas (hubTestSchema) - Inject test LiveKit client in voice handler tests (fixes 28 failures)
This commit is contained in:
@@ -2,6 +2,7 @@ package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
|
||||
@@ -9,14 +10,21 @@ import (
|
||||
"github.com/owncord/server/db"
|
||||
)
|
||||
|
||||
// DMBroadcaster is the interface needed to send WebSocket events from REST
|
||||
// handlers. Satisfied by *ws.Hub.
|
||||
type DMBroadcaster interface {
|
||||
SendToUser(userID int64, msg []byte) bool
|
||||
}
|
||||
|
||||
// MountDMRoutes registers DM-related routes onto r.
|
||||
// All routes require authentication.
|
||||
func MountDMRoutes(r chi.Router, database *db.DB) {
|
||||
// hub is used to send real-time WebSocket events on DM close.
|
||||
func MountDMRoutes(r chi.Router, database *db.DB, broadcaster DMBroadcaster) {
|
||||
r.Route("/api/v1/dms", func(r chi.Router) {
|
||||
r.Use(AuthMiddleware(database))
|
||||
r.Post("/", handleCreateDM(database))
|
||||
r.Get("/", handleListDMs(database))
|
||||
r.Delete("/{channelId}", handleCloseDM(database))
|
||||
r.Delete("/{channelId}", handleCloseDM(database, broadcaster))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -157,7 +165,7 @@ func handleListDMs(database *db.DB) http.HandlerFunc {
|
||||
}
|
||||
|
||||
// handleCloseDM removes a DM channel from the authenticated user's open list.
|
||||
func handleCloseDM(database *db.DB) http.HandlerFunc {
|
||||
func handleCloseDM(database *db.DB, broadcaster DMBroadcaster) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
user, ok := r.Context().Value(UserKey).(*db.User)
|
||||
if !ok || user == nil {
|
||||
@@ -202,6 +210,16 @@ func handleCloseDM(database *db.DB) http.HandlerFunc {
|
||||
return
|
||||
}
|
||||
|
||||
// Notify the closing user's WebSocket connections so the sidebar updates
|
||||
// immediately without waiting for a reconnect.
|
||||
if broadcaster != nil {
|
||||
closeMsg := []byte(fmt.Sprintf(`{"type":"dm_channel_close","payload":{"channel_id":%d}}`, channelID))
|
||||
if ok := broadcaster.SendToUser(user.ID, closeMsg); !ok {
|
||||
slog.Debug("handleCloseDM: user not connected, WS notify skipped",
|
||||
"user_id", user.ID, "channel_id", channelID)
|
||||
}
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user