initial commit from an older template
This commit is contained in:
486
Controllers/AuthController.cs
Executable file
486
Controllers/AuthController.cs
Executable file
@@ -0,0 +1,486 @@
|
||||
using GamificationService.Models.BasicResponses;
|
||||
using GamificationService.Models.Database;
|
||||
using GamificationService.Models.DTO;
|
||||
using GamificationService.Services.JWT;
|
||||
using GamificationService.Services.NotificationService;
|
||||
using GamificationService.Utils;
|
||||
using GamificationService.Utils.Factory;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace GamificationService.Controllers;
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
public class AuthController : ControllerBase
|
||||
{
|
||||
#region Services
|
||||
|
||||
private readonly ILogger<AuthController> _logger;
|
||||
private readonly UserManager<ApplicationUser> _userManager;
|
||||
private readonly SignInManager<ApplicationUser> _signInManager;
|
||||
private readonly IJwtService _jwtService;
|
||||
private readonly INotificationService _notificationService;
|
||||
private readonly MailNotificationsFactory _mailNotificationsFactory;
|
||||
private readonly PushNotificationsFactory _pushNotificationsFactory;
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
|
||||
public AuthController(ILogger<AuthController> logger, UserManager<ApplicationUser> userManager, SignInManager<ApplicationUser> signInManager, IJwtService jwtService, INotificationService notificationService, MailNotificationsFactory mailNotificationsFactory, PushNotificationsFactory pushNotificationsFactory)
|
||||
{
|
||||
_logger = logger;
|
||||
_userManager = userManager;
|
||||
_signInManager = signInManager;
|
||||
_jwtService = jwtService;
|
||||
_notificationService = notificationService;
|
||||
_mailNotificationsFactory = mailNotificationsFactory;
|
||||
_pushNotificationsFactory = pushNotificationsFactory;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Actions
|
||||
|
||||
#region Auth
|
||||
|
||||
/// <summary>
|
||||
/// Handles user registration.
|
||||
/// </summary>
|
||||
/// <param name="model">The registration model.</param>
|
||||
/// <returns>A response indicating the result of the registration.</returns>
|
||||
[HttpPost("register")]
|
||||
public async Task<IActionResult> Register([FromBody] AuthDTO model)
|
||||
{
|
||||
try
|
||||
{
|
||||
var user = new ApplicationUser()
|
||||
{
|
||||
UserName = model.Username,
|
||||
Email = model.Email,
|
||||
TwoFactorEnabled = false,
|
||||
TwoFactorProviders = new List<TwoFactorProvider>() { TwoFactorProvider.NONE }
|
||||
};
|
||||
|
||||
var result = await _userManager.CreateAsync(user, model.Password);
|
||||
|
||||
if (!result.Succeeded)
|
||||
{
|
||||
_logger.LogError("User registration failed: {Errors}", result.Errors);
|
||||
return BadRequest(new BasicResponse
|
||||
{
|
||||
Code = 400,
|
||||
Message = "User registration failed"
|
||||
});
|
||||
}
|
||||
|
||||
_logger.LogInformation("User registered successfully: {Username}", model.Username);
|
||||
return Ok(new BasicResponse
|
||||
{
|
||||
Code = 200,
|
||||
Message = "User created successfully"
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "An error occurred during user registration: {Message}", ex.Message);
|
||||
return StatusCode(500, new BasicResponse
|
||||
{
|
||||
Code = 500,
|
||||
Message = "An error occurred during user registration"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Handles user login.
|
||||
/// </summary>
|
||||
/// <param name="model">The login model.</param>
|
||||
/// <returns>A response indicating the result of the login.</returns>
|
||||
[HttpPost("login")]
|
||||
public async Task<IActionResult> Login([FromBody] AuthDTO model)
|
||||
{
|
||||
try
|
||||
{
|
||||
var user = await _userManager.FindByNameAsync(model.Username);
|
||||
|
||||
if (user == null)
|
||||
{
|
||||
_logger.LogError("Invalid username or password");
|
||||
return NotFound(new BasicResponse
|
||||
{
|
||||
Code = 404,
|
||||
Message = "Invalid username or password"
|
||||
});
|
||||
}
|
||||
var result = await _signInManager.PasswordSignInAsync( user, model.Password, false, model.RememberMe);
|
||||
|
||||
if (result.Succeeded & !result.RequiresTwoFactor)
|
||||
{
|
||||
var refreshToken = await _jwtService.GenerateRefreshTokenAsync(user);
|
||||
var accessToken = _jwtService.GenerateAccessToken(user);
|
||||
_logger.LogInformation("User logged in successfully: {Username}", model.Username);
|
||||
|
||||
return Ok(new LoginResultResponse()
|
||||
{
|
||||
RequiresTwoFactorAuth = false,
|
||||
Success = true,
|
||||
Token = new RefreshTokenDTO()
|
||||
{
|
||||
AccessToken = accessToken,
|
||||
RefreshToken = refreshToken.Token
|
||||
}
|
||||
});
|
||||
}
|
||||
else if(result.RequiresTwoFactor)
|
||||
{
|
||||
var providerWithMaxWeight = user.TwoFactorProviders
|
||||
.OrderByDescending(p => (int)p)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (providerWithMaxWeight == TwoFactorProvider.NONE)
|
||||
{
|
||||
_logger.LogInformation("User {Username} does not have any two-factor authentication enabled", model.Username);
|
||||
return StatusCode(418, new LoginResultResponse()
|
||||
{
|
||||
RequiresTwoFactorAuth = false,
|
||||
Success = true,
|
||||
TwoFactorProvider = (int)providerWithMaxWeight
|
||||
});
|
||||
}
|
||||
|
||||
var code = await _userManager.GenerateTwoFactorTokenAsync(user, providerWithMaxWeight.ToString());
|
||||
await SendNotificationAsync(user, "Two-factor authentication code", code, NotificationInformationType.AUTH,providerWithMaxWeight);
|
||||
_logger.LogInformation("Two-factor authentication required for user {Username}", model.Username);
|
||||
return Ok(new LoginResultResponse()
|
||||
{
|
||||
RequiresTwoFactorAuth = true,
|
||||
Success = true
|
||||
});
|
||||
}
|
||||
|
||||
_logger.LogError("Invalid username or password");
|
||||
return BadRequest(new BasicResponse
|
||||
{
|
||||
Code = 400,
|
||||
Message = "Invalid username or password"
|
||||
});
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "An error occurred during user login: {Message}", ex.Message);
|
||||
return StatusCode(500, new BasicResponse
|
||||
{
|
||||
Code = 500,
|
||||
Message = "An error occurred during user login"
|
||||
});
|
||||
}
|
||||
}
|
||||
[HttpPost("logout")]
|
||||
[Authorize]
|
||||
public async Task<IActionResult> Logout()
|
||||
{
|
||||
await _signInManager.SignOutAsync();
|
||||
return Ok("Logged out successfully");
|
||||
}
|
||||
|
||||
[HttpPost("revoke-token")]
|
||||
[Authorize]
|
||||
public async Task<IActionResult> RevokeToken()
|
||||
{
|
||||
var user = await _userManager.GetUserAsync(User);
|
||||
if (user == null)
|
||||
{
|
||||
return NotFound("User not found");
|
||||
}
|
||||
|
||||
await _jwtService.RevokeRefreshTokenAsync(user.Id, HttpContext.Request.Cookies["refresh_token"],GetRemoteIpAddress());
|
||||
return Ok("Token revoked successfully");
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Email
|
||||
|
||||
[HttpGet("{username}/init-email-verification")]
|
||||
public async Task<IActionResult> VerifyEmail(string username)
|
||||
{
|
||||
try
|
||||
{
|
||||
var user = await _userManager.FindByNameAsync(username);
|
||||
if (user == null)
|
||||
{
|
||||
_logger.LogError("Invalid username or password");
|
||||
return NotFound(new BasicResponse
|
||||
{
|
||||
Code = 404,
|
||||
Message = "Invalid username or password"
|
||||
});
|
||||
}
|
||||
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
|
||||
await SendNotificationAsync(user, "Email verification code", code, NotificationInformationType.AUTH, TwoFactorProvider.EMAIL);
|
||||
_logger.LogInformation("Email verification code sent to user {Username}", username);
|
||||
return Ok(new BasicResponse()
|
||||
{
|
||||
Code = 200,
|
||||
Message = "Email verification code sent"
|
||||
});
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogError(e, "An error occurred during email verification: {Message}", e.Message);
|
||||
return StatusCode(500, new BasicResponse
|
||||
{
|
||||
Code = 500,
|
||||
Message = "An error occurred during email verification"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet("{username}/verify-email/{code}")]
|
||||
public async Task<IActionResult> VerifyEmail(string username, string code)
|
||||
{
|
||||
try
|
||||
{
|
||||
var user = await _userManager.FindByNameAsync(username);
|
||||
if (user == null)
|
||||
{
|
||||
_logger.LogError("Invalid username or password");
|
||||
return NotFound(new BasicResponse
|
||||
{
|
||||
Code = 404,
|
||||
Message = "Invalid username or password"
|
||||
});
|
||||
}
|
||||
|
||||
var result = await _userManager.ConfirmEmailAsync(user,code);
|
||||
if (result.Succeeded)
|
||||
{
|
||||
_logger.LogInformation("Email verified for user {Username}", username);
|
||||
user.EmailConfirmed = true;
|
||||
await _userManager.UpdateAsync(user);
|
||||
return Ok(new BasicResponse()
|
||||
{
|
||||
Code = 200,
|
||||
Message = "Email verified"
|
||||
});
|
||||
}
|
||||
return BadRequest(new BasicResponse()
|
||||
{
|
||||
Code = 400,
|
||||
Message = "Email verification failed"
|
||||
});
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogError(e, "An error occurred during email verification: {Message}", e.Message);
|
||||
return StatusCode(500, new BasicResponse
|
||||
{
|
||||
Code = 500,
|
||||
Message = "An error occurred during email verification"
|
||||
});
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 2FA
|
||||
|
||||
[HttpPost("get-2fa-code")]
|
||||
public async Task<IActionResult> GetTwoFactorCode([FromBody] GetTwoFactorDTO model)
|
||||
{
|
||||
try
|
||||
{
|
||||
var user = await _userManager.FindByNameAsync(model.Username);
|
||||
|
||||
if (user == null)
|
||||
{
|
||||
_logger.LogError("Invalid username or password");
|
||||
return NotFound(new BasicResponse
|
||||
{
|
||||
Code = 404,
|
||||
Message = "Invalid username or password"
|
||||
});
|
||||
}
|
||||
|
||||
var providerWithRequiredWeight = user.TwoFactorProviders
|
||||
.FirstOrDefault(p => (int)p == model.TwoFactorProvider);
|
||||
var code = await _userManager.GenerateTwoFactorTokenAsync(user, providerWithRequiredWeight.ToString());
|
||||
await SendNotificationAsync(user, "Two-factor authentication code", code, NotificationInformationType.AUTH,providerWithRequiredWeight);
|
||||
_logger.LogInformation("Two-factor authentication code sent to user {Username}", model.Username);
|
||||
|
||||
return Ok(new BasicResponse()
|
||||
{
|
||||
Code = 200,
|
||||
Message = "Code sent successfully"
|
||||
});
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogError(e, e.Message);
|
||||
return StatusCode(500, new BasicResponse()
|
||||
{
|
||||
Code = 500,
|
||||
Message = "Failed to send code"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost("verify-2fa")]
|
||||
public async Task<IActionResult> VerifyTwoFactorCode([FromBody] TwoFactorDTO model)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (model.Username != null)
|
||||
{
|
||||
var user = await _userManager.FindByNameAsync(model.Username);
|
||||
var providerWithRequiredWeight = user.TwoFactorProviders
|
||||
.FirstOrDefault(p => (int)p == model.TwoFactorProvider);
|
||||
var signInResult = _signInManager.TwoFactorSignInAsync(providerWithRequiredWeight.ToString(),
|
||||
model.Code, false, model.RememberMe);
|
||||
|
||||
|
||||
if (!signInResult.Result.Succeeded)
|
||||
{
|
||||
return BadRequest(new BasicResponse()
|
||||
{
|
||||
Code = 400,
|
||||
Message = "Invalid code"
|
||||
});
|
||||
}
|
||||
|
||||
var token = _jwtService.GenerateAccessToken(user);
|
||||
var refreshToken = await _jwtService.GenerateRefreshTokenAsync(user);
|
||||
|
||||
_logger.LogInformation("User logged in successfully: {Username}", model.Username);
|
||||
await SendNotificationAsync(user, "Login successful", "You have successfully logged in", NotificationInformationType.WARNING,TwoFactorProvider.EMAIL);
|
||||
|
||||
return Ok( new LoginResultResponse()
|
||||
{
|
||||
RequiresTwoFactorAuth = false,
|
||||
Success = true,
|
||||
Token = new RefreshTokenDTO()
|
||||
{
|
||||
AccessToken = token,
|
||||
RefreshToken = refreshToken.Token
|
||||
}
|
||||
});
|
||||
}
|
||||
_logger.LogError("Username can't be empty");
|
||||
return NotFound(new BasicResponse()
|
||||
{
|
||||
Code = 404,
|
||||
Message = "Username can't be empty"
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "An error occurred during user verification: {Message}", ex.Message);
|
||||
return StatusCode(500, new BasicResponse()
|
||||
{
|
||||
Code = 500,
|
||||
Message = "An error occurred during user verification"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost("enable-2fa")]
|
||||
[Authorize]
|
||||
public async Task<IActionResult> EnableTwoFactor([FromBody]EnableTwoFactorDTO model)
|
||||
{
|
||||
var user = await _userManager.GetUserAsync(User);
|
||||
if (user == null)
|
||||
{
|
||||
return NotFound(new BasicResponse()
|
||||
{
|
||||
Code = 404,
|
||||
Message = "User not found"
|
||||
});
|
||||
}
|
||||
|
||||
user.TwoFactorProviders.Add((TwoFactorProvider)model.TwoFactorProvider);
|
||||
user.TwoFactorEnabled = true;
|
||||
await _userManager.UpdateAsync(user);
|
||||
var secretKey = await _userManager.GenerateTwoFactorTokenAsync(user, TwoFactorProvider.AUTHENTICATOR.ToString());
|
||||
_logger.LogInformation("User logged in successfully: {Username}", User);
|
||||
await SendNotificationAsync(user, "Login successful", "You have successfully logged in", NotificationInformationType.WARNING,(TwoFactorProvider)model.TwoFactorProvider);
|
||||
|
||||
return Ok(new BasicResponse()
|
||||
{
|
||||
Code = 200,
|
||||
Message = "Two-factor authentication enabled successfully"
|
||||
});
|
||||
}
|
||||
|
||||
[HttpPost("disable-2fa")]
|
||||
[Authorize]
|
||||
public async Task<IActionResult> DisableTwoFactor([FromBody] DisableTwoFactorDTO model)
|
||||
{
|
||||
var user = await _userManager.GetUserAsync(User);
|
||||
if (user == null)
|
||||
{
|
||||
return NotFound("User not found");
|
||||
}
|
||||
|
||||
if (!await _userManager.VerifyTwoFactorTokenAsync(user,model.TwoFactorProvider.ToString(),model.Code))
|
||||
{
|
||||
return BadRequest("Invalid verification code");
|
||||
}
|
||||
|
||||
user.TwoFactorEnabled = false;
|
||||
await _userManager.UpdateAsync(user);
|
||||
|
||||
return Ok("Two-factor authentication disabled");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helpers
|
||||
|
||||
private async Task SendNotificationAsync(ApplicationUser user,
|
||||
string title,
|
||||
string message,
|
||||
NotificationInformationType notificationInformationType,
|
||||
TwoFactorProvider provider)
|
||||
{
|
||||
try
|
||||
{
|
||||
switch (provider)
|
||||
{
|
||||
case TwoFactorProvider.EMAIL:
|
||||
await _notificationService.SendMailNotificationAsync(user, _mailNotificationsFactory.CreateNotification(notificationInformationType, title, message));
|
||||
break;
|
||||
case TwoFactorProvider.PHONE:
|
||||
throw new NotImplementedException();
|
||||
break;
|
||||
case TwoFactorProvider.PUSH:
|
||||
await _notificationService.SendPushNotificationAsync(user, _pushNotificationsFactory.CreateNotification(notificationInformationType, title, message));
|
||||
break;
|
||||
case TwoFactorProvider.AUTHENTICATOR:
|
||||
throw new NotImplementedException();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "An error occurred during notification: {Message}", ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private string GetRemoteIpAddress()
|
||||
{
|
||||
if (HttpContext.Connection.RemoteIpAddress != null)
|
||||
{
|
||||
return HttpContext.Connection.RemoteIpAddress.MapToIPv4().ToString();
|
||||
}
|
||||
return string.Empty;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
}
|
||||
166
Controllers/InstructionController.cs
Normal file
166
Controllers/InstructionController.cs
Normal file
@@ -0,0 +1,166 @@
|
||||
using GamificationService.Exceptions.Services.Instruction;
|
||||
using GamificationService.Models.Database;
|
||||
using GamificationService.Models.DTO;
|
||||
using GamificationService.Models.Messages.Instructions;
|
||||
using GamificationService.Services.Instructions;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace GamificationService.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
[Authorize(Policy = "User")]
|
||||
public class InstructionController : ControllerBase
|
||||
{
|
||||
private readonly IInstructionService _instructionService;
|
||||
private readonly UserManager<ApplicationUser> _userManager;
|
||||
private readonly ILogger<InstructionController> _logger;
|
||||
|
||||
public InstructionController(IInstructionService instructionService, UserManager<ApplicationUser> userManager, ILogger<InstructionController> logger)
|
||||
{
|
||||
_instructionService = instructionService;
|
||||
_userManager = userManager;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new instruction.
|
||||
/// </summary>
|
||||
/// <param name="model">The instruction model.</param>
|
||||
/// <returns><see cref="InstructionDTO"/> which was created</returns>
|
||||
/// <response code="200">Returns the created instruction</response>
|
||||
[HttpPost]
|
||||
[Authorize(Policy = "Admin")]
|
||||
public async Task<IActionResult> CreateInstruction([FromBody] CreateInstructionRequest model)
|
||||
{
|
||||
var instruction = await _instructionService.CreateInstruction(model);
|
||||
return Ok(instruction);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update an existing instruction.
|
||||
/// </summary>
|
||||
/// <param name="model">The instruction model. Id must match the object which is being updated.</param>
|
||||
/// <returns><see cref="bool"/></returns>
|
||||
/// <response code="200"></response>
|
||||
/// <response code="404">If the instruction is not found</response>
|
||||
[HttpPut]
|
||||
[Authorize(Policy = "Admin")]
|
||||
public async Task<IActionResult> UpdateInstruction([FromBody] UpdateInstructionRequest model)
|
||||
{
|
||||
var instruction = await _instructionService.UpdateInstructionById(model);
|
||||
return Ok(instruction);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Delete an existing instruction.
|
||||
/// </summary>
|
||||
/// <param name="id">The ID of the instruction to delete.</param>
|
||||
/// <returns><see cref="bool"/></returns>
|
||||
/// <response code="200"></response>
|
||||
/// <response code="404">If the instruction is not found</response>
|
||||
[HttpDelete]
|
||||
[Authorize(Policy = "Admin")]
|
||||
public async Task<IActionResult> DeleteInstruction(long id)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Ok(await _instructionService.DeleteInstructionById(id));
|
||||
}
|
||||
catch (InstructionNotFoundException)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve all instructions for the authenticated user.
|
||||
/// </summary>
|
||||
/// <returns>A list of <see cref="InstructionDTO"/> for the user.</returns>
|
||||
/// <response code="200">Returns the list of all instructions</response>
|
||||
[HttpGet("all")]
|
||||
public async Task<IActionResult> GetAllInstructions()
|
||||
{
|
||||
string username = User.Claims.First(c => c.Type == "username").Value;
|
||||
long userId = (await _userManager.FindByNameAsync(username))!.Id;
|
||||
|
||||
return Ok(_instructionService.GetAllInstructions(userId));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve all completed instructions for the authenticated user.
|
||||
/// </summary>
|
||||
/// <returns>A list of <see cref="InstructionDTO"/> that are completed for the user.</returns>
|
||||
/// <response code="200">Returns the list of completed instructions</response>
|
||||
[HttpGet("completed")]
|
||||
public async Task<IActionResult> GetCompletedInstructions()
|
||||
{
|
||||
string username = User.Claims.First(c => c.Type == "username").Value;
|
||||
long userId = (await _userManager.FindByNameAsync(username))!.Id;
|
||||
|
||||
return Ok(_instructionService.GetCompletedInstructions(userId));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve all unfinished instructions for the authenticated user.
|
||||
/// </summary>
|
||||
/// <returns>A list of <see cref="InstructionDTO"/> that are unfinished for the user.</returns>
|
||||
/// <response code="200">Returns the list of unfinished instructions</response>
|
||||
[HttpGet("unfinished")]
|
||||
public async Task<IActionResult> GetUnfinishedInstructions()
|
||||
{
|
||||
string username = User.Claims.First(c => c.Type == "username").Value;
|
||||
long userId = (await _userManager.FindByNameAsync(username))!.Id;
|
||||
|
||||
return Ok(_instructionService.GetUnfinishedInstructions(userId));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve instructions by category ID for the authenticated user.
|
||||
/// </summary>
|
||||
/// <param name="id">The ID of the category to filter instructions.</param>
|
||||
/// <returns>A list of <see cref="InstructionDTO"/> for the specified category.</returns>
|
||||
/// <response code="200">Returns the list of instructions for the specified category</response>
|
||||
/// <response code="404">If the category is not found</response>
|
||||
[HttpGet("category/{id}")]
|
||||
public async Task<IActionResult> GetInstructionsByCategoryId(long id)
|
||||
{
|
||||
try
|
||||
{
|
||||
string username = User.Claims.First(c => c.Type == "username").Value;
|
||||
long userId = (await _userManager.FindByNameAsync(username))!.Id;
|
||||
|
||||
return Ok(_instructionService.GetInstructionsByCategoryId(userId, id));
|
||||
}
|
||||
catch (CategoryNotFoundException)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve a specific instruction by its ID for the authenticated user.
|
||||
/// </summary>
|
||||
/// <param name="id">The ID of the instruction to retrieve.</param>
|
||||
/// <returns><see cref="InstructionDTO"/> for the specified instruction.</returns>
|
||||
/// <response code="200">Returns the instruction with the specified ID</response>
|
||||
/// <response code="404">If the instruction is not found</response>
|
||||
[HttpGet("{id}")]
|
||||
public async Task<IActionResult> GetInstructionById(long id)
|
||||
{
|
||||
try
|
||||
{
|
||||
string username = User.Claims.First(c => c.Type == "username").Value;
|
||||
long userId = (await _userManager.FindByNameAsync(username))!.Id;
|
||||
|
||||
return Ok(_instructionService.GetInstructionById(userId, id));
|
||||
}
|
||||
catch(InstructionNotFoundException)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
278
Controllers/InstructionTestController.cs
Normal file
278
Controllers/InstructionTestController.cs
Normal file
@@ -0,0 +1,278 @@
|
||||
using AutoMapper;
|
||||
using GamificationService.Exceptions.Services.Instruction;
|
||||
using GamificationService.Exceptions.Services.InstructionTest;
|
||||
using GamificationService.Models.BasicResponses;
|
||||
using GamificationService.Models.Database;
|
||||
using GamificationService.Models.DTO;
|
||||
using GamificationService.Services.InstructionTests;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace GamificationService.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
[Authorize(Policy = "User")]
|
||||
public class InstructionTestController : ControllerBase
|
||||
{
|
||||
private readonly IInstructionTestsService _instructionTestsService;
|
||||
private readonly UserManager<ApplicationUser> _userManager;
|
||||
private readonly ILogger<InstructionTestController> _logger;
|
||||
private readonly IMapper _mapper;
|
||||
|
||||
public InstructionTestController(IInstructionTestsService instructionTestsService, UserManager<ApplicationUser> userManager, ILogger<InstructionTestController> logger, IMapper mapper)
|
||||
{
|
||||
_instructionTestsService = instructionTestsService;
|
||||
_userManager = userManager;
|
||||
_logger = logger;
|
||||
_mapper = mapper;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an instruction test by its ID.
|
||||
/// </summary>
|
||||
/// <param name="id">The ID of the instruction test.</param>
|
||||
/// <returns>An <see cref="InstructionTestDTO"/> containing the instruction test DTO if found, or a 404 Not Found if not found.</returns>
|
||||
/// <response code="200">Returns the instruction test DTO</response>
|
||||
/// <response code="404">If the instruction test is not found</response>
|
||||
[HttpGet("{id}")]
|
||||
public IActionResult GetInstructionTestById(long id)
|
||||
{
|
||||
// TODO: verify admin access / user ownership
|
||||
try
|
||||
{
|
||||
var instructionTest = _instructionTestsService.GetInstructionTestById(id);
|
||||
return Ok(_mapper.Map<InstructionTestDTO>(instructionTest));
|
||||
}
|
||||
catch (InstructionTestNotFoundException)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an instruction test by its instruction ID.
|
||||
/// </summary>
|
||||
/// <param name="id">The ID of the instruction.</param>
|
||||
/// <returns>An <see cref="InstructionTestDTO"/> containing the instruction test DTO if found, or a 404 Not Found if not found.</returns>
|
||||
/// <response code="200">Returns the instruction test DTO</response>
|
||||
/// <response code="404">If the instruction is not found</response>
|
||||
[HttpGet("instruction/{id}")]
|
||||
public IActionResult GetInstructionTestsByInstructionId(long id)
|
||||
{
|
||||
// TODO: verify admin access / user ownership
|
||||
try
|
||||
{
|
||||
var instructionTest = _instructionTestsService.GetInstructionTestsByInstructionId(id);
|
||||
return Ok(_mapper.Map<InstructionTestDTO>(instructionTest));
|
||||
}
|
||||
catch (InstructionTestNotFoundException)
|
||||
{
|
||||
return Ok(new List<InstructionTestDTO>());
|
||||
}
|
||||
catch (InstructionNotFoundException)
|
||||
{
|
||||
return NotFound(new BasicResponse()
|
||||
{
|
||||
Code = 404,
|
||||
Message = "Instruction not found"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all instruction test questions by instruction test ID.
|
||||
/// </summary>
|
||||
/// <param name="instructionTestId">The ID of the instruction test.</param>
|
||||
/// <returns>A list of <see cref="InstructionTestQuestionDTO"/> containing the instruction test questions if found, or a 404 Not Found if not found.</returns>
|
||||
/// <response code="200">Returns the instruction test questions</response>
|
||||
/// <response code="404">If the instruction test questions are not found</response>
|
||||
[HttpGet("{instructionTestId}/questions")]
|
||||
public IActionResult GetInstructionTestQuestionsByInstructionTestId(long instructionTestId)
|
||||
{
|
||||
// TODO: verify admin access / user ownership
|
||||
try
|
||||
{
|
||||
var instructionTestQuestions = _instructionTestsService.GetInstructionTestQuestionsByInstructionTestId(instructionTestId);
|
||||
return Ok(instructionTestQuestions);
|
||||
}
|
||||
catch (InstructionTestNotFoundException)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all instruction test results for authorized user by instruction ID.
|
||||
/// </summary>
|
||||
/// <param name="instructionTestId">The ID of the instruction.</param>
|
||||
/// <returns>A list of <see cref="InstructionTestResultDTO"/> containing the instruction test results if found, or a 404 Not Found if not found.</returns>
|
||||
/// <response code="200">Returns the instruction test results</response>
|
||||
/// <response code="404">If the instruction test results are not found</response>
|
||||
[HttpGet("/{instructionTestId}/results")]
|
||||
public async Task<IActionResult> GetUserInstructionTestResultsByInstructionTestId(long instructionTestId)
|
||||
{
|
||||
// TODO: verify user ownership
|
||||
string username = User.Claims.First(c => c.Type == "username").Value;
|
||||
long userId = (await _userManager.FindByNameAsync(username))!.Id;
|
||||
|
||||
try
|
||||
{
|
||||
var instructionTestResults = _instructionTestsService.GetUserInstructionTestResultsByInstructionTestId(userId, instructionTestId);
|
||||
return Ok(instructionTestResults);
|
||||
}
|
||||
catch (InstructionTestNotFoundException)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all instruction test results for a specific user by instruction test ID (admin access).
|
||||
/// </summary>
|
||||
/// <param name="userId">The ID of the user whose results are being requested.</param>
|
||||
/// <param name="instructionTestId">The ID of the instruction.</param>
|
||||
/// <returns>A list of <see cref="InstructionTestResultDTO"/> containing the instruction test results if found, or a 404 Not Found if not found.</returns>
|
||||
/// <response code="200">Returns the instruction test results</response>
|
||||
/// <response code="404">If the instruction test results are not found</response>
|
||||
/// <response code="403">If the user is not an admin</response>
|
||||
[HttpGet("{instructionTestId}/user/{userId}/results")]
|
||||
[Authorize(Roles = "Admin")]
|
||||
public IActionResult GetInstructionTestResultsForUserByInstructionTestId(long userId, long instructionTestId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var instructionTestResults = _instructionTestsService.GetUserInstructionTestResultsByInstructionTestId(userId, instructionTestId);
|
||||
return Ok(instructionTestResults);
|
||||
}
|
||||
catch (InstructionTestNotFoundException)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all instruction test results for a user by user ID.
|
||||
/// </summary>
|
||||
/// <param name="id">The ID of the user.</param>
|
||||
/// <returns>A list of <see cref="InstructionTestResultDTO"/> containing the instruction test results if found, or a 404 Not Found if not found.</returns>
|
||||
/// <response code="200">Returns the instruction test results</response>
|
||||
/// <response code="404">If the instruction test results are not found</response>
|
||||
[HttpGet("user/{id}/results")]
|
||||
public IActionResult GetInstructionTestResultsByUserId(long id)
|
||||
{
|
||||
// TODO: verify admin access / user ownership
|
||||
try
|
||||
{
|
||||
var instructionTestResults = _instructionTestsService.GetInstructionTestResultsByUserId(id);
|
||||
return Ok(instructionTestResults);
|
||||
}
|
||||
catch (InstructionTestNotFoundException)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all completed instruction test results for a user by user ID.
|
||||
/// </summary>
|
||||
/// <param name="id">The ID of the user.</param>
|
||||
/// <returns>A list of <see cref="InstructionTestResultDTO"/> containing the instruction test results if found, or a 404 Not Found if not found.</returns>
|
||||
/// <response code="200">Returns the instruction test results</response>
|
||||
/// <response code="404">If the instruction test results are not found</response>
|
||||
[HttpGet("user/{id}/completed")]
|
||||
public IActionResult GetCompletedInstructionTestsByUserId(long id)
|
||||
{
|
||||
// TODO: verify admin access / user ownership
|
||||
try
|
||||
{
|
||||
var instructionTestResults = _instructionTestsService.GetCompletedInstructionTestsByUserId(id);
|
||||
return Ok(instructionTestResults);
|
||||
}
|
||||
catch (InstructionTestNotFoundException)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instruction test.
|
||||
/// </summary>
|
||||
/// <param name="model">The instruction test model.</param>
|
||||
/// <returns>A <see cref="InstructionTestDTO"/> containing the created instruction test if successful, or a 500 Internal Server Error if not successful.</returns>
|
||||
/// <response code="200">Returns the created instruction test</response>
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> CreateInstructionTest([FromBody] InstructionTestCreateDTO model)
|
||||
{
|
||||
try
|
||||
{
|
||||
var instructionTest = await _instructionTestsService.CreateInstructionTest(model);
|
||||
return Ok(instructionTest);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return StatusCode(500, "Failed to create instruction test");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates an existing instruction test.
|
||||
/// </summary>
|
||||
/// <param name="model">The instruction test model.</param>
|
||||
/// <returns>A <see cref="InstructionTestDTO"/> containing the updated instruction test if successful, or a 500 Internal Server Error if not successful.</returns>
|
||||
/// <response code="200">Returns the updated instruction test</response>
|
||||
[HttpPut]
|
||||
[Authorize(Policy = "Admin")]
|
||||
public async Task<IActionResult> UpdateInstructionTest([FromBody] InstructionTestCreateDTO model)
|
||||
{
|
||||
try
|
||||
{
|
||||
var instructionTest = await _instructionTestsService.UpdateInstructionTest(model);
|
||||
return Ok(instructionTest);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return StatusCode(500, "Failed to update instruction test");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes an existing instruction test.
|
||||
/// </summary>
|
||||
/// <param name="id">The ID of the instruction test to delete.</param>
|
||||
/// <returns>A <see cref="bool"/></returns>
|
||||
/// <response code="200">Returns the deletion status.</response>
|
||||
[HttpDelete("{id}")]
|
||||
[Authorize(Policy = "Admin")]
|
||||
public async Task<IActionResult> DeleteInstructionTest(long id)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _instructionTestsService.DeleteInstructionTestByIdAsync(id);
|
||||
return Ok();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return StatusCode(500, "Failed to delete instruction test");
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost("submit")]
|
||||
public async Task<IActionResult> SubmitInstructionTest([FromBody] InstructionTestSubmissionDTO model)
|
||||
{
|
||||
// TODO: verify user access
|
||||
string username = User.Claims.First(c => c.Type == "username").Value;
|
||||
long userId = (await _userManager.FindByNameAsync(username))!.Id;
|
||||
|
||||
try
|
||||
{
|
||||
await _instructionTestsService.SubmitInstructionTestAsync(userId, model);
|
||||
return Ok();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return StatusCode(500, "Failed to submit instruction test");
|
||||
}
|
||||
}
|
||||
}
|
||||
186
Controllers/RightsController.cs
Normal file
186
Controllers/RightsController.cs
Normal file
@@ -0,0 +1,186 @@
|
||||
using GamificationService.Models.BasicResponses;
|
||||
using GamificationService.Models.DTO;
|
||||
using GamificationService.Services.Rights;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace GamificationService.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
[Authorize(Policy = "Admin")]
|
||||
public class RightsController : ControllerBase
|
||||
{
|
||||
#region Services
|
||||
|
||||
private readonly IRightsService _rightsService;
|
||||
private readonly ILogger<RightsController> _logger;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
|
||||
public RightsController(IRightsService rightsService, ILogger<RightsController> logger)
|
||||
{
|
||||
_rightsService = rightsService;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> GetAllRightsAsync([FromQuery] int pageNumber = 1, [FromQuery] int pageSize = 10)
|
||||
{
|
||||
try
|
||||
{
|
||||
var (rights, totalCount) = await _rightsService.GetAllRightsAsync(pageNumber, pageSize);
|
||||
|
||||
_logger.LogInformation($"Retrieved {rights.Count} rights");
|
||||
|
||||
var response = new GetAllRightsResponse()
|
||||
{
|
||||
Rights = rights,
|
||||
TotalCount = totalCount,
|
||||
PageNumber = pageNumber,
|
||||
PageSize = pageSize
|
||||
};
|
||||
return Ok(response);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogError(e, e.Message);
|
||||
return StatusCode(500, new BasicResponse()
|
||||
{
|
||||
Code = 500,
|
||||
Message = "Failed to get rights.",
|
||||
});
|
||||
}
|
||||
}
|
||||
[HttpGet("{id}")]
|
||||
public async Task<IActionResult> GetRightByIdAsync(long id)
|
||||
{
|
||||
var right = await _rightsService.GetRightByIdAsync(id);
|
||||
_logger.LogInformation($"Retrieved right with id: {id}");
|
||||
if (right == null)
|
||||
{
|
||||
return NotFound(new BasicResponse()
|
||||
{
|
||||
|
||||
Code = 404,
|
||||
Message = "Right not found"
|
||||
|
||||
});
|
||||
}
|
||||
return Ok(right);
|
||||
}
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> CreateRightAsync([FromBody] RightDTO model)
|
||||
{
|
||||
try
|
||||
{
|
||||
var right = await _rightsService.CreateRightAsync(model.Name, model.Description);
|
||||
|
||||
_logger.LogInformation($"Created right: {right}");
|
||||
|
||||
return CreatedAtAction(nameof(CreateRightAsync), new { id = right.Id }, right);
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogError(e, e.Message);
|
||||
return StatusCode(500, new BasicResponse()
|
||||
{
|
||||
Code = 500,
|
||||
Message = "Failed to create right.",
|
||||
});
|
||||
}
|
||||
}
|
||||
[HttpPut("{id}")]
|
||||
public async Task<IActionResult> UpdateRightAsync(long id, [FromBody] RightDTO model)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (await _rightsService.UpdateRightAsync(id, model.Name, model.Description))
|
||||
{
|
||||
_logger.LogInformation($"Updated right: {id}");
|
||||
return Ok(new BasicResponse()
|
||||
{
|
||||
Code = 200,
|
||||
Message = "Rights updated",
|
||||
});
|
||||
}
|
||||
_logger.LogError($"Unknown with right updating, {id}");
|
||||
return StatusCode(418,
|
||||
new BasicResponse()
|
||||
{
|
||||
Code = 418,
|
||||
Message = "Failed to update right."
|
||||
});
|
||||
}
|
||||
catch (KeyNotFoundException)
|
||||
{
|
||||
_logger.LogError($"Right not found, {id} ");
|
||||
return NotFound(new BasicResponse()
|
||||
{
|
||||
Code = 404,
|
||||
Message = "Right not found"
|
||||
});
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogError(e, e.Message);
|
||||
return StatusCode(500, new BasicResponse()
|
||||
{
|
||||
Code = 500,
|
||||
Message = "Failed to update right"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
[HttpDelete("{id}")]
|
||||
public async Task<IActionResult> DeleteRightAsync(long id)
|
||||
{
|
||||
try
|
||||
{
|
||||
if( await _rightsService.DeleteRightAsync(id))
|
||||
{
|
||||
_logger.LogInformation($"Deleted right: {id}");
|
||||
return Ok(new BasicResponse()
|
||||
{
|
||||
Code = 200,
|
||||
Message = "Rights deleted",
|
||||
});
|
||||
}
|
||||
_logger.LogError($"Unknown error with right deleting, {id} ");
|
||||
return StatusCode(418, new BasicResponse()
|
||||
{
|
||||
Code = 418,
|
||||
Message = "Failed to delete right"
|
||||
});
|
||||
|
||||
}
|
||||
catch (KeyNotFoundException)
|
||||
{
|
||||
_logger.LogError($"Role not found, {id} ");
|
||||
return NotFound(new BasicResponse()
|
||||
{
|
||||
Code = 404,
|
||||
Message = "Right not found"
|
||||
});
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogError(e, e.Message);
|
||||
return StatusCode(500, new BasicResponse()
|
||||
{
|
||||
Code = 500,
|
||||
Message = "Failed to delete right"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
283
Controllers/RoleController.cs
Normal file
283
Controllers/RoleController.cs
Normal file
@@ -0,0 +1,283 @@
|
||||
using GamificationService.Models.BasicResponses;
|
||||
using GamificationService.Models.DTO;
|
||||
using GamificationService.Services.Roles;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http.HttpResults;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace GamificationService.Controllers;
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
[Authorize(Policy = "Admin")]
|
||||
public class RoleController : ControllerBase
|
||||
{
|
||||
#region Services
|
||||
|
||||
private readonly IRolesService _rolesService;
|
||||
private readonly ILogger<RoleController> _logger;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
|
||||
public RoleController(ILogger<RoleController> logger, IRolesService rolesService)
|
||||
{
|
||||
_logger = logger;
|
||||
_rolesService = rolesService;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ControllerMethods
|
||||
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> GetAllRolesAsync([FromQuery] int pageNumber = 1, [FromQuery] int pageSize = 10)
|
||||
{
|
||||
try
|
||||
{
|
||||
var (roles, totalCount) = await _rolesService.GetAllRolesAsync(pageNumber, pageSize);
|
||||
_logger.LogInformation($"Roles found successfully, {roles.Count}");
|
||||
var response = new GetAllRolesResponse()
|
||||
{
|
||||
Roles = roles,
|
||||
TotalCount = totalCount,
|
||||
PageNumber = pageNumber,
|
||||
PageSize = pageSize
|
||||
};
|
||||
return Ok(response);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex,ex.Message);
|
||||
return StatusCode(500, new BasicResponse()
|
||||
{
|
||||
Code = 500,
|
||||
Message = "Failed to get roles"
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
[HttpGet("{id}")]
|
||||
public async Task<IActionResult> GetRoleByIdAsync(long id)
|
||||
{
|
||||
var role = await _rolesService.GetRoleByIdAsync(id);
|
||||
_logger.LogInformation($"Role found successfully, {role.Id}");
|
||||
if (role == null)
|
||||
{
|
||||
return NotFound(new BasicResponse()
|
||||
{
|
||||
|
||||
Code = 404,
|
||||
Message = "Role not found"
|
||||
|
||||
});
|
||||
}
|
||||
return Ok(role);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> CreateRoleAsync([FromBody] RoleDTO model)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
var role = await _rolesService.CreateRoleAsync(model.Name, model.Description);
|
||||
_logger.LogInformation($"Role created successfully, {role.Id}");
|
||||
return CreatedAtAction(nameof(CreateRoleAsync), new { id = role.Id }, role);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogError(e, e.Message);
|
||||
return StatusCode(500, new BasicResponse()
|
||||
{
|
||||
Code = 500,
|
||||
Message = "Failed to create role"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[HttpPut("{id}")]
|
||||
public async Task<IActionResult> UpdateRoleAsync(long id, [FromBody] RoleDTO model)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (await _rolesService.UpdateRoleAsync(id, model.Name, model.Description))
|
||||
{
|
||||
_logger.LogInformation($"Role updated successfully, {id}");
|
||||
|
||||
return Ok(new BasicResponse()
|
||||
{
|
||||
Code = 200,
|
||||
Message = "Role updated successfully"
|
||||
});
|
||||
}
|
||||
|
||||
_logger.LogCritical($"Unknown error with role updating, {id}");
|
||||
return StatusCode(418,new BasicResponse()
|
||||
{
|
||||
Code = 418,
|
||||
Message = "Role not found"
|
||||
});
|
||||
|
||||
}
|
||||
catch (KeyNotFoundException)
|
||||
{
|
||||
_logger.LogError($"Role not found, {id} ");
|
||||
return NotFound(new BasicResponse()
|
||||
{
|
||||
Code = 404,
|
||||
Message = "Role not found"
|
||||
});
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogError(e, e.Message);
|
||||
return StatusCode(500, new BasicResponse()
|
||||
{
|
||||
Code = 500,
|
||||
Message = "Failed to update role"
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[HttpDelete("{id}")]
|
||||
public async Task<IActionResult> DeleteRoleAsync(long id)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (await _rolesService.DeleteRoleAsync(id))
|
||||
{
|
||||
|
||||
_logger.LogInformation($"Role updated successfully, {id}");
|
||||
|
||||
return Ok(new BasicResponse()
|
||||
{
|
||||
Code = 200,
|
||||
Message = "Role updated successfully"
|
||||
});
|
||||
}
|
||||
|
||||
_logger.LogCritical($"Unknown error with role deleting, RoleId {id}");
|
||||
return StatusCode(418,new BasicResponse()
|
||||
{
|
||||
Code = 418,
|
||||
Message = "Role not found"
|
||||
});
|
||||
}
|
||||
catch (KeyNotFoundException)
|
||||
{
|
||||
_logger.LogError($"Role not found, {id} ");
|
||||
return NotFound(new BasicResponse()
|
||||
{
|
||||
Code = 404,
|
||||
Message = "Role not found"
|
||||
});
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogError(e, e.Message);
|
||||
return StatusCode(500, new BasicResponse()
|
||||
{
|
||||
Code = 500,
|
||||
Message = "Failed to delete role"
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
[HttpPost("{roleId}/rights/{rightId}")]
|
||||
public async Task<IActionResult> AddRightToRoleAsync(long roleId, long rightId)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (await _rolesService.AddRightToRoleAsync(roleId, rightId))
|
||||
{
|
||||
_logger.LogInformation($"Right added to role successfully, RoleId: {roleId}, RightId: {rightId}");
|
||||
return Ok(new BasicResponse()
|
||||
{
|
||||
Code = 200,
|
||||
Message = "Right added to role successfully"
|
||||
});
|
||||
}
|
||||
|
||||
_logger.LogCritical($"Unknown error with adding right to role, RoleId: {roleId}, RightId: {rightId}");
|
||||
return StatusCode(418,new BasicResponse()
|
||||
{
|
||||
Code = 418,
|
||||
Message = "Right not found for role"
|
||||
});
|
||||
}
|
||||
catch(KeyNotFoundException e)
|
||||
{
|
||||
_logger.LogError(e, e.Message);
|
||||
return NotFound(new BasicResponse()
|
||||
{
|
||||
Code = 404,
|
||||
Message = "Right not found for role"
|
||||
});
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogError(e, e.Message);
|
||||
return StatusCode(500, new BasicResponse()
|
||||
{
|
||||
Code = 500,
|
||||
Message = "Failed to add right to role"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
[HttpDelete("{roleId}/rights/{rightId}")]
|
||||
public async Task<IActionResult> RemoveRightFromRoleAsync(long roleId, long rightId)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
if (await _rolesService.RemoveRightFromRoleAsync(roleId, rightId))
|
||||
{
|
||||
_logger.LogInformation($"Right removed from role successfully, RoleId: {roleId}, RightId: {rightId}");
|
||||
|
||||
return Ok(new BasicResponse()
|
||||
{
|
||||
Code = 200,
|
||||
Message = "Right removed from role successfully"
|
||||
});
|
||||
}
|
||||
|
||||
_logger.LogCritical($"Unknown error with removing right from role, RoleId: {roleId}, RightId: {rightId}");
|
||||
return StatusCode(418, new BasicResponse()
|
||||
{
|
||||
Code = 418,
|
||||
Message = "Right not found right for role"
|
||||
});
|
||||
|
||||
}
|
||||
catch (KeyNotFoundException e)
|
||||
{
|
||||
_logger.LogError(e, e.Message);
|
||||
return NotFound(new BasicResponse()
|
||||
{
|
||||
Code = 404,
|
||||
Message = "Right not found for role"
|
||||
});
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogError(e, e.Message);
|
||||
return StatusCode(500, new BasicResponse()
|
||||
{
|
||||
Code = 500,
|
||||
Message = "Failed to remove right from role"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
184
Controllers/UserProfileController.cs
Normal file
184
Controllers/UserProfileController.cs
Normal file
@@ -0,0 +1,184 @@
|
||||
using AutoMapper;
|
||||
using GamificationService.Exceptions.Services.ProfileService;
|
||||
using GamificationService.Models.Database;
|
||||
using GamificationService.Models.DTO;
|
||||
using GamificationService.Services.UsersProfile;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace GamificationService.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Authorize(Policy = "User")]
|
||||
[Route("api/[controller]")]
|
||||
public class UserProfileController : ControllerBase
|
||||
{
|
||||
private readonly IUserProfileService _userProfilesService;
|
||||
private readonly UserManager<ApplicationUser> _userManager;
|
||||
private readonly ILogger<UserProfileController> _logger;
|
||||
private readonly IMapper _mapper;
|
||||
|
||||
public UserProfileController(IUserProfileService userProfilesService, UserManager<ApplicationUser> userManager, ILogger<UserProfileController> logger, IMapper mapper)
|
||||
{
|
||||
_userProfilesService = userProfilesService;
|
||||
_userManager = userManager;
|
||||
_logger = logger;
|
||||
_mapper = mapper;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a user profile by its ID.
|
||||
/// </summary>
|
||||
/// <param name="username">The username of the user profile's owner.</param>
|
||||
/// <returns>An <see cref="UserProfileDTO"/> containing the user profile DTO if found, or a 404 Not Found if not found.</returns>
|
||||
/// <response code="200">Returns the user profile DTO</response>
|
||||
/// <response code="404">If the user profile is not found</response>
|
||||
[HttpGet("user/{username}")]
|
||||
public async Task<IActionResult> GetUserProfileByUsername(string username)
|
||||
{
|
||||
try
|
||||
{
|
||||
var user = (await _userManager.FindByNameAsync(username));
|
||||
if (user == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
var userProfile = _userProfilesService.GetUserProfileByUserId(user.Id);
|
||||
return Ok(_mapper.Map<UserProfileDTO>(userProfile));
|
||||
}
|
||||
catch (ProfileNotFoundException)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a user profile by its ID.
|
||||
/// </summary>
|
||||
/// <param name="id">The ID of the user profile.</param>
|
||||
/// <returns>An <see cref="UserProfileDTO"/> containing the user profile DTO if found, or a 404 Not Found if not found.</returns>
|
||||
/// <response code="200">Returns the user profile DTO</response>
|
||||
/// <response code="404">If the user profile is not found</response>
|
||||
[HttpGet("{id}")]
|
||||
public IActionResult GetUserProfileById(long id)
|
||||
{
|
||||
try
|
||||
{
|
||||
var userProfile = _userProfilesService.GetUserProfileById(id);
|
||||
return Ok(_mapper.Map<UserProfileDTO>(userProfile));
|
||||
}
|
||||
catch (ProfileNotFoundException)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new user profile.
|
||||
/// </summary>
|
||||
/// <param name="username">The username of the user.</param>
|
||||
/// <param name="model">The user profile model.</param>
|
||||
/// <returns>A <see cref="UserProfileDTO"/> containing the created user profile if successful, or a 500 Internal Server Error if not successful.</returns>
|
||||
/// <response code="200">Returns the created user profile</response>
|
||||
/// <response code="404">If the user is not found</response>
|
||||
[HttpPost("user/{username}")]
|
||||
[Authorize(Policy = "Admin")]
|
||||
public async Task<IActionResult> AddUserProfile(string username, [FromBody] UserProfileCreateDTO model)
|
||||
{
|
||||
var user = (await _userManager.FindByNameAsync(username));
|
||||
if (user == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var userProfile = await _userProfilesService.AddUserProfile(user.Id, model);
|
||||
return Ok(_mapper.Map<UserProfileDTO>(userProfile));
|
||||
}
|
||||
catch (ProfileNotFoundException)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update user profile for the logged in user.
|
||||
/// </summary>
|
||||
/// <param name="model">The user profile model.</param>
|
||||
/// <returns>A <see cref="UserProfileDTO"/> containing the updated user profile if successful, or a 500 Internal Server Error if not successful.</returns>
|
||||
/// <response code="200">Returns the updated user profile</response>
|
||||
/// <response code="404">If the user profile is not found</response>
|
||||
[HttpPut]
|
||||
public async Task<IActionResult> UpdateUserProfile([FromBody] UserProfileCreateDTO model)
|
||||
{
|
||||
string username = User.Claims.First(c => c.Type == "username").Value;
|
||||
long userId = (await _userManager.FindByNameAsync(username))!.Id;
|
||||
|
||||
try
|
||||
{
|
||||
bool result = await _userProfilesService.UpdateUserProfileByUserId(userId, model);
|
||||
return Ok(result);
|
||||
}
|
||||
catch (ProfileNotFoundException)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates an existing user profile.
|
||||
/// </summary>
|
||||
/// <param name="username">The username of the user.</param>
|
||||
/// <param name="model">The user profile model.</param>
|
||||
/// <returns>A <see cref="UserProfileDTO"/> containing the updated user profile if successful, or a 500 Internal Server Error if not successful.</returns>
|
||||
/// <response code="200">Returns the updated user profile</response>
|
||||
/// <response code="404">If the user profile is not found</response>
|
||||
[HttpPut]
|
||||
[Authorize(Policy = "Admin")]
|
||||
[Route("user/{userId}")]
|
||||
public async Task<IActionResult> UpdateUserProfileByUsername(string username, [FromBody] UserProfileCreateDTO model)
|
||||
{
|
||||
var user = (await _userManager.FindByNameAsync(username));
|
||||
if (user == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
bool result = await _userProfilesService.UpdateUserProfileByUserId(user.Id, model);
|
||||
return Ok(result);
|
||||
}
|
||||
catch (ProfileNotFoundException)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes an existing user profile.
|
||||
/// </summary>
|
||||
/// <param name="id">The ID of the user profile to delete.</param>
|
||||
/// <returns>A <see cref="bool"/></returns>
|
||||
/// <response code="200">Returns true.</response>
|
||||
/// <response code="404">If the user profile is not found</response>
|
||||
[HttpDelete("{id}")]
|
||||
[Authorize(Policy = "Admin")]
|
||||
public IActionResult DeleteUserProfile(long id)
|
||||
{
|
||||
try
|
||||
{
|
||||
_userProfilesService.DeleteUserProfile(id);
|
||||
return Ok();
|
||||
}
|
||||
catch (ProfileNotFoundException)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user