Documentation
¶
Overview ¶
Package auth owns login state: the encrypted session cookie, the route guards, password reset tokens and the login and password endpoints.
Index ¶
- Variables
- func Current(c echo.Context) (user.User, bool)
- func PasswordProblems(pw string) string
- type Config
- type CurrentUser
- type Handlers
- type LoginInput
- type LoginResponse
- type LoginResult
- type PasswordConfig
- type PasswordInput
- type Permissions
- type RedisConfig
- type ResetInput
- type Service
- func (s *Service) ChangePassword(ctx context.Context, u user.User, oldPassword, newPassword, confirm string) (user.User, error)
- func (s *Service) CheckResetToken(ctx context.Context, token string) error
- func (s *Service) Login(ctx context.Context, email, password, ip string) (LoginResult, error)
- func (s *Service) ResetPassword(ctx context.Context, token, newPassword, confirm string) error
- type Sessions
- func (s *Sessions) CookieStore() *sessions.CookieStore
- func (s *Sessions) Guards() web.Guards
- func (s *Sessions) Identify(next echo.HandlerFunc) echo.HandlerFunc
- func (s *Sessions) Login(w http.ResponseWriter, r *http.Request, u user.User, remember bool) error
- func (s *Sessions) Logout(w http.ResponseWriter, r *http.Request) error
- func (s *Sessions) Name() string
- func (s *Sessions) Refresh(w http.ResponseWriter, r *http.Request, u user.User) error
- func (s *Sessions) RequireLogin(next echo.HandlerFunc) echo.HandlerFunc
- func (s *Sessions) RequireRole(allowed func(role.Role) bool) echo.MiddlewareFunc
- func (s *Sessions) User(r *http.Request) (user.User, bool)
- type Tokens
- type UserGetter
- type UserStore
Constants ¶
This section is empty.
Variables ¶
var ErrInvalidCredentials = errors.New("invalid email or password")
ErrInvalidCredentials is returned for any failed login, without saying why.
var ErrTooManyAttempts = errors.New("too many sign-in attempts; try again in 15 minutes")
ErrTooManyAttempts is returned while sign-in is throttled.
Functions ¶
func PasswordProblems ¶
PasswordProblems describes what a new password is missing ("" when it is acceptable). Rules match legacy minRequirementsMet, including its "longer than 8 characters" length rule.
Types ¶
type Config ¶
Config configures the session cookie. Keys are hex encoded; an empty or invalid (non-hex) key falls back to a random one (sessions then reset on restart, exactly as today). A valid-hex key of an unexpected length (e.g. a truncated AuthenticationKey) is still used as-is — production keeps using its existing keys — but a startup warning is logged naming the weak key.
type CurrentUser ¶
type CurrentUser struct {
ID int `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
Phone string `json:"phone,omitempty"`
Role string `json:"role"`
TeamID int `json:"teamId,omitempty"`
ImageURL string `json:"imageUrl,omitempty"`
Permissions Permissions `json:"permissions"`
}
CurrentUser is the logged-in user as the API exposes it.
func NewCurrentUser ¶
func NewCurrentUser(u user.User, files *upload.Files) CurrentUser
NewCurrentUser projects u for the API; it never includes password data.
type Handlers ¶
type Handlers struct {
// contains filtered or unexported fields
}
Handlers serves the /auth endpoints.
func NewHandlers ¶
type LoginInput ¶
type LoginInput struct {
Email string `json:"email"`
Password string `json:"password"`
Remember bool `json:"remember"`
}
LoginInput is the body of POST /auth/login.
type LoginResponse ¶
type LoginResponse struct {
User *CurrentUser `json:"user,omitempty"`
ResetRequired bool `json:"resetRequired"`
ResetURL string `json:"resetUrl,omitempty"`
}
LoginResponse is either the logged-in user or a reset instruction.
type LoginResult ¶
LoginResult is a successful credential check. When ResetRequired is set no session should be created; the user must visit ResetURL.
type PasswordConfig ¶
type PasswordConfig struct {
Iterations int
ScryptWorkFactor int
ScryptBlockSize int
ScryptParallelismFactor int
KeyLength int
}
PasswordConfig holds the password hashing parameters (legacy PBKDF2 iterations plus scrypt parameters), loaded from the environment.
type PasswordInput ¶
type PasswordInput struct {
OldPassword string `json:"oldPassword"`
NewPassword string `json:"newPassword"`
ConfirmationPassword string `json:"confirmationPassword"`
}
PasswordInput is the body of POST /auth/password.
type Permissions ¶
type Permissions struct {
CanEdit bool `json:"canEdit"`
CanManageGallery bool `json:"canManageGallery"`
CanManagePlayers bool `json:"canManagePlayers"`
CanManageUsers bool `json:"canManageUsers"`
}
Permissions tells the client which admin controls to show. The server still enforces every rule with guards.
type RedisConfig ¶
type RedisConfig struct {
Addresses []string
MasterName string
Username string
Password string
DB int
TLS bool
// KeyPrefix namespaces keys per environment, e.g. "afc:prod:". Defaults to "afc:".
KeyPrefix string
}
RedisConfig configures the optional Redis/Valkey used to share reset tokens across instances. With no Addresses an in-process cache is used, which only works for a single instance.
type ResetInput ¶
type ResetInput struct {
NewPassword string `json:"newPassword"`
ConfirmationPassword string `json:"confirmationPassword"`
}
ResetInput is the body of POST /auth/reset/{token}.
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service handles logins and password changes.
func NewService ¶
func NewService(users UserStore, tokens *Tokens, passwords PasswordConfig) *Service
func (*Service) ChangePassword ¶
func (s *Service) ChangePassword(ctx context.Context, u user.User, oldPassword, newPassword, confirm string) (user.User, error)
ChangePassword changes the logged-in user's password after re-checking the old one. The change signs the user out everywhere, so it returns the user as they now are, for the caller to start a fresh session with.
func (*Service) CheckResetToken ¶
CheckResetToken reports NotFound for an unknown or expired token.
type Sessions ¶
type Sessions struct {
// contains filtered or unexported fields
}
Sessions reads and writes the session cookie.
func NewSessions ¶
func NewSessions(conf Config, users UserGetter) *Sessions
func (*Sessions) CookieStore ¶
func (s *Sessions) CookieStore() *sessions.CookieStore
CookieStore exposes the underlying store (tests decode the cookie with it).
func (*Sessions) Identify ¶
func (s *Sessions) Identify(next echo.HandlerFunc) echo.HandlerFunc
Identify loads the user when a valid session is present, but lets anonymous (or stale-session) requests through.
func (*Sessions) Refresh ¶
Refresh reissues the current session for u (e.g. after the user changed their own password, which bumps their session version), keeping its "remember me" length.
func (*Sessions) RequireLogin ¶
func (s *Sessions) RequireLogin(next echo.HandlerFunc) echo.HandlerFunc
RequireLogin rejects anonymous requests with 401. It reloads the user from the database so role changes and deletions take effect immediately.
func (*Sessions) RequireRole ¶
RequireRole rejects anonymous requests with 401 and users whose role fails allowed with 403.
type Tokens ¶
type Tokens struct {
// contains filtered or unexported fields
}
Tokens stores one-time password reset tokens.
func NewTokens ¶
func NewTokens(conf RedisConfig) *Tokens
type UserGetter ¶
UserGetter loads a user from the database (satisfied by *user.Store).
type UserStore ¶
type UserStore interface {
GetUser(ctx context.Context, userParam user.User) (user.User, error)
VerifyUser(ctx context.Context, userParam user.User, iter, workFactor, blockSize, parallelismFactor, keyLen int) (user.User, bool, error)
EditUserPassword(ctx context.Context, userParam user.User, workFactor, blockSize, parallelismFactor, keyLen int) error
}
UserStore is the credential side of the user store (satisfied by *user.Store).