feat: auth service + security audit fixes + cleanup legacy services
Major changes:
- Add auth-svc: JWT auth, register/login/refresh, password reset
- Add auth UI: modals, pages (/login, /register, /forgot-password)
- Add usage tracking (usage_metrics table, daily limits)
- Add tiered rate limiting (free/pro/business)
- Add LLM usage limits per tier
Security fixes:
- All repos now require userID for Update/Delete operations
- JWT middleware in chat-svc, llm-svc, agent-svc, discover-svc
- ErrNotFound/ErrForbidden errors for proper access control
Cleanup:
- Remove legacy TypeScript services/ directory
- Remove computer-svc (to be reimplemented)
- Remove old deploy/docker configs
New files:
- backend/cmd/auth-svc/main.go
- backend/internal/auth/{types,repository}.go
- backend/internal/usage/{types,repository}.go
- backend/pkg/middleware/{llm_limits,ratelimit_tiered}.go
- backend/webui/src/components/auth/*
- backend/webui/src/app/(auth)/*
Made-with: Cursor
This commit is contained in:
@@ -3,6 +3,7 @@ package main
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
@@ -12,8 +13,11 @@ import (
|
||||
"github.com/gofiber/fiber/v2/middleware/cors"
|
||||
"github.com/gofiber/fiber/v2/middleware/logger"
|
||||
"github.com/gooseek/backend/internal/llm"
|
||||
"github.com/gooseek/backend/internal/usage"
|
||||
"github.com/gooseek/backend/pkg/config"
|
||||
"github.com/gooseek/backend/pkg/middleware"
|
||||
"github.com/gooseek/backend/pkg/ndjson"
|
||||
_ "github.com/lib/pq"
|
||||
)
|
||||
|
||||
type GenerateRequest struct {
|
||||
@@ -36,6 +40,26 @@ func main() {
|
||||
log.Fatal("Failed to load config:", err)
|
||||
}
|
||||
|
||||
var usageRepo *usage.Repository
|
||||
if cfg.DatabaseURL != "" {
|
||||
db, err := sql.Open("postgres", cfg.DatabaseURL)
|
||||
if err != nil {
|
||||
log.Printf("Usage tracking unavailable: %v", err)
|
||||
} else {
|
||||
db.SetMaxOpenConns(5)
|
||||
db.SetMaxIdleConns(2)
|
||||
defer db.Close()
|
||||
|
||||
usageRepo = usage.NewRepository(db)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
if err := usageRepo.RunMigrations(ctx); err != nil {
|
||||
log.Printf("Usage migrations warning: %v", err)
|
||||
}
|
||||
cancel()
|
||||
log.Println("Usage tracking enabled")
|
||||
}
|
||||
}
|
||||
|
||||
app := fiber.New(fiber.Config{
|
||||
StreamRequestBody: true,
|
||||
BodyLimit: 10 * 1024 * 1024,
|
||||
@@ -90,7 +114,20 @@ func main() {
|
||||
})
|
||||
})
|
||||
|
||||
app.Post("/api/v1/generate", func(c *fiber.Ctx) error {
|
||||
llmAPI := app.Group("/api/v1", middleware.JWT(middleware.JWTConfig{
|
||||
Secret: cfg.JWTSecret,
|
||||
AuthSvcURL: cfg.AuthSvcURL,
|
||||
AllowGuest: false,
|
||||
}), middleware.LLMLimits(middleware.LLMLimitsConfig{
|
||||
UsageRepo: usageRepo,
|
||||
}))
|
||||
|
||||
llmAPI.Post("/generate", func(c *fiber.Ctx) error {
|
||||
userID := middleware.GetUserID(c)
|
||||
tier := middleware.GetUserTier(c)
|
||||
if tier == "" {
|
||||
tier = "free"
|
||||
}
|
||||
var req GenerateRequest
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
return c.Status(400).JSON(fiber.Map{"error": "Invalid request body"})
|
||||
@@ -100,6 +137,11 @@ func main() {
|
||||
return c.Status(400).JSON(fiber.Map{"error": "Messages required"})
|
||||
}
|
||||
|
||||
limits := usage.GetLimits(tier)
|
||||
if req.Options.MaxTokens == 0 || req.Options.MaxTokens > limits.MaxTokensPerReq {
|
||||
req.Options.MaxTokens = limits.MaxTokensPerReq
|
||||
}
|
||||
|
||||
client, err := llm.NewClient(llm.ProviderConfig{
|
||||
ProviderID: req.ProviderID,
|
||||
ModelKey: req.ModelKey,
|
||||
@@ -161,11 +203,19 @@ func main() {
|
||||
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
|
||||
if usageRepo != nil {
|
||||
go usageRepo.IncrementLLMUsage(context.Background(), userID, tier, len(response)/4)
|
||||
}
|
||||
|
||||
return c.JSON(fiber.Map{
|
||||
"content": response,
|
||||
})
|
||||
})
|
||||
|
||||
llmAPI.Post("/embed", func(c *fiber.Ctx) error {
|
||||
return c.Status(501).JSON(fiber.Map{"error": "Not implemented"})
|
||||
})
|
||||
|
||||
port := cfg.LLMSvcPort
|
||||
log.Printf("llm-svc listening on :%d", port)
|
||||
log.Fatal(app.Listen(fmt.Sprintf(":%d", port)))
|
||||
|
||||
Reference in New Issue
Block a user