using EARSystem.Core; using EARSystem.Infrastructure; using EARSystem.Web.Models; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; namespace EARSystem.Web.Controllers; public class AccountController(UserManager users, SignInManager signIn, AppDbContext db, IWebHostEnvironment environment, IConfiguration config) : Controller { [AllowAnonymous, HttpGet] public IActionResult Login(string? returnUrl) => View(new LoginInput { ReturnUrl = returnUrl }); [AllowAnonymous, HttpPost] public async Task Login(LoginInput input) { if (!ModelState.IsValid) return View(input); var result = await signIn.PasswordSignInAsync(input.Email.Trim(), input.Password, input.Remember, true); if (result.Succeeded) return LocalRedirect(Url.IsLocalUrl(input.ReturnUrl) ? input.ReturnUrl! : "/"); ModelState.AddModelError("", result.IsLockedOut ? "登录尝试过多,请 15 分钟后再试。" : "邮箱或密码不正确。"); return View(input); } [AllowAnonymous, HttpGet] public IActionResult Register() => View(new RegisterInput()); [AllowAnonymous, HttpPost] public async Task Register(RegisterInput input) { if (!ModelState.IsValid) return View(input); var email = input.Email.Trim(); var user = new ApplicationUser { UserName = email, Email = email, DisplayName = input.DisplayName.Trim() }; var result = await users.CreateAsync(user, input.Password); if (!result.Succeeded) { ModelState.AddModelError("", "注册失败:邮箱可能已使用,密码须至少 10 位并包含大小写字母、数字和符号。"); return View(input); } await users.AddToRoleAsync(user, "User"); db.Preferences.Add(new() { UserId = user.Id }); await db.SaveChangesAsync(); await signIn.SignInAsync(user, false); return Redirect("/"); } [AllowAnonymous, HttpPost] public async Task DemoLogin() { if (environment.IsProduction() || !config.GetValue("Demo:Enabled", false)) return NotFound(); var user = await users.FindByEmailAsync("demo01@ear.local"); if (user == null || !user.IsDemo) return NotFound(); await signIn.SignInAsync(user, false); return Redirect("/"); } [Authorize, HttpPost] public async Task Logout() { await signIn.SignOutAsync(); return Redirect("/"); } [AllowAnonymous] public IActionResult Denied() { Response.StatusCode = 403; return View(); } }