116 lines
4.0 KiB
C#
116 lines
4.0 KiB
C#
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
|
|
};
|
|
}
|