fix login
This commit is contained in:
parent
b30c1147ea
commit
7dfb4e84f4
@ -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`.
|
**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()`).
|
**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()`).
|
||||||
|
|
||||||
|
|||||||
@ -293,53 +293,59 @@ func main() {
|
|||||||
r.Get(cfg.Metrics.Path, promhttp.Handler().ServeHTTP)
|
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)
|
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.Route("/v1", func(r chi.Router) {
|
||||||
r.Use(middleware.CORS(cfg.Server.AllowedOrigins))
|
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).
|
// Public — CORS applied, no auth required.
|
||||||
piiAnalyzeHandler := pii.NewAnalyzeHandler(piiClient, logger)
|
r.Post("/auth/login", loginHandler.ServeHTTP)
|
||||||
r.Post("/pii/analyze", piiAnalyzeHandler.ServeHTTP)
|
|
||||||
|
|
||||||
// Admin API — routing policies + audit logs (Sprint 5 + Sprint 6)
|
// Protected — JWT auth + tenant rate limit.
|
||||||
// + user management + provider status (Sprint 8).
|
r.Group(func(r chi.Router) {
|
||||||
if routingEngine != nil {
|
r.Use(middleware.Auth(jwtVerifier))
|
||||||
var adminHandler *admin.Handler
|
r.Use(middleware.RateLimit(rateLimiter))
|
||||||
if auditLogger != nil {
|
|
||||||
adminHandler = admin.NewWithAudit(
|
r.Post("/chat/completions", proxyHandler.ServeHTTP)
|
||||||
routing.NewPgStore(db, logger),
|
|
||||||
routingEngine.Cache(),
|
// PII analyze endpoint for Playground (E8-11, Sprint 8).
|
||||||
auditLogger,
|
piiAnalyzeHandler := pii.NewAnalyzeHandler(piiClient, logger)
|
||||||
logger,
|
r.Post("/pii/analyze", piiAnalyzeHandler.ServeHTTP)
|
||||||
)
|
|
||||||
} else {
|
// Admin API — routing policies + audit logs (Sprint 5 + Sprint 6)
|
||||||
adminHandler = admin.New(
|
// + user management + provider status (Sprint 8).
|
||||||
routing.NewPgStore(db, logger),
|
if routingEngine != nil {
|
||||||
routingEngine.Cache(),
|
var adminHandler *admin.Handler
|
||||||
logger,
|
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).
|
// Compliance module — GDPR Art. 30 registry + AI Act classification + PDF reports (Sprint 9).
|
||||||
if db != nil {
|
if db != nil {
|
||||||
compStore := compliance.NewPgStore(db, logger)
|
compStore := compliance.NewPgStore(db, logger)
|
||||||
compHandler := compliance.New(compStore, logger).
|
compHandler := compliance.New(compStore, logger).
|
||||||
WithAudit(auditLogger).
|
WithAudit(auditLogger).
|
||||||
WithDB(db).
|
WithDB(db).
|
||||||
WithTenantName(cfg.Server.TenantName)
|
WithTenantName(cfg.Server.TenantName)
|
||||||
r.Route("/admin/compliance", compHandler.Routes)
|
r.Route("/admin/compliance", compHandler.Routes)
|
||||||
logger.Info("compliance module started")
|
logger.Info("compliance module started")
|
||||||
}
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
// ── HTTP server ───────────────────────────────────────────────────────────
|
// ── HTTP server ───────────────────────────────────────────────────────────
|
||||||
|
|||||||
@ -70,7 +70,7 @@ func (h *LoginHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
var u userInfo
|
var u userInfo
|
||||||
var passwordHash string
|
var passwordHash string
|
||||||
err := h.db.QueryRowContext(r.Context(),
|
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
|
FROM users
|
||||||
WHERE email = $1 AND is_active = TRUE
|
WHERE email = $1 AND is_active = TRUE
|
||||||
LIMIT 1`,
|
LIMIT 1`,
|
||||||
|
|||||||
@ -1,6 +1,9 @@
|
|||||||
-- Migration 000012: Add name column to users table.
|
-- Migration 000012: Add name column to users table.
|
||||||
-- Migration 000001 created users without a name column; migration 000006 used
|
-- 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.
|
-- 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 '';
|
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 = '';
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user