user

package
v1.0.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 28, 2026 License: Apache-2.0 Imports: 9 Imported by: 0

Documentation

Overview

Package user provides user domain models and repository interfaces.

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrUserNotFound       = errors.New("user not found")
	ErrEmailAlreadyExists = errors.New("email already exists")
	ErrInvalidRole        = errors.New("invalid role")
	// ErrLastOwner is returned when a change would leave the site without an owner.
	ErrLastOwner = errors.New("cannot remove or demote the last owner")
)

Common errors.

Functions

func ValidRole

func ValidRole(r Role) bool

ValidRole checks if a role is valid.

Types

type CreateUserInput

type CreateUserInput struct {
	Email    string
	Password string
	Role     Role
	Name     string
}

CreateUserInput represents input for creating a new user.

type PostgresRepository

type PostgresRepository struct {
	// contains filtered or unexported fields
}

PostgresRepository implements Repository using PostgreSQL.

func NewPostgresRepository

func NewPostgresRepository(db *database.DB) *PostgresRepository

NewPostgresRepository creates a new PostgreSQL user repository.

func (*PostgresRepository) Count

func (r *PostgresRepository) Count(ctx context.Context) (int, error)

Count returns the total number of users.

Path B PR 2b/3: dropped the tenantID parameter (see List).

func (*PostgresRepository) Create

func (r *PostgresRepository) Create(ctx context.Context, input *CreateUserInput, passwordHash string) (*User, error)

Create inserts a new user into the database. Multi-tenancy was removed in Path B; hatamoto_users has no tenant_id column and the User model has no TenantID field.

func (*PostgresRepository) Delete

func (r *PostgresRepository) Delete(ctx context.Context, id uuid.UUID) error

Delete removes a user from the database.

func (*PostgresRepository) GetByEmail

func (r *PostgresRepository) GetByEmail(ctx context.Context, email string) (*User, error)

GetByEmail retrieves a user by email address.

func (*PostgresRepository) GetByID

func (r *PostgresRepository) GetByID(ctx context.Context, id uuid.UUID) (*User, error)

GetByID retrieves a user by ID.

func (*PostgresRepository) List

func (r *PostgresRepository) List(ctx context.Context, limit, offset int) ([]*User, error)

List retrieves users with pagination.

Path B PR 2b/3: dropped the tenantID parameter — there's a single tenant so per-tenant filtering is meaningless. Callers must update their call sites accordingly.

func (*PostgresRepository) ListByEmail

func (r *PostgresRepository) ListByEmail(ctx context.Context, email string) ([]*User, error)

ListByEmail retrieves all users with the given email. Pre-Path-B this scanned across tenants for the multi-tenant cross-account login feature; post-strip the result set is at most 1 row but the API contract stays the same so callers (auth.Service) don't need adjusting.

func (*PostgresRepository) RecordFailedLogin

func (r *PostgresRepository) RecordFailedLogin(ctx context.Context, id uuid.UUID, maxAttempts int, lockFor time.Duration) error

RecordFailedLogin increments the failure counter and locks the account once the threshold is reached, in a single statement.

func (*PostgresRepository) ResetFailedLogins

func (r *PostgresRepository) ResetFailedLogins(ctx context.Context, id uuid.UUID) error

ResetFailedLogins clears the failure counter and unlocks the account.

func (*PostgresRepository) SetPassword

func (r *PostgresRepository) SetPassword(ctx context.Context, id uuid.UUID, passwordHash string) error

SetPassword replaces a user's password hash and clears any login lockout.

func (*PostgresRepository) Update

func (r *PostgresRepository) Update(ctx context.Context, id uuid.UUID, input *UpdateUserInput) (*User, error)

Update modifies a user's information.

func (*PostgresRepository) UpdateLastLogin

func (r *PostgresRepository) UpdateLastLogin(ctx context.Context, id uuid.UUID) error

UpdateLastLogin updates the user's last login timestamp.

type Repository

type Repository interface {
	Create(ctx context.Context, input *CreateUserInput, passwordHash string) (*User, error)
	GetByID(ctx context.Context, id uuid.UUID) (*User, error)
	GetByEmail(ctx context.Context, email string) (*User, error)
	ListByEmail(ctx context.Context, email string) ([]*User, error)
	Update(ctx context.Context, id uuid.UUID, input *UpdateUserInput) (*User, error)
	UpdateLastLogin(ctx context.Context, id uuid.UUID) error
	// RecordFailedLogin increments the consecutive-failure counter and, once it
	// reaches maxAttempts, sets locked_until to now()+lockFor.
	RecordFailedLogin(ctx context.Context, id uuid.UUID, maxAttempts int, lockFor time.Duration) error
	// ResetFailedLogins clears the failure counter and any lock (called on a
	// successful login).
	ResetFailedLogins(ctx context.Context, id uuid.UUID) error
	Delete(ctx context.Context, id uuid.UUID) error
	List(ctx context.Context, limit, offset int) ([]*User, error)
	Count(ctx context.Context) (int, error)
}

Repository defines the interface for user data operations.

Path B PR 2b/3: List and Count no longer take a tenantID — there is only one tenant. The signature change forces callers off the legacy code path rather than silently ignoring the argument.

type Role

type Role string

Role is a user's role: owner (everything) or editor (content).

const (
	RoleOwner  Role = "owner"
	RoleEditor Role = "editor"
)

Available user roles.

func ParseRole

func ParseRole(s string) (Role, error)

ParseRole parses a string into a Role.

type UpdateUserInput

type UpdateUserInput struct {
	Name      *string
	AvatarURL *string
	Role      *Role
}

UpdateUserInput represents input for updating a user.

type User

type User struct {
	ID           uuid.UUID  `json:"id"`
	Email        string     `json:"email"`
	PasswordHash string     `json:"-"` // Never expose
	Role         Role       `json:"role"`
	Name         *string    `json:"name,omitempty"`
	AvatarURL    *string    `json:"avatar_url,omitempty"`
	LastLoginAt  *time.Time `json:"last_login_at,omitempty"`
	// Login-lockout state (migration 004). Never serialized to clients.
	FailedLoginAttempts int        `json:"-"`
	LockedUntil         *time.Time `json:"-"`
	CreatedAt           time.Time  `json:"created_at"`
	UpdatedAt           time.Time  `json:"updated_at"`
}

User represents a tenant user.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL