Documentation
¶
Overview ¶
Package iam is the admin cockpit's typed reader for the Hanzo IAM management surface (/v1/iam/ native routes). IAM runs as its own deployment (not fused into this binary), so these are HTTP calls, not Go method dispatch. Every call REPLAYS THE CALLER'S OWN credential (session cookie + Authorization), so IAM authorizes the read as the same principal the gateway already validated as a SuperAdmin. admin adds NO service credential of its own here: it never widens what the caller could read directly, and IAM's own IsSuperAdmin gate stays the second line of defense.
The reads split two orthogonal ways: TYPED domain reads the cockpit folds into its own rows — Orgs/Users (paginated lists), Org/User (one row), SetUser (the one write) — and a generic verbatim List the cockpit forwards field-for-field (roles, applications, audit records). An unwired IAM (no base) is not Ready and every read reports the honest not-configured error.
Index ¶
- type Client
- func (c *Client) List(ctx context.Context, cr Creds, path string, q url.Values) (List, error)
- func (c *Client) Org(ctx context.Context, cr Creds, id string) (Org, error)
- func (c *Client) Orgs(ctx context.Context, cr Creds, q url.Values) (List, error)
- func (c *Client) Ready() bool
- func (c *Client) SetUser(ctx context.Context, cr Creds, id string, user map[string]any) error
- func (c *Client) User(ctx context.Context, cr Creds, id string) (map[string]any, error)
- func (c *Client) Users(ctx context.Context, cr Creds, q url.Values) (List, error)
- type Creds
- type List
- type Org
- type User
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client reads the IAM management surface (/v1/iam/ native routes) on behalf of a verified SuperAdmin caller.
func (*Client) List ¶
List calls an IAM get-* endpoint and returns the raw data array + data2 total — the verbatim-forward primitive (roles, applications, audit records reach the operator field-for-field). A non-ok envelope is an error (surfaced honestly to the operator).
func (*Client) Org ¶
Org fetches ONE organization row (GET /v1/iam/organizations/get?owner=&name=) as the typed Org subset the scoped read panels fold over. Replays the caller's own credential, so IAM authorizes the read as the same validated principal — a non-super caller can only ever read their OWN org this way (the second line of the tenant-scope defense). Best-effort by design: the scoped-orgs fan-in tolerates an error and falls back to a name-only row.
func (*Client) SetUser ¶
SetUser writes a full user object back (POST /v1/iam/update-user?id=owner/name). The caller's replayed credential is a VALIDATED SuperAdmin, whom IAM's CheckPermissionForUpdateUser admits to set privileged fields (isForbidden) on any user — a tenant/org-admin is refused by IAM itself, so this can never be abused to suspend across a boundary the caller couldn't already cross. admin adds no service credential of its own; IAM re-checks IsSuperAdmin.
func (*Client) User ¶
User fetches ONE user as its FULL wire object (GET /v1/iam/users/get?owner=&name= ; was get-user?id= owner/name), preserving every field. The suspend/reactivate action reads the whole object, flips isForbidden, and writes it back — update-user REPLACES the row, so operating on the full object (not a typed subset) is what keeps every other field intact. Replays the caller's own credential, so IAM authorizes the read as the same validated SuperAdmin.
type Creds ¶
Creds is the caller's replayed authorization context: the raw Cookie header and Authorization bearer captured off the inbound request. IAM authenticates exactly as it does for the browser (credentials: 'include').
type List ¶
type List struct {
Rows json.RawMessage
Total int
}
List is a decoded paginated read: the raw rows and the backend total.
type Org ¶
type Org struct {
Owner string `json:"owner"`
Name string `json:"name"`
DisplayName string `json:"displayName"`
CreatedTime string `json:"createdTime"`
}
Org is the IAM Organization subset the aggregators fold over.
type User ¶
type User struct {
Owner string `json:"owner"`
Name string `json:"name"`
Email string `json:"email"`
DisplayName string `json:"displayName"`
Tag string `json:"tag"`
CreatedTime string `json:"createdTime"`
LastSigninTime string `json:"lastSigninTime"`
IsAdmin bool `json:"isAdmin"`
IsForbidden bool `json:"isForbidden"`
AccessKey string `json:"accessKey"`
}
User is the IAM User subset mapped into OperatorUser. AccessKey is decoded ONLY to derive API-key PRESENCE (hasApiKey) for the customer detail — its VALUE is never surfaced in any admin response (the hk- key is a credential, not a display field), so no secret leaves this binary.