Files
vibeproxy/internal/database/repo_tokens.go
T
owenandClaude Sonnet 5 ba1f7c4c03 Initial vibeproxy implementation
Self-contained HTTP/HTTPS/TCP/UDP reverse proxy manager written in Go,
with SQLite storage, a Bootstrap 5 admin UI (Go templates, no JS
framework), and a REST API under /api/v1.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QTXFrNP1imCW7jtfL5SZrw
2026-08-17 10:28:59 -05:00

78 lines
2.2 KiB
Go

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
}