login

package
v0.9.0 Latest Latest
Warning

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

Go to latest
Published: May 10, 2026 License: MIT Imports: 25 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrInvalidCredentials = errors.New("invalid email or password")

Functions

func GeneratePassphrase added in v0.8.9

func GeneratePassphrase() string

GeneratePassphrase returns five dash-separated CVCVC pseudo-words drawn from crypto/rand. Each word is 5 chars, total 29 chars; entropy ≈ 5 words × log2(17²·5²·17) ≈ 78 bits — plenty for an initial admin password and easier to read aloud than a bare base32 string.

Example: "tokel-bavri-zenpu-makdo-flite"

func GetUser

func GetUser(ctx context.Context) *entity.User

GetUser retrieves the authenticated user from context. Returns nil if not logged in.

func GetUserTagIDs

func GetUserTagIDs(ctx context.Context) []string

GetUserTagIDs retrieves the filter tag IDs for the authenticated user from context. Populated by the Session middleware from the encrypted cookie.

func SetAfterLoginRedirect added in v0.4.0

func SetAfterLoginRedirect(w http.ResponseWriter, r *http.Request, path string)

SetAfterLoginRedirect stores a path the next successful login should land on, instead of "/". Paths must start with "/" and not "//". Used by /oauth/authorize when the user isn't logged in yet.

func WithUser added in v0.4.0

func WithUser(ctx context.Context, user *entity.User, tagIDs []string) context.Context

WithUser stamps a user + filter-tag-ID set onto the context using the same keys the cookie-session middleware does. Useful for non-cookie auth paths (MCP bearer middleware, OAuth) that need downstream code (`login.GetUser`, `login.GetUserTagIDs`, `Service.CanAccessTool`) to behave identically.

Types

type Handler

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

func NewHandler

func NewHandler(svc *Service, midd *Middleware, ssoSvc *sso.Service, cfg appConfig) *Handler

NewHandler wires the login routes. The handler reads SSO config from the sso.Service on every request so admin edits take effect without a restart.

func (*Handler) Register

func (h *Handler) Register(mux *http.ServeMux, sessionMidd *Middleware)

type Middleware

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

func NewMiddleware

func NewMiddleware(svc *Service, secrets SecretProvider) *Middleware

func (*Middleware) ClearSessionCookie

func (m *Middleware) ClearSessionCookie(w http.ResponseWriter)

ClearSessionCookie wipes the session cookie.

func (*Middleware) RequireAdmin

func (m *Middleware) RequireAdmin(next http.Handler) http.Handler

RequireAdmin returns 403 if the user is not an admin.

func (*Middleware) RequireAuth

func (m *Middleware) RequireAuth(next http.Handler) http.Handler

RequireAuth redirects to /auth/login if there is no authenticated, approved user.

First-login enforcement: admins land on /profile/setup until they rotate the auto-generated password (admin_password_changed=false). The setup form itself + POST endpoint are exempt so the user can actually complete the flow.

func (*Middleware) RequireJobAccess

func (m *Middleware) RequireJobAccess(next http.Handler) http.Handler

RequireJobAccess enforces per-job visibility on /jobs/{key} requests. It reuses the ToolPermission table (stored under "/jobs/{key}") and CanAccessTool logic. Session + RequireAuth must have run first.

func (*Middleware) RequireToolAccess

func (m *Middleware) RequireToolAccess(tools []ToolMeta) func(http.Handler) http.Handler

RequireToolAccess enforces per-tool visibility on requests under /tools/. For each request it finds the tool whose Path is the longest prefix of the request URL, then calls Service.CanAccessTool. Public tools let anyone through; Private tools require an approved login, plus a matching tag when the tool has required tags set. Session must have already populated the user in context.

func (*Middleware) Session

func (m *Middleware) Session(next http.Handler) http.Handler

Session decrypts the AES-GCM session cookie and populates the user and their filter tag IDs into the request context. Tampered or expired cookies are wiped. For guests (no session), it reads the guest theme cookie.

func (*Middleware) SetSessionCookie

