Newer
Older
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using UserMicroservice.Models;
using UserMicroservice.Services;
namespace UserMicroservice.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class UserController : ControllerBase
{
private readonly IUserService _userService;
private readonly IAuthService _authService;
public UserController(IUserService userService, IAuthService authService)
{
_userService = userService;
_authService = authService;
}
#region Auth Endpoints
[HttpPost("register")]
public IActionResult Register([FromBody] RegisterModel model)
{
try
{
User user = _userService.CreateUser(model.Email, model.Username, model.Password, model.UserType);
if (user == null)
return BadRequest();
setAuthCookies(user.Id);
return Ok(new { user.Id, user.Username, user.Email, user.Type });
}
catch (InvalidOperationException ex)
{
return BadRequest(ex.Message);
}
}
// POST: api/User/authorize
[HttpPost("authorize")]
public IActionResult Authorize()
{
string? refreshToken = Request.Cookies["RefreshToken"];
if (string.IsNullOrEmpty(refreshToken))
return BadRequest("Refresh token is missing.");
if (!_authService.ValidateRefreshToken(refreshToken))
return Unauthorized("Invalid or expired refresh token.");
string? userIdString = User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier)?.Value;
if(userIdString == null)
if (!int.TryParse(userIdString, out int userId))
return BadRequest("User ID is invalid.");
User? user = _userService.GetUser(userId);
if(user == null)
return Unauthorized();
setAuthCookies(userId);
return Ok(new { user.Id, user.Username, user.Email, user.Type });
[HttpPost("login")]
public IActionResult Login([FromBody] LoginModel model)
{
User? user = _userService.GetUser(model.Username, model.Password);
if(user == null)
return Unauthorized();
setAuthCookies(user.Id);
return Ok(new { user.Id, user.Username, user.Email, user.Type });
private void setAuthCookies(int userId)
AuthTokenPair authToken = _authService.AuthenticateUser(userId);
throw new ArgumentNullException(nameof(authToken));
// Set the access token as an HttpOnly cookie
Response.Cookies.Append("AccessToken", authToken.AccessToken, new CookieOptions
{
HttpOnly = true,
Secure = true,
SameSite = SameSiteMode.Strict,
Expires = DateTimeOffset.UtcNow.AddMinutes(30)
});
// Set the refresh token as an HttpOnly cookie
Response.Cookies.Append("RefreshToken", authToken.RefreshToken, new CookieOptions
{
HttpOnly = true,
Secure = true,
SameSite = SameSiteMode.Strict,
Expires = DateTimeOffset.UtcNow.AddDays(2)
});
}
[Authorize]
[HttpPost("logout")]
public IActionResult Logout()
{
string? refreshToken = Request.Cookies["RefreshToken"];
if(string.IsNullOrEmpty(refreshToken))
return BadRequest("Refresh token is missing.");
if (!_authService.ValidateRefreshToken(refreshToken))
return Unauthorized("Invalid or expired refresh token.");
_authService.RevokeRefreshToken(refreshToken);
// Clear the access token cookie and set it to expire immediately
Response.Cookies.Append("AccessToken", string.Empty, new CookieOptions
{
HttpOnly = true,
Secure = true,
Expires = DateTimeOffset.UtcNow.AddSeconds(-1)
});
// Clear the refresh token cookie and set it to expire immediately
Response.Cookies.Append("RefreshToken", string.Empty, new CookieOptions
{
HttpOnly = true,
Secure = true,
Expires = DateTimeOffset.UtcNow.AddSeconds(-1)
});
return Ok();
}
#endregion
[Authorize]
[HttpGet()]
public IActionResult GetUsers()
{
List<User> users = _userService.GetUsers();
if(users == null)
return BadRequest();
return Ok(users);
}
[Authorize]
[HttpGet("{id}")]
public IActionResult GetUser(int id)
{
User? user = _userService.GetUser(id);
if(user == null)
return NotFound($"User with {id} doesnt exist");
return Ok(new{ user.Id, user.Username, user.Email, user.Type });
}
// PUT: api/User/{id}
[Authorize]
[HttpPatch("{id}")]
public IActionResult UpdateUser(int id, [FromBody] UpdateUserModel model)
{
try
{
_userService.UpdateUser(id, model.Username, model.Email, model.Password);
return Ok();
}
catch (KeyNotFoundException exception)
{
return NotFound(exception.Message);
}
catch (DbUpdateException exception)
{
return BadRequest(exception.Message);
}