114 lines
4.3 KiB
C#
114 lines
4.3 KiB
C#
using Microsoft.AspNetCore.Identity;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using T120B165_ImgBoard.Dtos;
|
|
using T120B165_ImgBoard.Models;
|
|
using T120B165_ImgBoard.Services;
|
|
|
|
namespace T120B165_ImgBoard.Controllers;
|
|
|
|
|
|
[ApiController]
|
|
[Route("api/auth")]
|
|
public class AuthController(UserManager<User> userManager, ITokenService tokenService): ControllerBase
|
|
{
|
|
|
|
/// <summary>
|
|
/// Creates a new user account.
|
|
/// </summary>
|
|
/// <param name="dto">Registration data</param>
|
|
/// <response code="200">Returns user data</response>
|
|
/// <response code="400">If user supplied credentials fail validation</response>
|
|
[HttpPost("register")]
|
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
|
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
|
[ProducesResponseType(StatusCodes.Status422UnprocessableEntity)]
|
|
public async Task<ActionResult<SlimUserDto>> Register(RegisterDto dto)
|
|
{
|
|
var user = new User
|
|
{
|
|
UserName = dto.UserName,
|
|
Email = dto.Email,
|
|
};
|
|
|
|
var result = await userManager.CreateAsync(user, dto.Password);
|
|
await userManager.AddToRoleAsync(user, UserRoles.Regular);
|
|
|
|
Dictionary<string, object> idk = new()
|
|
{
|
|
["errors"] = result.Errors
|
|
};
|
|
|
|
if (!result.Succeeded)
|
|
{
|
|
return Problem(
|
|
statusCode: StatusCodes.Status422UnprocessableEntity,
|
|
extensions: idk
|
|
);
|
|
}
|
|
return Ok(SlimUserDto.FromUser(user));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Authenticates and creates a pair of access and refresh tokens.
|
|
/// </summary>
|
|
/// <param name="dto">Data with refresh token</param>
|
|
/// <response code="200">Returns refresh and access tokens</response>
|
|
/// <response code="401">If the credentials are incorrect</response>
|
|
[HttpPost("login")]
|
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
|
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
|
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
|
|
public async Task<ActionResult<TokenDto>> Login(LoginDto dto)
|
|
{
|
|
var user = await userManager.FindByEmailAsync(dto.Email);
|
|
if (user == null || !await userManager.CheckPasswordAsync(user, dto.Password))
|
|
return Unauthorized();
|
|
|
|
var accessToken = await tokenService.GenerateJwtToken(user);
|
|
var refreshToken = await tokenService.GenerateRefreshToken(user);
|
|
return Ok(new TokenDto(AccessToken: accessToken, RefreshToken: refreshToken));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Consume refresh token to create new access and refresh tokens.
|
|
/// </summary>
|
|
/// <param name="dto">Data with refresh token</param>
|
|
/// <response code="200">Returns new refresh and access tokens</response>
|
|
/// <response code="401">If refresh token is missing or is expired</response>
|
|
[HttpPost("refresh")]
|
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
|
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
|
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
|
|
public async Task<ActionResult<TokenDto>> Refresh(RefreshDto dto)
|
|
{
|
|
var token = await tokenService.GetRefreshTokenByValue(dto.RefreshToken);
|
|
if (token == null) return Unauthorized();
|
|
var user = token.User;
|
|
|
|
await tokenService.InvalidateRefreshToken(token);
|
|
|
|
var accessToken = await tokenService.GenerateJwtToken(user);
|
|
var newRefreshToken = await tokenService.GenerateRefreshToken(user);
|
|
return Ok(new TokenDto(AccessToken: accessToken, RefreshToken: newRefreshToken));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Revokes the refresh token.
|
|
/// </summary>
|
|
/// <param name="dto">Data with refresh token</param>
|
|
/// <response code="204">If token was revoked successfully</response>
|
|
/// <response code="401">If refresh token is missing or is expired</response>
|
|
[HttpPost("revoke")]
|
|
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
|
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
|
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
|
|
public async Task<ActionResult<TokenDto>> Revoke(RefreshDto dto)
|
|
{
|
|
var token = await tokenService.GetRefreshTokenByValue(dto.RefreshToken);
|
|
if (token == null) return Unauthorized();
|
|
|
|
await tokenService.InvalidateRefreshToken(token);
|
|
return NoContent();
|
|
}
|
|
}
|