func (m *Middleware) SetSessionCookie(w http.ResponseWriter, userID string, tagIDs []string, secure bool)

SetSessionCookie encrypts {userID, tagIDs} with AES-256-GCM and writes the result as an HttpOnly cookie. Callers should fetch filter tag IDs via svc.GetUserFilterTagIDs before calling this.

type SecretProvider

type SecretProvider interface {
	SessionSecret() string
	AdminPasswordChanged() bool
}

SecretProvider is the minimal interface Middleware needs to read the current session-signing secret + first-login state. configs.Service satisfies it.

type Service

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

func NewService

func NewService(db *gorm.DB, adminEmailsCSV string) *Service

func (*Service) BootstrapAdmin

func (s *Service) BootstrapAdmin(ctx context.Context, defaultPassword string, alreadyChanged bool) (generated string)

BootstrapAdmin seeds (or re-seeds) the default admin password while admin_password_changed is still false. Two cases:

  • No admin yet → create one per configured admin email and set the password.
  • Admin exists but flag is false → reset the password (the operator never completed first-login setup, so whatever hash is on disk is either "admin" or another stale auto-generated value the operator no longer has).

Once admin_password_changed=true, this function is a no-op so a live rotated password is never overwritten on boot.

If defaultPassword is empty, a 5-word passphrase is generated and returned so callers can surface it (logs, tray, INITIAL_CREDENTIALS file). The returned password is "" when nothing changed — either setup is already done or the explicit defaultPassword was used (and the caller already knows it from env).

func (*Service) CanAccessTool

func (s *Service) CanAccessTool(ctx context.Context, user *entity.User, toolPath string, defaultVis entity.ToolVisibility) bool

func (*Service) FirstAdmin added in v0.6.4

func (s *Service) FirstAdmin(ctx context.Context) (*entity.User, error)

FirstAdmin returns the oldest admin user, or nil when no admin exists. Stdio MCP uses this to bind its synthetic context to a real admin so wick_enc_ tokens minted from MCP can be decrypted by that admin in the web UI (per-user keys are HKDF-salted with user.ID).

func (*Service) GetUserByID

func (s *Service) GetUserByID(ctx context.Context, id string) (*entity.User, error)

func (*Service) GetUserFilterTagIDs

func (s *Service) GetUserFilterTagIDs(ctx context.Context, userID string) []string

GetUserFilterTagIDs fetches the filter-type tag IDs for a user. Called at login time; the result is embedded in the encrypted session cookie so subsequent requests do not need an extra DB query for tag matching.

func (*Service) LoginWithPassword

func (s *Service) LoginWithPassword(ctx context.Context, email, password string) (*entity.User, error)

func (*Service) SetEmail added in v0.8.9

func (s *Service) SetEmail(ctx context.Context, userID, newEmail string) error

SetEmail updates the user's email address. Used by the first-login setup flow so admins can rename the seed account (admin@admin.com) to a real address. Returns ErrEmailTaken when the new email already belongs to a different user.

func (*Service) SetHomeView

func (s *Service) SetHomeView(ctx context.Context, userID, view string) error

SetHomeView updates the user's home-grid view preference.

func (*Service) SetPassword

func (s *Service) SetPassword(ctx context.Context, userID, currentPassword, newPassword string) error

func (*Service) SetTheme

func (s *Service) SetTheme(ctx context.Context, userID, themeID string) error

SetTheme updates the user's UI theme preference. Empty id means "no preference" and the UI falls back to the device system setting.

func (*Service) UpsertUser

func (s *Service) UpsertUser(ctx context.Context, email, name, avatar string) (*entity.User, error)

type ToolMeta

type ToolMeta struct {
	Path              string
	DefaultVisibility entity.ToolVisibility
}

ToolMeta is the minimal info RequireToolAccess needs about each tool. Declared here so the login package doesn't import ui (avoids a cycle).

Directories

Path Synopsis
templ: version: v0.3.1001
templ: version: v0.3.1001

Jump to

Keyboard shortcuts

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