diff --git a/cmd/cycloid/middleware/middleware.go b/cmd/cycloid/middleware/middleware.go index 42aa99b9b..332645f88 100644 --- a/cmd/cycloid/middleware/middleware.go +++ b/cmd/cycloid/middleware/middleware.go @@ -98,6 +98,10 @@ type Middleware interface { GetOIDCIntegration(org string) (*OIDCIntegration, *http.Response, error) UpdateOIDCIntegration(org string, config map[string]interface{}) (*OIDCIntegration, *http.Response, error) + // organization_nav — per-org sidebar nav ordering + GetOrgNav(org string) (*NavConfig, *http.Response, error) + UpdateOrgNav(org string, items []*NavItem) (*NavConfig, *http.Response, error) + // organizations CreateOrganization(name string) (*models.Organization, *http.Response, error) UpdateOrganization(org, name string) (*models.Organization, *http.Response, error) diff --git a/cmd/cycloid/middleware/organization_nav.go b/cmd/cycloid/middleware/organization_nav.go new file mode 100644 index 000000000..47fbe581d --- /dev/null +++ b/cmd/cycloid/middleware/organization_nav.go @@ -0,0 +1,64 @@ +package middleware + +import ( + "fmt" + "net/http" +) + +// NavItem is a single sidebar entry with an explicit position. +// +// This type lives in the middleware package (not client/models) following the +// same convention as OIDCOrganizationSettings: the endpoint is simple enough +// (two fields, a GET/PUT pair) that a hand-defined type plus GenericRequest is +// more direct than swagger-driven codegen for it. +type NavItem struct { + // Type is either "native" (a built-in section, identified by name, e.g. + // "dashboard") or "plugin_widget" (identified by the widget's plugin ID as + // a string). + Type string `json:"type"` + Key string `json:"key"` + // Position is 1-indexed; positions must be unique within a NavConfig. + Position uint32 `json:"position"` +} + +// NavConfig is the per-organization sidebar nav ordering configuration. +// Items is empty when no ordering has been saved — the console falls back to +// its default ordering in that case. +type NavConfig struct { + Items []*NavItem `json:"items"` +} + +// GetOrgNav returns the org's sidebar nav ordering config. +func (m *middleware) GetOrgNav(org string) (*NavConfig, *http.Response, error) { + var result *NavConfig + resp, err := m.GenericRequest(Request{ + Method: "GET", + Organization: &org, + Route: []string{"organizations", org, "nav"}, + }, &result) + if err != nil { + return nil, resp, fmt.Errorf("failed to get organization nav ordering: %w", err) + } + return result, resp, nil +} + +// UpdateOrgNav creates or replaces the org's sidebar nav ordering config. +// Passing an empty (or nil) items slice resets the ordering to defaults. +func (m *middleware) UpdateOrgNav(org string, items []*NavItem) (*NavConfig, *http.Response, error) { + body := &NavConfig{Items: items} + if body.Items == nil { + body.Items = []*NavItem{} + } + + var result *NavConfig + resp, err := m.GenericRequest(Request{ + Method: "PUT", + Organization: &org, + Route: []string{"organizations", org, "nav"}, + Body: body, + }, &result) + if err != nil { + return nil, resp, fmt.Errorf("failed to update organization nav ordering: %w", err) + } + return result, resp, nil +}