Switch to phone auth via Twilio SMS and add feature flag system
Replace email-based auth (Resend) with phone-based auth (Twilio SMS). Add BBQ_FEATURES env var for toggling features at deploy time — when auth is disabled, no login routes are registered and the app works as before. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -32,21 +32,23 @@ var schemaSQL string
|
||||
var pageTmpl map[string]*template.Template
|
||||
|
||||
type Server struct {
|
||||
q *db.Queries
|
||||
db *sql.DB
|
||||
baseURL string
|
||||
q *db.Queries
|
||||
db *sql.DB
|
||||
baseURL string
|
||||
features Features
|
||||
|
||||
// SSE: map of event slug -> set of channels
|
||||
mu sync.Mutex
|
||||
clients map[string]map[chan struct{}]struct{}
|
||||
}
|
||||
|
||||
func NewServer(database *sql.DB, baseURL string) *Server {
|
||||
func NewServer(database *sql.DB, baseURL string, features Features) *Server {
|
||||
return &Server{
|
||||
q: db.New(database),
|
||||
db: database,
|
||||
baseURL: baseURL,
|
||||
clients: make(map[string]map[chan struct{}]struct{}),
|
||||
q: db.New(database),
|
||||
db: database,
|
||||
baseURL: baseURL,
|
||||
features: features,
|
||||
clients: make(map[string]map[chan struct{}]struct{}),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,6 +95,7 @@ func main() {
|
||||
port = v
|
||||
}
|
||||
baseURL := os.Getenv("BBQ_BASE_URL") // e.g. https://bbq.torrtle.co
|
||||
features := parseFeatures(os.Getenv("BBQ_FEATURES"))
|
||||
|
||||
database, err := sql.Open("sqlite3", dbPath+"?_journal_mode=WAL&_foreign_keys=on")
|
||||
if err != nil {
|
||||
@@ -121,7 +124,7 @@ func main() {
|
||||
// Parse each page with layout + shared partials
|
||||
pageTmpl = make(map[string]*template.Template)
|
||||
shared := []string{"templates/layout.html", "templates/slots.html"}
|
||||
for _, page := range []string{"home", "event"} {
|
||||
for _, page := range []string{"home", "event", "login", "dashboard", "name"} {
|
||||
files := append([]string{"templates/" + page + ".html"}, shared...)
|
||||
pageTmpl[page] = template.Must(
|
||||
template.New("").Funcs(funcMap).ParseFS(templateFS, files...),
|
||||
@@ -132,15 +135,30 @@ func main() {
|
||||
template.New("").Funcs(funcMap).ParseFS(templateFS, "templates/slots.html"),
|
||||
)
|
||||
|
||||
srv := NewServer(database, baseURL)
|
||||
srv := NewServer(database, baseURL, features)
|
||||
|
||||
r := chi.NewRouter()
|
||||
r.Use(middleware.Logger)
|
||||
r.Use(middleware.Recoverer)
|
||||
r.Use(srv.sessionMiddleware)
|
||||
|
||||
// Static files
|
||||
r.Handle("/static/*", http.FileServer(http.FS(staticFS)))
|
||||
|
||||
// Auth (conditional on feature flag)
|
||||
if features.Auth {
|
||||
r.Get("/login", srv.handleLoginPage)
|
||||
r.Post("/login", srv.handleLoginSubmit)
|
||||
r.Post("/login/verify", srv.handleVerifyCode)
|
||||
r.Post("/logout", srv.handleLogout)
|
||||
r.Group(func(r chi.Router) {
|
||||
r.Use(srv.requireAuth)
|
||||
r.Get("/dashboard", srv.handleDashboard)
|
||||
r.Get("/account/name", srv.handleNamePage)
|
||||
r.Post("/account/name", srv.handleNameSubmit)
|
||||
})
|
||||
}
|
||||
|
||||
// Home / create event
|
||||
r.Get("/", srv.handleHome)
|
||||
r.Post("/events", srv.handleCreateEvent)
|
||||
|
||||
Reference in New Issue
Block a user