username

package
v1.3.0 Latest Latest
Warning

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

Go to latest
Published: Oct 23, 2026 License: MIT, MIT Imports: 11 Imported by: 0

README

GoModularAuth Username Plugin (gomodularauth-username)

An optional, production-ready identity plugin for GoModularAuth that provides username-based authentication, normalization, validation, and lifecycle management without polluting the Core user.User entity.

Installation

go get github.com/BladiCreator/go-modular-auth/plugins/username

Quick Start

package main

import (
	"context"
	"fmt"
	"log"

	auth "github.com/BladiCreator/go-modular-auth"
	adaptermem "github.com/BladiCreator/go-modular-auth/adapters/memory"
	"github.com/BladiCreator/go-modular-auth/plugins/username"
)

func main() {
	ctx := context.Background()

	// 1. Initialize GoModularAuth with the Username plugin
	app, err := auth.New(auth.Config{
		Adapter: adaptermem.NewAdapter(),
		Cache:   adaptermem.NewCache(),
		Plugins: []auth.PluginModule{
			username.New(),
		},
	})
	if err != nil {
		log.Fatalf("auth initialization failed: %v", err)
	}

	// 2. Retrieve the typed username capability
	userPlugin, err := auth.Get[username.Capability](app)
	if err != nil {
		log.Fatalf("plugin lookup failed: %v", err)
	}

	// 3. Register a user with email + username + password
	result, err := userPlugin.Register(ctx, username.RegisterInput{
		Email:    "alice@example.com",
		Username: "AliceSmith",
		Password: "SuperSecretPassword123!",
	})
	if err != nil {
		log.Fatalf("registration failed: %v", err)
	}
	fmt.Printf("Registered user: %s with session token: %s\n", result.User.ID, result.Token)

	// 4. Authenticate using username (case-insensitive by default)
	authRes, err := userPlugin.Authenticate(ctx, username.AuthenticateInput{
		Username: "alicesmith",
		Password: "SuperSecretPassword123!",
	})
	if err != nil {
		log.Fatalf("authentication failed: %v", err)
	}
	fmt.Printf("Authenticated user %s, issued session %s\n", authRes.User.ID, authRes.Session.ID)
}

Detailed guide: doc/plugins/username.md.

Documentation

Overview

Package username enables username-based registration and authentication alongside email.

Index

Constants

View Source
const (
	// EventCreated is emitted when a username is assigned to a user.
	EventCreated auth.EventName = "username.created"

	// EventUpdated is emitted when an existing username is modified.
	EventUpdated auth.EventName = "username.updated"

	// EventDeleted is emitted when a username assignment is removed.
	EventDeleted auth.EventName = "username.deleted"
)
View Source
const (
	ModelUsernames = "usernames"
)
View Source
const PluginID = "username"

PluginID identifies this plugin in the GoModularAuth runtime.

Variables

View Source
var (
	// ErrNotFound is returned when a username or user record is not found.
	ErrNotFound = errors.New("username: not found")

	// ErrTaken is returned when a username is already claimed by another user.
	ErrTaken = errors.New("username: already taken")

	// ErrAlreadyAssigned is returned when a user already has an assigned username.
	ErrAlreadyAssigned = errors.New("username: user already has a username")

	// ErrInvalidFormat is returned when a username violates syntactic or character rules.
	ErrInvalidFormat = errors.New("username: invalid format")

	// ErrTooShort is returned when a username is shorter than the configured minimum length.
	ErrTooShort = errors.New("username: too short")

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

	// ErrReserved is returned when a username matches a reserved name.
	ErrReserved = errors.New("username: reserved name")

	// ErrUserNotFound is returned when the corresponding Core user does not exist.
	ErrUserNotFound = errors.New("username: core user not found")

	// ErrInvalidCredentials is returned when authentication fails.
	// Preserves timing and error semantics of auth.ErrInvalidCredentials to prevent enumeration.
	ErrInvalidCredentials = errors.New("auth: invalid credentials")
)
View Source
var DefaultReservedUsernames = map[string]struct{}{
	"admin":         {},
	"administrator": {},
	"root":          {},
	"system":        {},
	"sysadmin":      {},
	"support":       {},
	"help":          {},
	"api":           {},
	"auth":          {},
	"oauth":         {},
	"login":         {},
	"logout":        {},
	"signin":        {},
	"signup":        {},
	"register":      {},
	"security":      {},
	"staff":         {},
	"mod":           {},
	"moderator":     {},
	"guest":         {},
	"anonymous":     {},
	"null":          {},
	"undefined":     {},
	"void":          {},
	"me":            {},
	"self":          {},
	"test":          {},
	"dev":           {},
	"status":        {},
	"health":        {},
	"metrics":       {},
	"account":       {},
	"user":          {},
	"users":         {},
	"settings":      {},
	"profile":       {},
	"dashboard":     {},
	"billing":       {},
}

DefaultReservedUsernames contains common system, routing, and administrative handles to prevent identity squatting and URL collision.

Functions

func RegisterSchema added in v1.3.0

func RegisterSchema(s *schema.Schema) error

RegisterSchema registers the usernames model with the unified schema.

Types

type AuthenticateInput added in v1.3.0

type AuthenticateInput struct {
	Username string
	Password string
	Session  auth.SessionOptions
}

AuthenticateInput holds credentials for username-based sign in.

type Capability added in v1.3.0

