forked from Nixius/authelia
1
0
Fork 0
ATLAS/docker/ss-atlas/internal/handlers/admin.go

65 lines
1.9 KiB
Go

package handlers
import (
"encoding/json"
"log"
"net/http"
"regexp"
)
var validUsername = regexp.MustCompile(`^[a-z0-9][a-z0-9_-]*$`)
// handleDeleteUser fully deletes an account: LDAP user + customer stack and volumes.
// Requires ADMIN_SECRET env set and X-Admin-Secret header. POST /admin/delete-user?user=username
func (a *App) handleDeleteUser(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return
}
if a.cfg.AdminSecret == "" {
http.NotFound(w, r)
return
}
secret := r.Header.Get("X-Admin-Secret")
if secret != a.cfg.AdminSecret {
http.Error(w, "forbidden", http.StatusForbidden)
return
}
username := r.URL.Query().Get("user")
if username == "" {
username = r.FormValue("user")
}
if username == "" {
http.Error(w, "user required", http.StatusBadRequest)
return
}
if !validUsername.MatchString(username) {
http.Error(w, "invalid username", http.StatusBadRequest)
return
}
if err := a.ldap.DeleteUser(username); err != nil {
log.Printf("admin delete-user %s: ldap: %v", username, err)
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusInternalServerError)
json.NewEncoder(w).Encode(map[string]string{"error": err.Error()})
return
}
stackName := "customer-" + username
if err := a.swarm.RemoveStackAndVolumes(stackName); err != nil {
log.Printf("admin delete-user %s: stack/volumes: %v", username, err)
// LDAP user already deleted; report but don't fail
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(map[string]string{
"status": "user deleted",
"warning": "stack/volumes: " + err.Error(),
})
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]string{"status": "deleted", "user": username})
}