Documentation
¶
Overview ¶
Package user defines the user domain entity and its store interface.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func NormalizeEmail ¶
NormalizeEmail lowercases and trims an email address so lookups and uniqueness checks are case-insensitive and whitespace-insensitive.
Types ¶
type BatchGetter ¶ added in v1.9.3
BatchGetter is implemented by stores that can read many users in one call. GetUsers returns the users with the given IDs that exist and are not deleted, in no particular order. An ID with no live user is left out, not an error. Duplicate IDs are read once. An empty list returns an empty result without touching the database.
type List ¶
type List struct {
Users []*User `json:"users"`
NextCursor string `json:"next_cursor,omitempty"`
Total int `json:"total"`
}
List is a paginated list of users.
type Query ¶
type Query struct {
AppID id.AppID `json:"app_id"`
EnvID id.EnvironmentID `json:"env_id,omitempty"`
Email string `json:"email,omitempty"`
Cursor string `json:"cursor,omitempty"`
Limit int `json:"limit,omitempty"`
}
Query holds query parameters for listing users.
type Store ¶
type Store interface {
CreateUser(ctx context.Context, u *User) error
GetUser(ctx context.Context, userID id.UserID) (*User, error)
// GetUserByEmail resolves the user whose primary email matches within
// (appID, envID). A nil envID matches app-wide, mirroring GetUserByAnyEmail.
GetUserByEmail(ctx context.Context, appID id.AppID, envID id.EnvironmentID, email string) (*User, error)
// GetUserByPhone resolves the user owning phone within (appID, envID).
// A nil envID matches app-wide, mirroring GetUserByAnyEmail.
GetUserByPhone(ctx context.Context, appID id.AppID, envID id.EnvironmentID, phone string) (*User, error)
// GetUserByUsername resolves the user owning username within (appID,
// envID). A nil envID matches app-wide, which is what the signup and
// rename guards rely on to keep handles unique across a whole app.
GetUserByUsername(ctx context.Context, appID id.AppID, envID id.EnvironmentID, username string) (*User, error)
UpdateUser(ctx context.Context, u *User) error
DeleteUser(ctx context.Context, userID id.UserID) error
ListUsers(ctx context.Context, q *Query) (*List, error)
// CreateUserWithPrimaryEmail creates a user and its primary email row.
// The address must be free within (AppID, EnvID), else ErrEmailTaken.
CreateUserWithPrimaryEmail(ctx context.Context, u *User, primary *UserEmail) error
// AddUserEmail attaches an additional email to a user. Returns
// account.ErrEmailTaken if the address is already owned within the env.
AddUserEmail(ctx context.Context, e *UserEmail) error
// GetUserByAnyEmail resolves the user owning any (primary or secondary)
// verified-or-not email matching (appID, envID, email). ErrNotFound when none.
GetUserByAnyEmail(ctx context.Context, appID id.AppID, envID id.EnvironmentID, email string) (*User, error)
// GetUserEmailRecord returns the email row matching (appID, envID, email)
// so callers can inspect Verified before linking. ErrNotFound when none.
GetUserEmailRecord(ctx context.Context, appID id.AppID, envID id.EnvironmentID, email string) (*UserEmail, error)
// GetUserEmails returns all live emails for a user, primary first.
GetUserEmails(ctx context.Context, userID id.UserID) ([]*UserEmail, error)
// MarkUserEmailVerified marks an email verified, mirroring onto the user
// record when it is the primary email.
MarkUserEmailVerified(ctx context.Context, userID id.UserID, email string) error
// SetPrimaryEmail makes a verified, user-owned email primary, updating the
// user mirror. Returns account.ErrEmailNotVerified if the target is unverified.
SetPrimaryEmail(ctx context.Context, userID id.UserID, email string) error
// DeleteUserEmail soft-deletes a non-primary email. Refuses the primary
// with store.ErrConflict.
DeleteUserEmail(ctx context.Context, userID id.UserID, email string) error
}
Store defines the persistence interface for user operations.
type User ¶
type User struct {
ID id.UserID `json:"id"`
AppID id.AppID `json:"app_id"`
EnvID id.EnvironmentID `json:"env_id"`
Email string `json:"email"`
EmailVerified bool `json:"email_verified"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
Image string `json:"image,omitempty"`
Username string `json:"username,omitempty"`
DisplayUsername string `json:"display_username,omitempty"`
Phone string `json:"phone,omitempty"`
PhoneVerified bool `json:"phone_verified"`
PasswordHash string `json:"-"`
PasswordChangedAt *time.Time `json:"password_changed_at,omitempty"`
Banned bool `json:"banned"`
BanReason string `json:"ban_reason,omitempty"`
BanExpires *time.Time `json:"ban_expires,omitempty"`
Metadata Metadata `json:"metadata,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt *time.Time `json:"deleted_at,omitempty"`
}
User represents an authenticated identity within an application.
type UserEmail ¶
type UserEmail struct {
ID id.UserEmailID `json:"id"`
UserID id.UserID `json:"user_id"`
AppID id.AppID `json:"app_id"`
EnvID id.EnvironmentID `json:"env_id"`
Email string `json:"email"` // always stored lowercased + trimmed
Verified bool `json:"verified"`
IsPrimary bool `json:"is_primary"`
Source string `json:"source"` // e.g. "password", "social:github", "sso", "scim", "admin", "backfill"
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt *time.Time `json:"deleted_at,omitempty"`
}
UserEmail is a single email address belonging to a user. A user may own multiple emails; exactly one is marked primary and mirrors User.Email / User.EmailVerified. Email uniqueness is enforced per (AppID, EnvID, Email) so an address can belong to at most one account within an environment.
func NewPrimaryEmail ¶
NewPrimaryEmail builds the primary UserEmail row mirroring a user's current Email/EmailVerified, for use with Store.CreateUserWithPrimaryEmail. source records where the address came from (e.g. "password", "sso", "scim").