mirror of
https://github.com/J3vb/OwnCord.git
synced 2026-09-03 03:50:00 +03:00
Security audit across all 11 sections (AUTH-001 through DATA-001) found 0 critical, 1 high, 7 medium, 15 low issues. This commit addresses: - Add json:"-" to User.PasswordHash, User.TOTPSecret, Session.TokenHash to prevent accidental serialization of sensitive fields (M7) - Add X-Content-Type-Options: nosniff to file serve responses (M5) - Apply owner-only guard to backup list endpoint for consistency (M6) - Persist rate-limit lockouts to SQLite so they survive restarts (M2) - Normalize DM non-participant responses to 404 to prevent oracle (L3) - Add explicit per-entry expiry check in partial auth Lookup/Consume (L1) - Truncate unknown WS message type to 64 chars before echo (L6) - Rate-limit ping handler to 2/sec per user (L7) - Replace raw error strings in update handlers with generic messages (L15) - Update 4 tests to match new 404 behavior for DM non-participant
71 lines
3.1 KiB
Go
71 lines
3.1 KiB
Go
package admin
|
|
|
|
import (
|
|
"net/http"
|
|
|
|
"github.com/go-chi/chi/v5"
|
|
"github.com/owncord/server/auth"
|
|
"github.com/owncord/server/db"
|
|
"github.com/owncord/server/updater"
|
|
)
|
|
|
|
// ─── NewAdminAPI ──────────────────────────────────────────────────────────────
|
|
|
|
// NewAdminAPI returns a chi router with all /admin/api/* routes. All routes
|
|
// are protected by adminAuthMiddleware which requires the ADMINISTRATOR bit,
|
|
// except for the setup endpoints which are unauthenticated.
|
|
func NewAdminAPI(database *db.DB, version string, hub HubBroadcaster, u *updater.Updater, logBuf *RingBuffer, allowedOrigins []string) http.Handler {
|
|
r := chi.NewRouter()
|
|
|
|
// Setup endpoints — unauthenticated, only functional when no users exist.
|
|
setupLimiter := auth.NewRateLimiter()
|
|
r.Get("/setup/status", handleSetupStatus(database))
|
|
r.Post("/setup", handleSetup(database, setupLimiter, allowedOrigins))
|
|
|
|
// SSE log stream — auth is via a single-use ticket from POST /logs/ticket.
|
|
// EventSource cannot send Authorization headers, so the client first
|
|
// obtains a short-lived ticket via the authenticated ticket endpoint,
|
|
// then passes it as ?ticket= to the SSE stream.
|
|
if logBuf != nil {
|
|
r.Get("/logs/stream", handleLogStream(database, logBuf))
|
|
}
|
|
|
|
// All remaining routes require authentication and ADMINISTRATOR permission.
|
|
r.Group(func(r chi.Router) {
|
|
r.Use(adminAuthMiddleware(database))
|
|
|
|
// Log stream ticket — issues a single-use, 30s TTL ticket for SSE auth.
|
|
r.Post("/logs/ticket", handleLogTicket(database))
|
|
|
|
r.Get("/stats", handleGetStats(database, hub))
|
|
r.Get("/users", handleListUsers(database))
|
|
r.Patch("/users/{id}", handlePatchUser(database, hub))
|
|
r.Delete("/users/{id}/sessions", handleForceLogout(database))
|
|
r.Get("/channels", handleListChannels(database))
|
|
r.Post("/channels", handleCreateChannel(database, hub))
|
|
r.Patch("/channels/{id}", handlePatchChannel(database, hub))
|
|
r.Delete("/channels/{id}", handleDeleteChannel(database, hub))
|
|
r.Get("/audit-log", handleGetAuditLog(database))
|
|
r.Get("/settings", handleGetSettings(database))
|
|
r.Patch("/settings", handlePatchSettings(database))
|
|
r.Post("/backup", http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
|
ownerOnlyMiddleware(database, handleBackup(database)).ServeHTTP(w, req)
|
|
}))
|
|
r.Get("/backups", http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
|
ownerOnlyMiddleware(database, handleListBackups()).ServeHTTP(w, req)
|
|
}))
|
|
r.Delete("/backups/{name}", http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
|
ownerOnlyMiddleware(database, handleDeleteBackup(database)).ServeHTTP(w, req)
|
|
}))
|
|
r.Post("/backups/{name}/restore", http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
|
ownerOnlyMiddleware(database, handleRestoreBackup(database, hub)).ServeHTTP(w, req)
|
|
}))
|
|
r.Get("/updates", handleCheckUpdate(u))
|
|
r.Post("/updates/apply", http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
|
ownerOnlyMiddleware(database, handleApplyUpdate(u, hub, version)).ServeHTTP(w, req)
|
|
}))
|
|
})
|
|
|
|
return r
|
|
}
|