username

package
v0.27.2 Latest Latest
Warning

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

Go to latest
Published: Aug 31, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// EventSignInBefore is published before authenticating with username credentials.
	EventSignInBefore = "username:signin:before"

	// EventSignInAfter is published after successful authentication with username credentials.
	EventSignInAfter = "username:signin:after"

	// EventUpdateBefore is published before updating a user's username.
	EventUpdateBefore = "username:update:before"

	// EventUpdateAfter is published after updating a user's username.
	EventUpdateAfter = "username:update:after"
)

Standard Event names for the Username plugin.

View Source
const (
	FieldUsername        = "username"
	FieldDisplayUsername = "display_username"

	ExtraKeyUsername        = "username"
	ExtraKeyDisplayUsername = "display_username"
)

Standard Extra metadata keys and field names for the Username plugin.

View Source
const CredentialProvider = "credential"

CredentialProvider is the default account provider ID for password authentication ("credential").

View Source
const PluginID = "username"

PluginID is the unique string identifier for the Username plugin ("username").

Variables

View Source
var (
	// ErrInvalidUsernameOrPassword is returned when login credentials (username + password) do not match.
	ErrInvalidUsernameOrPassword = errors.New("username: invalid username or password")

	// ErrEmailNotVerified is returned when password sign-in is attempted with an unverified email address.
	ErrEmailNotVerified = errors.New("username: email not verified")

	// ErrUsernameAlreadyTaken is returned when attempting to claim a username that is already in use.
	ErrUsernameAlreadyTaken = errors.New("username: username is already taken")

	// ErrUsernameTooShort is returned when a username does not satisfy the minimum length requirement.
	ErrUsernameTooShort = errors.New("username: username is too short")

	// ErrUsernameTooLong is returned when a username exceeds the maximum allowed length.
	ErrUsernameTooLong = errors.New("username: username is too long")

	// ErrInvalidUsername is returned when a username fails character set regex validation.
	ErrInvalidUsername = errors.New("username: invalid username format")

	// ErrInvalidDisplayUsername is returned when a display username fails format requirements.
	ErrInvalidDisplayUsername = errors.New("username: invalid display username format")

	// ErrUserNotFound is returned when no user matches the queried username or ID.
	ErrUserNotFound = errors.New("username: user not found")

	// ErrCredentialAccountNotFound is returned when credential provider credentials are missing for a user.
	ErrCredentialAccountNotFound = errors.New("username: credential account not found")

	// ErrInvalidParameter is returned when a required parameter is missing or invalid.
	ErrInvalidParameter = errors.New("username: required parameter is missing or invalid")
)

Sentinel errors for the Username plugin.

Functions

This section is empty.

Types

type Config

type Config struct {
	// MinLength specifies the minimum allowed username length (default: 3).
	MinLength int

	// MaxLength specifies the maximum allowed username length (default: 30).
	MaxLength int

	// RegexValidator is the compiled regular expression used to validate format (default: ^[a-zA-Z0-9_.]+$).
	RegexValidator *regexp.Regexp

	// CustomValidator is an optional user-defined function for advanced username validation (e.g. reserved word check).
	CustomValidator CustomValidatorFunc

	// EnableNormalization determines whether username strings are automatically normalized (default: true).
	EnableNormalization bool

	// NormalizeFunc defines the normalization routine applied to usernames (default: strings.ToLower).
	NormalizeFunc NormalizationFunc

	// RequireEmailVerification enforces that user emails must be verified before username sign-in (default: false).
	RequireEmailVerification bool
}

Config holds all configuration parameters for the Username plugin.

func DefaultConfig

func DefaultConfig() Config

DefaultConfig returns the default configuration settings for the Username plugin.

type CustomValidatorFunc

type CustomValidatorFunc func(ctx context.Context, username string) error

CustomValidatorFunc defines a custom validation function signature for username validation.

type IsUsernameAvailableParams

type IsUsernameAvailableParams struct {
	// Username is the username candidate to check.
	Username string `json:"username"`

	plugin.ExtraContainer
}

IsUsernameAvailableParams defines parameters to check if a username is free for registration.

type IsUsernameAvailableResult

type IsUsernameAvailableResult struct {
	// Available indicates whether the queried username is free.
	Available bool `json:"available"`

	// Username is the processed username being queried.
	Username string `json:"username"`
}

IsUsernameAvailableResult reports username availability.

type NormalizationFunc

type NormalizationFunc func(username string) string

NormalizationFunc defines a function signature for normalizing username input.

type Option

type Option func(*Config)

