add auth
This commit is contained in:
+56
-19
@@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/joho/godotenv"
|
||||
)
|
||||
@@ -28,33 +29,46 @@ type Config struct {
|
||||
// DragonflyDB / Redis
|
||||
RedisURI string
|
||||
|
||||
// AWS S3
|
||||
S3Region string
|
||||
S3Bucket string
|
||||
S3AccessKey string
|
||||
S3SecretKey string
|
||||
S3Endpoint string // optional — for S3-compatible services (MinIO, etc.)
|
||||
// Cloudflare R2 (S3-compatible) — for avatar uploads via presigned URLs.
|
||||
R2AccountID string
|
||||
R2AccessKeyID string
|
||||
R2SecretAccessKey string
|
||||
R2Bucket string
|
||||
R2PublicURL string // Public base URL for objects, e.g. https://cdn.example.com or the R2 public bucket URL
|
||||
|
||||
// Push Notifications
|
||||
FCMCredentialsFile string // path to Firebase service account JSON
|
||||
APNsKeyFile string // path to APNs auth key
|
||||
// SMTP — used for password-reset and email-verification mails.
|
||||
SMTPHost string
|
||||
SMTPPort int
|
||||
SMTPUsername string
|
||||
SMTPPassword string
|
||||
SMTPFrom string // "Prabhupāda Says <noreply@prabhupadasays.org>"
|
||||
|
||||
// Push Notifications (existing — unchanged).
|
||||
FCMCredentialsFile string
|
||||
APNsKeyFile string
|
||||
APNsKeyID string
|
||||
APNsTeamID string
|
||||
APNsBundleID string
|
||||
|
||||
// JWT Auth
|
||||
JWTSecret string
|
||||
JWTExpiration string // e.g., "24h"
|
||||
JWTExpiration time.Duration // parsed at load time
|
||||
CookieDomain string // empty in dev; ".prabhupadasays.org" in prod
|
||||
CookieSecure bool // true in production
|
||||
|
||||
// Frontend
|
||||
FrontendURL string // for CORS
|
||||
FrontendURL string // for CORS + reset/verify links in emails
|
||||
}
|
||||
|
||||
// Load reads configuration from environment variables (with .env fallback).
|
||||
func Load() (*Config, error) {
|
||||
// Load .env file if present (ignored in production)
|
||||
_ = godotenv.Load()
|
||||
|
||||
jwtExp, err := time.ParseDuration(getEnv("JWT_EXPIRATION", "168h"))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid JWT_EXPIRATION: %w", err)
|
||||
}
|
||||
|
||||
cfg := &Config{
|
||||
Env: getEnv("APP_ENV", "development"),
|
||||
Port: getEnvInt("PORT", 8080),
|
||||
@@ -69,11 +83,17 @@ func Load() (*Config, error) {
|
||||
|
||||
RedisURI: getEnv("REDIS_URI", "redis://localhost:6379"),
|
||||
|
||||
S3Region: getEnv("S3_REGION", ""),
|
||||
S3Bucket: getEnv("S3_BUCKET", ""),
|
||||
S3AccessKey: getEnv("S3_ACCESS_KEY", ""),
|
||||
S3SecretKey: getEnv("S3_SECRET_KEY", ""),
|
||||
S3Endpoint: getEnv("S3_ENDPOINT", ""),
|
||||
R2AccountID: getEnv("R2_ACCOUNT_ID", ""),
|
||||
R2AccessKeyID: getEnv("R2_ACCESS_KEY_ID", ""),
|
||||
R2SecretAccessKey: getEnv("R2_SECRET_ACCESS_KEY", ""),
|
||||
R2Bucket: getEnv("R2_BUCKET", ""),
|
||||
R2PublicURL: getEnv("R2_PUBLIC_URL", ""),
|
||||
|
||||
SMTPHost: getEnv("SMTP_HOST", ""),
|
||||
SMTPPort: getEnvInt("SMTP_PORT", 587),
|
||||
SMTPUsername: getEnv("SMTP_USERNAME", ""),
|
||||
SMTPPassword: getEnv("SMTP_PASSWORD", ""),
|
||||
SMTPFrom: getEnv("SMTP_FROM", "noreply@localhost"),
|
||||
|
||||
FCMCredentialsFile: getEnv("FCM_CREDENTIALS_FILE", ""),
|
||||
APNsKeyFile: getEnv("APNS_KEY_FILE", ""),
|
||||
@@ -82,15 +102,23 @@ func Load() (*Config, error) {
|
||||
APNsBundleID: getEnv("APNS_BUNDLE_ID", ""),
|
||||
|
||||
JWTSecret: getEnv("JWT_SECRET", ""),
|
||||
JWTExpiration: getEnv("JWT_EXPIRATION", "24h"),
|
||||
JWTExpiration: jwtExp,
|
||||
CookieDomain: getEnv("COOKIE_DOMAIN", ""),
|
||||
CookieSecure: getEnvBool("COOKIE_SECURE", false),
|
||||
|
||||
FrontendURL: getEnv("FRONTEND_URL", "http://localhost:3000"),
|
||||
}
|
||||
|
||||
// Validate required fields
|
||||
if cfg.MongoURI == "" {
|
||||
return nil, fmt.Errorf("MONGO_URI is required")
|
||||
}
|
||||
if cfg.Env == "production" && cfg.JWTSecret == "" {
|
||||
return nil, fmt.Errorf("JWT_SECRET is required in production")
|
||||
}
|
||||
if cfg.JWTSecret == "" {
|
||||
// Dev fallback so the server can boot without secrets configured.
|
||||
cfg.JWTSecret = "dev-only-jwt-secret-do-not-use-in-production"
|
||||
}
|
||||
|
||||
return cfg, nil
|
||||
}
|
||||
@@ -110,3 +138,12 @@ func getEnvInt(key string, fallback int) int {
|
||||
}
|
||||
return fallback
|
||||
}
|
||||
|
||||
func getEnvBool(key string, fallback bool) bool {
|
||||
if v := os.Getenv(key); v != "" {
|
||||
if b, err := strconv.ParseBool(v); err == nil {
|
||||
return b
|
||||
}
|
||||
}
|
||||
return fallback
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user