fix login

This commit is contained in:
David 2026-03-10 09:20:38 +01:00
parent b30c1147ea
commit 7dfb4e84f4
5 changed files with 51 additions and 42 deletions

View File

@ -132,7 +132,7 @@ pytest services/pii/tests/test_file.py::test_function
**Config override:** Any config key can be overridden via env var with the `VEYLANT_` prefix and `.``_` replacement. Example: `VEYLANT_SERVER_PORT=9090` overrides `server.port`.
**Auth config:** `auth.jwt_secret` (env: `VEYLANT_AUTH_JWT_SECRET`) and `auth.jwt_ttl_hours`. Login endpoint: `POST /v1/auth/login` (public). Dev credentials: `admin@veylant.dev` / `admin123`. Tokens are HS256-signed JWTs; users stored in `users` table with bcrypt password hashes (migration 000010).
**Auth config:** `auth.jwt_secret` (env: `VEYLANT_AUTH_JWT_SECRET`) and `auth.jwt_ttl_hours`. Login endpoint: `POST /v1/auth/login` — public (no JWT required), CORS applied. Dev credentials: `admin@veylant.dev` / `admin123`. Tokens are HS256-signed JWTs; users stored in `users` table with bcrypt password hashes (migration 000010) and a `name TEXT` column (migration 000012). Login response includes `{token, user: {id, email, name, role, tenant_id, department}}`.
**Provider configs:** LLM provider API keys are stored encrypted (AES-256-GCM) in the `provider_configs` table (migration 000011). CRUD via `GET|POST /v1/admin/providers`, `PUT|DELETE|POST-test /v1/admin/providers/{id}`. Adapters hot-reload on save/update without proxy restart (`router.UpdateAdapter()` / `RemoveAdapter()`).

View File

@ -293,53 +293,59 @@ func main() {
r.Get(cfg.Metrics.Path, promhttp.Handler().ServeHTTP)
}
// Public login endpoint — must be registered before the auth middleware below.
loginHandler := auth.NewLoginHandler(db, cfg.Auth.JWTSecret, cfg.Auth.JWTTTLHours, logger)
r.Post("/v1/auth/login", loginHandler.ServeHTTP)
r.Route("/v1", func(r chi.Router) {
r.Use(middleware.CORS(cfg.Server.AllowedOrigins))
r.Use(middleware.Auth(jwtVerifier))
r.Use(middleware.RateLimit(rateLimiter))
r.Post("/chat/completions", proxyHandler.ServeHTTP)
// PII analyze endpoint for Playground (E8-11, Sprint 8).
piiAnalyzeHandler := pii.NewAnalyzeHandler(piiClient, logger)
r.Post("/pii/analyze", piiAnalyzeHandler.ServeHTTP)
// Public — CORS applied, no auth required.
r.Post("/auth/login", loginHandler.ServeHTTP)
// Admin API — routing policies + audit logs (Sprint 5 + Sprint 6)
// + user management + provider status (Sprint 8).
if routingEngine != nil {
var adminHandler *admin.Handler
if auditLogger != nil {
adminHandler = admin.NewWithAudit(
routing.NewPgStore(db, logger),
routingEngine.Cache(),
auditLogger,
logger,
)
} else {
adminHandler = admin.New(
routing.NewPgStore(db, logger),
routingEngine.Cache(),
logger,
)
// Protected — JWT auth + tenant rate limit.
r.Group(func(r chi.Router) {
r.Use(middleware.Auth(jwtVerifier))
r.Use(middleware.RateLimit(rateLimiter))
r.Post("/chat/completions", proxyHandler.ServeHTTP)
// PII analyze endpoint for Playground (E8-11, Sprint 8).
piiAnalyzeHandler := pii.NewAnalyzeHandler(piiClient, logger)
r.Post("/pii/analyze", piiAnalyzeHandler.ServeHTTP)
// Admin API — routing policies + audit logs (Sprint 5 + Sprint 6)
// + user management + provider status (Sprint 8).
if routingEngine != nil {
var adminHandler *admin.Handler
if auditLogger != nil {
adminHandler = admin.NewWithAudit(
routing.NewPgStore(db, logger),
routingEngine.Cache(),
auditLogger,
logger,
)
} else {
adminHandler = admin.New(
routing.NewPgStore(db, logger),
routingEngine.Cache(),
logger,
)
}
// Wire db, router, rate limiter, feature flags, and encryptor.
adminHandler.WithDB(db).WithRouter(providerRouter).WithRateLimiter(rateLimiter).WithFlagStore(flagStore).WithEncryptor(encryptor)
r.Route("/admin", adminHandler.Routes)
}
// Wire db, router, rate limiter, feature flags, and encryptor.
adminHandler.WithDB(db).WithRouter(providerRouter).WithRateLimiter(rateLimiter).WithFlagStore(flagStore).WithEncryptor(encryptor)
r.Route("/admin", adminHandler.Routes)
}
// Compliance module — GDPR Art. 30 registry + AI Act classification + PDF reports (Sprint 9).
if db != nil {
compStore := compliance.NewPgStore(db, logger)
compHandler := compliance.New(compStore, logger).
WithAudit(auditLogger).
WithDB(db).
WithTenantName(cfg.Server.TenantName)
r.Route("/admin/compliance", compHandler.Routes)
logger.Info("compliance module started")
}
// Compliance module — GDPR Art. 30 registry + AI Act classification + PDF reports (Sprint 9).
if db != nil {
compStore := compliance.NewPgStore(db, logger)
compHandler := compliance.New(compStore, logger).
WithAudit(auditLogger).
WithDB(db).
WithTenantName(cfg.Server.TenantName)
r.Route("/admin/compliance", compHandler.Routes)
logger.Info("compliance module started")
}
})
})
// ── HTTP server ───────────────────────────────────────────────────────────

View File

@ -70,7 +70,7 @@ func (h *LoginHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
var u userInfo
var passwordHash string
err := h.db.QueryRowContext(r.Context(),
`SELECT id, tenant_id, email, email, role, COALESCE(department,''), password_hash
`SELECT id, tenant_id, email, COALESCE(name,''), role, COALESCE(department,''), password_hash
FROM users
WHERE email = $1 AND is_active = TRUE
LIMIT 1`,

View File

@ -1,6 +1,9 @@
-- Migration 000012: Add name column to users table.
-- Migration 000001 created users without a name column; migration 000006 used
-- CREATE TABLE IF NOT EXISTS which was a no-op since the table already existed.
-- This migration adds the missing column retroactively.
-- This migration adds the missing column retroactively and seeds existing users.
ALTER TABLE users ADD COLUMN IF NOT EXISTS name TEXT NOT NULL DEFAULT '';
-- Seed name for the dev admin user created in migration 000001.
UPDATE users SET name = 'Admin Veylant' WHERE email = 'admin@veylant.dev' AND name = '';

BIN
proxy

Binary file not shown.