Option defines a functional option signature for configuring the Username plugin.

func WithCustomValidator

func WithCustomValidator(fn CustomValidatorFunc) Option

WithCustomValidator attaches an asynchronous custom validator callback.

func WithMaxLength

func WithMaxLength(maxLen int) Option

WithMaxLength sets the maximum allowed username length.

func WithMinLength

func WithMinLength(minLen int) Option

WithMinLength sets the minimum allowed username length.

func WithNormalization

func WithNormalization(enable bool) Option

WithNormalization enables or disables automatic username normalization.

func WithNormalizationFunc

func WithNormalizationFunc(fn NormalizationFunc) Option

WithNormalizationFunc sets a custom normalization routine (e.g. lowercasing / trimming).

func WithRequireEmailVerification

func WithRequireEmailVerification(require bool) Option

WithRequireEmailVerification configures whether email verification is required prior to sign-in.

func WithUsernameValidator

func WithUsernameValidator(pattern string) Option

WithUsernameValidator sets a custom regex pattern string for format validation.

type Plugin

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

Plugin implements the username authentication plugin for go-modular-auth.

func New

func New(repo Repository, opts ...Option) *Plugin

New instantiates a new Username plugin configured with the given repository and options.

func (*Plugin) Config

func (p *Plugin) Config() Config

Config returns a copy of the active plugin configuration.

func (*Plugin) ID

func (p *Plugin) ID() string

ID returns the unique string identifier for the plugin ("username").

func (*Plugin) Init

func (p *Plugin) Init(ctx *plugin.Context) error

Init initializes the plugin with the shared execution context.

func (*Plugin) IsAvailable

func (p *Plugin) IsAvailable(ctx context.Context, username string) (*IsUsernameAvailableResult, error)

IsAvailable checks whether the specified username is free for registration.

func (*Plugin) Normalize

func (p *Plugin) Normalize(username string) string

Normalize applies the configured normalization routine to a username string (e.g. lowercasing).

func (*Plugin) ProcessSignUpUsername

func (p *Plugin) ProcessSignUpUsername(ctx context.Context, rawUsername, rawDisplayUsername string) (normalizedUsername, finalDisplayUsername string, err error)

ProcessSignUpUsername validates, normalizes, and prepares username & displayUsername for user registration. If displayUsername is empty, it defaults to the unnormalized or normalized username.

func (*Plugin) SignIn

SignIn authenticates a user by username and password. Employs a dummy bcrypt check on nonexistent users to prevent timing attacks.

func (*Plugin) UpdateUsername

func (p *Plugin) UpdateUsername(ctx context.Context, params UpdateUsernameParams) (*UpdateUsernameResult, error)

UpdateUsername validates and modifies the username and displayUsername for a user entity.

func (*Plugin) ValidateUsername

func (p *Plugin) ValidateUsername(ctx context.Context, username string) error

ValidateUsername checks format, length, regex, and custom validation rules for a username.

type Repository

