session

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: May 10, 2026 License: AGPL-3.0 Imports: 9 Imported by: 0

Documentation

Overview

Package session owns the cookie-based session pipeline. S02 ships the AEAD-encrypted cookie store; the Store interface lets later sprints add a server-side store for revocation without touching handlers.

Index

Constants

View Source
const CookieName = "_shithub_session"

CookieName is the canonical session cookie name. Prefixed with an underscore so it doesn't collide with any future user-controllable name.

View Source
const DefaultMaxAge = 30 * 24 * time.Hour

DefaultMaxAge is the default cookie lifetime.

Variables

View Source
var (
	ErrInvalidKey = errors.New("session: invalid key size")
)

Sentinel errors callers may check for.

Functions

func GenerateKey

func GenerateKey() ([]byte, error)

GenerateKey returns a new random 32-byte key suitable for NewCookieStore. Used by the operator's first-run setup; production keys come from config.

Types

type CookieStore

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

CookieStore is the AEAD-encrypted-cookie implementation.

func NewCookieStore

func NewCookieStore(cfg CookieStoreConfig) (*CookieStore, error)

NewCookieStore constructs a store. Returns an error if the key is wrong size — this is a configuration error and must surface at startup.

func (*CookieStore) Clear

func (c *CookieStore) Clear(w http.ResponseWriter)

Clear deletes the session cookie.

func (*CookieStore) Load

func (c *CookieStore) Load(r *http.Request) (*Session, error)

Load returns the session bound to the cookie, or a fresh empty session when none is present or the cookie is invalid (expired / wrong key / tampered). Errors are surfaced for malformed input but a missing or invalid cookie yields an empty session, not an error — the caller can proceed with anonymous handling.

func (*CookieStore) Save

Save serializes, encrypts, and sets the session cookie.

type CookieStoreConfig

type CookieStoreConfig struct {
	Key      []byte
	MaxAge   time.Duration
	Secure   bool
	Domain   string
	Path     string
	SameSite http.SameSite
}

CookieStoreConfig holds the ergonomic options. Key MUST be 32 bytes.

type Session

type Session struct {
	UserID       int64 `json:"uid,omitempty"`
	Pre2FAUserID int64 `json:"p2,omitempty"` // set after password OK, before TOTP step
	Recent2FAAt  int64 `json:"r2,omitempty"` // unix-seconds of last successful 2FA challenge
	// Epoch is the users.session_epoch value at issue time. The session
	// loader compares it against the current DB value on every request;
	// "log out everywhere" bumps the column, invalidating every cookie
	// that still carries the old epoch. Zero is the unbumped baseline
	// and matches the migration's column default.
	Epoch     int32             `json:"e,omitempty"`
	CSRFToken string            `json:"csrf,omitempty"`
	Theme     string            `json:"theme,omitempty"`
	Flashes   []string          `json:"flashes,omitempty"`
	Extras    map[string]string `json:"extras,omitempty"`
	IssuedAt  int64             `json:"iat,omitempty"`
	// ImpersonatedUserID — when non-zero, the admin (UserID above) is
	// currently viewing as this user. ImpersonateWriteOK gates writes
	// (defaults false; admin opts in via the typed-name confirm step
	// in /admin/impersonate). ImpersonationStartedAt drives the
	// inactivity timeout (S34: 1 hour idle).
	ImpersonatedUserID     int64 `json:"imp,omitempty"`
	ImpersonateWriteOK     bool  `json:"impw,omitempty"`
	ImpersonationStartedAt int64 `json:"impt,omitempty"`
}

Session is the data carried in a cookie. The shape is intentionally small; anything that doesn't fit a few hundred bytes belongs server-side.

func (*Session) AddFlash

func (s *Session) AddFlash(msg string)

AddFlash appends a flash message; it'll be rendered + cleared on the next page load.

func (*Session) IsAnonymous

func (s *Session) IsAnonymous() bool

IsAnonymous returns true when no user is bound to the session.

func (*Session) PopFlashes

func (s *Session) PopFlashes() []string

PopFlashes returns and clears any pending flash messages.

type Store

type Store interface {
	Load(r *http.Request) (*Session, error)
	Save(w http.ResponseWriter, r *http.Request, s *Session) error
	Clear(w http.ResponseWriter)
}

Store is the abstraction every handler uses. The cookie implementation stores everything client-side; future implementations may persist server-side rows for revocation.

Jump to

Keyboard shortcuts

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