261 lines
8.2 KiB
C#
261 lines
8.2 KiB
C#
using Microsoft.AspNetCore.Authentication.Cookies;
|
||
using Microsoft.AspNetCore.Authentication.Google;
|
||
using Microsoft.AspNetCore.Authentication.MicrosoftAccount;
|
||
using Microsoft.AspNetCore.Localization;
|
||
using Microsoft.AspNetCore.StaticFiles;
|
||
using Microsoft.Extensions.Caching.Distributed;
|
||
using Microsoft.Extensions.Localization;
|
||
using MongoDB.Driver;
|
||
using QRRapidoApp.Data;
|
||
using QRRapidoApp.Middleware;
|
||
using QRRapidoApp.Services;
|
||
using QRRapidoApp.Services.Monitoring;
|
||
using QRRapidoApp.Services.HealthChecks;
|
||
using StackExchange.Redis;
|
||
using Stripe;
|
||
using System.Globalization;
|
||
using Serilog;
|
||
using Serilog.Events;
|
||
using Serilog.Sinks.SystemConsole.Themes;
|
||
using Microsoft.AspNetCore.Mvc.Razor;
|
||
|
||
var builder = WebApplication.CreateBuilder(args);
|
||
|
||
// Configure Serilog
|
||
Log.Logger = new LoggerConfiguration()
|
||
.ReadFrom.Configuration(builder.Configuration)
|
||
.Enrich.FromLogContext()
|
||
.Enrich.WithEnvironmentName()
|
||
.Enrich.WithProcessId()
|
||
.Enrich.WithThreadId()
|
||
.Enrich.WithProperty("ApplicationName", builder.Configuration["ApplicationName"] ?? "QRRapido")
|
||
.Enrich.WithProperty("Environment", "Dev")
|
||
.WriteTo.Async(a => a.Console(
|
||
outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} {Properties:j}{NewLine}{Exception}",
|
||
theme: AnsiConsoleTheme.Code))
|
||
.WriteTo.Async(a => a.Seq(builder.Configuration["Serilog:SeqUrl"],
|
||
apiKey: builder.Configuration["Serilog:ApiKey"]=="" ? null : builder.Configuration["Serilog:ApiKey"]))
|
||
.CreateLogger();
|
||
|
||
builder.Host.UseSerilog();
|
||
|
||
// Add services to the container
|
||
builder.Services.AddControllersWithViews()
|
||
.AddViewLocalization(Microsoft.AspNetCore.Mvc.Razor.LanguageViewLocationExpanderFormat.Suffix)
|
||
.AddDataAnnotationsLocalization();
|
||
|
||
builder.Services.AddDistributedMemoryCache(); // Armazena os dados da sess<73>o na mem<65>ria
|
||
builder.Services.AddSession(options =>
|
||
{
|
||
options.Cookie.HttpOnly = true;
|
||
options.Cookie.IsEssential = true;
|
||
options.IdleTimeout = TimeSpan.FromMinutes(30); // Tempo de expira<72><61>o
|
||
});
|
||
|
||
// Add HttpClient for health checks
|
||
builder.Services.AddHttpClient();
|
||
|
||
// MongoDB Configuration - optional for development
|
||
var mongoConnectionString = builder.Configuration.GetConnectionString("MongoDB");
|
||
if (!string.IsNullOrEmpty(mongoConnectionString))
|
||
{
|
||
try
|
||
{
|
||
builder.Services.AddSingleton<IMongoClient>(serviceProvider =>
|
||
{
|
||
return new MongoClient(mongoConnectionString);
|
||
});
|
||
builder.Services.AddScoped<MongoDbContext>();
|
||
}
|
||
catch
|
||
{
|
||
// MongoDB not available - services will handle gracefully
|
||
builder.Services.AddScoped<MongoDbContext>();
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// Development mode without MongoDB
|
||
builder.Services.AddScoped<MongoDbContext>();
|
||
}
|
||
|
||
// Cache Configuration - use Redis if available, otherwise memory cache
|
||
var redisConnectionString = builder.Configuration.GetConnectionString("Redis");
|
||
if (!string.IsNullOrEmpty(redisConnectionString))
|
||
{
|
||
try
|
||
{
|
||
builder.Services.AddStackExchangeRedisCache(options =>
|
||
{
|
||
options.Configuration = redisConnectionString;
|
||
});
|
||
}
|
||
catch
|
||
{
|
||
// Fallback to memory cache if Redis fails
|
||
builder.Services.AddMemoryCache();
|
||
builder.Services.AddSingleton<IDistributedCache, QRRapidoApp.Services.MemoryDistributedCacheWrapper>();
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// Use memory cache when Redis is not configured
|
||
builder.Services.AddMemoryCache();
|
||
builder.Services.AddSingleton<IDistributedCache, MemoryDistributedCacheWrapper>();
|
||
}
|
||
|
||
// Authentication Configuration
|
||
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
|
||
.AddCookie(options =>
|
||
{
|
||
options.LoginPath = "/Account/Login";
|
||
options.LogoutPath = "/Account/Logout";
|
||
options.ExpireTimeSpan = TimeSpan.FromDays(30);
|
||
options.SlidingExpiration = true;
|
||
})
|
||
.AddGoogle(GoogleDefaults.AuthenticationScheme, options =>
|
||
{
|
||
options.ClientId = builder.Configuration["Authentication:Google:ClientId"];
|
||
options.ClientSecret = builder.Configuration["Authentication:Google:ClientSecret"];
|
||
})
|
||
.AddMicrosoftAccount(MicrosoftAccountDefaults.AuthenticationScheme, options =>
|
||
{
|
||
options.ClientId = builder.Configuration["Authentication:Microsoft:ClientId"];
|
||
options.ClientSecret = builder.Configuration["Authentication:Microsoft:ClientSecret"];
|
||
});
|
||
|
||
// Stripe Configuration
|
||
StripeConfiguration.ApiKey = builder.Configuration["Stripe:SecretKey"];
|
||
|
||
// Localization
|
||
builder.Services.AddLocalization(options => options.ResourcesPath = "");
|
||
//builder.Services.AddLocalization(options => options.ResourcesPath = "Resources");
|
||
builder.Services.Configure<RequestLocalizationOptions>(options =>
|
||
{
|
||
var supportedCultures = new[]
|
||
{
|
||
new CultureInfo("pt-BR"),
|
||
new CultureInfo("es"),
|
||
new CultureInfo("en")
|
||
};
|
||
|
||
options.DefaultRequestCulture = new RequestCulture("pt-BR", "pt-BR");
|
||
options.SupportedCultures = supportedCultures;
|
||
options.SupportedUICultures = supportedCultures;
|
||
|
||
options.FallBackToParentCultures = true;
|
||
options.FallBackToParentUICultures = true;
|
||
|
||
// Clear default providers and add custom ones in priority order
|
||
options.RequestCultureProviders.Clear();
|
||
options.RequestCultureProviders.Add(new RouteDataRequestCultureProvider());
|
||
options.RequestCultureProviders.Add(new QueryStringRequestCultureProvider());
|
||
options.RequestCultureProviders.Add(new CookieRequestCultureProvider());
|
||
});
|
||
|
||
// Custom Services
|
||
builder.Services.AddScoped<IQRCodeService, QRRapidoService>();
|
||
builder.Services.AddScoped<IUserService, UserService>();
|
||
builder.Services.AddScoped<IPlanService, QRRapidoApp.Services.PlanService>();
|
||
builder.Services.AddScoped<AdDisplayService>();
|
||
builder.Services.AddScoped<StripeService>();
|
||
|
||
// Background Services
|
||
builder.Services.AddHostedService<HistoryCleanupService>();
|
||
|
||
// Monitoring Services
|
||
if (builder.Configuration.GetValue<bool>("ResourceMonitoring:Enabled", true))
|
||
{
|
||
builder.Services.AddHostedService<ResourceMonitoringService>();
|
||
}
|
||
|
||
if (builder.Configuration.GetValue<bool>("MongoDbMonitoring:Enabled", true))
|
||
{
|
||
builder.Services.AddHostedService<MongoDbMonitoringService>();
|
||
}
|
||
|
||
// CORS for API endpoints
|
||
builder.Services.AddCors(options =>
|
||
{
|
||
options.AddPolicy("AllowSpecificOrigins", policy =>
|
||
{
|
||
policy.WithOrigins("https://qrrapido.site", "https://www.qrrapido.site")
|
||
.AllowAnyHeader()
|
||
.AllowAnyMethod();
|
||
});
|
||
});
|
||
|
||
// Health checks with custom implementations
|
||
builder.Services.AddScoped<MongoDbHealthCheck>();
|
||
builder.Services.AddScoped<SeqHealthCheck>();
|
||
builder.Services.AddScoped<ResourceHealthCheck>();
|
||
builder.Services.AddScoped<ExternalServicesHealthCheck>();
|
||
|
||
builder.Services.AddHealthChecks()
|
||
.AddCheck<MongoDbHealthCheck>("mongodb")
|
||
.AddCheck<SeqHealthCheck>("seq")
|
||
.AddCheck<ResourceHealthCheck>("resources")
|
||
.AddCheck<ExternalServicesHealthCheck>("external_services");
|
||
|
||
var app = builder.Build();
|
||
|
||
// Configure the HTTP request pipeline
|
||
if (!app.Environment.IsDevelopment())
|
||
{
|
||
app.UseExceptionHandler("/Home/Error");
|
||
app.UseHsts();
|
||
}
|
||
|
||
app.UseHttpsRedirection();
|
||
|
||
app.UseStaticFiles();
|
||
|
||
// Language redirection middleware (before routing)
|
||
app.UseMiddleware<LanguageRedirectionMiddleware>();
|
||
|
||
app.UseRouting();
|
||
|
||
app.UseCors("AllowSpecificOrigins");
|
||
|
||
// Localization middleware
|
||
app.UseRequestLocalization();
|
||
|
||
app.UseAuthentication();
|
||
app.UseAuthorization();
|
||
|
||
app.UseSession();
|
||
|
||
// Custom middleware
|
||
app.UseMiddleware<LastLoginUpdateMiddleware>();
|
||
|
||
// Health check endpoint
|
||
app.MapHealthChecks("/health");
|
||
|
||
// Language routes (must be first)
|
||
app.MapControllerRoute(
|
||
name: "localized",
|
||
pattern: "{culture:regex(^(pt-BR|es|en)$)}/{controller=Home}/{action=Index}/{id?}");
|
||
|
||
// API routes
|
||
app.MapControllerRoute(
|
||
name: "api",
|
||
pattern: "api/{controller}/{action=Index}/{id?}");
|
||
|
||
// Default fallback route (for development/testing without culture)
|
||
app.MapControllerRoute(
|
||
name: "default",
|
||
pattern: "{controller=Home}/{action=Index}/{id?}");
|
||
|
||
try
|
||
{
|
||
Log.Information("Starting QRRapido application");
|
||
app.Run();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Log.Fatal(ex, "QRRapido application terminated unexpectedly");
|
||
}
|
||
finally
|
||
{
|
||
Log.CloseAndFlush();
|
||
} |