type Repository interface {
	// GetUserByUsername retrieves a user entity matching the provided username.
	//
	// Function:
	//   Used during username + password sign-in to locate the target user.
	//
	// Storage:
	//   Database (GORM / SQL) - Query user by case-insensitive username index.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//   - username: Username string.
	//
	// Returns:
	//   - *entity.User: Matching user entity if found.
	//   - error: ErrUserNotFound if missing, or database error.
	//
	// Example SQL:
	//   SELECT id, username, display_username, email, name, email_verified, created_at, updated_at FROM users WHERE LOWER(username) = LOWER($1) LIMIT 1;
	GetUserByUsername(ctx context.Context, username string) (*entity.User, error)

	// GetUserByID retrieves a user entity matching the provided unique identifier.
	//
	// Function:
	//   Used when retrieving user details during username updates or profile management.
	//
	// Storage:
	//   Database (GORM / SQL) - User primary key lookup.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//   - userID: Target user primary key ID.
	//
	// Returns:
	//   - *entity.User: Matching user entity if found.
	//   - error: ErrUserNotFound if missing.
	//
	// Example SQL:
	//   SELECT id, username, display_username, email, name, email_verified, created_at, updated_at FROM users WHERE id = $1 LIMIT 1;
	GetUserByID(ctx context.Context, userID string) (*entity.User, error)

	// IsUsernameAvailable checks if a given username is unregistered and available for use.
	//
	// Function:
	//   Called prior to assigning or changing a username to prevent duplicate username claims.
	//
	// Storage:
	//   Database (GORM / SQL) - Unique username count check.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//   - username: Proposed username string.
	//
	// Returns:
	//   - bool: True if available (unclaimed), false if already taken.
	//   - error: Nil on success, or database error.
	//
	// Example SQL:
	//   SELECT COUNT(*) FROM users WHERE LOWER(username) = LOWER($1);
	IsUsernameAvailable(ctx context.Context, username string) (bool, error)

	// UpdateUsername updates the username and display_username fields for a user.
	//
	// Function:
	//   Called when a user modifies their handle or display username.
	//
	// Storage:
	//   Database (GORM / SQL) - User handle update.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//   - userID: Target user ID.
	//   - username: Normalized lowercase username.
	//   - displayUsername: Original casing display username.
	//
	// Returns:
	//   - error: ErrUsernameAlreadyTaken on constraint conflict.
	//
	// Example SQL:
	//   UPDATE users SET username = $1, display_username = $2, updated_at = $3 WHERE id = $4;
	UpdateUsername(ctx context.Context, userID, username, displayUsername string) error

	// GetAccountByUserIDAndProvider retrieves provider credentials matching a user ID and provider ("credential").
	//
	// Function:
	//   Used during username sign-in to fetch stored password hash for verification.
	//
	// Storage:
	//   Database (GORM / SQL) - Credentials record lookup.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//   - userID: User ID.
	//   - providerID: Provider string ("credential").
	//
	// Returns:
	//   - *entity.Account: Account entity containing PasswordHash.
	//   - error: ErrCredentialAccountNotFound if missing.
	//
	// Example SQL:
	//   SELECT id, user_id, provider, password_hash FROM accounts WHERE user_id = $1 AND provider = $2 LIMIT 1;
	GetAccountByUserIDAndProvider(ctx context.Context, userID, providerID string) (*entity.Account, error)

	// CreateSession persists a new active user session in storage.
	//
	// Function:
	//   Called after successful username + password verification to issue a session.
	//
	// Storage:
	//   Database (GORM / SQL) - Active session creation.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//   - params: Session creation parameters.
	//
	// Returns:
	//   - *entity.Session: Active session entity.
	//   - error: Nil on success.
	//
	// Example SQL:
	//   INSERT INTO sessions (id, user_id, token, expires_at, created_at, updated_at) VALUES ($1, $2, $3, $4, $5, $6);
	CreateSession(ctx context.Context, params *dto.CreateSessionParams) (*entity.Session, error)
}

Repository defines the persistent storage contract required by the Username plugin. Implement this interface on your custom database adapter (e.g. PostgreSQL, MySQL, SQLite, MongoDB, GORM).

Implementation Example (GORM / database/sql):

type GormUsernameRepository struct {
	db *gorm.DB
}

func (r *GormUsernameRepository) GetUserByUsername(ctx context.Context, username string) (*entity.User, error) {
	var u entity.User
	if err := r.db.WithContext(ctx).Where("LOWER(username) = LOWER(?)", username).First(&u).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, username.ErrUserNotFound
		}
		return nil, err
	}
	return &u, nil
}

type SignInUsernameParams

type SignInUsernameParams struct {
	// Username is the target account username (required).
	Username string `json:"username"`

	// Password is the plain text user password (required).
	Password string `json:"password"`

	// RememberMe extends session lifespan if true.
	RememberMe *bool `json:"remember_me,omitempty"`

	plugin.ExtraContainer
}

SignInUsernameParams defines input parameters to authenticate a user using username and password.

type SignInUsernameResult

type SignInUsernameResult struct {
	// User is the authenticated user entity.
	User *entity.User `json:"user"`

	// SessionToken is the raw unique session token string.
	SessionToken string `json:"session_token"`

	// Session is the persisted active session entity.
	Session *entity.Session `json:"session"`
}

SignInUsernameResult contains the authenticated user entity and session details.

type UpdateUsernameParams

type UpdateUsernameParams struct {
	// UserID is the unique identifier of the user (required).
	UserID string `json:"user_id"`

	// Username is the new username string (required).
	Username string `json:"username"`

	// DisplayUsername is the optional display username (defaults to Username if empty).
	DisplayUsername string `json:"display_username,omitempty"`

	plugin.ExtraContainer
}

UpdateUsernameParams defines parameters to update a user's username and display_username.

type UpdateUsernameResult

type UpdateUsernameResult struct {
	// Success indicates if the username update completed successfully.
	Success bool `json:"success"`

	// User is the updated user entity.
	User *entity.User `json:"user"`
}

UpdateUsernameResult reports the result of updating a username.

Jump to

Keyboard shortcuts

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