initial commit

This commit is contained in:
m.zare
2026-04-10 18:25:21 +03:30
commit 77ca6c34a3
263 changed files with 34470 additions and 0 deletions

View File

@@ -0,0 +1,6 @@
package config
// AzureBlobStorageConfig holds configuration for Azure Blob Storage
type AzureBlobStorageConfig struct {
BlobEndpoint string `mapstructure:"blob_endpoint"` // e.g. https://account.blob.core.windows.net - base URL for asset/avatar URLs
}

View File

@@ -0,0 +1,8 @@
package config
type AzureCommunicationConfig struct {
Endpoint string
AccessKey string
ApiVersion string
SenderAddress string
}

View File

@@ -0,0 +1,16 @@
package config
// AzureServiceBusConfig holds configuration for Azure Service Bus
type AzureServiceBusConfig struct {
// ConnectionString is the Azure Service Bus connection string
// If provided, this will be used for authentication
ConnectionString string
// Namespace is the Azure Service Bus namespace
// Required when using managed identity authentication
Namespace string
// UseManagedIdentity determines whether to use managed identity for authentication
// If true, managed identity will be used instead of connection string
UseManagedIdentity bool
}

508
config/config.go Normal file
View File

@@ -0,0 +1,508 @@
package config
import (
"errors"
"fmt"
"strings"
"time"
"github.com/rs/zerolog"
"github.com/spf13/viper"
)
// AppConfig contains the application configuration
type AppConfig struct {
Env string
// Server configuration
Port int
// Application configuration
Name string
Environment string
VendorLockTimeOut int
Database DatabaseConfig
Redis RedisConfig
Server ServerConfig
RabbitMQ RabbitMQConfig
Syslog SyslogConfig
Metrics MetricsConfig
AzureCommunicationConfig AzureCommunicationConfig
AzureBlobStorage AzureBlobStorageConfig
AzureServiceBus AzureServiceBusConfig
PgDatabaseConfig PgDatabaseConfig
JWT JWTConfig
OAuth OAuthConfig
}
// PrintConfig logs the current configuration
func PrintConfig(logger zerolog.Logger, config *AppConfig) {
logger.
Info().
Str("port", config.Server.WebPort).
Str("name", config.Name).
Str("environment", config.Environment).
Msg("Application configuration")
}
// NewConfig creates a new configuration from environment variables or config file
func NewConfig() (*AppConfig, error) {
viper.SetConfigName("config")
viper.SetConfigType("yaml")
viper.AddConfigPath(".")
viper.AddConfigPath("./config")
// Enable automatic environment variable binding
viper.AutomaticEnv()
// Set environment variable prefix and replace dots with underscores
viper.SetEnvPrefix("base")
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
// Set defaults
viper.SetDefault("environment", "local")
viper.SetDefault("name", "base")
viper.SetDefault("debug", true)
viper.SetDefault("port", 8080)
viper.SetDefault("vendor_lock_time_out", 5)
// Database defaults
viper.SetDefault("database.host", "localhost")
viper.SetDefault("database.port", "3306")
viper.SetDefault("database.user", "base")
viper.SetDefault("database.password", "base123")
viper.SetDefault("database.name", "base")
viper.SetDefault("database.max_idle_conns", 10)
viper.SetDefault("database.max_open_conns", 20)
viper.SetDefault("database.conn_max_idle_time", "2m")
viper.SetDefault("database.conn_max_lifetime", "9m")
viper.SetDefault("database.ro_user", "base")
viper.SetDefault("database.ro_password", "base123")
viper.SetDefault("database.ro_max_idle_conns", 10)
viper.SetDefault("database.ro_max_open_conns", 20)
// PgDatabase defaults
viper.SetDefault("pg_database.host", "localhost")
viper.SetDefault("pg_database.port", 5430)
viper.SetDefault("pg_database.user", "alinmeuser")
viper.SetDefault("pg_database.password", "password")
viper.SetDefault("pg_database.name", "alinmedb")
viper.SetDefault("pg_database.ssl_mode", "disable")
viper.SetDefault("pg_database.connection_timeout", 1*time.Minute)
viper.SetDefault("pg_database.query_timeout", 60*time.Second)
viper.SetDefault("pg_database.pool_config.max_conn", 20)
viper.SetDefault("pg_database.pool_config.min_conn", 5)
viper.SetDefault("pg_database.pool_config.max_conn_lifetime", 5*time.Minute)
viper.SetDefault("pg_database.pool_config.max_conn_idle_time", 30*time.Minute)
viper.SetDefault("pg_database.migrations.enabled", true)
viper.SetDefault("pg_database.migrations.dir", "./database/migrations")
// Redis defaults
viper.SetDefault("redis.host", "localhost")
viper.SetDefault("redis.port", "6379")
viper.SetDefault("redis.password", "")
viper.SetDefault("redis.database", 0)
viper.SetDefault("redis.url", "")
// Server defaults
viper.SetDefault("server.host", "localhost")
viper.SetDefault("server.port", "8080")
viper.SetDefault("rpc.host", "0.0.0.0")
viper.SetDefault("rpc.port", "8102")
viper.SetDefault("web.host", "localhost")
viper.SetDefault("web.port", "8101")
viper.SetDefault("server.max_file_size_mb", 10) // Default 10MB file size limit
viper.SetDefault("server.cleanup_queues", false) // Default to false for production safety
// JWT defaults
viper.SetDefault("jwt.secret", "default-secret-key-change-in-production")
viper.SetDefault("jwt.access_token_expiration", "24h")
viper.SetDefault("jwt.refresh_token_expiration", "168h") // 7 days
// OAuth defaults
viper.SetDefault("oauth.google.client_id", "")
viper.SetDefault("oauth.google.client_secret", "")
viper.SetDefault("oauth.google.redirect_url", "")
viper.SetDefault("oauth.google.scopes", []string{"openid", "profile", "email"})
viper.SetDefault("oauth.github.client_id", "")
viper.SetDefault("oauth.github.client_secret", "")
viper.SetDefault("oauth.github.redirect_url", "")
viper.SetDefault("oauth.github.scopes", []string{"user:email"})
viper.SetDefault("oauth.linkedin.client_id", "")
viper.SetDefault("oauth.linkedin.client_secret", "")
viper.SetDefault("oauth.linkedin.redirect_url", "")
viper.SetDefault("oauth.linkedin.scopes", []string{"r_liteprofile", "r_emailaddress"})
viper.SetDefault("oauth.mock.enabled", false)
viper.SetDefault("oauth.mock.base_url", "http://localhost:9999")
viper.SetDefault("oauth.mock.client_id", "mock-client")
viper.SetDefault("oauth.mock.client_secret", "mock-secret")
viper.SetDefault("oauth.mock.redirect_url", "http://localhost:3000/auth/callback")
// RabbitMQ defaults
viper.SetDefault("rabbitmq.host", "localhost")
viper.SetDefault("rabbitmq.port", "5678")
viper.SetDefault("rabbitmq.user", "root")
viper.SetDefault("rabbitmq.password", "root")
viper.SetDefault("rabbitmq.vhost", "/")
viper.SetDefault("rabbitmq.exchange", "base_exchange")
viper.SetDefault("rabbitmq.internal_exchange", "base_internal_exchange")
viper.SetDefault("rabbitmq.max_channels", "1")
viper.SetDefault("rabbitmq.max_retry_attempts", 3)
viper.SetDefault("rabbitmq.prefetch_count", 5)
viper.SetDefault("rabbitmq.retry_ttl", "10s")
// BarcodeMapping defaults
viper.SetDefault("barcodemapping.host", "localhost")
viper.SetDefault("barcodemapping.port", "8081")
viper.SetDefault("barcodemapping.cache", false)
viper.SetDefault("barcodemapping.prefix", "barcodemapping")
viper.SetDefault("barcodemapping.ttl", "5m")
// Discount defaults
viper.SetDefault("discount.url", "http://localhost")
viper.SetDefault("discount.port", 8082)
viper.SetDefault("discount.cache", false)
viper.SetDefault("discount.prefix", "discount")
viper.SetDefault("discount.ttl", "30s")
// Syslog defaults
viper.SetDefault("syslog.host", "localhost")
viper.SetDefault("syslog.port", "1514")
viper.SetDefault("syslog.protocol", "udp")
viper.SetDefault("syslog.log_level", "INFO")
// Auth defaults
viper.SetDefault("vendorauth.url", "")
viper.SetDefault("vendorauth.client_id", "base")
viper.SetDefault("vendorauth.client_secret", "")
viper.SetDefault("vendorauth.cache", false)
viper.SetDefault("vendorauth.prefix", "vendorauth")
viper.SetDefault("vendorauth.ttl", "5m")
viper.SetDefault("authshield.url", "http://chart-shield.auth-shield.svc.cluster.local/auth-shield/authorize")
viper.SetDefault("authshield.cache", false)
viper.SetDefault("authshield.prefix", "authshield")
viper.SetDefault("authshield.ttl", "5m")
// Metrics defaults
viper.SetDefault("metrics.enabled", true)
viper.SetDefault("metrics.service_name", "base")
viper.SetDefault("metrics.path", "/metrics")
viper.SetDefault("metrics.port", "8080")
// Bind environment variables explicitly for better control
bindEnvVars()
// Try to read config file, but don't fail if it doesn't exist
if err := viper.ReadInConfig(); err != nil {
var configFileNotFoundError viper.ConfigFileNotFoundError
if errors.As(err, &configFileNotFoundError) {
fmt.Println("Config file not found, using environment variables and defaults")
} else {
return nil, fmt.Errorf("failed to read config file: %w", err)
}
}
config := &AppConfig{
Name: viper.GetString("name"),
Environment: viper.GetString("environment"),
Port: viper.GetInt("port"),
VendorLockTimeOut: viper.GetInt("vendor_lock_time_out"),
RabbitMQ: RabbitMQConfig{
Host: viper.GetString("rabbitmq.host"),
Port: viper.GetInt("rabbitmq.port"),
User: viper.GetString("rabbitmq.user"),
Password: viper.GetString("rabbitmq.password"),
VHost: viper.GetString("rabbitmq.vhost"),
MaxConnections: viper.GetInt("rabbitmq.max_connections"),
MaxChannels: viper.GetInt("rabbitmq.max_channels"),
ConnectionTimeout: viper.GetDuration("rabbitmq.connection_timeout"),
HeartbeatInterval: viper.GetDuration("rabbitmq.heartbeat_interval"),
ReconnectDelay: viper.GetDuration("rabbitmq.reconnect_delay"),
MaxReconnectDelay: viper.GetDuration("rabbitmq.max_reconnect_delay"),
ReconnectAttempts: viper.GetInt("rabbitmq.reconnect_attempts"),
EnableAutoReconnect: viper.GetBool("rabbitmq.enable_auto_reconnect"),
LogLevel: viper.GetString("rabbitmq.log_level"),
MaxRetryAttempts: viper.GetInt("rabbitmq.max_retry_attempts"),
PrefetchCount: viper.GetInt("rabbitmq.prefetch_count"),
RetryTTL: viper.GetDuration("rabbitmq.retry_ttl"),
},
Database: DatabaseConfig{
User: viper.GetString("database.user"),
Password: viper.GetString("database.password"),
Host: viper.GetString("database.host"),
Port: viper.GetString("database.port"),
Name: viper.GetString("database.name"),
MaxIdleConns: viper.GetInt("database.max_idle_conns"),
MaxOpenConns: viper.GetInt("database.max_open_conns"),
ConnMaxIdleTime: viper.GetString("database.conn_max_idle_time"),
ConnMaxLifetime: viper.GetString("database.conn_max_lifetime"),
},
Redis: RedisConfig{
Host: viper.GetString("redis.host"),
Port: viper.GetString("redis.port"),
Password: viper.GetString("redis.password"),
Database: viper.GetInt("redis.database"),
URL: viper.GetString("redis.url"),
},
Server: ServerConfig{
Domain: viper.GetString("server.host"),
HTTPPort: viper.GetString("server.port"),
GRPCPort: viper.GetString("server.port"),
RPCHost: viper.GetString("rpc.host"),
RPCPort: viper.GetString("rpc.port"),
WebHost: viper.GetString("web.host"),
WebPort: viper.GetString("web.port"),
MaxFileSizeMB: viper.GetInt("server.max_file_size_mb"),
CleanupQueues: viper.GetBool("server.cleanup_queues"),
JWTSecret: viper.GetString("server.jwt_secret"),
},
Syslog: SyslogConfig{
Host: viper.GetString("syslog.host"),
Port: viper.GetString("syslog.port"),
Protocol: viper.GetString("syslog.protocol"),
LogLevel: viper.GetString("syslog.log_level"),
},
Metrics: MetricsConfig{
Enabled: viper.GetBool("metrics.enabled"),
ServiceName: viper.GetString("metrics.service_name"),
Path: viper.GetString("metrics.path"),
Port: viper.GetString("metrics.port"),
},
AzureCommunicationConfig: AzureCommunicationConfig{
Endpoint: GetStringOrDefault("email.endpoint", ""),
AccessKey: GetStringOrDefault("email.access_key", ""),
ApiVersion: GetStringOrDefault("email.api_version", "2025-03-01"),
SenderAddress: GetStringOrDefault("email.sender_address", "no-reply@alinme.com"),
},
AzureBlobStorage: AzureBlobStorageConfig{
BlobEndpoint: GetStringOrDefault("azure_blob_storage.blob_endpoint", "https://alinmestorage.blob.core.windows.net"),
},
PgDatabaseConfig: PgDatabaseConfig{
Host: viper.GetString("pg_database.host"),
Port: viper.GetInt("pg_database.port"),
User: viper.GetString("pg_database.user"),
Password: viper.GetString("pg_database.password"),
Name: viper.GetString("pg_database.name"),
SSLMode: viper.GetString("pg_database.ssl_mode"),
ConnectionTimeout: viper.GetDuration("pg_database.connection_timeout"),
QueryTimeout: viper.GetDuration("pg_database.query_timeout"),
PoolConfig: PgPoolConfig{
MaxConn: viper.GetInt32("pg_database.pool_config.max_conn"),
MinConn: viper.GetInt32("pg_database.pool_config.min_conn"),
MaxConnLifetime: viper.GetDuration("pg_database.pool_config.max_conn_lifetime"),
MaxConnIdleTime: viper.GetDuration("pg_database.pool_config.max_conn_idle_time"),
},
Migrations: MigrationsConfig{
Enabled: viper.GetBool("pg_database.migrations.enabled"),
Dir: viper.GetString("pg_database.migrations.dir"),
},
},
JWT: func() JWTConfig {
// Use jwt.secret if set, otherwise fall back to server.jwt_secret for backward compatibility
secret := viper.GetString("jwt.secret")
if secret == "" || secret == "default-secret-key-change-in-production" {
if serverSecret := viper.GetString("server.jwt_secret"); serverSecret != "" {
secret = serverSecret
}
}
return JWTConfig{
Secret: secret,
AccessTokenExpiration: viper.GetDuration("jwt.access_token_expiration"),
RefreshTokenExpiration: viper.GetDuration("jwt.refresh_token_expiration"),
}
}(),
OAuth: OAuthConfig{
Google: OAuthProviderConfig{
ClientID: viper.GetString("oauth.google.client_id"),
ClientSecret: viper.GetString("oauth.google.client_secret"),
RedirectURL: viper.GetString("oauth.google.redirect_url"),
Scopes: viper.GetStringSlice("oauth.google.scopes"),
},
GitHub: OAuthProviderConfig{
ClientID: viper.GetString("oauth.github.client_id"),
ClientSecret: viper.GetString("oauth.github.client_secret"),
RedirectURL: viper.GetString("oauth.github.redirect_url"),
Scopes: viper.GetStringSlice("oauth.github.scopes"),
},
LinkedIn: OAuthProviderConfig{
ClientID: viper.GetString("oauth.linkedin.client_id"),
ClientSecret: viper.GetString("oauth.linkedin.client_secret"),
RedirectURL: viper.GetString("oauth.linkedin.redirect_url"),
Scopes: viper.GetStringSlice("oauth.linkedin.scopes"),
},
Mock: OAuthMockConfig{
Enabled: viper.GetBool("oauth.mock.enabled"),
BaseURL: viper.GetString("oauth.mock.base_url"),
OAuthProviderConfig: OAuthProviderConfig{
ClientID: viper.GetString("oauth.mock.client_id"),
ClientSecret: viper.GetString("oauth.mock.client_secret"),
RedirectURL: viper.GetString("oauth.mock.redirect_url"),
Scopes: viper.GetStringSlice("oauth.mock.scopes"),
},
},
},
}
return config, nil
}
// bindEnvVars explicitly binds environment variables for better control
func bindEnvVars() {
// Application level
BindEnv("environment", "base_ENVIRONMENT")
BindEnv("name", "APP_NAME")
BindEnv("debug", "base_DEBUG")
BindEnv("port", "base_PORT")
BindEnv("vendor_lock_time_out", "base_VENDOR_LOCK_TIMEOUT")
// Database
BindEnv("database.host", "base_DB_HOST")
BindEnv("database.port", "base_DB_PORT")
BindEnv("database.user", "base_DB_USERNAME")
BindEnv("database.password", "base_DB_PASSWORD")
BindEnv("database.name", "base_DB_NAME")
BindEnv("database.max_idle_conns", "base_DB_MAX_IDLE_CONNS")
BindEnv("database.max_open_conns", "base_DB_MAX_OPEN_CONNS")
BindEnv("database.conn_max_idle_time", "base_DB_CONN_MAX_IDLE_TIME")
BindEnv("database.conn_max_lifetime", "base_DB_CONN_MAX_LIFETIME")
BindEnv("database.ro_user", "base_DB_RO_USERNAME")
BindEnv("database.ro_password", "base_DB_RO_PASSWORD")
BindEnv("database.ro_max_idle_conns", "base_DB_RO_MAX_IDLE_CONNS")
BindEnv("database.ro_max_open_conns", "base_DB_RO_MAX_OPEN_CONNS")
// Redis
BindEnv("redis.host", "base_REDIS_HOST")
BindEnv("redis.port", "base_REDIS_PORT")
BindEnv("redis.password", "base_REDIS_PASSWORD")
BindEnv("redis.database", "base_REDIS_DATABASE")
BindEnv("redis.url", "base_REDIS_URL")
// Server
BindEnv("server.host", "base_SERVER_HOST")
BindEnv("server.port", "base_SERVER_PORT")
BindEnv("rpc.host", "base_RPC_HOST")
BindEnv("rpc.port", "base_RPC_PORT")
BindEnv("web.host", "base_WEB_HOST")
BindEnv("web.port", "base_WEB_PORT")
BindEnv("server.max_file_size_mb", "base_SERVER_MAX_FILE_SIZE_MB")
BindEnv("server.cleanup_queues", "base_SERVER_CLEANUP_QUEUES")
BindEnv("server.jwt_secret", "base_SERVER_JWT_SECRET")
// JWT
BindEnv("jwt.secret", "base_JWT_SECRET")
BindEnv("jwt.access_token_expiration", "base_JWT_ACCESS_TOKEN_EXPIRATION")
BindEnv("jwt.refresh_token_expiration", "base_JWT_REFRESH_TOKEN_EXPIRATION")
// OAuth
BindEnv("oauth.google.client_id", "base_OAUTH_GOOGLE_CLIENT_ID")
BindEnv("oauth.google.client_secret", "base_OAUTH_GOOGLE_CLIENT_SECRET")
BindEnv("oauth.google.redirect_url", "base_OAUTH_GOOGLE_REDIRECT_URL")
BindEnv("oauth.github.client_id", "base_OAUTH_GITHUB_CLIENT_ID")
BindEnv("oauth.github.client_secret", "base_OAUTH_GITHUB_CLIENT_SECRET")
BindEnv("oauth.github.redirect_url", "base_OAUTH_GITHUB_REDIRECT_URL")
BindEnv("oauth.linkedin.client_id", "base_OAUTH_LINKEDIN_CLIENT_ID")
BindEnv("oauth.linkedin.client_secret", "base_OAUTH_LINKEDIN_CLIENT_SECRET")
BindEnv("oauth.linkedin.redirect_url", "base_OAUTH_LINKEDIN_REDIRECT_URL")
BindEnv("oauth.mock.enabled", "base_OAUTH_MOCK_ENABLED")
BindEnv("oauth.mock.base_url", "base_OAUTH_MOCK_BASE_URL")
BindEnv("oauth.mock.client_id", "base_OAUTH_MOCK_CLIENT_ID")
BindEnv("oauth.mock.client_secret", "base_OAUTH_MOCK_CLIENT_SECRET")
BindEnv("oauth.mock.redirect_url", "base_OAUTH_MOCK_REDIRECT_URL")
// RabbitMQ
BindEnv("rabbitmq.host", "base_RABBITMQ_HOST")
BindEnv("rabbitmq.port", "base_RABBITMQ_PORT")
BindEnv("rabbitmq.user", "base_RABBIT_USERNAME")
BindEnv("rabbitmq.password", "base_RABBIT_PASSWORD")
BindEnv("rabbitmq.vhost", "base_RABBITMQ_VHOST")
BindEnv("rabbitmq.max_connections", "base_RABBITMQ_MAX_CONNECTIONS")
BindEnv("rabbitmq.max_channels", "base_RABBITMQ_MAX_CHANNELS")
BindEnv("rabbitmq.connection_timeout", "base_RABBITMQ_CONNECTION_TIMEOUT")
BindEnv("rabbitmq.heartbeat_interval", "base_RABBITMQ_HEARTBEAT_INTERVAL")
BindEnv("rabbitmq.reconnect_delay", "base_RABBITMQ_RECONNECT_DELAY")
BindEnv("rabbitmq.max_reconnect_delay", "base_RABBITMQ_MAX_RECONNECT_DELAY")
BindEnv("rabbitmq.reconnect_attempts", "base_RABBITMQ_RECONNECT_ATTEMPTS")
BindEnv("rabbitmq.enable_auto_reconnect", "base_RABBITMQ_ENABLE_AUTO_RECONNECT")
BindEnv("rabbitmq.log_level", "base_RABBITMQ_LOG_LEVEL")
BindEnv("rabbitmq.max_retry_attempts", "base_RABBITMQ_MAX_RETRY_ATTEMPTS")
BindEnv("rabbitmq.prefetch_count", "base_RABBITMQ_PREFETCH_COUNT")
BindEnv("rabbitmq.retry_ttl", "base_RABBITMQ_RETRY_TTL")
// Azure Blob Storage
BindEnv("azure_blob_storage.blob_endpoint", "base_AZURE_BLOB_STORAGE_BLOB_ENDPOINT")
// Azure Service Bus
BindEnv("azure_service_bus.connection_string", "base_AZURE_SERVICE_BUS_CONNECTION_STRING")
BindEnv("azure_service_bus.namespace", "base_AZURE_SERVICE_BUS_NAMESPACE")
BindEnv("azure_service_bus.use_managed_identity", "base_AZURE_SERVICE_BUS_USE_MANAGED_IDENTITY")
// BarcodeMapping
BindEnv("barcodemapping.host", "base_BARCODEMAPPING_HOST")
BindEnv("barcodemapping.port", "base_BARCODEMAPPING_PORT")
BindEnv("barcodemapping.cache", "base_BARCODEMAPPING_CACHE")
BindEnv("barcodemapping.ttl", "base_BARCODEMAPPING_TTL")
BindEnv("barcodemapping.prefix", "base_BARCODEMAPPING_PREFIX")
// Discount
BindEnv("discount.url", "base_DISCOUNT_URL")
BindEnv("discount.port", "base_DISCOUNT_PORT")
BindEnv("discount.cache", "base_DISCOUNT_CACHE")
BindEnv("discount.ttl", "base_DISCOUNT_TTL")
BindEnv("discount.prefix", "base_DISCOUNT_PREFIX")
// Syslog
BindEnv("syslog.host", "base_SYSLOG_HOST")
BindEnv("syslog.port", "base_SYSLOG_PORT")
BindEnv("syslog.protocol", "base_SYSLOG_PROTOCOL")
BindEnv("syslog.log_level", "base_SYSLOG_LOG_LEVEL")
// Auth
BindEnv("vendorauth.url", "base_VENDOR_AUTH_URL")
BindEnv("vendorauth.client_id", "base_VENDOR_AUTH_CLIENT_ID")
BindEnv("vendorauth.client_secret", "base_VENDOR_AUTH_SECRET")
BindEnv("vendorauth.cache", "base_VENDOR_AUTH_CACHE")
BindEnv("vendorauth.prefix", "base_VENDOR_AUTH_PREFIX")
BindEnv("vendorauth.ttl", "base_VENDOR_AUTH_TTL")
BindEnv("authshield.url", "base_AUTH_SHIELD_URL")
BindEnv("authshield.cache", "base_AUTH_SHIELD_CACHE")
BindEnv("authshield.prefix", "base_AUTH_SHIELD_PREFIX")
BindEnv("authshield.ttl", "base_AUTH_SHIELD_TTL")
// Metrics
BindEnv("metrics.enabled", "base_METRICS_ENABLED")
BindEnv("metrics.service_name", "base_METRICS_SERVICE_NAME")
BindEnv("metrics.path", "base_METRICS_PATH")
BindEnv("metrics.port", "base_METRICS_PORT")
// PgDatabase
BindEnv("pg_database.host", "base_PG_DATABASE_HOST")
BindEnv("pg_database.port", "base_PG_DATABASE_PORT")
BindEnv("pg_database.user", "base_PG_DATABASE_USER")
BindEnv("pg_database.password", "base_PG_DATABASE_PASSWORD")
BindEnv("pg_database.name", "base_PG_DATABASE_NAME")
BindEnv("pg_database.ssl_mode", "base_PG_DATABASE_SSL_MODE")
BindEnv("pg_database.connection_timeout", "base_PG_DATABASE_CONNECTION_TIMEOUT")
BindEnv("pg_database.query_timeout", "base_PG_DATABASE_QUERY_TIMEOUT")
BindEnv("pg_database.pool_config.max_conn", "base_PG_DATABASE_POOL_CONFIG_MAX_CONN")
BindEnv("pg_database.pool_config.min_conn", "base_PG_DATABASE_POOL_CONFIG_MIN_CONN")
BindEnv("pg_database.pool_config.max_conn_lifetime", "base_PG_DATABASE_POOL_CONFIG_MAX_CONN_LIFETIME")
BindEnv("pg_database.pool_config.max_conn_idle_time", "base_PG_DATABASE_POOL_CONFIG_MAX_CONN_IDLE_TIME")
BindEnv("pg_database.migrations.enabled", "base_PG_DATABASE_MIGRATIONS_ENABLED")
BindEnv("pg_database.migrations.dir", "base_PG_DATABASE_MIGRATIONS_DIR")
}
func BindEnv(input, envKey string) {
if err := viper.BindEnv(input, envKey); err != nil {
panic(err)
}
}
func GetStringOrDefault(key string, defaultValue string) string {
if viper.IsSet(key) {
return viper.GetString(key)
}
return defaultValue
}

