package database import ( "database/sql" "errors" "github.com/owen/vibeproxy/internal/models" ) func CreateAPIToken(db *sql.DB, name, tokenHash, prefix string) (int64, error) { res, err := db.Exec(`INSERT INTO api_tokens (name, token_hash, prefix) VALUES (?, ?, ?)`, name, tokenHash, prefix) if err != nil { return 0, err } return res.LastInsertId() } func ListAPITokens(db *sql.DB) ([]models.APIToken, error) { rows, err := db.Query(`SELECT id, name, token_hash, prefix, created_at, last_used_at, revoked_at FROM api_tokens ORDER BY id DESC`) if err != nil { return nil, err } defer rows.Close() var out []models.APIToken for rows.Next() { var t models.APIToken var created string var lastUsed, revoked sql.NullString if err := rows.Scan(&t.ID, &t.Name, &t.TokenHash, &t.Prefix, &created, &lastUsed, &revoked); err != nil { return nil, err } t.CreatedAt = parseTime(created) if lastUsed.Valid { tt := parseTime(lastUsed.String) t.LastUsedAt = &tt } if revoked.Valid { tt := parseTime(revoked.String) t.RevokedAt = &tt } out = append(out, t) } return out, rows.Err() } func GetAPITokenByHash(db *sql.DB, hash string) (*models.APIToken, error) { row := db.QueryRow(`SELECT id, name, token_hash, prefix, created_at, last_used_at, revoked_at FROM api_tokens WHERE token_hash = ?`, hash) var t models.APIToken var created string var lastUsed, revoked sql.NullString if err := row.Scan(&t.ID, &t.Name, &t.TokenHash, &t.Prefix, &created, &lastUsed, &revoked); err != nil { if errors.Is(err, sql.ErrNoRows) { return nil, ErrNotFound } return nil, err } t.CreatedAt = parseTime(created) if lastUsed.Valid { tt := parseTime(lastUsed.String) t.LastUsedAt = &tt } if revoked.Valid { tt := parseTime(revoked.String) t.RevokedAt = &tt } return &t, nil } func TouchAPIToken(db *sql.DB, id int64) error { _, err := db.Exec(`UPDATE api_tokens SET last_used_at = strftime('%Y-%m-%dT%H:%M:%fZ','now') WHERE id = ?`, id) return err } func RevokeAPIToken(db *sql.DB, id int64) error { _, err := db.Exec(`UPDATE api_tokens SET revoked_at = strftime('%Y-%m-%dT%H:%M:%fZ','now') WHERE id = ? AND revoked_at IS NULL`, id) return err }