Files
EmailBill/WebApi/Program.cs
孙诚 728c39f43d
All checks were successful
Docker Build & Deploy / Build Docker Image (push) Successful in 30s
Docker Build & Deploy / Deploy to Production (push) Successful in 5s
登录功能
2025-12-25 13:27:23 +08:00

149 lines
4.0 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.Text;
using FreeSql;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using Scalar.AspNetCore;
using Serilog;
using Service.AppSettingModel;
using Yitter.IdGenerator;
// 初始化雪花算法ID生成器
var options = new IdGeneratorOptions(1); // WorkerId 为 1可根据实际部署情况调整
YitIdHelper.SetIdGenerator(options);
var builder = WebApplication.CreateBuilder(args);
// 配置 Serilog
builder.Host.UseSerilog((context, loggerConfig) =>
{
loggerConfig.ReadFrom.Configuration(context.Configuration);
});
// Add services to the container.
builder.Services.AddControllers();
builder.Services.AddOpenApi();
builder.Services.AddHttpClient();
// 配置 CORS
builder.Services.AddCors(options =>
{
options.AddDefaultPolicy(policy =>
{
policy.WithOrigins("http://localhost:5173")
.AllowAnyHeader()
.AllowAnyMethod();
});
});
// 绑定配置
builder.Services.Configure<EmailSettings>(builder.Configuration.GetSection("EmailSettings"));
builder.Services.Configure<AISettings>(builder.Configuration.GetSection("OpenAI"));
builder.Services.Configure<JwtSettings>(builder.Configuration.GetSection("JwtSettings"));
builder.Services.Configure<AuthSettings>(builder.Configuration.GetSection("AuthSettings"));
// 配置JWT认证
var jwtSettings = builder.Configuration.GetSection("JwtSettings");
var secretKey = jwtSettings["SecretKey"]!;
var key = Encoding.UTF8.GetBytes(secretKey);
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(key),
ClockSkew = TimeSpan.Zero
};
});
builder.Services.AddAuthorization();
// 配置 FreeSql + SQLite
var dbPath = Path.Combine(AppContext.BaseDirectory, "database");
if (!Directory.Exists(dbPath))
{
Directory.CreateDirectory(dbPath);
}
// 使用绝对路径作为数据库文件路径
var dbFilePath = Path.Combine(dbPath, "EmailBill.db");
var connectionString = $"Data Source={dbFilePath}";
Log.Information("数据库路径: {DbPath}", dbFilePath);
var fsql = new FreeSqlBuilder()
.UseConnectionString(DataType.Sqlite, connectionString)
.UseAutoSyncStructure(true)
.UseLazyLoading(true)
.UseMonitorCommand(
cmd =>
{
Log.Information("执行SQL: {Sql}", cmd.CommandText);
}
)
.Build();
builder.Services.AddSingleton(fsql);
// 自动扫描注册服务和仓储
builder.Services.AddServices();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.MapOpenApi();
app.MapScalarApiReference();
}
// 启用静态文件服务
app.UseDefaultFiles();
app.UseStaticFiles();
// 启用 CORS
app.UseCors();
// 启用认证和授权
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
// 添加 SPA 回退路由(用于前端路由)
app.MapFallbackToFile("index.html");
// 启动后台邮件抓取服务(必须只注册一次)
app.Lifetime.ApplicationStarted.Register(() =>
{
try
{
if (app.Services.GetRequiredService<IEmailBackgroundService>() is not EmailBackgroundService emailService)
{
return;
}
// 检查是否已在运行,避免重复启动
if (!emailService.IsBusy)
{
emailService.RunWorkerAsync();
}
}
catch (Exception ex)
{
var logger = app.Services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "启动后台服务失败");
}
});
app.Run();