Files
catalyst/app/router/demomode.go
2025-09-21 12:08:28 +00:00

80 lines
1.8 KiB
Go

package router
import (
"context"
"log/slog"
"net/http"
"slices"
"strings"
"github.com/SecurityBrewery/catalyst/app/database"
"github.com/SecurityBrewery/catalyst/app/database/sqlc"
)
func demoMode(queries *sqlc.Queries) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if isCriticalPath(r) && isCriticalMethod(r) && isDemoMode(r.Context(), queries) {
http.Error(w, "Cannot modify reactions or files in demo mode", http.StatusForbidden)
return
}
next.ServeHTTP(w, r)
})
}
}
func isCriticalPath(r *http.Request) bool {
// Define critical paths that should not be accessed in demo mode
criticalPaths := []string{
"/api/files",
"/api/groups",
"/api/reactions",
"/api/settings",
"/api/users",
"/api/webhooks",
}
for _, path := range criticalPaths {
if strings.Contains(r.URL.Path, path) {
return true
}
}
return false
}
func isCriticalMethod(r *http.Request) bool {
return !slices.Contains([]string{http.MethodHead, http.MethodGet}, r.Method)
}
func isDemoMode(ctx context.Context, queries *sqlc.Queries) bool {
var demoMode bool
if err := database.Paginate(ctx, func(ctx context.Context, offset, limit int64) (nextPage bool, err error) {
slog.InfoContext(ctx, "Checking for demo mode", "offset", offset, "limit", limit)
features, err := queries.ListFeatures(ctx, sqlc.ListFeaturesParams{Offset: offset, Limit: limit})
if err != nil {
return false, err
}
for _, feature := range features {
if feature.Key == "demo" {
demoMode = true
return false, nil // Stop pagination if demo mode is found
}
}
return len(features) > 0, nil
}); err != nil {
slog.ErrorContext(ctx, "Failed to check demo mode", "error", err)
return false
}
return demoMode
}