Documentation
¶
Overview ¶
Package userdir assembles the known-users directory (#614) behind one Handle: the Postgres-backed user store and the *user.Directory that wraps it with throttled, asynchronous upserts of authenticated people.
Construction takes a single explicit input — a *sql.DB — so the subsystem is constructible and testable without a Platform. It imports pkg/user and pkg/middleware (for the authenticated-user shape), never pkg/platform. The *sql.DB is a shared foundation owned by the caller and passed in.
New returns nil when db is nil: the directory needs a database, so a no-DB deployment gets the nil Handle and every accessor and observer degrades to a no-op (consumers fall back to free-typed email sharing). The two Observe methods are the seams the caller wires as the authenticator's UserObserver and the browser-session login callback; the directory itself sanitizes, throttles, and writes asynchronously, so both are cheap. The layer owns no background goroutine of its own, so it needs no Stop/Close.
Index ¶
- type Handle
- func (h *Handle) BindResourceFold(deps resource.Deps)
- func (h *Handle) BoundPrincipal(ctx context.Context, email string) (*auth.BoundPrincipal, error)
- func (h *Handle) Directory() *user.Directory
- func (h *Handle) ObserveAuthenticated(info *middleware.UserInfo)
- func (h *Handle) ObserveBrowserLogin(email, firstName, lastName, subject string, roles []string)
- func (h *Handle) Store() user.Store
- func (h *Handle) Subjects() *subjects.Book
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Handle ¶
type Handle struct {
// contains filtered or unexported fields
}
Handle owns the assembled known-users directory: the user store and the *user.Directory. Store() backs the callers that surface the directory (the find-tools / portal directory endpoints); Directory() is read to decide whether to wrap the authenticator. Both are nil on a nil Handle (no database), and the Observe methods are no-ops there, so every consumer degrades cleanly.
func New ¶
New builds the user store and directory from db. It returns nil when db is nil (the directory is a no-op without a database), so the caller holds a nil Handle that every accessor and observer treats as disabled.
func (*Handle) BindResourceFold ¶ added in v1.131.1
BindResourceFold supplies what the fold of an address-keyed library into the subject-keyed one refiles through, once the managed-resource layer exists.
func (*Handle) BoundPrincipal ¶ added in v1.132.0
BoundPrincipal resolves the person an API key is issued against: the subject their own sessions authenticate as, their address as the directory holds it, and the roles the identity provider last said they hold (#1759).
It answers auth.ErrNoBoundPrincipal for somebody the platform cannot speak for: an address the directory has no row for (including a person an administrator has since removed, which is how removing them revokes their keys) and one it has never seen sign in, which has no subject to present and no roles to carry. A read that FAILED reports that failure instead, so a key is refused rather than resolved against a directory that could not answer, and a caller can tell "there is nobody" from "I could not look".
The two reads are independent and are made together, so a bound key costs one round trip's worth of latency rather than two.
func (*Handle) Directory ¶
Directory returns the throttled async directory, or nil on a nil Handle. The caller reads it to decide whether to wrap the authenticator with the observer.
func (*Handle) ObserveAuthenticated ¶
func (h *Handle) ObserveAuthenticated(info *middleware.UserInfo)
ObserveAuthenticated records an authenticated person in the directory. It is wired as the UserObserver on the authenticator, so it runs on every successful authentication. Only real people (OIDC/OAuth) are recorded; API keys and anonymous sessions are not persons to share with. No-op on a nil Handle, a nil directory, or a nil info.
func (*Handle) ObserveBrowserLogin ¶
ObserveBrowserLogin records a portal/admin SPA user in the directory at login. The browser-session flow already supplies a split first/last name and the subject and roles it extracted from the id_token, so this routes straight to the directory (which sanitizes, throttles, and writes asynchronously). No-op on a nil Handle or a nil directory.
The subject pair is recorded here as well as on the token path. A person who only ever signs in through the portal never passes through the authenticator, so this is the only place the platform learns what they authenticate as -- which a managed-script run acting for them reads (#1677), and which a key issued against their account authenticates as (#1759).