mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-05-07 00:37:36 +00:00
88 lines
2.4 KiB
Go
88 lines
2.4 KiB
Go
package api
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/rcourtman/pulse-go-rewrite/internal/config"
|
|
internalauth "github.com/rcourtman/pulse-go-rewrite/pkg/auth"
|
|
"github.com/rs/zerolog/log"
|
|
)
|
|
|
|
type firstRunResetResponse struct {
|
|
BootstrapToken string `json:"bootstrapToken"`
|
|
BootstrapTokenPath string `json:"bootstrapTokenPath,omitempty"`
|
|
}
|
|
|
|
func devModeEnabled() bool {
|
|
return os.Getenv("PULSE_DEV") == "true" || strings.EqualFold(os.Getenv("NODE_ENV"), "development")
|
|
}
|
|
|
|
func (r *Router) handleResetFirstRunSecurity(w http.ResponseWriter, req *http.Request) {
|
|
if req.Method != http.MethodPost {
|
|
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
|
return
|
|
}
|
|
if !devModeEnabled() {
|
|
http.Error(w, "Development mode required", http.StatusForbidden)
|
|
return
|
|
}
|
|
if !CheckAuth(r.config, w, req) {
|
|
return
|
|
}
|
|
if !ensureSettingsWriteScope(r.config, w, req) {
|
|
return
|
|
}
|
|
|
|
config.Mu.Lock()
|
|
previousAuthUser := strings.TrimSpace(r.config.AuthUser)
|
|
r.config.AuthUser = ""
|
|
r.config.AuthPass = ""
|
|
r.config.APIToken = ""
|
|
r.config.APITokens = nil
|
|
config.Mu.Unlock()
|
|
|
|
for _, key := range []string{
|
|
"PULSE_AUTH_USER",
|
|
"PULSE_AUTH_PASS",
|
|
"REQUIRE_AUTH",
|
|
} {
|
|
_ = os.Unsetenv(key)
|
|
}
|
|
|
|
if previousAuthUser != "" {
|
|
InvalidateUserSessions(previousAuthUser)
|
|
}
|
|
r.clearSession(w, req)
|
|
r.clearBootstrapToken()
|
|
|
|
if err := removeAuthEnvFiles(r.config.ConfigPath, r.config.DataPath); err != nil {
|
|
log.Warn().Err(err).Msg("Failed to remove auth env files during first-run reset")
|
|
http.Error(w, "Failed to remove persisted auth configuration", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
if r.persistence != nil {
|
|
if err := r.persistence.SaveAPITokens([]config.APITokenRecord{}); err != nil {
|
|
log.Warn().Err(err).Msg("Failed to clear persisted API tokens during first-run reset")
|
|
http.Error(w, "Failed to clear persisted API tokens", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
}
|
|
|
|
token, _, path, err := loadOrCreateBootstrapToken(r.config.DataPath)
|
|
if err != nil {
|
|
log.Error().Err(err).Msg("Failed to recreate bootstrap token during first-run reset")
|
|
http.Error(w, "Failed to recreate bootstrap token", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
r.bootstrapTokenHash = internalauth.HashAPIToken(token)
|
|
r.bootstrapTokenPath = path
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
_ = json.NewEncoder(w).Encode(firstRunResetResponse{
|
|
BootstrapToken: token,
|
|
BootstrapTokenPath: path,
|
|
})
|
|
}
|