40
config/database.go Normal file
View File

@@ -0,0 +1,40 @@
package config
import "time"
// DatabaseConfig holds configuration for database
type DatabaseConfig struct {
User string
Password string
Host string
Port string
Name string
MaxIdleConns int
MaxOpenConns int
ConnMaxIdleTime string
ConnMaxLifetime string
}
type PgDatabaseConfig struct {
Host string
Port int
User string
Password string
Name string
SSLMode string
ConnectionTimeout time.Duration
QueryTimeout time.Duration
PoolConfig PgPoolConfig
Migrations MigrationsConfig
}
type MigrationsConfig struct {
Enabled bool
Dir string
}
type PgPoolConfig struct {
MaxConn int32
MinConn int32
MaxConnLifetime time.Duration
MaxConnIdleTime time.Duration
}

7
config/env.go Normal file
View File

@@ -0,0 +1,7 @@
package config
const (
Local = "local"
Prod = "prod"
Stage = "stage"
)

10
config/jwt.go Normal file
View File

@@ -0,0 +1,10 @@
package config
import "time"
// JWTConfig holds configuration for JWT token service
type JWTConfig struct {
Secret string `mapstructure:"secret"` // JWT secret key for token signing
AccessTokenExpiration time.Duration `mapstructure:"access_token_expiration"` // Access token expiration duration
RefreshTokenExpiration time.Duration `mapstructure:"refresh_token_expiration"` // Refresh token expiration duration
}

