Files
bbq/migrate.go
T
ryan 4915af0665 Fix login on legacy DBs: drop NOT NULL phone/email from verification_codes
Old prod DBs had verification_codes.phone (or email) as NOT NULL with no
default, so inserting a code via identifier-only failed silently — users
received an emailed code that was never stored, and verify always said
"Invalid or expired code." Drop the legacy columns in a migration and
stop swallowing the CreateVerificationCode error.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 19:07:18 -04:00

51 lines
2.0 KiB
Go

package main
import (
"database/sql"
"log"
"strings"
)
func runMigrations(database *sql.DB) {
migrations := []string{
`ALTER TABLE events ADD COLUMN description TEXT DEFAULT ''`,
`ALTER TABLE events ADD COLUMN user_id INTEGER REFERENCES users(id)`,
// Users may have email, phone, or both. Add whichever column is missing.
`ALTER TABLE users ADD COLUMN phone TEXT UNIQUE`,
`ALTER TABLE users ADD COLUMN email TEXT UNIQUE`,
// Verification codes use a generic identifier column.
`ALTER TABLE verification_codes ADD COLUMN identifier TEXT NOT NULL DEFAULT ''`,
// Indexes for auth tables (created here so they run after column migrations).
`CREATE INDEX IF NOT EXISTS idx_sessions_user ON sessions(user_id)`,
`CREATE INDEX IF NOT EXISTS idx_verification_codes_identifier ON verification_codes(identifier)`,
// Dedupe RSVPs: keep earliest per (event_id, name).
`DELETE FROM rsvps WHERE id NOT IN (SELECT MIN(id) FROM rsvps GROUP BY event_id, name COLLATE NOCASE)`,
// Plus-one tracking for RSVPs.
`ALTER TABLE rsvps ADD COLUMN plus_one INTEGER NOT NULL DEFAULT 0`,
// Drop legacy phone/email columns from verification_codes. They were
// NOT NULL with no default, so inserts using only identifier failed.
`DROP INDEX IF EXISTS idx_verification_codes_phone`,
`DROP INDEX IF EXISTS idx_verification_codes_email`,
`ALTER TABLE verification_codes DROP COLUMN phone`,
`ALTER TABLE verification_codes DROP COLUMN email`,
// SMS consent logging for Twilio compliance.
`CREATE TABLE IF NOT EXISTS sms_consents (
id INTEGER PRIMARY KEY AUTOINCREMENT,
phone TEXT NOT NULL,
ip_address TEXT NOT NULL DEFAULT '',
user_agent TEXT NOT NULL DEFAULT '',
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
)`,
}
for _, m := range migrations {
_, err := database.Exec(m)
if err != nil {
if strings.Contains(err.Error(), "duplicate column name") ||
strings.Contains(err.Error(), "no such column") {
continue
}
log.Printf("migration warning: %v", err)
}
}
}