using System; using System.Collections.Generic; using System.Configuration; using System.Data.SqlClient; using System.Net; using System.Net.Mail; using System.Text.RegularExpressions; namespace framework_library { public static class ConfigResolver { private const string DefaultCentralCatalog = "Framework_EVOL-1"; private static readonly object CatalogLock = new object(); private static string _centralCatalog; private static string _tenantCatalog; private static bool _centralCatalogResolved; private static bool _tenantCatalogResolved; private static readonly Regex CatalogNamePattern = new Regex(@"^Framework_[A-Za-z0-9_-]+$", RegexOptions.CultureInvariant); private static readonly Dictionary SecretKeyEnvMap = new Dictionary(StringComparer.OrdinalIgnoreCase) { { "conn", "DB_CONNECTION_STRING" }, { "connExt", "DB_EXT_CONNECTION_STRING" }, { "connLive", "DB_LIVE_CONNECTION_STRING" }, { "smsU", "SMS_USERNAME" }, { "smsP", "SMS_PASSWORD" }, }; private static readonly Dictionary DbKeyEnvMap = new Dictionary(StringComparer.OrdinalIgnoreCase) { { "conn", "DB_CONNECTION_STRING" }, { "Quotes", "DB_CONNECTION_STRING" }, { "connExt", "DB_EXT_CONNECTION_STRING" }, { "connLive", "DB_LIVE_CONNECTION_STRING" }, }; public static string GetAppSetting(string appSettingsKey) { if (SecretKeyEnvMap.TryGetValue(appSettingsKey, out string envName)) return GetSecretSetting(appSettingsKey, envName); return ConfigurationManager.AppSettings[appSettingsKey] ?? string.Empty; } public static string GetSecretSetting(string appSettingsKey, string envVarName) { string env = Environment.GetEnvironmentVariable(envVarName); if (!string.IsNullOrEmpty(env)) return env; string configValue = ConfigurationManager.AppSettings[appSettingsKey]; if (configValue != null) return configValue; return string.Empty; } public static string GetConnectionString(string appSettingsKey = "conn") { string envVarName = DbKeyEnvMap.TryGetValue(appSettingsKey, out string mapped) ? mapped : "DB_CONNECTION_STRING"; string value = GetSecretSetting(appSettingsKey, envVarName); if (string.IsNullOrEmpty(value) && ConfigurationManager.ConnectionStrings[appSettingsKey] != null) value = ConfigurationManager.ConnectionStrings[appSettingsKey].ConnectionString; return value ?? string.Empty; } /// /// Central auth catalog (EVOL). Resolution: DB_CENTRAL_CATALOG, then Initial Catalog /// from DB_LIVE_CONNECTION_STRING, then Framework_EVOL-1. /// public static string GetCentralCatalog() { if (_centralCatalogResolved) return _centralCatalog; lock (CatalogLock) { if (_centralCatalogResolved) return _centralCatalog; string explicitCatalog = Environment.GetEnvironmentVariable("DB_CENTRAL_CATALOG"); if (!string.IsNullOrWhiteSpace(explicitCatalog)) { _centralCatalog = ValidateCatalogName(explicitCatalog.Trim()); } else { string parsed = ParseCatalog(GetConnectionString("connLive")); _centralCatalog = string.IsNullOrEmpty(parsed) ? DefaultCentralCatalog : ValidateCatalogName(parsed); } _centralCatalogResolved = true; return _centralCatalog; } } /// /// Tenant application catalog from DB_CONNECTION_STRING (or DB_TENANT_CATALOG). /// Throws when conn uses the scheduler {catalog} placeholder. /// public static string GetTenantCatalog() { if (_tenantCatalogResolved) return _tenantCatalog; lock (CatalogLock) { if (_tenantCatalogResolved) return _tenantCatalog; string explicitCatalog = Environment.GetEnvironmentVariable("DB_TENANT_CATALOG"); if (!string.IsNullOrWhiteSpace(explicitCatalog)) { _tenantCatalog = ValidateCatalogName(explicitCatalog.Trim()); } else { string parsed = ParseCatalog(GetConnectionString("conn")); if (string.IsNullOrEmpty(parsed)) { throw new InvalidOperationException( "Cannot resolve tenant catalog: DB_CONNECTION_STRING is unset or uses the {catalog} placeholder."); } _tenantCatalog = ValidateCatalogName(parsed); } _tenantCatalogResolved = true; return _tenantCatalog; } } /// /// Returns Initial Catalog from a connection string, or empty when unset or {catalog}. /// public static string ParseCatalog(string connectionString) { if (string.IsNullOrWhiteSpace(connectionString)) return string.Empty; if (connectionString.IndexOf("{catalog}", StringComparison.OrdinalIgnoreCase) >= 0) return string.Empty; try { var builder = new SqlConnectionStringBuilder(connectionString); string catalog = builder.InitialCatalog; return string.IsNullOrWhiteSpace(catalog) ? string.Empty : catalog.Trim(); } catch (ArgumentException) { return string.Empty; } } public static SqlConnection OpenConnection(string appSettingsKey = "conn") { string connectionString = GetConnectionString(appSettingsKey); if (string.IsNullOrEmpty(connectionString)) { throw new InvalidOperationException( "Connection string for '" + appSettingsKey + "' is not configured."); } SqlConnection connection = new SqlConnection(connectionString); connection.Open(); return connection; } private static string ValidateCatalogName(string catalog) { if (string.IsNullOrWhiteSpace(catalog) || !CatalogNamePattern.IsMatch(catalog)) { throw new InvalidOperationException( "Invalid SQL catalog name '" + catalog + "'. Expected pattern Framework_."); } return catalog; } public static void ConfigureSmtp(SmtpClient client) { string host = Environment.GetEnvironmentVariable("SMTP_HOST"); if (string.IsNullOrEmpty(host)) return; client.Host = host; client.Port = int.Parse(Environment.GetEnvironmentVariable("SMTP_PORT") ?? "587"); client.EnableSsl = (Environment.GetEnvironmentVariable("SMTP_ENABLE_SSL") ?? "true") .Equals("true", StringComparison.OrdinalIgnoreCase); string user = Environment.GetEnvironmentVariable("SMTP_USER"); string pass = Environment.GetEnvironmentVariable("SMTP_PASSWORD"); if (string.IsNullOrEmpty(user) || string.IsNullOrEmpty(pass)) throw new InvalidOperationException("SMTP_USER and SMTP_PASSWORD must be set when SMTP_HOST is set."); client.Credentials = new NetworkCredential(user, pass); client.DeliveryMethod = SmtpDeliveryMethod.Network; } } }