Files
vibetree/internal/web/app.go
T
Owen f3a959334f Rename project from inventree to vibetree
- go.mod module path (and every internal/vibetree import) inventree -> vibetree
- cmd/inventree/ -> cmd/vibetree/, deploy/inventree.service -> vibetree.service
- Default site name (seed data + the siteName template func's fallback)
  is now "vibetree", shown in the navbar, <title>, and login page
- Session cookie renamed inventree_session -> vibetree_session
- Default DB path data/inventree.db -> data/vibetree.db, CLI/log text,
  Dockerfile, docker-compose.yml, README, .gitignore/.dockerignore all
  updated to match

Existing installs: this changes the session cookie name (users will be
signed out once) and the default DB filename (point -db at your existing
file, or rename it, to keep your data).
2026-08-17 17:14:52 -05:00

92 lines
2.2 KiB
Go

// Package web implements the HTTP server: routing, session middleware,
// template rendering, and all page/API handlers for vibetree.
package web
import (
"context"
"database/sql"
"log/slog"
"net/http"
"time"
"vibetree/internal/assets"
"vibetree/internal/auth"
"vibetree/internal/folders"
"vibetree/internal/itemtypes"
"vibetree/internal/settings"
"vibetree/internal/statuses"
"vibetree/internal/users"
)
// App holds every dependency HTTP handlers need: data stores, templates, and
// server-wide configuration.
type App struct {
DB *sql.DB
Auth *auth.Store
Users *users.Store
Folders *folders.Store
Assets *assets.Store
ItemTypes *itemtypes.Store
Statuses *statuses.Store
Settings *settings.Store
templates *templateSet
Log *slog.Logger
// SecureCookies controls the Secure flag on the session cookie; set
// true when serving over HTTPS.
SecureCookies bool
}
// NewApp wires all stores together from a shared database handle.
func NewApp(db *sql.DB, log *slog.Logger, secureCookies bool) (*App, error) {
userStore := users.NewStore(db)
folderStore := folders.NewStore(db)
settingsStore := settings.NewStore(db)
app := &App{
DB: db,
Users: userStore,
Folders: folderStore,
ItemTypes: itemtypes.NewStore(db),
Statuses: statuses.NewStore(db),
Settings: settingsStore,
Assets: assets.NewStore(db, settingsStore, folderStore),
Auth: auth.NewStore(db, userStore),
Log: log,
SecureCookies: secureCookies,
}
tmpl, err := loadTemplates(app)
if err != nil {
return nil, err
}
app.templates = tmpl
return app, nil
}
// StartSessionJanitor periodically removes expired sessions until ctx (via
// the returned stop channel) signals shutdown.
func (a *App) StartSessionJanitor(stop <-chan struct{}) {
ticker := time.NewTicker(1 * time.Hour)
go func() {
defer ticker.Stop()
for {
select {
case <-ticker.C:
if err := a.Auth.CleanExpired(context.Background()); err != nil {
a.Log.Warn("session cleanup failed", "error", err)
}
case <-stop:
return
}
}
}()
}
func writeErr(w http.ResponseWriter, status int, msg string) {
http.Error(w, msg, status)
}