all repos

onasty @ e771742

a one-time notes service

onasty/internal/config/config.go (view raw)

Olexandr Smirnov Olexandr Smirnov
ss2316544@gmail.com
docs: add missing code comments (#185)..., 9 months ago
1
package config
2
3
import (
4
	"errors"
5
	"os"
6
	"strconv"
7
	"strings"
8
	"time"
9
)
10
11
// Environment represents current app environment.
12
type Environment string
13
14
func (e Environment) IsDevMode() bool {
15
	return e == "debug" || e == "test"
16
}
17
18
type Config struct {
19
	AppEnv  Environment
20
	AppURL  string
21
	NatsURL string
22
23
	CORSAllowedOrigins []string
24
	CORSMaxAge         time.Duration
25
26
	HTTPPort            int
27
	HTTPWriteTimeout    time.Duration
28
	HTTPReadTimeout     time.Duration
29
	HTTPHeaderMaxSizeMb int
30
31
	PostgresDSN      string
32
	PasswordSalt     string
33
	NotePasswordSalt string
34
35
	RedisAddr     string
36
	RedisPassword string
37
	RedisDB       int
38
39
	CacheUsersTTL time.Duration
40
	CacheNoteTTL  time.Duration
41
42
	JwtSigningKey      string
43
	JwtAccessTokenTTL  time.Duration
44
	JwtRefreshTokenTTL time.Duration
45
46
	GoogleClientID    string
47
	GoogleSecret      string
48
	GoogleRedirectURL string
49
50
	GitHubClientID    string
51
	GitHubSecret      string
52
	GitHubRedirectURL string
53
54
	VerificationTokenTTL  time.Duration
55
	ResetPasswordTokenTTL time.Duration
56
57
	MetricsEnabled bool
58
	MetricsPort    int
59
60
	LogLevel    string
61
	LogFormat   string
62
	LogShowLine bool
63
64
	RateLimiterRPS       int
65
	RateLimiterBurst     int
66
	RateLimiterTTL       time.Duration
67
	SlowRateLimiterRPS   int
68
	SlowRateLimiterBurst int
69
	SlowRateLimiterTTL   time.Duration
70
}
71
72
func NewConfig() *Config {
73
	return &Config{
74
		AppEnv:  Environment(getenvOrDefault("APP_ENV", "debug")),
75
		AppURL:  getenvOrDefault("APP_URL", ""),
76
		NatsURL: getenvOrDefault("NATS_URL", ""),
77
78
		CORSAllowedOrigins: strings.Split(getenvOrDefault("CORS_ALLOWED_ORIGINS", "*"), ","),
79
		CORSMaxAge:         mustParseDuration(getenvOrDefault("CORS_MAX_AGE", "12h")),
80
81
		HTTPPort:            mustGetenvOrDefaultInt("HTTP_PORT", 3000),
82
		HTTPWriteTimeout:    mustParseDuration(getenvOrDefault("HTTP_WRITE_TIMEOUT", "10s")),
83
		HTTPReadTimeout:     mustParseDuration(getenvOrDefault("HTTP_READ_TIMEOUT", "10s")),
84
		HTTPHeaderMaxSizeMb: mustGetenvOrDefaultInt("HTTP_HEADER_MAX_SIZE_MB", 1),
85
86
		PostgresDSN:      getenvOrDefault("POSTGRESQL_DSN", ""),
87
		PasswordSalt:     getenvOrDefault("PASSWORD_SALT", ""),
88
		NotePasswordSalt: getenvOrDefault("NOTE_PASSWORD_SALT", ""),
89
90
		RedisAddr:     getenvOrDefault("REDIS_ADDR", ""),
91
		RedisPassword: getenvOrDefault("REDIS_PASSWORD", ""),
92
		RedisDB:       mustGetenvOrDefaultInt(getenvOrDefault("REDIS_DB", "0"), 0),
93
94
		CacheUsersTTL: mustParseDuration(getenvOrDefault("CACHE_USERS_TTL", "1h")),
95
		CacheNoteTTL:  mustParseDuration(getenvOrDefault("CACHE_NOTE_TTL", "1h")),
96
97
		JwtSigningKey: getenvOrDefault("JWT_SIGNING_KEY", ""),
98
		JwtAccessTokenTTL: mustParseDuration(
99
			getenvOrDefault("JWT_ACCESS_TOKEN_TTL", "15m"),
100
		),
101
		JwtRefreshTokenTTL: mustParseDuration(
102
			getenvOrDefault("JWT_REFRESH_TOKEN_TTL", "24h"),
103
		),
104
105
		GoogleClientID:    getenvOrDefault("GOOGLE_CLIENTID", ""),
106
		GoogleSecret:      getenvOrDefault("GOOGLE_SECRET", ""),
107
		GoogleRedirectURL: getenvOrDefault("GOOGLE_REDIRECTURL", ""),
108
109
		GitHubClientID:    getenvOrDefault("GITHUB_CLIENTID", ""),
110
		GitHubSecret:      getenvOrDefault("GITHUB_SECRET", ""),
111
		GitHubRedirectURL: getenvOrDefault("GITHUB_REDIRECTURL", ""),
112
113
		VerificationTokenTTL:  mustParseDuration(getenvOrDefault("VERIFICATION_TOKEN_TTL", "24h")),
114
		ResetPasswordTokenTTL: mustParseDuration(getenvOrDefault("RESET_PASSWORD_TOKEN_TTL", "1h")),
115
116
		MetricsPort:    mustGetenvOrDefaultInt("METRICS_PORT", 3001),
117
		MetricsEnabled: getenvOrDefault("METRICS_ENABLED", "true") == "true",
118
119
		LogLevel:    getenvOrDefault("LOG_LEVEL", "debug"),
120
		LogFormat:   getenvOrDefault("LOG_FORMAT", "json"),
121
		LogShowLine: getenvOrDefault("LOG_SHOW_LINE", "true") == "true",
122
123
		RateLimiterRPS:       mustGetenvOrDefaultInt("RATELIMITER_RPS", 100),
124
		RateLimiterBurst:     mustGetenvOrDefaultInt("RATELIMITER_BURST", 10),
125
		RateLimiterTTL:       mustParseDuration(getenvOrDefault("RATELIMITER_TTL", "1m")),
126
		SlowRateLimiterRPS:   mustGetenvOrDefaultInt("SLOW_RATELIMITER_RPS", 2),
127
		SlowRateLimiterBurst: mustGetenvOrDefaultInt("SLOW_RATELIMITER_BURST", 2),
128
		SlowRateLimiterTTL:   mustParseDuration(getenvOrDefault("SLOW_RATELIMITER_TTL", "1m")),
129
	}
130
}
131
132
func getenvOrDefault(key, def string) string {
133
	if v, ok := os.LookupEnv(key); ok {
134
		return v
135
	}
136
	return def
137
}
138
139
func mustGetenvOrDefaultInt(key string, def int) int {
140
	if v, ok := os.LookupEnv(key); ok {
141
		r, err := strconv.Atoi(v)
142
		if err != nil {
143
			panic(err)
144
		}
145
		return r
146
	}
147
	return def
148
}
149
150
func mustParseDuration(dur string) time.Duration {
151
	d, err := time.ParseDuration(dur)
152
	if err != nil {
153
		panic(errors.Join(errors.New("cannot time.ParseDuration"), err)) //nolint:err113
154
	}
155
156
	return d
157
}