feat: Add Integrations page with API token management
New Integrations page in Wild Central UI for managing API tokens. Provides token display, copy, and rotation so Wild Cloud and other services can easily retrieve their authentication credentials. - GET /api/v1/integrations returns current API token - POST /api/v1/integrations/api-token/rotate generates a new token - Frontend with show/hide toggle, copy button, and usage instructions - Added to sidebar navigation under Central section
This commit is contained in:
@@ -278,6 +278,10 @@ func (api *API) RegisterRoutes(r *mux.Router, bearerToken string, devMode bool)
|
||||
r.HandleFunc("/api/v1/secrets", api.GetGlobalSecrets).Methods("GET")
|
||||
r.HandleFunc("/api/v1/secrets", api.UpdateGlobalSecrets).Methods("PUT")
|
||||
|
||||
// Integrations (API token management)
|
||||
r.HandleFunc("/api/v1/integrations", api.GetIntegrations).Methods("GET")
|
||||
r.HandleFunc("/api/v1/integrations/api-token/rotate", api.RotateAPIToken).Methods("POST")
|
||||
|
||||
// Daemon control
|
||||
r.HandleFunc("/api/v1/daemon/restart", api.DaemonRestart).Methods("POST")
|
||||
|
||||
|
||||
44
internal/api/v1/handlers_integrations.go
Normal file
44
internal/api/v1/handlers_integrations.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
"net/http"
|
||||
|
||||
"github.com/wild-cloud/wild-central/internal/secrets"
|
||||
)
|
||||
|
||||
// GetIntegrations returns integration info including the API bearer token.
|
||||
func (api *API) GetIntegrations(w http.ResponseWriter, r *http.Request) {
|
||||
token, err := api.secrets.GetSecret("api.bearerToken")
|
||||
if err != nil {
|
||||
token = ""
|
||||
}
|
||||
|
||||
respondJSON(w, http.StatusOK, map[string]any{
|
||||
"apiToken": map[string]any{
|
||||
"token": token,
|
||||
"description": "Bearer token for authenticating with the Wild Central API. Used by Wild Cloud and other services.",
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// RotateAPIToken generates a new API bearer token and saves it to secrets.
|
||||
func (api *API) RotateAPIToken(w http.ResponseWriter, r *http.Request) {
|
||||
token, err := secrets.GenerateSecret(secrets.DefaultSecretLength)
|
||||
if err != nil {
|
||||
respondError(w, http.StatusInternalServerError, "Failed to generate token")
|
||||
return
|
||||
}
|
||||
|
||||
if err := api.secrets.SetSecret("api.bearerToken", token); err != nil {
|
||||
respondError(w, http.StatusInternalServerError, "Failed to save token")
|
||||
return
|
||||
}
|
||||
|
||||
slog.Info("API bearer token rotated")
|
||||
|
||||
respondJSON(w, http.StatusOK, map[string]any{
|
||||
"token": token,
|
||||
"message": "API token rotated. Services using the old token will need to be updated.",
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user