mirror of
https://github.com/netbirdio/netbird.git
synced 2026-08-25 00:51:28 +02:00
Declarative API clients (the Terraform provider, scripted PUTs) hit three places where the agent-network API broke its own contract or left users stuck, forcing client-side workarounds. The settings GET answered 200 with a JSON null body for unbootstrapped accounts while the OpenAPI spec documented 404; it now returns the 404. The settings PUT still replaces every mutable field like the other PUT endpoints, but a request may now carry the cluster: on an account without a settings row it bootstraps one (assigning the subdomain), so settings can be managed before the first provider exists; on a bootstrapped account a differing cluster is rejected instead of silently ignored. The provider PUT handler built a fresh row from the request, so the fields the schema documents as omit-preserves (extra_values, metadata_disabled, enabled, skip_tls_verification, identity headers) silently reset to zero when omitted. The handler now overlays the request onto the stored row, making the documented nil-gating real. Identity headers are always present in provider responses so an explicitly cleared header round-trips as an empty string rather than vanishing.
69 lines
2.4 KiB
Go
69 lines
2.4 KiB
Go
package handlers
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
|
|
"github.com/gorilla/mux"
|
|
|
|
"github.com/netbirdio/netbird/management/internals/modules/agentnetwork/types"
|
|
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
|
"github.com/netbirdio/netbird/shared/management/http/api"
|
|
"github.com/netbirdio/netbird/shared/management/http/util"
|
|
)
|
|
|
|
// addSettingsEndpoints registers the Agent Network settings routes. The
|
|
// settings row is bootstrapped server-side on first provider create or on the
|
|
// first PUT carrying a cluster; GET reads it and PUT applies a partial update
|
|
// of the mutable collection toggles (cluster/subdomain stay immutable).
|
|
func (h *handler) addSettingsEndpoints(router *mux.Router) {
|
|
router.HandleFunc("/agent-network/settings", h.getSettings).Methods("GET", "OPTIONS")
|
|
router.HandleFunc("/agent-network/settings", h.updateSettings).Methods("PUT", "OPTIONS")
|
|
}
|
|
|
|
// updateSettings replaces the mutable settings fields on the account's row.
|
|
// A request carrying a cluster bootstraps the row when the account doesn't
|
|
// have one yet.
|
|
func (h *handler) updateSettings(w http.ResponseWriter, r *http.Request) {
|
|
userAuth, err := nbcontext.GetUserAuthFromContext(r.Context())
|
|
if err != nil {
|
|
util.WriteError(r.Context(), err, w)
|
|
return
|
|
}
|
|
|
|
var req api.AgentNetworkSettingsRequest
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
util.WriteErrorResponse("couldn't parse JSON request", http.StatusBadRequest, w)
|
|
return
|
|
}
|
|
|
|
settings := &types.Settings{AccountID: userAuth.AccountId}
|
|
settings.FromAPIRequest(&req)
|
|
|
|
updated, err := h.manager.UpdateSettings(r.Context(), userAuth.UserId, settings)
|
|
if err != nil {
|
|
util.WriteError(r.Context(), err, w)
|
|
return
|
|
}
|
|
util.WriteJSONObject(r.Context(), w, updated.ToAPIResponse())
|
|
}
|
|
|
|
// getSettings returns the account's agent-network settings. Freshly-onboarded
|
|
// accounts have no settings row until a provider create (or a settings PUT
|
|
// with a cluster) bootstraps one; per the OpenAPI contract that reads as a
|
|
// plain 404.
|
|
func (h *handler) getSettings(w http.ResponseWriter, r *http.Request) {
|
|
userAuth, err := nbcontext.GetUserAuthFromContext(r.Context())
|
|
if err != nil {
|
|
util.WriteError(r.Context(), err, w)
|
|
return
|
|
}
|
|
|
|
settings, err := h.manager.GetSettings(r.Context(), userAuth.AccountId, userAuth.UserId)
|
|
if err != nil {
|
|
util.WriteError(r.Context(), err, w)
|
|
return
|
|
}
|
|
util.WriteJSONObject(r.Context(), w, settings.ToAPIResponse())
|
|
}
|