Files
ClusterCanvas/service/internal/api/security_handlers.go
T

99 lines
2.8 KiB
Go

package api
import (
"encoding/json"
"errors"
"net/http"
"codeberg.org/SquidSE/ClusterCanvas/service/internal/settings"
)
const (
minIdleTimeoutMinutes = 1
maxIdleTimeoutMinutes = 240 // 4 hours
minSessionLifetimeHours = 1
minReauthGraceMinutes = 0
)
type securityResponse struct {
Security settings.SecuritySettings `json:"security"`
}
type putSecurityRequest struct {
Security settings.SecuritySettings `json:"security"`
}
func securityGetHandler(configDir string) http.HandlerFunc {
return func(writer http.ResponseWriter, request *http.Request) {
settingsPayload, err := loadSettingsOrDefault(configDir)
if err != nil {
writeJSON(writer, http.StatusInternalServerError, apiErrorResponse{Error: err.Error()})
return
}
writeJSON(writer, http.StatusOK, securityResponse{
Security: effectiveSecurity(settingsPayload.Security),
})
}
}
func securityPutHandler(configDir string) http.HandlerFunc {
return func(writer http.ResponseWriter, request *http.Request) {
if err := authorizeSecurityWrite(request); err != nil {
writeJSON(writer, http.StatusForbidden, apiErrorResponse{Error: err.Error()})
return
}
var payload putSecurityRequest
if err := json.NewDecoder(request.Body).Decode(&payload); err != nil {
writeJSON(writer, http.StatusBadRequest, apiErrorResponse{Error: "invalid JSON body"})
return
}
if err := validateSecuritySettings(payload.Security); err != nil {
writeJSON(writer, http.StatusBadRequest, apiErrorResponse{Error: err.Error()})
return
}
settingsPayload, err := loadSettingsOrDefault(configDir)
if err != nil {
writeJSON(writer, http.StatusInternalServerError, apiErrorResponse{Error: err.Error()})
return
}
settingsPayload.Security = payload.Security
if err := settings.SaveSettings(configDir, settingsPayload); err != nil {
writeJSON(writer, http.StatusInternalServerError, apiErrorResponse{Error: err.Error()})
return
}
writeJSON(writer, http.StatusOK, securityResponse{Security: settingsPayload.Security})
}
}
func authorizeSecurityWrite(_ *http.Request) error {
// TODO: integrate authz middleware.
return nil
}
func effectiveSecurity(security settings.SecuritySettings) settings.SecuritySettings {
if err := validateSecuritySettings(security); err != nil {
return settings.DefaultSecuritySettings()
}
return security
}
func validateSecuritySettings(security settings.SecuritySettings) error {
if security.IdleTimeoutMinutes < minIdleTimeoutMinutes ||
security.IdleTimeoutMinutes > maxIdleTimeoutMinutes {
return errors.New("idle_timeout_minutes must be between 1 and 240")
}
if security.SessionLifetimeHours < minSessionLifetimeHours {
return errors.New("session_lifetime_hours must be at least 1")
}
if security.ReauthGraceMinutes < minReauthGraceMinutes {
return errors.New("reauth_grace_minutes must be at least 0")
}
return nil
}