- Klick auf Kundenzeile klappt Key-Panel auf
- Zeigt Agent + Read-only Keys mit Permission-Badge
- Key teilweise maskiert, Kopier-Button vorhanden
- Backend: GET /api/v1/customers/{id}/apikeys
- DB: ListCustomerAPIKeys() nach customer_id gefiltert
93 lines
2.6 KiB
Go
93 lines
2.6 KiB
Go
package api
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"encoding/hex"
|
|
"encoding/json"
|
|
"log"
|
|
"net/http"
|
|
"strconv"
|
|
)
|
|
|
|
// GET /api/v1/apikeys
|
|
func (h *Handler) listAPIKeys(w http.ResponseWriter, r *http.Request) {
|
|
keys, err := h.db.ListAPIKeys()
|
|
if err != nil {
|
|
log.Printf("API-Keys laden fehlgeschlagen: %v", err)
|
|
writeError(w, http.StatusInternalServerError, "Laden fehlgeschlagen")
|
|
return
|
|
}
|
|
writeJSON(w, http.StatusOK, keys)
|
|
}
|
|
|
|
// POST /api/v1/apikeys
|
|
func (h *Handler) createAPIKey(w http.ResponseWriter, r *http.Request) {
|
|
var req struct {
|
|
Name string `json:"name"`
|
|
Permissions string `json:"permissions"` // "agent" | "read" | "write" | "admin"
|
|
CustomerID *int `json:"customer_id"` // optional, null = global
|
|
}
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil || req.Name == "" {
|
|
writeError(w, http.StatusBadRequest, "Parameter 'name' erforderlich")
|
|
return
|
|
}
|
|
|
|
// Permissions validieren, default: "read"
|
|
validPerms := map[string]bool{"agent": true, "read": true, "write": true, "admin": true}
|
|
if req.Permissions == "" {
|
|
req.Permissions = "read"
|
|
}
|
|
if !validPerms[req.Permissions] {
|
|
writeError(w, http.StatusBadRequest, "Ungueltige Permissions (agent|read|write|admin)")
|
|
return
|
|
}
|
|
|
|
// Zufaelligen 32-Byte Key generieren
|
|
b := make([]byte, 16)
|
|
rand.Read(b)
|
|
key := hex.EncodeToString(b)
|
|
|
|
apiKey, err := h.db.CreateAPIKey(req.Name, key, req.Permissions, req.CustomerID)
|
|
if err != nil {
|
|
log.Printf("API-Key erstellen fehlgeschlagen: %v", err)
|
|
writeError(w, http.StatusInternalServerError, "Erstellen fehlgeschlagen")
|
|
return
|
|
}
|
|
|
|
log.Printf("Neuer API-Key erstellt: %s (%s...) perm=%s", apiKey.Name, key[:8], apiKey.Permissions)
|
|
writeJSON(w, http.StatusCreated, apiKey)
|
|
}
|
|
|
|
// GET /api/v1/customers/{id}/apikeys
|
|
func (h *Handler) listCustomerAPIKeys(w http.ResponseWriter, r *http.Request) {
|
|
id, err := strconv.Atoi(r.PathValue("id"))
|
|
if err != nil {
|
|
writeError(w, http.StatusBadRequest, "Ungueltige ID")
|
|
return
|
|
}
|
|
keys, err := h.db.ListCustomerAPIKeys(id)
|
|
if err != nil {
|
|
writeError(w, http.StatusInternalServerError, "Laden fehlgeschlagen")
|
|
return
|
|
}
|
|
writeJSON(w, http.StatusOK, keys)
|
|
}
|
|
|
|
// DELETE /api/v1/apikeys/{id}
|
|
func (h *Handler) deleteAPIKey(w http.ResponseWriter, r *http.Request) {
|
|
idStr := r.PathValue("id")
|
|
id, err := strconv.Atoi(idStr)
|
|
if err != nil {
|
|
writeError(w, http.StatusBadRequest, "Ungueltige ID")
|
|
return
|
|
}
|
|
|
|
if err := h.db.DeleteAPIKey(id); err != nil {
|
|
writeError(w, http.StatusNotFound, "API-Key nicht gefunden")
|
|
return
|
|
}
|
|
|
|
log.Printf("API-Key %d geloescht", id)
|
|
writeJSON(w, http.StatusOK, map[string]string{"message": "API-Key geloescht"})
|
|
}
|