9
config/metrics.go Normal file
View File

@@ -0,0 +1,9 @@
package config
// MetricsConfig holds configuration for metrics
type MetricsConfig struct {
Enabled bool
ServiceName string
Path string
Port string
}

24
config/oauth.go Normal file
View File

@@ -0,0 +1,24 @@
package config
// OAuthConfig holds configuration for OAuth providers
type OAuthConfig struct {
Google OAuthProviderConfig `mapstructure:"google"`
GitHub OAuthProviderConfig `mapstructure:"github"`
LinkedIn OAuthProviderConfig `mapstructure:"linkedin"`
Mock OAuthMockConfig `mapstructure:"mock"`
}
// OAuthMockConfig holds configuration for the mock OAuth server (local dev only)
type OAuthMockConfig struct {
Enabled bool `mapstructure:"enabled"`
BaseURL string `mapstructure:"base_url"` // e.g. http://localhost:9999
OAuthProviderConfig
}
// OAuthProviderConfig holds configuration for a single OAuth provider
type OAuthProviderConfig struct {
ClientID string `mapstructure:"client_id"`
ClientSecret string `mapstructure:"client_secret"` // Ov23liSo5eCfXJ11k7mr
RedirectURL string `mapstructure:"redirect_url"`
Scopes []string `mapstructure:"scopes"`
}

