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
195 lines
5.6 KiB
Go
195 lines
5.6 KiB
Go
package config
|
|
|
|
import (
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/joho/godotenv"
|
|
)
|
|
|
|
type Config struct {
|
|
Environment string
|
|
LogLevel string
|
|
|
|
// Service ports
|
|
APIGatewayPort int
|
|
ChatSvcPort int
|
|
AgentSvcPort int
|
|
SearchSvcPort int
|
|
LLMSvcPort int
|
|
ScraperSvcPort int
|
|
AdminSvcPort int
|
|
|
|
// Service URLs
|
|
ChatSvcURL string
|
|
AgentSvcURL string
|
|
SearchSvcURL string
|
|
LLMSvcURL string
|
|
ScraperSvcURL string
|
|
MemorySvcURL string
|
|
LibrarySvcURL string
|
|
AdminSvcURL string
|
|
|
|
// External services
|
|
SearXNGURL string
|
|
SearXNGFallbackURL []string
|
|
Crawl4AIURL string
|
|
RedisURL string
|
|
DatabaseURL string
|
|
DiscoverSvcURL string
|
|
CollectionSvcURL string
|
|
FileSvcURL string
|
|
ThreadSvcURL string
|
|
ComputerSvcURL string
|
|
FinanceHeatmapURL string
|
|
LearningSvcURL string
|
|
|
|
// MinIO / S3 storage
|
|
MinioEndpoint string
|
|
MinioAccessKey string
|
|
MinioSecretKey string
|
|
MinioBucket string
|
|
MinioUseSSL bool
|
|
|
|
// Auth
|
|
JWTSecret string
|
|
AuthSvcURL string
|
|
|
|
// LLM defaults
|
|
DefaultLLMProvider string
|
|
DefaultLLMModel string
|
|
OpenAIAPIKey string
|
|
AnthropicAPIKey string
|
|
GeminiAPIKey string
|
|
|
|
// Timeweb Cloud AI
|
|
TimewebAPIBaseURL string
|
|
TimewebAgentAccessID string
|
|
TimewebAPIKey string
|
|
TimewebProxySource string
|
|
|
|
// Timeouts
|
|
HTTPTimeout time.Duration
|
|
LLMTimeout time.Duration
|
|
ScrapeTimeout time.Duration
|
|
SearchTimeout time.Duration
|
|
|
|
// CORS
|
|
AllowedOrigins []string
|
|
}
|
|
|
|
var cfg *Config
|
|
|
|
func Load() (*Config, error) {
|
|
_ = godotenv.Load()
|
|
_ = godotenv.Load("../.env")
|
|
_ = godotenv.Load("../../.env")
|
|
|
|
cfg = &Config{
|
|
Environment: getEnv("ENVIRONMENT", "production"),
|
|
LogLevel: getEnv("LOG_LEVEL", "info"),
|
|
|
|
APIGatewayPort: getEnvInt("API_GATEWAY_PORT", 3015),
|
|
ChatSvcPort: getEnvInt("CHAT_SVC_PORT", 3005),
|
|
AgentSvcPort: getEnvInt("AGENT_SVC_PORT", 3018),
|
|
SearchSvcPort: getEnvInt("SEARCH_SVC_PORT", 3001),
|
|
LLMSvcPort: getEnvInt("LLM_SVC_PORT", 3020),
|
|
ScraperSvcPort: getEnvInt("SCRAPER_SVC_PORT", 3021),
|
|
AdminSvcPort: getEnvInt("ADMIN_SVC_PORT", 3040),
|
|
|
|
ChatSvcURL: getEnv("CHAT_SVC_URL", "http://localhost:3005"),
|
|
AgentSvcURL: getEnv("MASTER_AGENTS_SVC_URL", "http://localhost:3018"),
|
|
SearchSvcURL: getEnv("SEARCH_SVC_URL", "http://localhost:3001"),
|
|
LLMSvcURL: getEnv("LLM_SVC_URL", "http://localhost:3020"),
|
|
ScraperSvcURL: getEnv("SCRAPER_SVC_URL", "http://localhost:3021"),
|
|
MemorySvcURL: getEnv("MEMORY_SVC_URL", ""),
|
|
LibrarySvcURL: getEnv("LIBRARY_SVC_URL", "http://localhost:3009"),
|
|
AdminSvcURL: getEnv("ADMIN_SVC_URL", "http://localhost:3040"),
|
|
|
|
SearXNGURL: getEnv("SEARXNG_URL", "http://searxng:8080"),
|
|
SearXNGFallbackURL: strings.Split(getEnv("SEARXNG_FALLBACK_URL", ""), ","),
|
|
Crawl4AIURL: getEnv("CRAWL4AI_URL", "http://crawl4ai:11235"),
|
|
RedisURL: getEnv("REDIS_URL", "redis://localhost:6379"),
|
|
DatabaseURL: getEnv("DATABASE_URL", ""),
|
|
DiscoverSvcURL: getEnv("DISCOVER_SVC_URL", "http://localhost:3002"),
|
|
CollectionSvcURL: getEnv("COLLECTION_SVC_URL", "http://localhost:3025"),
|
|
FileSvcURL: getEnv("FILE_SVC_URL", "http://localhost:3026"),
|
|
ThreadSvcURL: getEnv("THREAD_SVC_URL", "http://localhost:3027"),
|
|
ComputerSvcURL: getEnv("COMPUTER_SVC_URL", "http://localhost:3030"),
|
|
FinanceHeatmapURL: getEnv("FINANCE_HEATMAP_SVC_URL", "http://localhost:3033"),
|
|
LearningSvcURL: getEnv("LEARNING_SVC_URL", "http://localhost:3034"),
|
|
|
|
MinioEndpoint: getEnv("MINIO_ENDPOINT", "minio:9000"),
|
|
MinioAccessKey: getEnv("MINIO_ACCESS_KEY", "minioadmin"),
|
|
MinioSecretKey: getEnv("MINIO_SECRET_KEY", "minioadmin"),
|
|
MinioBucket: getEnv("MINIO_BUCKET", "gooseek"),
|
|
MinioUseSSL: getEnv("MINIO_USE_SSL", "false") == "true",
|
|
|
|
JWTSecret: getEnv("JWT_SECRET", ""),
|
|
AuthSvcURL: getEnv("AUTH_SVC_URL", ""),
|
|
|
|
DefaultLLMProvider: getEnv("DEFAULT_LLM_PROVIDER", "openai"),
|
|
DefaultLLMModel: getEnv("DEFAULT_LLM_MODEL", "gpt-4o-mini"),
|
|
OpenAIAPIKey: getEnv("OPENAI_API_KEY", ""),
|
|
AnthropicAPIKey: getEnv("ANTHROPIC_API_KEY", ""),
|
|
GeminiAPIKey: getEnv("GEMINI_API_KEY", ""),
|
|
|
|
TimewebAPIBaseURL: getEnv("TIMEWEB_API_BASE_URL", "https://api.timeweb.cloud"),
|
|
TimewebAgentAccessID: getEnv("TIMEWEB_AGENT_ACCESS_ID", ""),
|
|
TimewebAPIKey: getEnv("TIMEWEB_API_KEY", ""),
|
|
TimewebProxySource: getEnv("TIMEWEB_X_PROXY_SOURCE", "gooseek"),
|
|
|
|
HTTPTimeout: time.Duration(getEnvInt("HTTP_TIMEOUT_MS", 60000)) * time.Millisecond,
|
|
LLMTimeout: time.Duration(getEnvInt("LLM_TIMEOUT_MS", 120000)) * time.Millisecond,
|
|
ScrapeTimeout: time.Duration(getEnvInt("SCRAPE_TIMEOUT_MS", 25000)) * time.Millisecond,
|
|
SearchTimeout: time.Duration(getEnvInt("SEARCH_TIMEOUT_MS", 10000)) * time.Millisecond,
|
|
|
|
AllowedOrigins: parseOrigins(getEnv("ALLOWED_ORIGINS", "*")),
|
|
}
|
|
|
|
return cfg, nil
|
|
}
|
|
|
|
func Get() *Config {
|
|
if cfg == nil {
|
|
cfg, _ = Load()
|
|
}
|
|
return cfg
|
|
}
|
|
|
|
func getEnv(key, defaultValue string) string {
|
|
if value := os.Getenv(key); value != "" {
|
|
return value
|
|
}
|
|
return defaultValue
|
|
}
|
|
|
|
func getEnvInt(key string, defaultValue int) int {
|
|
if value := os.Getenv(key); value != "" {
|
|
if i, err := strconv.Atoi(value); err == nil {
|
|
return i
|
|
}
|
|
}
|
|
return defaultValue
|
|
}
|
|
|
|
func GetEnvInt(key string, defaultValue int) int {
|
|
return getEnvInt(key, defaultValue)
|
|
}
|
|
|
|
func parseOrigins(s string) []string {
|
|
if s == "*" {
|
|
return []string{"*"}
|
|
}
|
|
origins := strings.Split(s, ",")
|
|
result := make([]string, 0, len(origins))
|
|
for _, o := range origins {
|
|
if trimmed := strings.TrimSpace(o); trimmed != "" {
|
|
result = append(result, trimmed)
|
|
}
|
|
}
|
|
return result
|
|
}
|