Documentation
¶
Overview ¶
Package user owns user persistence, password hashing, authorization guards, and the user HTTP surface.
Index ¶
- Constants
- func NormalizeOptionalEmail(email *string) (*string, error)
- func RegisterUsers(api huma.API, userService *UserService, invalidateUserTokenCache func(string), ...)
- type Argon2Params
- type CreateUserInput
- type CreateUserOutput
- type DeleteUserInput
- type DeleteUserOutput
- type Dependencies
- type GetUserAvatarInput
- type GetUserAvatarOutput
- type GetUserInput
- type GetUserOutput
- type ListUsersInput
- type ListUsersOutput
- type Module
- type UpdateUserInput
- type UpdateUserOutput
- type UserAvatar
- type UserHandler
- func (h *UserHandler) CreateUser(ctx context.Context, input *CreateUserInput) (*CreateUserOutput, error)
- func (h *UserHandler) DeleteUser(ctx context.Context, input *DeleteUserInput) (*DeleteUserOutput, error)
- func (h *UserHandler) GetUser(ctx context.Context, input *GetUserInput) (*GetUserOutput, error)
- func (h *UserHandler) GetUserAvatar(ctx context.Context, input *GetUserAvatarInput) (*GetUserAvatarOutput, error)
- func (h *UserHandler) ListUsers(ctx context.Context, input *ListUsersInput) (*ListUsersOutput, error)
- func (h *UserHandler) UpdateUser(ctx context.Context, input *UpdateUserInput) (*UpdateUserOutput, error)
- type UserService
- func (s *UserService) AttachOidcSubjectTransactional(ctx context.Context, userID string, subject string, ...) (*common.User, error)
- func (s *UserService) CreateDefaultAdmin(ctx context.Context) error
- func (s *UserService) CreateUser(ctx context.Context, user *common.User) (*common.User, error)
- func (s *UserService) DeleteAvatar(ctx context.Context, userID string) error
- func (s *UserService) DeleteUser(ctx context.Context, id string, actorPerms *authz.PermissionSet) error
- func (s *UserService) GetAvatar(ctx context.Context, userID string) ([]byte, string, error)
- func (s *UserService) GetUser(ctx context.Context, userID string) (*common.User, error)
- func (s *UserService) GetUserByEmail(ctx context.Context, email string) (*common.User, error)
- func (s *UserService) GetUserByID(ctx context.Context, id string) (*common.User, error)
- func (s *UserService) GetUserByOidcSubjectId(ctx context.Context, subjectId string) (*common.User, error)
- func (s *UserService) GetUserByUsername(ctx context.Context, username string) (*common.User, error)
- func (s *UserService) HashPassword(password string) (string, error)
- func (s *UserService) ListUsersPaginated(ctx context.Context, params pagination.QueryParams) ([]user.User, pagination.Response, error)
- func (s *UserService) ResolveUserPermissions(ctx context.Context, userID string) (*authz.PermissionSet, error)
- func (s *UserService) SetPassword(ctx context.Context, user *common.User, password string) (*common.User, error)
- func (s *UserService) SetPasswordAndRevokeSessionsExcept(ctx context.Context, user *common.User, password, exceptSessionID string) (*common.User, error)
- func (s *UserService) ToUserResponseDto(ctx context.Context, u common.User) (user.User, error)
- func (s *UserService) UpdateUser(ctx context.Context, user *common.User, actorPerms *authz.PermissionSet) (*common.User, error)
- func (s *UserService) UploadAvatar(ctx context.Context, userID string, data []byte, mimeType string) error
- func (s *UserService) ValidatePassword(encodedHash, password string) error
- func (s *UserService) WithRoleService(roleService *role.RoleService) *UserService
Constants ¶
const ( ErrCannotRemoveLastAdmin = errors.Sentinel("cannot remove the last admin user") // ErrInsufficientPrivilege is returned when a caller attempts to modify a // target whose effective privilege is equal to or higher than the caller's // (e.g. a delegated users:update holder trying to edit a global admin). ErrInsufficientPrivilege = errors.Sentinel("insufficient privilege to modify this user") )
Variables ¶
This section is empty.
Functions ¶
func NormalizeOptionalEmail ¶
func RegisterUsers ¶
func RegisterUsers(api huma.API, userService *UserService, invalidateUserTokenCache func(string), settingsService *settings.SettingsService)
RegisterUsers registers all user management endpoints.
Types ¶
type Argon2Params ¶
type Argon2Params struct {
// contains filtered or unexported fields
}
func DefaultArgon2Params ¶
func DefaultArgon2Params() *Argon2Params
type CreateUserInput ¶
type CreateUserInput struct {
Body usertypes.CreateUser
}
type CreateUserOutput ¶
type CreateUserOutput struct {
Body base.ApiResponse[usertypes.User]
}
type DeleteUserInput ¶
type DeleteUserInput struct {
UserID string `path:"userId" doc:"User ID"`
}
type DeleteUserOutput ¶
type DeleteUserOutput struct {
Body base.ApiResponse[base.MessageResponse]
}
type Dependencies ¶
type Dependencies struct {
Service *UserService
InvalidateUserTokenCache func(string)
Settings *settings.SettingsService
}
type GetUserAvatarInput ¶
type GetUserAvatarInput struct {
UserID string `path:"userId" doc:"User ID"`
}
type GetUserAvatarOutput ¶
type GetUserInput ¶
type GetUserInput struct {
UserID string `path:"userId" doc:"User ID"`
}
type GetUserOutput ¶
type GetUserOutput struct {
Body base.ApiResponse[usertypes.User]
}
type ListUsersInput ¶
type ListUsersInput struct {
Search string `query:"search" doc:"Search query"`
Sort string `query:"sort" doc:"Column to sort by"`
Order string `query:"order" default:"asc" doc:"Sort direction"`
Start int `query:"start" default:"0" doc:"Start index"`
Limit int `query:"limit" default:"20" doc:"Items per page"`
}
type Module ¶
type Module struct {
// contains filtered or unexported fields
}
func New ¶
func New(deps Dependencies) *Module
func (*Module) RegisterRoutes ¶
func (*Module) Service ¶
func (m *Module) Service() *UserService
type UpdateUserInput ¶
type UpdateUserInput struct {
UserID string `path:"userId" doc:"User ID"`
Body usertypes.UpdateUser
}
type UpdateUserOutput ¶
type UpdateUserOutput struct {
Body base.ApiResponse[usertypes.User]
}
type UserAvatar ¶ added in v2.8.1
type UserAvatar struct {
UserID string `json:"userId" gorm:"column:user_id;primaryKey"`
Data []byte `json:"-" gorm:"column:data;type:blob;not null"`
MimeType string `json:"mimeType" gorm:"column:mime_type;not null"`
}
UserAvatar represents the raw profile picture data for a user. Stored separately from the main User struct to prevent loading up to 2MB of binary data on every user query.
func (UserAvatar) TableName ¶ added in v2.8.1
func (UserAvatar) TableName() string
type UserHandler ¶
type UserHandler struct {
// contains filtered or unexported fields
}
UserHandler handles user management endpoints.
func (*UserHandler) CreateUser ¶
func (h *UserHandler) CreateUser(ctx context.Context, input *CreateUserInput) (*CreateUserOutput, error)
CreateUser creates a new usertypes.
func (*UserHandler) DeleteUser ¶
func (h *UserHandler) DeleteUser(ctx context.Context, input *DeleteUserInput) (*DeleteUserOutput, error)
DeleteUser deletes a usertypes.
func (*UserHandler) GetUser ¶
func (h *UserHandler) GetUser(ctx context.Context, input *GetUserInput) (*GetUserOutput, error)
GetUser returns a user by ID.
func (*UserHandler) GetUserAvatar ¶
func (h *UserHandler) GetUserAvatar(ctx context.Context, input *GetUserAvatarInput) (*GetUserAvatarOutput, error)
GetUserAvatar returns the custom profile picture for a usertypes.
func (*UserHandler) ListUsers ¶
func (h *UserHandler) ListUsers(ctx context.Context, input *ListUsersInput) (*ListUsersOutput, error)
ListUsers returns a paginated list of users.
func (*UserHandler) UpdateUser ¶
func (h *UserHandler) UpdateUser(ctx context.Context, input *UpdateUserInput) (*UpdateUserOutput, error)
UpdateUser updates a usertypes.
type UserService ¶
type UserService struct {
// contains filtered or unexported fields
}
func NewUserService ¶
func NewUserService(db *database.DB) *UserService
func (*UserService) AttachOidcSubjectTransactional ¶
func (s *UserService) AttachOidcSubjectTransactional(ctx context.Context, userID string, subject string, updateFn func(u *common.User)) (*common.User, error)
AttachOidcSubjectTransactional safely links an OIDC subject to the given user inside a DB transaction. It uses a row lock (FOR UPDATE) to prevent concurrent merges from racing and validates that the user isn't already linked to a different subject. The provided updateFn can mutate the user (e.g., roles, display name, tokens, last login) before persisting.
Note: The clause.Locking{Strength: "UPDATE"} statement is used to acquire a row-level lock. This MUST be done inside a transaction to ensure the lock is held until the update is committed.
func (*UserService) CreateDefaultAdmin ¶
func (s *UserService) CreateDefaultAdmin(ctx context.Context) error
func (*UserService) CreateUser ¶
func (*UserService) DeleteAvatar ¶
func (s *UserService) DeleteAvatar(ctx context.Context, userID string) error
DeleteAvatar removes the avatar for a user.
func (*UserService) DeleteUser ¶
func (s *UserService) DeleteUser(ctx context.Context, id string, actorPerms *authz.PermissionSet) error
DeleteUser removes the user with the given id. actorPerms identifies the caller performing the deletion; authenticated global-admin callers must also be present in ctx. Pass nil for internal service-to-service calls. A non-admin caller may not delete a global admin target.
func (*UserService) GetAvatar ¶
GetAvatar returns the raw avatar data and MIME type for a user. Returns (nil, "", nil) when the user has no custom avatar.
func (*UserService) GetUserByEmail ¶
GetUserByEmail returns the user with the given email. The schema does not enforce email uniqueness, so a lookup matching more than one account returns common.ErrAmbiguousUserEmail instead of arbitrarily selecting one.
func (*UserService) GetUserByID ¶
func (*UserService) GetUserByOidcSubjectId ¶
func (*UserService) GetUserByUsername ¶
func (*UserService) HashPassword ¶
func (s *UserService) HashPassword(password string) (string, error)
func (*UserService) ListUsersPaginated ¶
func (s *UserService) ListUsersPaginated(ctx context.Context, params pagination.QueryParams) ([]user.User, pagination.Response, error)
func (*UserService) ResolveUserPermissions ¶
func (s *UserService) ResolveUserPermissions(ctx context.Context, userID string) (*authz.PermissionSet, error)
ResolveUserPermissions returns the effective PermissionSet for the given user ID, or nil when no role.RoleService is wired (RBAC disabled paths).
func (*UserService) SetPassword ¶
func (s *UserService) SetPassword(ctx context.Context, user *common.User, password string) (*common.User, error)
SetPassword hashes and persists a new password for the given user and clears the first-login password-change requirement for trusted internal callers.
func (*UserService) SetPasswordAndRevokeSessionsExcept ¶
func (s *UserService) SetPasswordAndRevokeSessionsExcept(ctx context.Context, user *common.User, password, exceptSessionID string) (*common.User, error)
SetPasswordAndRevokeSessionsExcept atomically sets a new password, clears the first-login password-change requirement, and revokes every session for the user except exceptSessionID. Pass an empty exceptSessionID to revoke all sessions. This is for trusted internal callers.
func (*UserService) ToUserResponseDto ¶
func (*UserService) UpdateUser ¶
func (s *UserService) UpdateUser(ctx context.Context, user *common.User, actorPerms *authz.PermissionSet) (*common.User, error)
UpdateUser persists the given user. actorPerms identifies the caller performing the change; authenticated global-admin callers must also be present in ctx. Pass nil for internal service-to-service calls.
func (*UserService) UploadAvatar ¶
func (s *UserService) UploadAvatar(ctx context.Context, userID string, data []byte, mimeType string) error
UploadAvatar stores avatar bytes for a user, replacing any existing avatar.
func (*UserService) ValidatePassword ¶
func (s *UserService) ValidatePassword(encodedHash, password string) error
func (*UserService) WithRoleService ¶
func (s *UserService) WithRoleService(roleService *role.RoleService) *UserService
WithRoleService wires the role.RoleService dependency. Separated from the constructor so the bootstrap can construct UserService first (role.RoleService itself has no UserService dependency).