38
config/rabbit.go Normal file
View File

@@ -0,0 +1,38 @@
package config
import (
"fmt"
"time"
)
// RabbitMQConfig holds configuration for RabbitMQ
type RabbitMQConfig struct {
Host string
Port int
User string
Password string
VHost string
MaxConnections int
MaxChannels int
ConnectionTimeout time.Duration
HeartbeatInterval time.Duration
ReconnectDelay time.Duration
MaxReconnectDelay time.Duration
ReconnectAttempts int
EnableAutoReconnect bool
LogLevel string
MaxRetryAttempts int
PrefetchCount int
RetryTTL time.Duration
}
// RabbitMQConnectionString returns the formatted RabbitMQ connection URI
func (c *AppConfig) RabbitMQConnectionString() string {
return fmt.Sprintf("amqp://%s:%s@%s:%d/%s",
c.RabbitMQ.User,
c.RabbitMQ.Password,
c.RabbitMQ.Host,
c.RabbitMQ.Port,
c.RabbitMQ.VHost,
)
}

10
config/redis.go Normal file
View File

@@ -0,0 +1,10 @@
package config
// RedisConfig holds configuration for Redis
type RedisConfig struct {
Host string
Port string
Password string
Database int
URL string
}

25
config/server.go Normal file
View File

