all repos

onasty @ 9f4dd4b

a one-time notes service

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package config

import (
	"errors"
	"os"
	"strconv"
	"strings"
	"time"
)

type Config struct {
	AppEnv  string
	AppURL  string
	NatsURL string

	CORSAllowedOrigins []string
	CORSMaxAge         time.Duration

	HTTPPort            int
	HTTPWriteTimeout    time.Duration
	HTTPReadTimeout     time.Duration
	HTTPHeaderMaxSizeMb int

	PostgresDSN      string
	PasswordSalt     string
	NotePasswordSalt string

	RedisAddr     string
	RedisPassword string
	RedisDB       int

	CacheUsersTTL time.Duration
	CacheNoteTTL  time.Duration

	JwtSigningKey      string
	JwtAccessTokenTTL  time.Duration
	JwtRefreshTokenTTL time.Duration

	GoogleClientID    string
	GoogleSecret      string
	GoogleRedirectURL string

	GitHubClientID    string
	GitHubSecret      string
	GitHubRedirectURL string

	VerificationTokenTTL  time.Duration
	ResetPasswordTokenTTL time.Duration

	MetricsEnabled bool
	MetricsPort    int

	LogLevel    string
	LogFormat   string
	LogShowLine bool

	RateLimiterRPS   int
	RateLimiterBurst int
	RateLimiterTTL   time.Duration
}

func NewConfig() *Config {
	return &Config{
		AppEnv:  getenvOrDefault("APP_ENV", "debug"),
		AppURL:  getenvOrDefault("APP_URL", ""),
		NatsURL: getenvOrDefault("NATS_URL", ""),

		CORSAllowedOrigins: strings.Split(getenvOrDefault("CORS_ALLOWED_ORIGINS", "*"), ","),
		CORSMaxAge:         mustParseDuration(getenvOrDefault("CORS_MAX_AGE", "12h")),

		HTTPPort:            mustGetenvOrDefaultInt("HTTP_PORT", 3000),
		HTTPWriteTimeout:    mustParseDuration(getenvOrDefault("HTTP_WRITE_TIMEOUT", "10s")),
		HTTPReadTimeout:     mustParseDuration(getenvOrDefault("HTTP_READ_TIMEOUT", "10s")),
		HTTPHeaderMaxSizeMb: mustGetenvOrDefaultInt("HTTP_HEADER_MAX_SIZE_MB", 1),

		PostgresDSN:      getenvOrDefault("POSTGRESQL_DSN", ""),
		PasswordSalt:     getenvOrDefault("PASSWORD_SALT", ""),
		NotePasswordSalt: getenvOrDefault("NOTE_PASSWORD_SALT", ""),

		RedisAddr:     getenvOrDefault("REDIS_ADDR", ""),
		RedisPassword: getenvOrDefault("REDIS_PASSWORD", ""),
		RedisDB:       mustGetenvOrDefaultInt(getenvOrDefault("REDIS_DB", "0"), 0),

		CacheUsersTTL: mustParseDuration(getenvOrDefault("CACHE_USERS_TTL", "1h")),
		CacheNoteTTL:  mustParseDuration(getenvOrDefault("CACHE_NOTE_TTL", "1h")),

		JwtSigningKey: getenvOrDefault("JWT_SIGNING_KEY", ""),
		JwtAccessTokenTTL: mustParseDuration(
			getenvOrDefault("JWT_ACCESS_TOKEN_TTL", "15m"),
		),
		JwtRefreshTokenTTL: mustParseDuration(
			getenvOrDefault("JWT_REFRESH_TOKEN_TTL", "24h"),
		),

		GoogleClientID:    getenvOrDefault("GOOGLE_CLIENTID", ""),
		GoogleSecret:      getenvOrDefault("GOOGLE_SECRET", ""),
		GoogleRedirectURL: getenvOrDefault("GOOGLE_REDIRECTURL", ""),

		GitHubClientID:    getenvOrDefault("GITHUB_CLIENTID", ""),
		GitHubSecret:      getenvOrDefault("GITHUB_SECRET", ""),
		GitHubRedirectURL: getenvOrDefault("GITHUB_REDIRECTURL", ""),

		VerificationTokenTTL:  mustParseDuration(getenvOrDefault("VERIFICATION_TOKEN_TTL", "24h")),
		ResetPasswordTokenTTL: mustParseDuration(getenvOrDefault("RESET_PASSWORD_TOKEN_TTL", "1h")),

		MetricsPort:    mustGetenvOrDefaultInt("METRICS_PORT", 3001),
		MetricsEnabled: getenvOrDefault("METRICS_ENABLED", "true") == "true",

		LogLevel:    getenvOrDefault("LOG_LEVEL", "debug"),
		LogFormat:   getenvOrDefault("LOG_FORMAT", "json"),
		LogShowLine: getenvOrDefault("LOG_SHOW_LINE", "true") == "true",

		RateLimiterRPS:   mustGetenvOrDefaultInt("RATELIMITER_RPS", 100),
		RateLimiterBurst: mustGetenvOrDefaultInt("RATELIMITER_BURST", 10),
		RateLimiterTTL:   mustParseDuration(getenvOrDefault("RATELIMITER_TTL", "1m")),
	}
}

func (c *Config) IsDevMode() bool {
	return c.AppEnv == "debug" || c.AppEnv == "test"
}

func getenvOrDefault(key, def string) string {
	if v, ok := os.LookupEnv(key); ok {
		return v
	}
	return def
}

func mustGetenvOrDefaultInt(key string, def int) int {
	if v, ok := os.LookupEnv(key); ok {
		r, err := strconv.Atoi(v)
		if err != nil {
			panic(err)
		}
		return r
	}
	return def
}

func mustParseDuration(dur string) time.Duration {
	d, err := time.ParseDuration(dur)
	if err != nil {
		panic(errors.Join(errors.New("cannot time.ParseDuration"), err)) //nolint:err113
	}

	return d
}