Documentation
¶
Overview ¶
Package auth provides authentication as a burrow contrib app.
It implements WebAuthn (passkeys), recovery codes, email verification, and invite-only registration. Context helpers provide access to the authenticated user from any handler.
Index ¶
- Constants
- Variables
- func DefaultAuthLayout() burrow.LayoutFunc
- func GenerateInviteToken() (plaintext, hash string, err error)
- func GenerateToken() (string, string, time.Time, error)
- func HashToken(token string) string
- func IsAdminEditLastAdmin(ctx context.Context) bool
- func IsAdminEditSelf(ctx context.Context) bool
- func IsAuthenticated(ctx context.Context) bool
- func LogoFromContext(ctx context.Context) template.HTML
- func NormalizeCode(code string) string
- func RequireAdmin() func(http.Handler) http.Handler
- func RequireAuth() func(http.Handler) http.Handler
- func SafeRedirectPath(next, defaultPath string) string
- func TransportsFromWebAuthn(transports []protocol.AuthenticatorTransport) string
- func WithLogo(ctx context.Context, logo template.HTML) context.Context
- func WithUser(ctx context.Context, user *User) context.Context
- type App
- func (a *App) AdminNavItems() []burrow.NavItem
- func (a *App) AdminRoutes(r chi.Router)
- func (a *App) CLICommands() []*cli.Command
- func (a *App) Configure(cmd *cli.Command) error
- func (a *App) Dependencies() []string
- func (a *App) Flags(configSource func(key string) cli.ValueSource) []cli.Flag
- func (a *App) FuncMap() template.FuncMap
- func (a *App) Handlers() *Handlers
- func (a *App) Middleware() []func(http.Handler) http.Handler
- func (a *App) MigrationFS() fs.FS
- func (a *App) Name() string
- func (a *App) Register(cfg *burrow.AppConfig) error
- func (a *App) Repo() *Repository
- func (a *App) RequestFuncMap(r *http.Request) template.FuncMap
- func (a *App) Routes(r chi.Router)
- func (a *App) Shutdown(_ context.Context) error
- func (a *App) StaticFS() (string, fs.FS)
- func (a *App) TemplateFS() fs.FS
- func (a *App) TranslationFS() fs.FS
- type Config
- type CreateInviteRequest
- type Credential
- type EmailService
- type EmailVerificationToken
- type Handlers
- func (h *Handlers) AcknowledgeRecoveryCodes(w http.ResponseWriter, r *http.Request) error
- func (h *Handlers) AddCredentialBegin(w http.ResponseWriter, r *http.Request) error
- func (h *Handlers) AddCredentialFinish(w http.ResponseWriter, r *http.Request) error
- func (h *Handlers) CredentialsPage(w http.ResponseWriter, r *http.Request) error
- func (h *Handlers) DeleteCredential(w http.ResponseWriter, r *http.Request) error
- func (h *Handlers) IsInviteOnly() bool
- func (h *Handlers) LoginBegin(w http.ResponseWriter, r *http.Request) error
- func (h *Handlers) LoginFinish(w http.ResponseWriter, r *http.Request) error
- func (h *Handlers) LoginPage(w http.ResponseWriter, r *http.Request) error
- func (h *Handlers) Logout(w http.ResponseWriter, r *http.Request) error
- func (h *Handlers) RecoveryCodesPage(w http.ResponseWriter, r *http.Request) error
- func (h *Handlers) RecoveryLogin(w http.ResponseWriter, r *http.Request) error
- func (h *Handlers) RecoveryPage(w http.ResponseWriter, r *http.Request) error
- func (h *Handlers) RegenerateRecoveryCodes(w http.ResponseWriter, r *http.Request) error
- func (h *Handlers) RegisterBegin(w http.ResponseWriter, r *http.Request) error
- func (h *Handlers) RegisterFinish(w http.ResponseWriter, r *http.Request) error
- func (h *Handlers) RegisterPage(w http.ResponseWriter, r *http.Request) error
- func (h *Handlers) ResendVerification(w http.ResponseWriter, r *http.Request) error
- func (h *Handlers) UseEmailMode() bool
- func (h *Handlers) VerifyEmail(w http.ResponseWriter, r *http.Request) error
- func (h *Handlers) VerifyPendingPage(w http.ResponseWriter, r *http.Request) error
- type Invite
- type Option
- type RecoveryCode
- type RecoveryLoginRequest
- type RecoveryService
- type RegisterBeginRequest
- type Renderer
- type Repository
- func (r *Repository) CountAdminUsers(ctx context.Context) (int, error)
- func (r *Repository) CountUserCredentials(ctx context.Context, userID int64) (int64, error)
- func (r *Repository) CountUsers(ctx context.Context) (int, error)
- func (r *Repository) CreateCredential(ctx context.Context, cred *Credential) error
- func (r *Repository) CreateEmailVerificationToken(ctx context.Context, userID int64, tokenHash string, expiresAt time.Time) error
- func (r *Repository) CreateInvite(ctx context.Context, invite *Invite) error
- func (r *Repository) CreateRecoveryCodes(ctx context.Context, userID int64, codeHashes []string) error
- func (r *Repository) CreateUser(ctx context.Context, username, name string) (*User, error)
- func (r *Repository) CreateUserWithEmail(ctx context.Context, email, name string) (*User, error)
- func (r *Repository) DeleteCredential(ctx context.Context, credID, userID int64) error
- func (r *Repository) DeleteEmailVerificationToken(ctx context.Context, tokenID int64) error
- func (r *Repository) DeleteExpiredEmailVerificationTokens(ctx context.Context) error
- func (r *Repository) DeleteInvite(ctx context.Context, inviteID int64) error
- func (r *Repository) DeleteRecoveryCodes(ctx context.Context, userID int64) error
- func (r *Repository) DeleteUser(ctx context.Context, id int64) error
- func (r *Repository) DeleteUserEmailVerificationTokens(ctx context.Context, userID int64) error
- func (r *Repository) EmailExists(ctx context.Context, email string) (bool, error)
- func (r *Repository) GetCredentialsByUserID(ctx context.Context, userID int64) ([]Credential, error)
- func (r *Repository) GetEmailVerificationToken(ctx context.Context, tokenHash string) (*EmailVerificationToken, error)
- func (r *Repository) GetInviteByTokenHash(ctx context.Context, tokenHash string) (*Invite, error)
- func (r *Repository) GetUnusedRecoveryCodeCount(ctx context.Context, userID int64) (int64, error)
- func (r *Repository) GetUnusedRecoveryCodes(ctx context.Context, userID int64) ([]RecoveryCode, error)
- func (r *Repository) GetUserByEmail(ctx context.Context, email string) (*User, error)
- func (r *Repository) GetUserByID(ctx context.Context, id int64) (*User, error)
- func (r *Repository) GetUserByIDWithCredentials(ctx context.Context, id int64) (*User, error)
- func (r *Repository) GetUserByUsername(ctx context.Context, username string) (*User, error)
- func (r *Repository) HasRecoveryCodes(ctx context.Context, userID int64) (bool, error)
- func (r *Repository) ListInvites(ctx context.Context) ([]Invite, error)
- func (r *Repository) ListUsers(ctx context.Context) ([]User, error)
- func (r *Repository) MarkEmailVerified(ctx context.Context, userID int64) error
- func (r *Repository) MarkInviteUsed(ctx context.Context, inviteID, userID int64) error
- func (r *Repository) MarkRecoveryCodeUsed(ctx context.Context, codeID int64) error
- func (r *Repository) SetUserActive(ctx context.Context, userID int64, active bool) error
- func (r *Repository) SetUserRole(ctx context.Context, userID int64, role string) error
- func (r *Repository) UpdateCredentialSignCount(ctx context.Context, credentialID []byte, signCount uint32) error
- func (r *Repository) UpdateUser(ctx context.Context, user *User) error
- func (r *Repository) UserExists(ctx context.Context, username string) (bool, error)
- func (r *Repository) ValidateAndUseRecoveryCode(ctx context.Context, userID int64, code string) (bool, error)
- type ResendVerificationRequest
- type User
- type WebAuthnService
Constants ¶
const ( RoleUser = "user" RoleAdmin = "admin" )
Role constants.
const ( // TokenLength is the number of random bytes for verification tokens. TokenLength = 32 // TokenExpiry is how long verification tokens are valid. TokenExpiry = 24 * time.Hour // InviteExpiry is how long an invite token is valid. InviteExpiry = 7 * 24 * time.Hour )
const ( // CodeLength is the length of each recovery code (without dashes). CodeLength = 12 // CodeCount is the default number of recovery codes to generate. CodeCount = 8 )
Variables ¶
var ErrNotFound = sql.ErrNoRows
ErrNotFound is returned when a record is not found.
Functions ¶
func DefaultAuthLayout ¶
func DefaultAuthLayout() burrow.LayoutFunc
DefaultAuthLayout returns a minimal HTML layout for unauthenticated auth pages. It renders a clean page with Bootstrap CSS but no navbar or navigation. This is used as the default for auth.New(); pass a custom layout via WithAuthLayout() to override.
func GenerateInviteToken ¶
GenerateInviteToken generates a random invite token and its SHA256 hash.
func GenerateToken ¶
GenerateToken generates a new verification token. Returns (plaintext token, SHA256 hash for storage, expiry time, error).
func IsAdminEditLastAdmin ¶
IsAdminEditLastAdmin reports whether the viewed user is the only remaining admin.
func IsAdminEditSelf ¶
IsAdminEditSelf reports whether the admin is viewing their own user detail page.
func IsAuthenticated ¶
IsAuthenticated returns true if a user is present in the context.
func LogoFromContext ¶
LogoFromContext retrieves the logo HTML from context, or empty if not set.
func NormalizeCode ¶
NormalizeCode removes dashes and converts to lowercase for comparison.
func RequireAdmin ¶
RequireAdmin returns middleware that returns 403 if the user is not an admin.
func RequireAuth ¶
RequireAuth returns middleware that redirects to login if not authenticated. The original request URL is stored in the session as "redirect_after_login" so the user can be redirected back after successful authentication.
func SafeRedirectPath ¶
SafeRedirectPath validates a redirect path, falling back to defaultPath.
func TransportsFromWebAuthn ¶
func TransportsFromWebAuthn(transports []protocol.AuthenticatorTransport) string
TransportsFromWebAuthn converts WebAuthn transports to a comma-separated string.
Types ¶
type App ¶
type App struct {
// contains filtered or unexported fields
}
App implements the auth contrib app.
func New ¶
New creates a new auth app with the given options. By default, the built-in HTML renderer and auth layout are used. Use WithRenderer() and WithAuthLayout() to override.
func (*App) AdminNavItems ¶
AdminNavItems returns navigation items for the admin panel.
func (*App) AdminRoutes ¶
AdminRoutes registers admin routes for user and invite management. The router is expected to already have auth middleware applied.
func (*App) CLICommands ¶
CLICommands returns auth-related CLI subcommands (promote, demote, create-invite).
func (*App) Dependencies ¶
func (*App) MigrationFS ¶
func (*App) Repo ¶
func (a *App) Repo() *Repository
Repo returns the auth repository for external access.
func (*App) RequestFuncMap ¶
RequestFuncMap returns request-scoped template functions for auth state.
func (*App) Shutdown ¶
Shutdown stops the background cleanup goroutine. Safe to call multiple times or if Configure was never called.
func (*App) StaticFS ¶
StaticFS returns the embedded static assets (webauthn.js) under the "auth" prefix.
func (*App) TemplateFS ¶
TemplateFS returns the embedded HTML template files.
func (*App) TranslationFS ¶
TranslationFS returns the embedded translation files for auto-discovery by the i18n app.
type Config ¶
type Config struct {
LoginRedirect string
LogoutRedirect string
BaseURL string
UseEmail bool
RequireVerification bool
InviteOnly bool
}
Config holds auth-specific configuration.
type CreateInviteRequest ¶
CreateInviteRequest is the request body for creating an invite.
type Credential ¶
type Credential struct {
bun.BaseModel `bun:"table:credentials,alias:c"`
DeletedAt time.Time `bun:",soft_delete,nullzero" json:"-"`
CreatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp" json:"created_at"`
AttestationType string `json:"-"`
Transports string `json:"-"`
Name string `bun:",notnull" json:"name"`
CredentialID []byte `bun:",unique,notnull" json:"-"`
PublicKey []byte `bun:",notnull" json:"-"`
AAGUID []byte `json:"-"`
ID int64 `bun:",pk,autoincrement" json:"id"`
UserID int64 `bun:",notnull" json:"user_id"`
SignCount uint32 `bun:",default:0" json:"-"`
BackupState bool `bun:",default:false" json:"-"`
BackupEligible bool `bun:",default:false" json:"-"`
}
Credential stores a WebAuthn credential for a user.
func NewCredentialFromWebAuthn ¶
func NewCredentialFromWebAuthn(userID int64, cred *webauthn.Credential) *Credential
NewCredentialFromWebAuthn creates a Credential from a WebAuthn registration result.
func (*Credential) ToWebAuthn ¶
func (c *Credential) ToWebAuthn() webauthn.Credential
ToWebAuthn converts the stored credential to the WebAuthn library type.
type EmailService ¶
type EmailService interface {
SendVerification(ctx context.Context, toEmail, verifyURL string) error
SendInvite(ctx context.Context, toEmail, inviteURL string) error
}
EmailService defines email operations.
type EmailVerificationToken ¶
type EmailVerificationToken struct {
bun.BaseModel `bun:"table:email_verification_tokens,alias:evt"`
ExpiresAt time.Time `bun:",notnull" json:"expires_at"`
CreatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp" json:"created_at"`
DeletedAt time.Time `bun:",soft_delete,nullzero" json:"-"`
TokenHash string `bun:",unique,notnull" json:"-"`
ID int64 `bun:",pk,autoincrement" json:"id"`
UserID int64 `bun:",notnull" json:"user_id"`
}
EmailVerificationToken stores a hashed token for email verification.
type Handlers ¶
type Handlers struct {
// contains filtered or unexported fields
}
Handlers contains all auth and invite HTTP handlers.
func NewHandlers ¶
func NewHandlers( repo *Repository, wa WebAuthnService, email EmailService, renderer Renderer, config *Config, ) *Handlers
NewHandlers creates a new Handlers instance. email can be nil if email mode is disabled.
func (*Handlers) AcknowledgeRecoveryCodes ¶
AcknowledgeRecoveryCodes clears recovery codes from the session and redirects.
func (*Handlers) AddCredentialBegin ¶
AddCredentialBegin starts the process of adding a new credential.
func (*Handlers) AddCredentialFinish ¶
AddCredentialFinish completes adding a new credential.
func (*Handlers) CredentialsPage ¶
CredentialsPage renders the credentials management page.
func (*Handlers) DeleteCredential ¶
DeleteCredential removes a credential.
func (*Handlers) IsInviteOnly ¶
IsInviteOnly returns true if invite-only registration is enabled.
func (*Handlers) LoginBegin ¶
LoginBegin starts the WebAuthn discoverable login process.
func (*Handlers) LoginFinish ¶
LoginFinish completes the WebAuthn discoverable login.
func (*Handlers) RecoveryCodesPage ¶
RecoveryCodesPage renders the dedicated recovery codes page. Codes are read from the session; if none are present, redirects to login redirect.
func (*Handlers) RecoveryLogin ¶
RecoveryLogin authenticates a user with a recovery code.
func (*Handlers) RecoveryPage ¶
RecoveryPage renders the recovery login page.
func (*Handlers) RegenerateRecoveryCodes ¶
RegenerateRecoveryCodes generates new recovery codes and invalidates old ones. Stores codes in session and returns a redirect to the recovery codes page.
func (*Handlers) RegisterBegin ¶
RegisterBegin starts the WebAuthn registration process.
func (*Handlers) RegisterFinish ¶
RegisterFinish completes the WebAuthn registration process.
func (*Handlers) RegisterPage ¶
RegisterPage renders the registration page.
func (*Handlers) ResendVerification ¶
ResendVerification resends the verification email.
func (*Handlers) UseEmailMode ¶
UseEmailMode returns true if email-based authentication is enabled.
func (*Handlers) VerifyEmail ¶
VerifyEmail handles the email verification link.
func (*Handlers) VerifyPendingPage ¶
VerifyPendingPage renders the "check your email" page.
type Invite ¶
type Invite struct {
bun.BaseModel `bun:"table:invites,alias:inv"`
ExpiresAt time.Time `bun:",notnull" json:"expires_at" form:"-" verbose:"Expires at"`
CreatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp" json:"created_at" form:"-" verbose:"Created at"`
DeletedAt time.Time `bun:",soft_delete,nullzero" json:"-" form:"-"`
UsedAt *time.Time `json:"used_at,omitempty" form:"-"`
UsedBy *int64 `json:"used_by,omitempty" form:"-"`
CreatedBy *int64 `json:"created_by,omitempty" form:"-"`
Email string `bun:",notnull" json:"email" verbose:"Email"`
Label string `bun:",notnull,default:''" json:"label" verbose:"Label"`
TokenHash string `bun:",unique,notnull" json:"-" form:"-"`
ID int64 `bun:",pk,autoincrement" json:"id" verbose:"ID"`
}
Invite represents an invitation to register.
type Option ¶
type Option func(*App)
Option configures the auth app.
func WithAuthLayout ¶
func WithAuthLayout(fn burrow.LayoutFunc) Option
WithAuthLayout sets an optional layout for public (unauthenticated) auth pages. When set, pages like login, register, and recovery use this layout instead of the global app layout. Authenticated routes (credentials, recovery codes) continue to use the global layout.
func WithEmailService ¶
func WithEmailService(e EmailService) Option
WithEmailService sets the email service for the auth app.
func WithLogoComponent ¶
WithLogoComponent sets an optional logo HTML rendered above auth page content. When set, the logo appears on login, register, and recovery pages.
func WithRenderer ¶
WithRenderer sets the page renderer for auth views.
type RecoveryCode ¶
type RecoveryCode struct {
bun.BaseModel `bun:"table:recovery_codes,alias:rc"`
CreatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp" json:"created_at"`
DeletedAt time.Time `bun:",soft_delete,nullzero" json:"-"`
UsedAt *time.Time `json:"used_at,omitempty"`
CodeHash string `bun:",notnull" json:"-"`
ID int64 `bun:",pk,autoincrement" json:"id"`
UserID int64 `bun:",notnull" json:"user_id"`
Used bool `bun:",notnull,default:false" json:"used"`
}
RecoveryCode stores a hashed recovery code for account recovery.
type RecoveryLoginRequest ¶
type RecoveryLoginRequest struct {
Username string `json:"username" form:"username"`
Code string `json:"code" form:"code"`
}
RecoveryLoginRequest is the request body for recovery login.
type RecoveryService ¶
type RecoveryService struct{}
RecoveryService handles recovery code generation.
func NewRecoveryService ¶
func NewRecoveryService() *RecoveryService
NewRecoveryService creates a new recovery service.
func (*RecoveryService) GenerateCodes ¶
func (s *RecoveryService) GenerateCodes(count int) ([]string, []string, error)
GenerateCodes generates recovery codes and their bcrypt hashes. Returns (plaintext codes for display, hashed codes for storage, error).
type RegisterBeginRequest ¶
type RegisterBeginRequest struct {
Username string `json:"username"`
Email string `json:"email"`
Name string `json:"name"`
Invite string `json:"invite"`
}
RegisterBeginRequest is the request body for starting registration.
type Renderer ¶
type Renderer interface {
RegisterPage(w http.ResponseWriter, r *http.Request, useEmail, inviteOnly bool, email, invite string) error
LoginPage(w http.ResponseWriter, r *http.Request, loginRedirect string) error
CredentialsPage(w http.ResponseWriter, r *http.Request, creds []Credential) error
RecoveryPage(w http.ResponseWriter, r *http.Request, loginRedirect string) error
RecoveryCodesPage(w http.ResponseWriter, r *http.Request, codes []string) error
VerifyPendingPage(w http.ResponseWriter, r *http.Request) error
VerifyEmailSuccess(w http.ResponseWriter, r *http.Request) error
VerifyEmailError(w http.ResponseWriter, r *http.Request, errorCode string) error
}
Renderer defines the page rendering interface for auth templates. Projects implement this to provide their own template rendering.
func DefaultRenderer ¶
func DefaultRenderer() Renderer
DefaultRenderer returns the default Renderer that uses the built-in HTML templates. Templates use burrow.RenderTemplate which reads layout from context: if a layout is set, page content is wrapped in it; otherwise bare content is rendered.
type Repository ¶
type Repository struct {
// contains filtered or unexported fields
}
Repository provides data access for auth models.
func NewRepository ¶
func NewRepository(db *bun.DB) *Repository
NewRepository creates a new auth Repository.
func (*Repository) CountAdminUsers ¶
func (r *Repository) CountAdminUsers(ctx context.Context) (int, error)
CountAdminUsers returns the number of users with the admin role.
func (*Repository) CountUserCredentials ¶
CountUserCredentials counts the number of credentials for a user.
func (*Repository) CountUsers ¶
func (r *Repository) CountUsers(ctx context.Context) (int, error)
CountUsers returns the total number of non-deleted users.
func (*Repository) CreateCredential ¶
func (r *Repository) CreateCredential(ctx context.Context, cred *Credential) error
CreateCredential creates a new WebAuthn credential.
func (*Repository) CreateEmailVerificationToken ¶
func (r *Repository) CreateEmailVerificationToken(ctx context.Context, userID int64, tokenHash string, expiresAt time.Time) error
CreateEmailVerificationToken creates a new email verification token.
func (*Repository) CreateInvite ¶
func (r *Repository) CreateInvite(ctx context.Context, invite *Invite) error
CreateInvite creates a new invite record.
func (*Repository) CreateRecoveryCodes ¶
func (r *Repository) CreateRecoveryCodes(ctx context.Context, userID int64, codeHashes []string) error
CreateRecoveryCodes creates recovery codes for a user.
func (*Repository) CreateUser ¶
CreateUser creates a new user with a username and optional name.
func (*Repository) CreateUserWithEmail ¶
CreateUserWithEmail creates a new user with email and optional name.
func (*Repository) DeleteCredential ¶
func (r *Repository) DeleteCredential(ctx context.Context, credID, userID int64) error
DeleteCredential soft-deletes a credential.
func (*Repository) DeleteEmailVerificationToken ¶
func (r *Repository) DeleteEmailVerificationToken(ctx context.Context, tokenID int64) error
DeleteEmailVerificationToken hard-deletes a token.
func (*Repository) DeleteExpiredEmailVerificationTokens ¶
func (r *Repository) DeleteExpiredEmailVerificationTokens(ctx context.Context) error
DeleteExpiredEmailVerificationTokens hard-deletes expired tokens.
func (*Repository) DeleteInvite ¶
func (r *Repository) DeleteInvite(ctx context.Context, inviteID int64) error
DeleteInvite hard-deletes an invite (revoke).
func (*Repository) DeleteRecoveryCodes ¶
func (r *Repository) DeleteRecoveryCodes(ctx context.Context, userID int64) error
DeleteRecoveryCodes hard-deletes all recovery codes for a user.
func (*Repository) DeleteUser ¶
func (r *Repository) DeleteUser(ctx context.Context, id int64) error
DeleteUser soft-deletes a user by ID.
func (*Repository) DeleteUserEmailVerificationTokens ¶
func (r *Repository) DeleteUserEmailVerificationTokens(ctx context.Context, userID int64) error
DeleteUserEmailVerificationTokens hard-deletes all tokens for a user.
func (*Repository) EmailExists ¶
EmailExists checks if a user with the given email exists.
func (*Repository) GetCredentialsByUserID ¶
func (r *Repository) GetCredentialsByUserID(ctx context.Context, userID int64) ([]Credential, error)
GetCredentialsByUserID retrieves all credentials for a user.
func (*Repository) GetEmailVerificationToken ¶
func (r *Repository) GetEmailVerificationToken(ctx context.Context, tokenHash string) (*EmailVerificationToken, error)
GetEmailVerificationToken retrieves a token by hash.
func (*Repository) GetInviteByTokenHash ¶
GetInviteByTokenHash retrieves an invite by its token hash.
func (*Repository) GetUnusedRecoveryCodeCount ¶
GetUnusedRecoveryCodeCount returns the count of unused recovery codes.
func (*Repository) GetUnusedRecoveryCodes ¶
func (r *Repository) GetUnusedRecoveryCodes(ctx context.Context, userID int64) ([]RecoveryCode, error)
GetUnusedRecoveryCodes retrieves unused recovery codes for a user.
func (*Repository) GetUserByEmail ¶
GetUserByEmail retrieves a user by email.
func (*Repository) GetUserByID ¶
GetUserByID retrieves a user by ID.
func (*Repository) GetUserByIDWithCredentials ¶
GetUserByIDWithCredentials retrieves a user by ID with preloaded credentials.
func (*Repository) GetUserByUsername ¶
GetUserByUsername retrieves a user by username.
func (*Repository) HasRecoveryCodes ¶
HasRecoveryCodes checks if a user has any recovery codes.
func (*Repository) ListInvites ¶
func (r *Repository) ListInvites(ctx context.Context) ([]Invite, error)
ListInvites returns all invites ordered by creation date descending.
func (*Repository) ListUsers ¶
func (r *Repository) ListUsers(ctx context.Context) ([]User, error)
ListUsers returns all non-deleted users ordered by ID ascending.
func (*Repository) MarkEmailVerified ¶
func (r *Repository) MarkEmailVerified(ctx context.Context, userID int64) error
MarkEmailVerified marks a user's email as verified.
func (*Repository) MarkInviteUsed ¶
func (r *Repository) MarkInviteUsed(ctx context.Context, inviteID, userID int64) error
MarkInviteUsed marks an invite as used by the given user.
func (*Repository) MarkRecoveryCodeUsed ¶
func (r *Repository) MarkRecoveryCodeUsed(ctx context.Context, codeID int64) error
MarkRecoveryCodeUsed marks a recovery code as used.
func (*Repository) SetUserActive ¶
SetUserActive sets a user's is_active flag.
func (*Repository) SetUserRole ¶
SetUserRole updates a user's role.
func (*Repository) UpdateCredentialSignCount ¶
func (r *Repository) UpdateCredentialSignCount(ctx context.Context, credentialID []byte, signCount uint32) error
UpdateCredentialSignCount updates the sign count for a credential.
func (*Repository) UpdateUser ¶
func (r *Repository) UpdateUser(ctx context.Context, user *User) error
UpdateUser updates a user record.
func (*Repository) UserExists ¶
UserExists checks if a user with the given username exists.
func (*Repository) ValidateAndUseRecoveryCode ¶
func (r *Repository) ValidateAndUseRecoveryCode(ctx context.Context, userID int64, code string) (bool, error)
ValidateAndUseRecoveryCode validates and marks a recovery code as used.
type ResendVerificationRequest ¶
type ResendVerificationRequest struct {
Email string `json:"email" form:"email"`
}
ResendVerificationRequest is the request body for resending verification email.
type User ¶
type User struct {
bun.BaseModel `bun:"table:users,alias:u"`
DeletedAt time.Time `bun:",soft_delete,nullzero" json:"-" form:"-"`
UpdatedAt time.Time `bun:",nullzero" json:"updated_at" form:"-"`
CreatedAt time.Time `bun:",nullzero,notnull,default:current_timestamp" json:"created_at" form:"-" verbose:"Created at"`
EmailVerifiedAt *time.Time `json:"email_verified_at,omitempty" form:"-"`
Email *string `bun:",unique" json:"email,omitempty" form:"-" verbose:"Email"`
Name string `bun:",nullzero" json:"name,omitempty" verbose:"Name"`
Bio string `bun:",nullzero" json:"bio,omitempty"`
Role string `bun:",notnull,default:'user'" json:"role" verbose:"Role"`
Username string `bun:",unique,notnull" json:"username" form:"-" verbose:"Username"`
Credentials []Credential `bun:"rel:has-many,join:id=user_id" json:"credentials,omitempty" form:"-"`
ID int64 `bun:",pk,autoincrement" json:"id" verbose:"ID"`
EmailVerified bool `bun:",notnull,default:false" json:"email_verified" form:"-"`
IsActive bool `bun:",notnull,default:true" json:"is_active" form:"-" verbose:"Active"`
}
User represents an authenticated user with WebAuthn credentials.
func UserFromContext ¶
UserFromContext retrieves the authenticated user from the context.
func (*User) WebAuthnCredentials ¶
func (u *User) WebAuthnCredentials() []webauthn.Credential
WebAuthnCredentials returns the user's WebAuthn credentials.
func (*User) WebAuthnDisplayName ¶
WebAuthnDisplayName returns the display name or falls back to username.
func (*User) WebAuthnID ¶
WebAuthnID returns the user ID as bytes for the WebAuthn protocol.
func (*User) WebAuthnIcon ¶
WebAuthnIcon returns an empty string (deprecated by the spec).
type WebAuthnService ¶
type WebAuthnService interface {
WebAuthn() *gowebauthn.WebAuthn
StoreRegistrationSession(userID int64, data *gowebauthn.SessionData)
GetRegistrationSession(userID int64) (*gowebauthn.SessionData, error)
StoreDiscoverableSession(sessionID string, data *gowebauthn.SessionData)
GetDiscoverableSession(sessionID string) (*gowebauthn.SessionData, error)
}
WebAuthnService defines WebAuthn operations.
func NewWebAuthnService ¶
func NewWebAuthnService(ctx context.Context, rpDisplayName, rpID, rpOrigin string) (WebAuthnService, error)
NewWebAuthnService creates a new WebAuthn service with the given RP configuration. The context controls the lifetime of the background cleanup goroutine.