using AmtScanner.Api.Configuration; using AmtScanner.Api.Data; using AmtScanner.Api.Middleware; using AmtScanner.Api.Models; using AmtScanner.Api.Services; using AmtScanner.Api.Repositories; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.EntityFrameworkCore; using Microsoft.IdentityModel.Tokens; using System.Net; using System.Net.Security; using System.Security.Cryptography.X509Certificates; using System.Text; // Disable SSL certificate validation for AMT devices (they use self-signed certs) ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true; var builder = WebApplication.CreateBuilder(args); // Add services to the container builder.Services.AddControllers(); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); // Add CORS builder.Services.AddCors(options => { options.AddPolicy("AllowFrontend", policy => { policy.WithOrigins("http://localhost:5173", "http://localhost:3000", "http://localhost:3001") .AllowAnyHeader() .AllowAnyMethod() .AllowCredentials(); }); }); // Add SignalR for WebSocket builder.Services.AddSignalR(); // Add Database var databaseProvider = builder.Configuration.GetValue("DatabaseProvider", "SQLite"); if (databaseProvider == "MySQL") { var connectionString = builder.Configuration.GetConnectionString("MySqlConnection"); builder.Services.AddDbContext(options => options.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString))); } else { builder.Services.AddDbContext(options => options.UseSqlite(builder.Configuration.GetConnectionString("DefaultConnection"))); } // Add Services builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddHttpClient(); // Add JWT Configuration builder.Services.Configure(builder.Configuration.GetSection(JwtSettings.SectionName)); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); // Add JWT Authentication var jwtSettings = builder.Configuration.GetSection(JwtSettings.SectionName).Get()!; builder.Services.AddAuthentication(options => { options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = jwtSettings.Issuer, ValidAudience = jwtSettings.Audience, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings.SecretKey)), ClockSkew = TimeSpan.Zero }; options.Events = new JwtBearerEvents { OnAuthenticationFailed = context => { if (context.Exception.GetType() == typeof(SecurityTokenExpiredException)) { context.Response.Headers.Append("Token-Expired", "true"); } return Task.CompletedTask; } }; }); var app = builder.Build(); // Configure the HTTP request pipeline if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseCors("AllowFrontend"); // Add global exception handler app.UseGlobalExceptionHandler(); app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); // Map SignalR Hub app.MapHub("/scanHub"); // Ensure database is created using (var scope = app.Services.CreateScope()) { var db = scope.ServiceProvider.GetRequiredService(); try { // Apply migrations (create database and tables) // 如果迁移失败(表已存在),尝试手动标记迁移为已完成 try { db.Database.Migrate(); } catch (Exception migrationEx) when (migrationEx.Message.Contains("already exists")) { Console.WriteLine("⚠️ 表已存在,尝试标记迁移为已完成..."); var pendingMigrations = db.Database.GetPendingMigrations().ToList(); foreach (var migration in pendingMigrations) { try { db.Database.ExecuteSqlRaw( "INSERT IGNORE INTO `__EFMigrationsHistory` (`MigrationId`, `ProductVersion`) VALUES ({0}, {1})", migration, "8.0.0"); Console.WriteLine($"✅ 已标记迁移: {migration}"); } catch { } } } // Add default credential if not exists if (!db.AmtCredentials.Any()) { var credentialService = scope.ServiceProvider.GetRequiredService(); var defaultCredential = new AmtCredential { Name = "Default Admin", Username = "admin", Password = credentialService.EncryptPassword("Guo1wu3shi4!"), IsDefault = true, Description = "默认管理员凭据", CreatedAt = DateTime.UtcNow, UpdatedAt = DateTime.UtcNow }; db.AmtCredentials.Add(defaultCredential); db.SaveChanges(); Console.WriteLine("✅ 默认凭据已创建: admin / Guo1wu3shi4!"); } Console.WriteLine($"✅ 数据库连接成功: {databaseProvider}"); // 初始化种子数据 await DbSeeder.SeedAsync(db); } catch (Exception ex) { Console.WriteLine($"❌ 数据库初始化失败: {ex.Message}"); throw; } } app.Run();