Documentation
¶
Overview ¶
Package iam is the admin cockpit's typed reader for the Hanzo IAM management surface (/v1/iam/get-*). 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/get-*) 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/get-organization?id=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/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.