WAU Compliance: agent collector, backend endpoints, frontend badge + panel
- Agent: WAU registry config check (include/exclude URLs), pending updates count - Backend: /wau/compliance per customer, /wau/compliance/summary all customers - Frontend: compliance badge in customer list, compliance panel in WAU tab - config.js: no longer gitignored (secrets-free, reads from env/window.__RMM_CONFIG__) - vite.config.js: reads backend URL from .env instead of hardcoded value - .env.example added for clean setup
This commit is contained in:
+55
-3
@@ -10,10 +10,14 @@ import (
|
||||
// setupWAURoutes registriert alle WAU-Endpunkte
|
||||
func (h *Handler) setupWAURoutes(mux *http.ServeMux) {
|
||||
// Authentifizierte Endpunkte (API-Key oder JWT)
|
||||
mux.HandleFunc("GET /api/v1/customers/{id}/wau/rules", h.listWAURules)
|
||||
mux.HandleFunc("POST /api/v1/customers/{id}/wau/rules", h.addWAURule)
|
||||
mux.HandleFunc("GET /api/v1/customers/{id}/wau/rules", h.listWAURules)
|
||||
mux.HandleFunc("POST /api/v1/customers/{id}/wau/rules", h.addWAURule)
|
||||
mux.HandleFunc("DELETE /api/v1/customers/{id}/wau/rules/{rid}", h.deleteWAURule)
|
||||
mux.HandleFunc("GET /api/v1/customers/{id}/wau/inventory", h.getWAUInventory)
|
||||
mux.HandleFunc("GET /api/v1/customers/{id}/wau/inventory", h.getWAUInventory)
|
||||
mux.HandleFunc("GET /api/v1/customers/{id}/wau/compliance", h.getWAUCompliance)
|
||||
|
||||
// Compliance-Summary für alle Kunden
|
||||
mux.HandleFunc("GET /api/v1/wau/compliance/summary", h.getWAUComplianceSummary)
|
||||
|
||||
// Plaintext-Endpunkte für WAU (kein Auth nötig — enthält nur App-IDs)
|
||||
mux.HandleFunc("GET /api/v1/customers/{id}/wau/included", h.wauIncludedList)
|
||||
@@ -149,3 +153,51 @@ func (h *Handler) serveWAUList(w http.ResponseWriter, r *http.Request, ruleType
|
||||
w.Write([]byte("\r\n"))
|
||||
}
|
||||
}
|
||||
|
||||
// wauExpectedURLs leitet die erwarteten WAU-URLs aus dem Request-Host ab
|
||||
func wauExpectedURLs(r *http.Request, customerID int) (includeURL, excludeURL string) {
|
||||
scheme := "https"
|
||||
if r.TLS == nil && (r.Header.Get("X-Forwarded-Proto") == "" || r.Header.Get("X-Forwarded-Proto") == "http") {
|
||||
scheme = "http"
|
||||
}
|
||||
if fwd := r.Header.Get("X-Forwarded-Proto"); fwd != "" {
|
||||
scheme = fwd
|
||||
}
|
||||
host := r.Host
|
||||
base := scheme + "://" + host
|
||||
includeURL = base + "/api/v1/customers/" + strconv.Itoa(customerID) + "/wau/included"
|
||||
excludeURL = base + "/api/v1/customers/" + strconv.Itoa(customerID) + "/wau/excluded"
|
||||
return
|
||||
}
|
||||
|
||||
// GET /api/v1/customers/{id}/wau/compliance
|
||||
func (h *Handler) getWAUCompliance(w http.ResponseWriter, r *http.Request) {
|
||||
customerID, err := strconv.Atoi(r.PathValue("id"))
|
||||
if err != nil {
|
||||
writeError(w, http.StatusBadRequest, "Ungültige Kunden-ID")
|
||||
return
|
||||
}
|
||||
includeURL, excludeURL := wauExpectedURLs(r, customerID)
|
||||
agents, err := h.db.GetWAUCompliance(customerID, includeURL, excludeURL)
|
||||
if err != nil {
|
||||
writeError(w, http.StatusInternalServerError, "Fehler beim Laden der Compliance-Daten")
|
||||
return
|
||||
}
|
||||
writeJSON(w, http.StatusOK, map[string]interface{}{
|
||||
"agents": agents,
|
||||
"include_url": includeURL,
|
||||
"exclude_url": excludeURL,
|
||||
})
|
||||
}
|
||||
|
||||
// GET /api/v1/wau/compliance/summary — Zusammenfassung für alle Kunden
|
||||
func (h *Handler) getWAUComplianceSummary(w http.ResponseWriter, r *http.Request) {
|
||||
// Ohne customer_id können wir keine URLs ableiten — wir geben Summary ohne URL-Check zurück
|
||||
// oder nutzen customer_id=0 als Wildcard (kein URL-Check)
|
||||
summaries, err := h.db.GetAllCustomersWAUSummary("", "")
|
||||
if err != nil {
|
||||
writeError(w, http.StatusInternalServerError, "Fehler beim Laden der Compliance-Daten")
|
||||
return
|
||||
}
|
||||
writeJSON(w, http.StatusOK, summaries)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user