using System; using System.Collections.Generic; using System.Linq; using System.Security.Claims; using System.Threading.Tasks; using IOL.WebApi.Template.Data.Database; using IOL.WebApi.Template.Data.Dtos; using IOL.WebApi.Template.Data.Result; using IOL.Helpers; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; namespace IOL.WebApi.Template.Controllers { public class AccountController : AppControllerBase { private readonly AppDbContext _context; private readonly IAuthenticationService _authentication; public AccountController( AppDbContext context, IAuthenticationService authentication ) { _context = context; _authentication = authentication; } [AllowAnonymous] [HttpPost("login")] public ActionResult Login(LoginRequestDto payload) { if (!ModelState.IsValid) return BadRequest(ModelState); var user = _context.Users.SingleOrDefault(u => u.Username == payload.Username); if (user == default || !user.VerifyPassword(payload.Password)) return BadRequest(new ErrorResult("Invalid username or password")); var claims = new List { new(ClaimTypes.NameIdentifier, user.Id.ToString()), new(ClaimTypes.Name, user.Username), }; var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme); var principal = new ClaimsPrincipal(identity); var authenticationProperties = new AuthenticationProperties { AllowRefresh = true, IssuedUtc = DateTimeOffset.UtcNow, }; if (payload.Persist) { authenticationProperties.ExpiresUtc = DateTimeOffset.UtcNow.AddMonths(6); authenticationProperties.IsPersistent = true; } HttpContext.SignInAsync(principal, authenticationProperties); return Ok(); } [HttpGet("logout")] [AllowAnonymous] public ActionResult Logout() { HttpContext.SignOutAsync(); return Ok(); } [AllowAnonymous] [HttpGet("create-initial")] public ActionResult CreateInitialUser(string username, string password) { if (_context.Users.Any()) { return NotFound(); } var user = new User(username); user.HashAndSetPassword(password); _context.Users.Add(user); _context.SaveChanges(); return Ok(); } [AllowAnonymous] [HttpGet("me")] public async Task GetLoggedInUser() { var authres = await _authentication.AuthenticateAsync(HttpContext, CookieAuthenticationDefaults.AuthenticationScheme); if (authres.Succeeded) return Ok(LoggedInUser); await HttpContext.SignOutAsync(); return StatusCode(403); } [HttpPost("update-password")] public ActionResult UpdatePassword([FromBody] string newPassword) { if (newPassword.IsNullOrWhiteSpace()) { return BadRequest(new ErrorResult("Invalid request", "The new password field is required")); } if (newPassword.Length < 6) { return BadRequest(new ErrorResult("Invalid request", "The new password must contain atleast 6 characters")); } var user = _context.Users.SingleOrDefault(c => c.Id == LoggedInUser.Id); if (user == default) { HttpContext.SignOutAsync(); return StatusCode(403); } user.HashAndSetPassword(newPassword); _context.SaveChanges(); return Ok(); } } }