diff --git a/.gitignore b/.gitignore index 75d92e9..35ac2be 100644 --- a/.gitignore +++ b/.gitignore @@ -27,6 +27,10 @@ Project_Readme.html # User-specific files (MonoDevelop/Xamarin Studio) *.userprefs .idea/ +.mono/ + +# secret folder '.secrets' all over the project git controlled +.secrets/ # Build results [Dd]ebug/ @@ -226,6 +230,8 @@ Thumbs.db .idea/ # custom +# Ignore environment-specific appsettings, but allow .example files /**/**/appsettings.*.json +!/**/**/appsettings.*.json.example **/**/deployment.yml diff --git a/src/Nocr.TelegramClient.Host/Infrastructure/HostBuilderFactory.cs b/src/Nocr.TelegramClient.Host/Infrastructure/HostBuilderFactory.cs index 2d5e82d..3fc00f9 100644 --- a/src/Nocr.TelegramClient.Host/Infrastructure/HostBuilderFactory.cs +++ b/src/Nocr.TelegramClient.Host/Infrastructure/HostBuilderFactory.cs @@ -8,12 +8,24 @@ public class HostBuilderFactory where TStartup : class { var builder = Microsoft.Extensions.Hosting.Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(host => { host.UseStartup(); }) - .ConfigureAppConfiguration((_, configurationBuilder) => + .ConfigureAppConfiguration((context, configurationBuilder) => { if (!string.IsNullOrWhiteSpace(baseDirectory)) configurationBuilder.SetBasePath(baseDirectory); - configurationBuilder.AddJsonFile("appsettings.protected.json", optional: true); + // Configuration priority (low to high): + // 1. appsettings.json (already loaded by CreateDefaultBuilder) + // 2. appsettings.{Environment}.json (already loaded) + // 3. User Secrets (already loaded in Development) + // 4. Environment Variables (already loaded) ← highest priority + + // Debug mode: log configuration on startup + if (Environment.GetEnvironmentVariable("NOCR_DEBUG_MODE") == "true") + { + Console.WriteLine("[NOCR_DEBUG] Configuration debug mode enabled"); + Console.WriteLine($"[NOCR_DEBUG] Environment: {context.HostingEnvironment.EnvironmentName}"); + Console.WriteLine($"[NOCR_DEBUG] Base Path: {baseDirectory ?? configurationBuilder.Build().GetValue("ContentRoot") ?? "default"}"); + } }) .UseSerilog((ctx, logBuilder) => { diff --git a/src/Nocr.TelegramClient.Host/Infrastructure/Startup.cs b/src/Nocr.TelegramClient.Host/Infrastructure/Startup.cs index f8ff2cc..4d587be 100644 --- a/src/Nocr.TelegramClient.Host/Infrastructure/Startup.cs +++ b/src/Nocr.TelegramClient.Host/Infrastructure/Startup.cs @@ -25,6 +25,12 @@ public class Startup public void ConfigureServices(IServiceCollection services) { + // Debug mode: log loaded configuration + if (Environment.GetEnvironmentVariable("NOCR_DEBUG_MODE") == "true") + { + LogConfigurationDebug(); + } + var localizerConfiguration = Configuration .GetSection(nameof(LocalizerConfiguration)) .Get(); @@ -60,8 +66,41 @@ public class Startup public void Configure(IApplicationBuilder app) { app.UseHealthChecks("/health"); - + var bus = app.ApplicationServices.GetRequiredService(); bus.Advanced.Topics.Subscribe("nocr.text.matcher.matched").GetAwaiter().GetResult(); } + + private void LogConfigurationDebug() + { + Console.WriteLine("=== [NOCR_DEBUG] Configuration Values ==="); + + var rebusOptions = Configuration.GetSection(nameof(RebusRabbitMqOptions)); + Console.WriteLine($"[NOCR_DEBUG] RebusRabbitMqOptions:"); + Console.WriteLine($"[NOCR_DEBUG] ConnectionString: {MaskConnectionString(rebusOptions["ConnectionString"])}"); + Console.WriteLine($"[NOCR_DEBUG] InputQueueName: {rebusOptions["InputQueueName"]}"); + Console.WriteLine($"[NOCR_DEBUG] DirectExchangeName: {rebusOptions["DirectExchangeName"]}"); + Console.WriteLine($"[NOCR_DEBUG] TopicsExchangeName: {rebusOptions["TopicsExchangeName"]}"); + + var botOptions = Configuration.GetSection("BotConfiguration"); + Console.WriteLine($"[NOCR_DEBUG] BotConfiguration:"); + Console.WriteLine($"[NOCR_DEBUG] BotToken: {MaskSecret(botOptions["BotToken"])}"); + + Console.WriteLine("=== [NOCR_DEBUG] End Configuration ==="); + } + + private static string MaskConnectionString(string? value) + { + if (string.IsNullOrEmpty(value)) return "(empty)"; + // Mask password in connection string: amqp://user:pass@host -> amqp://user:***@host + var masked = System.Text.RegularExpressions.Regex.Replace(value, @"(?<=://)([^:]+):([^@]+)(?=@)", m => $"{m.Groups[1].Value}:***"); + return masked; + } + + private static string MaskSecret(string? value) + { + if (string.IsNullOrEmpty(value)) return "(empty)"; + if (value.Length <= 4) return "***"; + return $"{value.Substring(0, 2)}...{value.Substring(value.Length - 2)}"; + } } \ No newline at end of file diff --git a/src/Nocr.TelegramClient.Host/appsettings.Development.json.example b/src/Nocr.TelegramClient.Host/appsettings.Development.json.example new file mode 100644 index 0000000..d242436 --- /dev/null +++ b/src/Nocr.TelegramClient.Host/appsettings.Development.json.example @@ -0,0 +1,21 @@ +{ + // This file provides an example configuration for local VS Code debugging. + // Copy this file to appsettings.Development.json and fill in your actual values. + + "RebusRabbitMqOptions": { + // RabbitMQ connection string for local development + "ConnectionString": "amqp://admin:admin@localhost:5672/" + }, + "UsersRestEaseOptions": { + // Users service API endpoint + "BasePath": "http://localhost:5042" + }, + "TextMatcherRestEaseOptions": { + // TextMatcher service API endpoint + "BasePath": "http://localhost:5041" + }, + "TelegramBotOptions": { + // Bot token from @BotFather + "Token": "YOUR_BOT_TOKEN_HERE" + } +} diff --git a/src/Nocr.TelegramClient.Host/appsettings.DockerCompose.json.example b/src/Nocr.TelegramClient.Host/appsettings.DockerCompose.json.example new file mode 100644 index 0000000..3be720f --- /dev/null +++ b/src/Nocr.TelegramClient.Host/appsettings.DockerCompose.json.example @@ -0,0 +1,19 @@ +{ + // This file provides an example configuration for Docker Compose deployment. + // Copy this file to appsettings.DockerCompose.json (or use environment variables). + + "RebusRabbitMqOptions": { + // RabbitMQ connection - use service name from docker-compose.yml + "ConnectionString": "amqp://admin:admin@nocr-rabbitmq:5672/" + }, + "UsersRestEaseOptions": { + // Users service - use service name from docker-compose.yml + "BasePath": "http://nocr-users:8080" + }, + "TextMatcherRestEaseOptions": { + // TextMatcher service - use service name from docker-compose.yml + "BasePath": "http://nocr-text-matcher:8080" + } + // Note: TelegramBotOptions.Token should be provided via environment variables + // See docker-compose.yml or use .env file +}