Initial commit: HelpDesk ICHN - .NET 10 backend + Next.js 16 frontend

This commit is contained in:
Nurfog committed 2026-09-10 10:20:51 -03:00
commit 359f0caf85
90 files changed
+13395

No files matched your search

@@ -0,0 +1,115 @@
using System.Security.Claims;
using HelpDesk.API.Services;
using HelpDesk.Data.Repositories;
using HelpDesk.Models.DTOs;
using HelpDesk.Models.Entities;
using HelpDesk.Models.Enums;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace HelpDesk.API.Controllers;
[ApiController]
[Route("api/[controller]")]
public class AuthController : ControllerBase
{
private readonly IUserRepository _userRepository;
private readonly IJwtService _jwtService;
private readonly IPasswordService _passwordService;
public AuthController(IUserRepository userRepository, IJwtService jwtService, IPasswordService passwordService)
{
_userRepository = userRepository;
_jwtService = jwtService;
_passwordService = passwordService;
}
[HttpPost("login")]
public async Task<ActionResult<AuthResponse>> Login([FromBody] LoginRequest request)
{
if (string.IsNullOrWhiteSpace(request.Email) || string.IsNullOrWhiteSpace(request.Password))
return BadRequest(new { error = "Email and password are required." });
var user = await _userRepository.GetByEmailAsync(request.Email);
if (user == null || !_passwordService.VerifyPassword(request.Password, user.PasswordHash))
return Unauthorized(new { error = "Invalid email or password." });
if (!user.IsActive)
return Unauthorized(new { error = "Account is deactivated." });
var token = _jwtService.GenerateToken(user.Id, user.Email, user.Role);
return Ok(new AuthResponse
{
Token = token,
Expiration = DateTime.UtcNow.AddMinutes(60),
User = MapToDto(user)
});
}
[HttpPost("register")]
public async Task<ActionResult<AuthResponse>> Register([FromBody] RegisterRequest request)
{
if (string.IsNullOrWhiteSpace(request.Email) || string.IsNullOrWhiteSpace(request.Password))
return BadRequest(new { error = "Email and password are required." });
if (string.IsNullOrWhiteSpace(request.FirstName) || string.IsNullOrWhiteSpace(request.LastName))
return BadRequest(new { error = "First name and last name are required." });
if (request.Password.Length < 6)
return BadRequest(new { error = "Password must be at least 6 characters." });
if (await _userRepository.ExistsAsync(request.Email))
return Conflict(new { error = "Email is already registered." });
var user = new User
{
Email = request.Email,
PasswordHash = _passwordService.HashPassword(request.Password),
FirstName = request.FirstName,
LastName = request.LastName,
Role = UserRole.Customer,
CreatedAt = DateTime.UtcNow
};
var created = await _userRepository.CreateAsync(user);
var token = _jwtService.GenerateToken(created.Id, created.Email, created.Role);
return CreatedAtAction(nameof(GetMe), new AuthResponse
{
Token = token,
Expiration = DateTime.UtcNow.AddMinutes(60),
User = MapToDto(created)
});
}
[Authorize]
[HttpGet("me")]
public async Task<ActionResult<UserDto>> GetMe()
{
var userId = GetUserId();
if (userId == null) return Unauthorized();
var user = await _userRepository.GetByIdAsync(userId.Value);
if (user == null) return NotFound(new { error = "User not found." });
return Ok(MapToDto(user));
}
private Guid? GetUserId()
{
var claim = User.FindFirst("userId") ?? User.FindFirst(ClaimTypes.NameIdentifier);
return claim != null && Guid.TryParse(claim.Value, out var id) ? id : null;
}
private static UserDto MapToDto(User user) => new()
{
Id = user.Id,
Email = user.Email,
FirstName = user.FirstName,
LastName = user.LastName,
Role = user.Role,
IsActive = user.IsActive,
CreatedAt = user.CreatedAt,
PhoneNumber = user.PhoneNumber,
AvatarUrl = user.AvatarUrl
};
}