Replace token-based admin auth with JWT session authentication
CI / test (push) Failing after 12m45s

- Add AdminUser model (bcrypt hashed passwords) and admin_users table
- Add AdminJWTService for HS256 JWT sessions (24h TTL)
- Add AdminSessionAuth middleware for /api/v1/admin/* routes
- Add admin handlers: login, logout, me, change-password, users CRUD
- Keys and model management routes now require admin JWT session
- Remove ADMIN_TOKEN, add ADMIN_USERNAME, ADMIN_PASSWORD env vars
- Update frontend: username/password login, admin_session storage, AdminUsers CRUD view
This commit is contained in:
2026-07-31 17:15:29 -04:00
parent b18d4bd146
commit 4d34c6d31a
21 changed files with 828 additions and 57 deletions
+14 -2
View File
@@ -33,7 +33,10 @@ type Config struct {
RateLimitStorage string // "memory" or "redis"
// Auth
AdminToken string
AdminUsername string
AdminPassword string
JWTSecret []byte
AdminSessionTTL int // seconds
// Logging
LogLevel string
@@ -58,10 +61,19 @@ func Load() *Config {
ModelSwapCooldown: intEnv("MODEL_SWAP_COOLDOWN", 2),
RateLimitPerMinute: intEnv("RATE_LIMIT_PER_MINUTE", 60),
RateLimitStorage: getEnv("RATE_LIMIT_STORAGE", "memory"),
AdminToken: getEnv("ADMIN_TOKEN", "changeme"),
AdminUsername: getEnv("ADMIN_USERNAME", "admin"),
AdminPassword: getEnv("ADMIN_PASSWORD", ""),
AdminSessionTTL: intEnv("ADMIN_SESSION_TTL", 86400),
LogLevel: getEnv("LOG_LEVEL", "info"),
LogFormat: getEnv("LOG_FORMAT", "json"),
}
secretKey := getEnv("LLAMALINK_SECRET_KEY", "change-me-in-production")
if secretKey == "change-me-in-production" {
slog.Warn("LLAMALINK_SECRET_KEY is using the default value — set a secure random string in production")
}
c.JWTSecret = []byte(secretKey)
return c
}