Documentation
¶
Overview ¶
Package users manages operator identities + API keys. It issues a per-user bearer key (shown once), authenticates a presented token by its hash, and seeds a bootstrap admin from SYNAPSE_API_TOKEN so existing deployments keep working and historical "operator" attribution stays valid.
Index ¶
- Constants
- func HashToken(token string) string
- type Actor
- type Service
- func (s *Service) Authenticate(ctx context.Context, token string) (*user.User, error)
- func (s *Service) CreateUser(ctx context.Context, actor Actor, tenantID string, name string, role user.Role) (*user.User, string, error)
- func (s *Service) EnsureBootstrapAdmin(ctx context.Context, token string) error
- func (s *Service) List(ctx context.Context, actor Actor) ([]*user.User, error)
- func (s *Service) RotateAPIKey(ctx context.Context, actor Actor, id shared.ID) (*user.User, string, error)
- func (s *Service) SetDisabled(ctx context.Context, actor Actor, id shared.ID, disabled bool) (*user.User, error)
- func (s *Service) SetTransactionRunner(transactions ports.TenantTransactionRunner)
- func (s *Service) Update(ctx context.Context, actor Actor, id shared.ID, name string, role user.Role) (*user.User, error)
Constants ¶
const BootstrapID = "operator"
BootstrapID is the stable id of the bootstrap admin. Historical actions were attributed to "operator", so the bootstrap user owns that id and history stays coherent ("who did this?" resolves to the bootstrap admin, not a dangling string).
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Actor ¶ added in v0.2.0
Actor is the authenticated caller of a user-management action. It carries the caller's own tenant, which is the tenant every action is confined to.
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service manages users + authentication.
func NewService ¶
func NewService(repo ports.UserRepository, audit ports.AuditLogger, clock ports.Clock, ids ports.IDGenerator) (*Service, error)
NewService validates dependencies and returns the users service.
func (*Service) Authenticate ¶
Authenticate resolves a presented bearer token to its (enabled) user, or an error.
func (*Service) CreateUser ¶
func (s *Service) CreateUser(ctx context.Context, actor Actor, tenantID string, name string, role user.Role) (*user.User, string, error)
CreateUser provisions a new operator and returns the raw API key ONCE (it is never recoverable afterwards). tenantID is assigned server-side by the admin provisioning the user (never from the new user's own token) and must be the actor's own tenant unless the actor is the platform admin; empty means the actor's tenant, so a single-tenant admin keeps creating users with no ceremony. The tenant the user lands in is what scopes every read/write they later make, so it is captured in the audit record. Audited.
func (*Service) EnsureBootstrapAdmin ¶
EnsureBootstrapAdmin idempotently makes the bootstrap admin (id "operator") whose key is the env SYNAPSE_API_TOKEN, so the existing token keeps authenticating – now as a real, admin user. Safe to call on every startup.
func (*Service) List ¶
List returns the users of the actor's own tenant (the hash is on the struct; the adapter must not serialize it). No caller, the platform admin included, lists another tenant's roster.
func (*Service) RotateAPIKey ¶ added in v0.2.0
func (s *Service) RotateAPIKey(ctx context.Context, actor Actor, id shared.ID) (*user.User, string, error)
RotateAPIKey issues a new API key for a user in the actor's tenant and returns it ONCE. The previous key stops authenticating immediately, which is how a leaked key is revoked from the product. Audited; the key itself never reaches the audit log. A disabled user may be rotated — rotation invalidates the old credential whether or not the account is currently usable.
func (*Service) SetDisabled ¶ added in v0.2.0
func (s *Service) SetDisabled(ctx context.Context, actor Actor, id shared.ID, disabled bool) (*user.User, error)
SetDisabled turns a user's credentials off or back on inside the actor's tenant. Disabling is the revocation the product offers instead of deletion: the identity, and therefore every past attribution, is preserved while authentication stops. Disabling the tenant's last enabled admin is refused, else nobody could administer the tenant afterwards. Audited.
func (*Service) SetTransactionRunner ¶ added in v0.2.0
func (s *Service) SetTransactionRunner(transactions ports.TenantTransactionRunner)
SetTransactionRunner makes the last-admin guard atomic against a concurrent second mutation. Without it the count and the write commit separately, and the roster can change in between.
func (*Service) Update ¶ added in v0.2.0
func (s *Service) Update(ctx context.Context, actor Actor, id shared.ID, name string, role user.Role) (*user.User, error)
Update changes a user's display name and role inside the actor's tenant. An empty name or role leaves that field unchanged, so a caller can rename without knowing the current role. Demoting the tenant's last enabled admin is refused, else the tenant would be left unmanageable. Audited.