Revert "updates on the otp updates on the customer app"
This reverts commit 89321c9e06.
This commit is contained in:
108
config/config.go
108
config/config.go
@@ -1,13 +1,7 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"doormile/utils"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
@@ -58,93 +52,25 @@ type Config struct {
|
||||
}
|
||||
|
||||
func Load() *Config {
|
||||
cfg := load()
|
||||
cfg.hardenSecrets()
|
||||
return cfg
|
||||
}
|
||||
|
||||
// IsProduction reports whether this process is running as production. Used by
|
||||
// the guards that must behave differently there — a fixed OTP, a missing JWT
|
||||
// secret — rather than scattering string comparisons.
|
||||
func (c *Config) IsProduction() bool {
|
||||
return strings.EqualFold(strings.TrimSpace(c.Env), "production")
|
||||
}
|
||||
|
||||
// hardenSecrets refuses to let the service run on a guessable signing key.
|
||||
//
|
||||
// JWT_SECRET_KEY used to default to a literal in this file. Anyone holding the
|
||||
// repository could mint a token for any user id and any role, against any
|
||||
// deployment that had not overridden it — which is the whole authorisation
|
||||
// model, given away by a git clone.
|
||||
//
|
||||
// In production an unset secret is fatal: booting with a known key is worse
|
||||
// than not booting, because nothing external shows that anything is wrong.
|
||||
// Anywhere else it becomes a random per-process key, so local development
|
||||
// works without configuration while tokens stop surviving a restart and can
|
||||
// never be valid anywhere but this process.
|
||||
func (c *Config) hardenSecrets() {
|
||||
if strings.TrimSpace(c.JWTSecret) != "" {
|
||||
return
|
||||
}
|
||||
// In production an absent secret is left absent, so Validate can refuse the
|
||||
// boot with a clear message. Generating one here would be worse than the
|
||||
// old default: every restart would invalidate every live session, and
|
||||
// nothing would say why.
|
||||
if c.IsProduction() {
|
||||
return
|
||||
}
|
||||
b := make([]byte, 32)
|
||||
if _, err := rand.Read(b); err != nil {
|
||||
// Leave it empty; Validate turns this into a refusal to start.
|
||||
return
|
||||
}
|
||||
c.JWTSecret = hex.EncodeToString(b)
|
||||
utils.Warn("JWT_SECRET_KEY is not set — generated an ephemeral key for this process only. " +
|
||||
"Tokens will not survive a restart. Set JWT_SECRET_KEY for a stable local session.")
|
||||
}
|
||||
|
||||
// Validate reports configuration that must prevent the service from starting.
|
||||
// Called by main; kept separate from Load so that loading stays free of side
|
||||
// effects and the package remains testable.
|
||||
func (c *Config) Validate() error {
|
||||
if strings.TrimSpace(c.JWTSecret) == "" {
|
||||
return fmt.Errorf("JWT_SECRET_KEY is not set (ENV=%s): refusing to start, because "+
|
||||
"booting on a default or empty signing key lets anyone holding this repository "+
|
||||
"mint a valid token for any account", c.Env)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func load() *Config {
|
||||
return &Config{
|
||||
Env: getEnv("ENV", "development"),
|
||||
Port: getEnv("APP_PORT", "8081"),
|
||||
DBName: getEnv("DB_NAME", "logistics"),
|
||||
DBUser: getEnv("DB_USER", "admin"),
|
||||
DBPassword: getEnv("DB_PASSWORD", ""),
|
||||
DBPort: getEnv("DB_PORT", "5433"),
|
||||
DBHost: getEnv("DB_HOST", "127.0.0.1"),
|
||||
RedisHost: getEnv("REDIS_HOST", "127.0.0.1"),
|
||||
RedisPort: getEnv("REDIS_PORT", "6379"),
|
||||
RedisUser: getEnv("REDIS_USER", ""),
|
||||
RedisPassword: getEnv("REDIS_PASSWORD", ""),
|
||||
// No default. See hardenSecrets below — an unset secret is either a
|
||||
// refusal to boot or an ephemeral per-process key, never a shared one
|
||||
// baked into the source.
|
||||
JWTSecret: getEnv("JWT_SECRET_KEY", ""),
|
||||
Env: getEnv("ENV", "development"),
|
||||
Port: getEnv("APP_PORT", "8081"),
|
||||
DBName: getEnv("DB_NAME", "logistics"),
|
||||
DBUser: getEnv("DB_USER", "admin"),
|
||||
DBPassword: getEnv("DB_PASSWORD", "Package@321#"),
|
||||
DBPort: getEnv("DB_PORT", "5433"),
|
||||
DBHost: getEnv("DB_HOST", "127.0.0.1"),
|
||||
RedisHost: getEnv("REDIS_HOST", "127.0.0.1"),
|
||||
RedisPort: getEnv("REDIS_PORT", "6379"),
|
||||
RedisUser: getEnv("REDIS_USER", ""),
|
||||
RedisPassword: getEnv("REDIS_PASSWORD", ""),
|
||||
JWTSecret: getEnv("JWT_SECRET_KEY", "DoormileSuperSecretJWTKey2026!"),
|
||||
NatsURL: getEnv("NATS_URL", "nats://66.116.226.161:4223"),
|
||||
NatsUser: getEnv("NATS_USER", "doormile"),
|
||||
NatsPassword: getEnv("NATS_PASSWORD", "Package@321#"),
|
||||
AILayerBaseURL: getEnv("AI_LAYER_BASE_URL", "https://routemate.workolik.com"),
|
||||
|
||||
// These defaulted to the real production hosts and credentials, which
|
||||
// meant `go run .` on a laptop silently joined the live NATS stream and
|
||||
// competed with the production workers for the same durable consumer.
|
||||
// Empty now: InitNATS skips connecting, routing.BaseURL == "" disables
|
||||
// sequencing, and the AI layer falls back to legacy scoring. Fail
|
||||
// closed, so reaching production is something you opt into.
|
||||
NatsURL: getEnv("NATS_URL", ""),
|
||||
NatsUser: getEnv("NATS_USER", ""),
|
||||
NatsPassword: getEnv("NATS_PASSWORD", ""),
|
||||
AILayerBaseURL: getEnv("AI_LAYER_BASE_URL", ""),
|
||||
|
||||
RouteOptimizerURL: getEnv("ROUTE_OPTIMIZER_URL", ""),
|
||||
RouteOptimizerURL: getEnv("ROUTE_OPTIMIZER_URL", "https://routes.workolik.com"),
|
||||
GeocoderURL: getEnv("GEOCODER_URL", "https://nominatim.openstreetmap.org"),
|
||||
GeocoderEmail: getEnv("GEOCODER_EMAIL", ""),
|
||||
TrustedProxies: getEnv("TRUSTED_PROXIES", ""),
|
||||
|
||||
Reference in New Issue
Block a user