@@ -0,0 +1,25 @@
package config
// ServerConfig holds configuration for HTTP server
type ServerConfig struct {
Domain string `mapstructure:"domain"`
HTTPPort string `mapstructure:"http_port"`
GRPCPort string `mapstructure:"grpc_port"`
RPCHost string `mapstructure:"rpc_host"`
RPCPort string `mapstructure:"rpc_port"`
WebHost string `mapstructure:"web_host"`
WebPort string `mapstructure:"web_port"`
MaxFileSize int64 `mapstructure:"max_file_size"` // Maximum file size in bytes
MaxFileSizeMB int `mapstructure:"max_file_size_mb"` // Maximum file size in MB (for convenience)
CleanupQueues bool `mapstructure:"cleanup_queues"` // Whether to cleanup existing queues on startup
JWTSecret string `mapstructure:"jwt_secret"` // JWT secret key for token signing
}
// GetMaxFileSizeBytes returns the maximum file size in bytes
func (s *ServerConfig) GetMaxFileSizeBytes() int64 {
if s.MaxFileSize > 0 {
return s.MaxFileSize
}
// Convert MB to bytes if MaxFileSize is not set
return int64(s.MaxFileSizeMB) * 1024 * 1024
}

8
config/syslog.go Normal file
View File

@@ -0,0 +1,8 @@
package config
type SyslogConfig struct {
Host string
Port string
Protocol string
LogLevel string
}