type Capability interface {
	// Authenticate validates the username and password, issuing an opaque session.
	// Applies timing equalization to prevent username enumeration if user does not exist.
	Authenticate(ctx context.Context, in AuthenticateInput) (*auth.AuthResult, error)

	// Register atomically creates a new Core User, Account, Credential, and Username mapping.
	Register(ctx context.Context, in RegisterInput) (*auth.AuthResult, error)

	// Set assigns a username to an existing Core user.
	Set(ctx context.Context, userID, rawUsername string) error

	// Change modifies an existing username for a user, invalidating caches.
	Change(ctx context.Context, userID, newRawUsername string) error

	// Delete removes the username assignment for a user.
	Delete(ctx context.Context, userID string) error

	// GetByUserID retrieves the username record for a given Core user ID.
	GetByUserID(ctx context.Context, userID string) (*Record, error)

	// GetByUsername retrieves the username record for a raw username.
	GetByUsername(ctx context.Context, rawUsername string) (*Record, error)

	// Lookup returns the Core user ID associated with the username.
	Lookup(ctx context.Context, rawUsername string) (string, error)

	// Validate checks if a raw username satisfies validation rules.
	Validate(rawUsername string) error

	// Normalize computes the canonical representation of a raw username.
	Normalize(rawUsername string) (string, error)
}

Capability defines the typed contract for username operations. Applications access it via auth.Get[username.Capability](a) or auth.Get[username.Username](a).

type Config

type Config struct {
	MinLength     int
	MaxLength     int
	CaseSensitive bool
	Reserved      map[string]struct{}
	Normalizer    Normalizer
	Validator     Validator
	CacheTTL      time.Duration
}

Config holds configuration parameters for the username plugin.

type CreatedPayload added in v1.3.0

type CreatedPayload struct {
	UserID     string `json:"user_id"`
	Username   string `json:"username"`
	Normalized string `json:"normalized"`
}

CreatedPayload holds observational metadata for EventCreated.

type DeletedPayload added in v1.3.0

type DeletedPayload struct {
	UserID     string `json:"user_id"`
	Username   string `json:"username"`
	Normalized string `json:"normalized"`
}

DeletedPayload holds observational metadata for EventDeleted.

type Module added in v1.3.0

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

Module implements auth.PluginModule using plugin-sdk.

func New

func New(opts ...Option) *Module

New creates an installable username PluginModule with optional functional configurations.

func (*Module) ID added in v1.3.0

func (m *Module) ID() string

ID returns the module identifier.

func (*Module) Init added in v1.3.0

func (m *Module) Init(h *auth.Host) error

Init configures infrastructure and registers the typed Capability into GoModularAuth via plugin-sdk.

func (*Module) RegisterSchema added in v1.3.0

func (m *Module) RegisterSchema(s *schema.Schema) error

RegisterSchema registers the plugin's models into the schema.

type Normalizer added in v1.3.0

type Normalizer func(username string) (string, error)

Normalizer transforms a raw username into its canonical lookup and uniqueness key.

func DefaultNormalizer added in v1.3.0

func DefaultNormalizer(caseSensitive bool) Normalizer

DefaultNormalizer returns the trimmed, lowercase representation of a username. When caseSensitive is true, only leading/trailing whitespace is trimmed.

type Option

type Option func(*Config)

Option modifies plugin configuration.

func WithCacheTTL added in v1.3.0

func WithCacheTTL(d time.Duration) Option

WithCacheTTL sets the cache duration for username records.

func WithCaseSensitive added in v1.3.0

func WithCaseSensitive(sensitive bool) Option

WithCaseSensitive explicitly sets whether usernames are case-sensitive. When false (default), comparisons and uniqueness are case-insensitive.

func WithMaxLength

func WithMaxLength(max int) Option

WithMaxLength sets the maximum allowed username length.

func WithMinLength

func WithMinLength(min int) Option

WithMinLength sets the minimum allowed username length.

func WithNormalizer added in v1.3.0

func WithNormalizer(n Normalizer) Option

WithNormalizer sets a custom normalization function.

func WithReserved added in v1.3.0

func WithReserved(names ...string) Option

WithReserved adds additional names to the reserved keywords list.

func WithValidator added in v1.3.0

func WithValidator(v Validator) Option

WithValidator sets a custom validation function.

type Record added in v1.3.0

type Record struct {
	UserID     string    `json:"user_id"`
	Username   string    `json:"username"`   // Display username in original casing
	Normalized string    `json:"normalized"` // Canonical search key for uniqueness & lookups
	CreatedAt  time.Time `json:"created_at"`
	UpdatedAt  time.Time `json:"updated_at"`
}

Record is the persistent representation of a username mapping.

type RegisterInput added in v1.3.0

type RegisterInput struct {
	Email    string
	Username string
	Password string
	Session  auth.SessionOptions
}

RegisterInput holds user details for registration with a username.

type UpdatedPayload added in v1.3.0

type UpdatedPayload struct {
	UserID        string `json:"user_id"`
	OldUsername   string `json:"old_username"`
	NewUsername   string `json:"new_username"`
	OldNormalized string `json:"old_normalized"`
	NewNormalized string `json:"new_normalized"`
}

UpdatedPayload holds observational metadata for EventUpdated.

type Username added in v1.3.0

type Username = Capability

Username is a type alias for Capability, supporting both auth.Get[username.Username](a) and auth.Get[username.Capability](a).

type Validator added in v1.3.0

type Validator func(username string) error

Validator is a function that checks if a raw username satisfies syntactic and business rules.

func DefaultValidator added in v1.3.0

func DefaultValidator(minLen, maxLen int, reserved map[string]struct{}) Validator

DefaultValidator creates a validator verifying length constraints, character patterns, consecutive separators, and reserved keywords.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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