From 349b3965884d73586bd6b2afa48c120f380cffc0 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Thu, 13 Nov 2025 17:04:00 +0000 Subject: [PATCH] Add authentication controller. --- Marechai.Data/Models/AuthRequest.cs | 16 ++++++ Marechai.Data/Models/AuthResponse.cs | 13 +++++ Marechai.Server/Controllers/AuthController.cs | 56 +++++++++++++++++++ Marechai.Server/Marechai.Server.csproj | 1 + 4 files changed, 86 insertions(+) create mode 100644 Marechai.Data/Models/AuthRequest.cs create mode 100644 Marechai.Data/Models/AuthResponse.cs create mode 100644 Marechai.Server/Controllers/AuthController.cs diff --git a/Marechai.Data/Models/AuthRequest.cs b/Marechai.Data/Models/AuthRequest.cs new file mode 100644 index 00000000..5e154636 --- /dev/null +++ b/Marechai.Data/Models/AuthRequest.cs @@ -0,0 +1,16 @@ +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; + +namespace Marechai.Data.Models; + +public sealed record AuthRequest +{ + [Required] + [EmailAddress] + [JsonPropertyName("email")] + public string Email { get; set; } = null!; + [Required] + [DataType(DataType.Password)] + [JsonPropertyName("password")] + public string Password { get; set; } = null!; +} \ No newline at end of file diff --git a/Marechai.Data/Models/AuthResponse.cs b/Marechai.Data/Models/AuthResponse.cs new file mode 100644 index 00000000..309d6712 --- /dev/null +++ b/Marechai.Data/Models/AuthResponse.cs @@ -0,0 +1,13 @@ +using System.Text.Json.Serialization; + +namespace Marechai.Data.Models; + +public sealed record AuthResponse +{ + [JsonPropertyName("succeeded")] + public bool Succeeded { get; set; } + [JsonPropertyName("message")] + public string Message { get; set; } = null!; + [JsonPropertyName("token")] + public string Token { get; set; } = null!; +} \ No newline at end of file diff --git a/Marechai.Server/Controllers/AuthController.cs b/Marechai.Server/Controllers/AuthController.cs new file mode 100644 index 00000000..3496546e --- /dev/null +++ b/Marechai.Server/Controllers/AuthController.cs @@ -0,0 +1,56 @@ +using System.Linq; +using System.Threading.Tasks; +using Marechai.Data.Models; +using Marechai.Database.Models; +using Marechai.Server.Services; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Mvc; + +namespace Marechai.Server.Controllers; + +[ApiController] +[Route("auth")] +public class AuthController + (UserManager userManager, MarechaiContext context, TokenService tokenService) : ControllerBase +{ + [HttpPost] + [Route("login")] + [ProducesResponseType(typeof(AuthResponse), + StatusCodes.Status200OK, + Description = + "Authenticates a user with email and password, returning an access token if successful.")] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + [AllowAnonymous] + [Produces("application/json")] + [Consumes("application/json")] + public async Task> Authenticate([FromBody] AuthRequest request) + { + if(!ModelState.IsValid) return BadRequest(ModelState); + + ApplicationUser managedUser = await userManager.FindByEmailAsync(request.Email); + + if(managedUser == null) return Unauthorized("Bad credentials"); + + bool isPasswordValid = await userManager.CheckPasswordAsync(managedUser, request.Password); + + if(!isPasswordValid) return Unauthorized("Bad credentials"); + + ApplicationUser userInDb = context.Users.FirstOrDefault(u => u.Email == request.Email); + + if(userInDb is null) return Unauthorized(); + + string accessToken = tokenService.CreateToken(userInDb, await userManager.GetRolesAsync(managedUser)); + await context.SaveChangesAsync(); + + return Ok(new AuthResponse + { + Message = "", + Succeeded = true, + Token = accessToken + }); + } +} \ No newline at end of file diff --git a/Marechai.Server/Marechai.Server.csproj b/Marechai.Server/Marechai.Server.csproj index d4ee83db..a9d21b16 100644 --- a/Marechai.Server/Marechai.Server.csproj +++ b/Marechai.Server/Marechai.Server.csproj @@ -15,6 +15,7 @@ +