chore: deleted all the stuff we don't need here
This commit is contained in:
@@ -1,486 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
||||||
@@ -1,186 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
||||||
@@ -1,283 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
||||||
@@ -1,184 +0,0 @@
|
|||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,32 +1,16 @@
|
|||||||
using GamificationService.Models.Database;
|
|
||||||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
namespace GamificationService.Database;
|
namespace GamificationService.Database;
|
||||||
|
|
||||||
|
|
||||||
public class ApplicationContext : IdentityDbContext<ApplicationUser, ApplicationRole, long>
|
public class ApplicationContext : DbContext
|
||||||
{
|
{
|
||||||
public ApplicationContext(DbContextOptions<ApplicationContext> options) : base(options)
|
public ApplicationContext(DbContextOptions<ApplicationContext> options) : base(options)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public DbSet<Right> Rights { get; set; }
|
|
||||||
public DbSet<RefreshToken> RefreshTokens { get; set; }
|
|
||||||
public DbSet<ApplicationUser> Users { get; set; }
|
|
||||||
public DbSet<ApplicationRole> Roles { get; set; }
|
|
||||||
public DbSet<UserRole> UserRoles { get; set; }
|
|
||||||
public DbSet<RoleRight> RoleRights { get; set; }
|
|
||||||
public DbSet<UserProfile> UserProfiles { get; set; }
|
|
||||||
|
|
||||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||||
{
|
{
|
||||||
base.OnModelCreating(modelBuilder);
|
base.OnModelCreating(modelBuilder);
|
||||||
|
|
||||||
modelBuilder.Entity<UserRole>()
|
|
||||||
.HasKey(ur => new { ur.UserId, ur.RoleId });
|
|
||||||
|
|
||||||
modelBuilder.Entity<RoleRight>()
|
|
||||||
.HasKey(rr => new { rr.RoleId, rr.RightId });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,54 +1,5 @@
|
|||||||
using GamificationService.Models.Database;
|
|
||||||
using GamificationService.Services.CurrentUsers;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.ChangeTracking;
|
|
||||||
|
|
||||||
namespace GamificationService.Database.Extensions;
|
namespace GamificationService.Database.Extensions;
|
||||||
|
|
||||||
public static class ChangeTrackerExtensions
|
public static class ChangeTrackerExtensions
|
||||||
{
|
{
|
||||||
public static void SetAuditProperties(this ChangeTracker changeTracker, ICurrentUserService currentUserService)
|
|
||||||
{
|
|
||||||
changeTracker.DetectChanges();
|
|
||||||
IEnumerable<EntityEntry> entities =
|
|
||||||
changeTracker
|
|
||||||
.Entries()
|
|
||||||
.Where(t => t.Entity is AuditableEntity &&
|
|
||||||
(
|
|
||||||
t.State == EntityState.Deleted
|
|
||||||
|| t.State == EntityState.Added
|
|
||||||
|| t.State == EntityState.Modified
|
|
||||||
));
|
|
||||||
|
|
||||||
if (entities.Any())
|
|
||||||
{
|
|
||||||
DateTimeOffset timestamp = DateTimeOffset.UtcNow;
|
|
||||||
|
|
||||||
string user = currentUserService.GetCurrentUser().Login ?? "Unknown";
|
|
||||||
|
|
||||||
foreach (EntityEntry entry in entities)
|
|
||||||
{
|
|
||||||
AuditableEntity entity = (AuditableEntity)entry.Entity;
|
|
||||||
|
|
||||||
switch (entry.State)
|
|
||||||
{
|
|
||||||
case EntityState.Added:
|
|
||||||
entity.CreatedOn = timestamp;
|
|
||||||
entity.CreatedBy = user;
|
|
||||||
entity.UpdatedOn = timestamp;
|
|
||||||
entity.UpdatedBy = user;
|
|
||||||
break;
|
|
||||||
case EntityState.Modified:
|
|
||||||
entity.UpdatedOn = timestamp;
|
|
||||||
entity.UpdatedBy = user;
|
|
||||||
break;
|
|
||||||
case EntityState.Deleted:
|
|
||||||
entity.UpdatedOn = timestamp;
|
|
||||||
entity.UpdatedBy = user;
|
|
||||||
entry.State = EntityState.Deleted;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
using GamificationService.Models.Database;
|
|
||||||
using Microsoft.EntityFrameworkCore.Storage;
|
using Microsoft.EntityFrameworkCore.Storage;
|
||||||
|
|
||||||
namespace GamificationService.Database.Repositories;
|
namespace GamificationService.Database.Repositories;
|
||||||
@@ -8,12 +7,6 @@ public class UnitOfWork : IDisposable
|
|||||||
#region fields
|
#region fields
|
||||||
|
|
||||||
private ApplicationContext _context;
|
private ApplicationContext _context;
|
||||||
private GenericRepository<UserProfile> _userProfileRepository;
|
|
||||||
private GenericRepository<ApplicationRole> _roleRepository;
|
|
||||||
private GenericRepository<Right?> _rightRepository;
|
|
||||||
private GenericRepository<RefreshToken> _refreshTokenRepository;
|
|
||||||
private GenericRepository<RoleRight> _roleRightRepository;
|
|
||||||
private GenericRepository<UserRole> _userRoleRepository;
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -28,78 +21,6 @@ public class UnitOfWork : IDisposable
|
|||||||
|
|
||||||
#region Properties
|
#region Properties
|
||||||
|
|
||||||
public GenericRepository<UserProfile> UserProfileRepository
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (this._userProfileRepository == null)
|
|
||||||
{
|
|
||||||
this._userProfileRepository = new GenericRepository<UserProfile>(_context);
|
|
||||||
}
|
|
||||||
return _userProfileRepository;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public GenericRepository<ApplicationRole> RoleRepository
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (this._roleRepository == null)
|
|
||||||
{
|
|
||||||
this._roleRepository = new GenericRepository<ApplicationRole>(_context);
|
|
||||||
}
|
|
||||||
return _roleRepository;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public GenericRepository<Right?> RightRepository
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (this._rightRepository == null)
|
|
||||||
{
|
|
||||||
this._rightRepository = new GenericRepository<Right?>(_context);
|
|
||||||
}
|
|
||||||
return _rightRepository;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public GenericRepository<RefreshToken> RefreshTokenRepository
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (this._refreshTokenRepository == null)
|
|
||||||
{
|
|
||||||
this._refreshTokenRepository = new GenericRepository<RefreshToken>(_context);
|
|
||||||
}
|
|
||||||
return _refreshTokenRepository;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public GenericRepository<RoleRight> RoleRightRepository
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (this._roleRightRepository == null)
|
|
||||||
{
|
|
||||||
this._roleRightRepository = new GenericRepository<RoleRight>(_context);
|
|
||||||
}
|
|
||||||
return _roleRightRepository;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public GenericRepository<UserRole> UserRoleRepository
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (this._userRoleRepository == null)
|
|
||||||
{
|
|
||||||
this._userRoleRepository = new GenericRepository<UserRole>(_context);
|
|
||||||
}
|
|
||||||
return _userRoleRepository;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
public bool Save()
|
public bool Save()
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
namespace GamificationService.Exceptions.Services.AuthService;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents an exception related to authentication service operations.
|
|
||||||
/// </summary>
|
|
||||||
public class AuthServiceException : Exception
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="AuthServiceException"/> class.
|
|
||||||
/// </summary>
|
|
||||||
public AuthServiceException() : base() { }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="AuthServiceException"/> class with a specified error message.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="message">The message that describes the error.</param>
|
|
||||||
public AuthServiceException(string message) : base(message) { }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="AuthServiceException"/> class with a specified error message and a reference to the inner exception that is the cause of this exception.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="message">The error message that explains the reason for the exception.</param>
|
|
||||||
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference if no inner exception is specified.</param>
|
|
||||||
public AuthServiceException(string message, Exception innerException) : base(message, innerException) { }
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
namespace GamificationService.Exceptions.Services.JwtService;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents an exception related to jwt token service operations.
|
|
||||||
/// </summary>
|
|
||||||
public class GenerateRefreshTokenException : Exception
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="enerateRefreshTokenException"/> class.
|
|
||||||
/// </summary>
|
|
||||||
public GenerateRefreshTokenException() : base() { }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="GenerateRefreshTokenException"/> class with a specified error message.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="message">The message that describes the error.</param>
|
|
||||||
public GenerateRefreshTokenException(string message) : base(message) { }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="GenerateRefreshTokenException"/> class with a specified error message and a reference to the inner exception that is the cause of this exception.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="message">The error message that explains the reason for the exception.</param>
|
|
||||||
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference if no inner exception is specified.</param>
|
|
||||||
public GenerateRefreshTokenException(string message, Exception innerException) : base(message, innerException) { }
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
namespace GamificationService.Exceptions.Services.JwtService;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents an exception related to jwt token service operations.
|
|
||||||
/// </summary>
|
|
||||||
public class JwtServiceException : Exception
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="JwtServiceException"/> class.
|
|
||||||
/// </summary>
|
|
||||||
public JwtServiceException() : base() { }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="JwtServiceException"/> class with a specified error message.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="message">The message that describes the error.</param>
|
|
||||||
public JwtServiceException(string message) : base(message) { }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="JwtServiceException"/> class with a specified error message and a reference to the inner exception that is the cause of this exception.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="message">The error message that explains the reason for the exception.</param>
|
|
||||||
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference if no inner exception is specified.</param>
|
|
||||||
public JwtServiceException(string message, Exception innerException) : base(message, innerException) { }
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
namespace GamificationService.Exceptions.Services.ProfileService;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents an exception that occurs during profile creation operations.
|
|
||||||
/// </summary>
|
|
||||||
public class ProfileCreationException : Exception
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="ProfileCreationException"/> class.
|
|
||||||
/// </summary>
|
|
||||||
public ProfileCreationException() : base() { }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="ProfileCreationException"/> class with a specified error message.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="message">The message that describes the error.</param>
|
|
||||||
public ProfileCreationException(string message) : base(message) { }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="ProfileCreationException"/> class with a specified error message and a reference to the inner exception that is the cause of this exception.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="message">The error message that explains the reason for the exception.</param>
|
|
||||||
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference if no inner exception is specified.</param>
|
|
||||||
public ProfileCreationException(string message, Exception innerException) : base(message, innerException) { }
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
namespace GamificationService.Exceptions.Services.ProfileService;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents an exception that occurs during profile deletion operations.
|
|
||||||
/// </summary>
|
|
||||||
public class ProfileDeletionException : Exception
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="ProfileDeletionException"/> class.
|
|
||||||
/// </summary>
|
|
||||||
public ProfileDeletionException() : base() { }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="ProfileDeletionException"/> class with a specified error message.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="message">The message that describes the error.</param>
|
|
||||||
public ProfileDeletionException(string message) : base(message) { }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="ProfileDeletionException"/> class with a specified error message and a reference to the inner exception that is the cause of this exception.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="message">The error message that explains the reason for the exception.</param>
|
|
||||||
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference if no inner exception is specified.</param>
|
|
||||||
public ProfileDeletionException(string message, Exception innerException) : base(message, innerException) { }
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
namespace GamificationService.Exceptions.Services.ProfileService;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents an exception that occurs when a profile already exists.
|
|
||||||
/// </summary>
|
|
||||||
public class ProfileExistsException : Exception
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="ProfileExistsException"/> class.
|
|
||||||
/// </summary>
|
|
||||||
public ProfileExistsException() : base() { }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="ProfileExistsException"/> class with a specified error message.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="message">The message that describes the error.</param>
|
|
||||||
public ProfileExistsException(string message) : base(message) { }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="ProfileExistsException"/> class with a specified error message and a reference to the inner exception that is the cause of this exception.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="message">The error message that explains the reason for the exception.</param>
|
|
||||||
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference if no inner exception is specified.</param>
|
|
||||||
public ProfileExistsException(string message, Exception innerException) : base(message, innerException) { }
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
namespace GamificationService.Exceptions.Services.ProfileService;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents an exception that occurs when a profile is not found.
|
|
||||||
/// </summary>
|
|
||||||
public class ProfileNotFoundException : Exception
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="ProfileNotFoundException"/> class.
|
|
||||||
/// </summary>
|
|
||||||
public ProfileNotFoundException() : base() { }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="ProfileNotFoundException"/> class with a specified error message.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="message">The message that describes the error.</param>
|
|
||||||
public ProfileNotFoundException(string message) : base(message) { }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="ProfileNotFoundException"/> class with a specified error message and a reference to the inner exception that is the cause of this exception.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="message">The error message that explains the reason for the exception.</param>
|
|
||||||
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference if no inner exception is specified.</param>
|
|
||||||
public ProfileNotFoundException(string message, Exception innerException) : base(message, innerException) { }
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
namespace GamificationService.Exceptions.Services.ProfileService;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents an exception that occurs during profile update operations.
|
|
||||||
/// </summary>
|
|
||||||
public class ProfileUpdateException : Exception
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="ProfileUpdateException"/> class.
|
|
||||||
/// </summary>
|
|
||||||
public ProfileUpdateException() : base() { }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="ProfileUpdateException"/> class with a specified error message.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="message">The message that describes the error.</param>
|
|
||||||
public ProfileUpdateException(string message) : base(message) { }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="ProfileUpdateException"/> class with a specified error message and a reference to the inner exception that is the cause of this exception.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="message">The error message that explains the reason for the exception.</param>
|
|
||||||
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference if no inner exception is specified.</param>
|
|
||||||
public ProfileUpdateException(string message, Exception innerException) : base(message, innerException) { }
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -6,14 +6,6 @@ using GamificationService.Database;
|
|||||||
using GamificationService.Database.Repositories;
|
using GamificationService.Database.Repositories;
|
||||||
using GamificationService.Logs;
|
using GamificationService.Logs;
|
||||||
using GamificationService.Mapper;
|
using GamificationService.Mapper;
|
||||||
using GamificationService.Services.Cookies;
|
|
||||||
using GamificationService.Services.CurrentUsers;
|
|
||||||
using GamificationService.Services.JWT;
|
|
||||||
using GamificationService.Services.NotificationService;
|
|
||||||
using GamificationService.Services.Rights;
|
|
||||||
using GamificationService.Services.Roles;
|
|
||||||
using GamificationService.Utils;
|
|
||||||
using GamificationService.Utils.Factory;
|
|
||||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.IdentityModel.Tokens;
|
using Microsoft.IdentityModel.Tokens;
|
||||||
@@ -135,56 +127,6 @@ public static class UtilServicesExtensions
|
|||||||
{
|
{
|
||||||
public static IServiceCollection AddUtilServices(this IServiceCollection services)
|
public static IServiceCollection AddUtilServices(this IServiceCollection services)
|
||||||
{
|
{
|
||||||
services.AddScoped<IJwtService, JwtService>();
|
|
||||||
services.AddScoped<ICookieService, CookieService>();
|
|
||||||
services.AddScoped<INotificationService,NotificationService>();
|
|
||||||
services.AddScoped<IRightsService,RightsService>();
|
|
||||||
services.AddScoped<IRolesService, RolesService>();
|
|
||||||
services.AddScoped<ICurrentUserService, CurrentUserService>();
|
|
||||||
return services;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class NotificationSettings
|
|
||||||
{
|
|
||||||
public static IServiceCollection AddPushNotifications(this IServiceCollection services, IConfiguration configuration)
|
|
||||||
{
|
|
||||||
var notificationSettings = configuration.GetSection("NotificationSettings");
|
|
||||||
var apiKey = notificationSettings["ApiKey"];
|
|
||||||
var token = notificationSettings["Token"];
|
|
||||||
var baseUrl = notificationSettings["Url"];
|
|
||||||
var projectId = notificationSettings["ProjectId"];
|
|
||||||
|
|
||||||
HttpClient client = new HttpClient();
|
|
||||||
client.BaseAddress = new Uri(baseUrl);
|
|
||||||
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {apiKey}");
|
|
||||||
|
|
||||||
services.AddSingleton(provider =>
|
|
||||||
{
|
|
||||||
var logger = provider.GetRequiredService<ILogger<PushNotificationsClient>>();
|
|
||||||
return new PushNotificationsClient(client, logger, token, projectId);
|
|
||||||
});
|
|
||||||
return services;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public static class EmailExtensions
|
|
||||||
{
|
|
||||||
public static IServiceCollection AddEmail(this IServiceCollection services, IConfiguration configuration)
|
|
||||||
{
|
|
||||||
var smtpSettings = configuration.GetSection("EmailSettings");
|
|
||||||
var host = smtpSettings["Host"] ?? "localhost";
|
|
||||||
var port = Convert.ToInt32(smtpSettings["Port"] ?? "25");
|
|
||||||
var username = smtpSettings["Username"] ?? "username";
|
|
||||||
var password = smtpSettings["Password"] ?? "password";
|
|
||||||
var email = smtpSettings["EmailFrom"] ?? "email";
|
|
||||||
services.AddScoped<SmtpClient>(sp => new SmtpClient(host)
|
|
||||||
{
|
|
||||||
Port = port,
|
|
||||||
Credentials = new NetworkCredential(username, password),
|
|
||||||
EnableSsl = true,
|
|
||||||
});
|
|
||||||
|
|
||||||
services.AddSingleton<EmailClient>();
|
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -193,8 +135,6 @@ public static class FactoryExtensions
|
|||||||
{
|
{
|
||||||
public static IServiceCollection AddFactories(this IServiceCollection services)
|
public static IServiceCollection AddFactories(this IServiceCollection services)
|
||||||
{
|
{
|
||||||
services.AddSingleton<MailNotificationsFactory>();
|
|
||||||
services.AddSingleton<PushNotificationsFactory>();
|
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
using GamificationService.Models.Database;
|
|
||||||
using GamificationService.Models.DTO;
|
|
||||||
|
|
||||||
namespace GamificationService.Mapper;
|
namespace GamificationService.Mapper;
|
||||||
|
|
||||||
|
|
||||||
@@ -9,43 +6,5 @@ public class MappingProfile : Profile
|
|||||||
{
|
{
|
||||||
public MappingProfile()
|
public MappingProfile()
|
||||||
{
|
{
|
||||||
#region UserProfileMapping
|
|
||||||
|
|
||||||
CreateMap<UserProfile, UserProfileDTO>()
|
|
||||||
.ForMember(x => x.Id, opt => opt.MapFrom(src => src.Id))
|
|
||||||
.ForMember(x => x.UserId, opt => opt.MapFrom(src => src.UserId))
|
|
||||||
.ForMember(x => x.Name, opt => opt.MapFrom(src => src.Name))
|
|
||||||
.ForMember(x => x.Surname, opt => opt.MapFrom(src => src.Surname))
|
|
||||||
.ForMember(x => x.Patronymic, opt => opt.MapFrom(src => src.Patronymic))
|
|
||||||
.ForMember(x => x.Birthdate, opt => opt.MapFrom(src => src.Birthdate))
|
|
||||||
.ForMember(x => x.Gender, opt => opt.MapFrom(src => src.Gender))
|
|
||||||
.ForMember(x => x.ContactEmail, opt => opt.MapFrom(src => src.ContactEmail))
|
|
||||||
.ForMember(x => x.ContactPhone, opt => opt.MapFrom(src => src.ContactPhone))
|
|
||||||
.ForMember(x => x.ProfilePicture, opt => opt.MapFrom(src => src.ProfilePicture));
|
|
||||||
|
|
||||||
CreateMap<UserProfileDTO, UserProfile>()
|
|
||||||
.ForMember(x => x.Id, opt => opt.MapFrom(src => src.Id))
|
|
||||||
.ForMember(x => x.UserId, opt => opt.MapFrom(src => src.UserId))
|
|
||||||
.ForMember(x => x.Name, opt => opt.MapFrom(src => src.Name))
|
|
||||||
.ForMember(x => x.Surname, opt => opt.MapFrom(src => src.Surname))
|
|
||||||
.ForMember(x => x.Patronymic, opt => opt.MapFrom(src => src.Patronymic))
|
|
||||||
.ForMember(x => x.Birthdate, opt => opt.MapFrom(src => src.Birthdate))
|
|
||||||
.ForMember(x => x.Gender, opt => opt.MapFrom(src => src.Gender))
|
|
||||||
.ForMember(x => x.ContactEmail, opt => opt.MapFrom(src => src.ContactEmail))
|
|
||||||
.ForMember(x => x.ContactPhone, opt => opt.MapFrom(src => src.ContactPhone))
|
|
||||||
.ForMember(x => x.ProfilePicture, opt => opt.MapFrom(src => src.ProfilePicture));
|
|
||||||
|
|
||||||
CreateMap<UserProfileCreateDTO, UserProfile>()
|
|
||||||
.ForMember(x => x.Name, opt => opt.MapFrom(src => src.Name))
|
|
||||||
.ForMember(x => x.Surname, opt => opt.MapFrom(src => src.Surname))
|
|
||||||
.ForMember(x => x.Patronymic, opt => opt.MapFrom(src => src.Patronymic))
|
|
||||||
.ForMember(x => x.Birthdate, opt => opt.MapFrom(src => src.Birthdate))
|
|
||||||
.ForMember(x => x.Gender, opt => opt.MapFrom(src => src.Gender))
|
|
||||||
.ForMember(x => x.ContactEmail, opt => opt.MapFrom(src => src.ContactEmail))
|
|
||||||
.ForMember(x => x.ContactPhone, opt => opt.MapFrom(src => src.ContactPhone))
|
|
||||||
.ForMember(x => x.ProfilePicture, opt => opt.MapFrom(src => src.ProfilePicture));
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
|
|
||||||
namespace GamificationService.Models.DTO;
|
|
||||||
|
|
||||||
public class AuthDTO
|
|
||||||
{
|
|
||||||
[Required]
|
|
||||||
[StringLength(50, MinimumLength = 3, ErrorMessage = "Username must be between 3 and 50 characters")]
|
|
||||||
public string Username { get; set; } = null!;
|
|
||||||
|
|
||||||
[Required]
|
|
||||||
[EmailAddress(ErrorMessage = "Invalid email address")]
|
|
||||||
public string Email { get; set; } = null!;
|
|
||||||
|
|
||||||
[Required]
|
|
||||||
[StringLength(100, MinimumLength = 8, ErrorMessage = "Password must be between 8 and 100 characters")]
|
|
||||||
public string Password { get; set; } = null!;
|
|
||||||
|
|
||||||
[Required]
|
|
||||||
public bool RememberMe { get; set; }
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
namespace GamificationService.Models.DTO;
|
|
||||||
|
|
||||||
public class DisableTwoFactorDTO
|
|
||||||
{
|
|
||||||
public int TwoFactorProvider { get; set; }
|
|
||||||
public string Code { get; set; }
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
namespace GamificationService.Models.DTO;
|
|
||||||
|
|
||||||
public class EnableTwoFactorDTO
|
|
||||||
{
|
|
||||||
public int TwoFactorProvider { get; set; }
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
using GamificationService.Models.Database;
|
|
||||||
|
|
||||||
namespace GamificationService.Models.DTO;
|
|
||||||
|
|
||||||
public class GetAllRightsResponse
|
|
||||||
{
|
|
||||||
public List<Right> Rights { get; set; }
|
|
||||||
public int TotalCount { get; set; }
|
|
||||||
public int PageNumber { get; set; }
|
|
||||||
public int PageSize { get; set; }
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
using GamificationService.Models.Database;
|
|
||||||
|
|
||||||
namespace GamificationService.Models.DTO;
|
|
||||||
|
|
||||||
public class GetAllRolesResponse
|
|
||||||
{
|
|
||||||
public List<ApplicationRole> Roles { get; set; }
|
|
||||||
public int TotalCount { get; set; }
|
|
||||||
public int PageNumber { get; set; }
|
|
||||||
public int PageSize { get; set; }
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
|
|
||||||
namespace GamificationService.Models.DTO;
|
|
||||||
|
|
||||||
public class GetTwoFactorDTO
|
|
||||||
{
|
|
||||||
[Required]
|
|
||||||
public int TwoFactorProvider { get; set; }
|
|
||||||
[StringLength(50, MinimumLength = 3, ErrorMessage = "Username must be between 3 and 50 characters")]
|
|
||||||
public string? Username { get; set; } = null!;
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
namespace GamificationService.Models.DTO;
|
|
||||||
|
|
||||||
public class LoginResultResponse
|
|
||||||
{
|
|
||||||
public bool? RequiresTwoFactorAuth { get; set; }
|
|
||||||
public bool Success { get; set; }
|
|
||||||
public RefreshTokenDTO? Token { get; set; }
|
|
||||||
public int? TwoFactorProvider { get; set; }
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
namespace GamificationService.Models.DTO;
|
|
||||||
|
|
||||||
public class RefreshTokenDTO
|
|
||||||
{
|
|
||||||
public string AccessToken { get; set; } = null!;
|
|
||||||
public string RefreshToken { get; set; } = null!;
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
namespace GamificationService.Models.DTO;
|
|
||||||
|
|
||||||
public class RightDTO
|
|
||||||
{
|
|
||||||
public string Name { get; set; }
|
|
||||||
public string Description { get; set; }
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
namespace GamificationService.Models.DTO;
|
|
||||||
|
|
||||||
public class RoleDTO
|
|
||||||
{
|
|
||||||
public string Name { get; set; }
|
|
||||||
public string Description { get; set; }
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
|
|
||||||
namespace GamificationService.Models.DTO;
|
|
||||||
|
|
||||||
public class TwoFactorDTO
|
|
||||||
{
|
|
||||||
[Required]
|
|
||||||
public int TwoFactorProvider { get; set; }
|
|
||||||
[StringLength(50, MinimumLength = 3, ErrorMessage = "Username must be between 3 and 50 characters")]
|
|
||||||
public string? Username { get; set; } = null!;
|
|
||||||
|
|
||||||
[Required]
|
|
||||||
[StringLength(6, MinimumLength = 6, ErrorMessage = "Code must be 6 characters long")]
|
|
||||||
public string Code { get; set; } = null!;
|
|
||||||
public bool RememberMe { get; set; }
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using GamificationService.Utils.Enums;
|
|
||||||
|
|
||||||
namespace GamificationService.Models.DTO;
|
|
||||||
|
|
||||||
public class UserProfileCreateDTO
|
|
||||||
{
|
|
||||||
[Required(ErrorMessage = "Name is required")]
|
|
||||||
[StringLength(100, ErrorMessage = "Name must be less than 100 characters")]
|
|
||||||
public string Name { get; set; } = null!;
|
|
||||||
|
|
||||||
[Required(ErrorMessage = "Surname is required")]
|
|
||||||
[StringLength(100, ErrorMessage = "Surname must be less than 100 characters")]
|
|
||||||
public string Surname { get; set; } = null!;
|
|
||||||
|
|
||||||
[StringLength(50, ErrorMessage = "Patronymic must be less than 50 characters")]
|
|
||||||
public string? Patronymic { get; set; }
|
|
||||||
|
|
||||||
[Required(ErrorMessage = "Birthdate is required")]
|
|
||||||
public DateTime Birthdate { get; set; }
|
|
||||||
|
|
||||||
[Required(ErrorMessage = "Gender is required")]
|
|
||||||
public Gender Gender { get; set; }
|
|
||||||
|
|
||||||
[EmailAddress(ErrorMessage = "Invalid email")]
|
|
||||||
public string? ContactEmail { get; set; }
|
|
||||||
|
|
||||||
[Phone(ErrorMessage = "Invalid contact phone number")]
|
|
||||||
public string? ContactPhone { get; set; }
|
|
||||||
|
|
||||||
[Url(ErrorMessage = "Invalid avatar url")]
|
|
||||||
public string? ProfilePicture { get; set; }
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using GamificationService.Utils.Enums;
|
|
||||||
|
|
||||||
namespace GamificationService.Models.DTO;
|
|
||||||
|
|
||||||
public class UserProfileDTO
|
|
||||||
{
|
|
||||||
public long? Id { get; set; }
|
|
||||||
|
|
||||||
public long? UserId { get; set; }
|
|
||||||
|
|
||||||
[Required(ErrorMessage = "Name is required")]
|
|
||||||
[StringLength(100, ErrorMessage = "Name must be less than 100 characters")]
|
|
||||||
public string Name { get; set; } = null!;
|
|
||||||
|
|
||||||
[Required(ErrorMessage = "Surname is required")]
|
|
||||||
[StringLength(100, ErrorMessage = "Surname must be less than 100 characters")]
|
|
||||||
public string Surname { get; set; } = null!;
|
|
||||||
|
|
||||||
[StringLength(50, ErrorMessage = "Patronymic must be less than 50 characters")]
|
|
||||||
public string? Patronymic { get; set; }
|
|
||||||
|
|
||||||
[Required(ErrorMessage = "Birthdate is required")]
|
|
||||||
public DateTime Birthdate { get; set; }
|
|
||||||
|
|
||||||
[Required(ErrorMessage = "Gender is required")]
|
|
||||||
public Gender Gender { get; set; }
|
|
||||||
|
|
||||||
[EmailAddress(ErrorMessage = "Invalid email")]
|
|
||||||
public string? ContactEmail { get; set; }
|
|
||||||
|
|
||||||
[Phone(ErrorMessage = "Invalid contact phone number")]
|
|
||||||
public string? ContactPhone { get; set; }
|
|
||||||
|
|
||||||
[Url(ErrorMessage = "Invalid avatar url")]
|
|
||||||
public string? ProfilePicture { get; set; }
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
using Microsoft.AspNetCore.Identity;
|
|
||||||
using StackExchange.Redis;
|
|
||||||
|
|
||||||
namespace GamificationService.Models.Database;
|
|
||||||
|
|
||||||
|
|
||||||
public class ApplicationRole : IdentityRole<long>
|
|
||||||
{
|
|
||||||
public ApplicationRole() : base() { }
|
|
||||||
public ApplicationRole(string roleName) : base(roleName) { }
|
|
||||||
public string? Description { get; set; }
|
|
||||||
|
|
||||||
public List<UserRole> UserRoles { get; set; } = new List<UserRole>();
|
|
||||||
public List<RoleRight> RoleRights { get; set; } = new List<RoleRight>();
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using GamificationService.Utils;
|
|
||||||
using Microsoft.AspNetCore.Identity;
|
|
||||||
|
|
||||||
namespace GamificationService.Models.Database;
|
|
||||||
|
|
||||||
public class ApplicationUser : IdentityUser<long>
|
|
||||||
{
|
|
||||||
[Required(ErrorMessage = "Username is required")]
|
|
||||||
[StringLength(50, ErrorMessage = "Username must be less than 50 characters")]
|
|
||||||
public string Username { get; set; } = null!;
|
|
||||||
public bool TwoFactorEnabled { get; set; }
|
|
||||||
public string? TwoFactorSecret { get; set; }
|
|
||||||
public bool EmailConfirmed { get; set; }
|
|
||||||
public List<TwoFactorProvider> TwoFactorProviders { get; set; } = new List<TwoFactorProvider>();
|
|
||||||
public List<RefreshToken> RefreshTokens { get; set; } = new List<RefreshToken>();
|
|
||||||
|
|
||||||
public List<UserRole> UserRoles { get; set; } = new List<UserRole>();
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
|
|
||||||
namespace GamificationService.Models.Database;
|
|
||||||
|
|
||||||
public class RefreshToken
|
|
||||||
{
|
|
||||||
[Key]
|
|
||||||
public long Id { get; set; }
|
|
||||||
|
|
||||||
public long UserId { get; set; }
|
|
||||||
public ApplicationUser User { get; set; } = null!;
|
|
||||||
|
|
||||||
[Required]
|
|
||||||
public string Token { get; set; } = null!;
|
|
||||||
|
|
||||||
public DateTime Expires { get; set; }
|
|
||||||
public DateTime Created { get; set; }
|
|
||||||
public bool IsExpired => DateTime.UtcNow >= Expires;
|
|
||||||
|
|
||||||
public bool IsRevoked { get; set; }
|
|
||||||
public string? RevokedByIp { get; set; }
|
|
||||||
public DateTime? RevokedOn { get; set; }
|
|
||||||
|
|
||||||
public bool IsActive => !IsRevoked && !IsExpired;
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
|
|
||||||
namespace GamificationService.Models.Database;
|
|
||||||
|
|
||||||
public class Right
|
|
||||||
{
|
|
||||||
[Key]
|
|
||||||
public long Id { get; set; }
|
|
||||||
|
|
||||||
[Required]
|
|
||||||
[StringLength(50)]
|
|
||||||
public string Name { get; set; } = null!;
|
|
||||||
|
|
||||||
[StringLength(100)]
|
|
||||||
public string? Description { get; set; }
|
|
||||||
|
|
||||||
public List<RoleRight> RoleRights { get; set; } = new List<RoleRight>();
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
namespace GamificationService.Models.Database;
|
|
||||||
|
|
||||||
public class RoleRight
|
|
||||||
{
|
|
||||||
public long RoleId { get; set; }
|
|
||||||
public ApplicationRole Role { get; set; } = null!;
|
|
||||||
|
|
||||||
public long RightId { get; set; }
|
|
||||||
public Right Right { get; set; } = null!;
|
|
||||||
}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using GamificationService.Utils.Enums;
|
|
||||||
|
|
||||||
namespace GamificationService.Models.Database;
|
|
||||||
|
|
||||||
public class UserProfile
|
|
||||||
{
|
|
||||||
[Key]
|
|
||||||
public long Id { get; set; }
|
|
||||||
|
|
||||||
[Required(ErrorMessage = "User is required")]
|
|
||||||
public long UserId { get; set; }
|
|
||||||
public ApplicationUser? User { get; set; }
|
|
||||||
|
|
||||||
[Required(ErrorMessage = "Name is required")]
|
|
||||||
[StringLength(100, ErrorMessage = "Name must be less than 100 characters")]
|
|
||||||
public string Name { get; set; } = null!;
|
|
||||||
|
|
||||||
[Required(ErrorMessage = "Surname is required")]
|
|
||||||
[StringLength(100, ErrorMessage = "Surname must be less than 100 characters")]
|
|
||||||
public string Surname { get; set; } = null!;
|
|
||||||
|
|
||||||
[StringLength(50, ErrorMessage = "Patronymic must be less than 50 characters")]
|
|
||||||
public string? Patronymic { get; set; }
|
|
||||||
|
|
||||||
[Required(ErrorMessage = "Gender is required")]
|
|
||||||
public Gender Gender { get; set; }
|
|
||||||
|
|
||||||
[Required(ErrorMessage = "Birthdate is required")]
|
|
||||||
public DateTime Birthdate { get; set; }
|
|
||||||
|
|
||||||
[EmailAddress(ErrorMessage = "Invalid email")]
|
|
||||||
public string? ContactEmail { get; set; }
|
|
||||||
|
|
||||||
[Phone(ErrorMessage = "Invalid contact phone number")]
|
|
||||||
public string? ContactPhone { get; set; }
|
|
||||||
|
|
||||||
[Url(ErrorMessage = "Invalid avatar url")]
|
|
||||||
public string? ProfilePicture { get; set; }
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
namespace GamificationService.Models.Database;
|
|
||||||
|
|
||||||
public class UserRole
|
|
||||||
{
|
|
||||||
public long UserId { get; set; }
|
|
||||||
public ApplicationUser User { get; set; } = null!;
|
|
||||||
|
|
||||||
public long RoleId { get; set; }
|
|
||||||
public ApplicationRole Role { get; set; } = null!;
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
namespace GamificationService.Models.Messages.UserProfiles;
|
|
||||||
|
|
||||||
public class CreateUserProfileRequest
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
namespace GamificationService.Models.Messages.UserProfiles;
|
|
||||||
|
|
||||||
public class CreateUserProfileResponse
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
namespace GamificationService.Models.Messages.UserProfiles;
|
|
||||||
|
|
||||||
public class UpdateUserProfileRequest
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
namespace GamificationService.Models.Messages.UserProfiles;
|
|
||||||
|
|
||||||
public class UpdateUserProfileResponse
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
namespace GamificationService.Models;
|
|
||||||
|
|
||||||
public class UserSession
|
|
||||||
{
|
|
||||||
public string? Login { get; set; }
|
|
||||||
public bool IsAuthenticated { get; set; }
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
using GamificationService.Exceptions.UtilServices.Cookies;
|
|
||||||
|
|
||||||
namespace GamificationService.Services.Cookies;
|
|
||||||
|
|
||||||
public class CookieService : ICookieService
|
|
||||||
{
|
|
||||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
|
||||||
private readonly ILogger<CookieService> _logger;
|
|
||||||
private readonly IConfiguration _configuration;
|
|
||||||
|
|
||||||
public CookieService(IHttpContextAccessor httpContextAccessor, ILogger<CookieService> logger, IConfiguration configuration)
|
|
||||||
{
|
|
||||||
_httpContextAccessor = httpContextAccessor;
|
|
||||||
_logger = logger;
|
|
||||||
_configuration = configuration;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task<bool> SetCookie(string key, string value, CookieOptions options)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_logger.LogDebug("Adding cookie {CookieKey} with value {CookieValue}", key, value);
|
|
||||||
_httpContextAccessor.HttpContext.Response.Cookies.Append(key, value, options);
|
|
||||||
return Task.FromResult(true);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_logger.LogError(ex, "Failed to add cookie {CookieKey}", key);
|
|
||||||
throw new SetCookiesException(ex.Message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<bool> RemoveCookie(string key)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_logger.LogDebug("Deleting cookie {CookieKey}", key);
|
|
||||||
_httpContextAccessor.HttpContext.Response.Cookies.Delete(key);
|
|
||||||
return await Task.FromResult(true);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_logger.LogError(ex, "Failed to delete cookie {CookieKey}", key);
|
|
||||||
throw new DeleteCookiesException(ex.Message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
namespace GamificationService.Services.Cookies;
|
|
||||||
|
|
||||||
public interface ICookieService
|
|
||||||
{
|
|
||||||
Task<bool> SetCookie(string key, string value, CookieOptions options);
|
|
||||||
Task<bool> RemoveCookie(string key);
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
using GamificationService.Models;
|
|
||||||
|
|
||||||
namespace GamificationService.Services.CurrentUsers;
|
|
||||||
|
|
||||||
public class CurrentUserService : ICurrentUserService
|
|
||||||
{
|
|
||||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
|
||||||
private readonly ILogger<ICurrentUserService> _logger;
|
|
||||||
public CurrentUserService(IHttpContextAccessor httpContextAccessor, ILogger<ICurrentUserService> logger)
|
|
||||||
{
|
|
||||||
_httpContextAccessor = httpContextAccessor;
|
|
||||||
_logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
public UserSession GetCurrentUser()
|
|
||||||
{
|
|
||||||
UserSession currentUser = new UserSession
|
|
||||||
{
|
|
||||||
IsAuthenticated = _httpContextAccessor.HttpContext.User.Identity != null && _httpContextAccessor.HttpContext.User.Identity.IsAuthenticated,
|
|
||||||
Login = _httpContextAccessor.HttpContext.User.Identity.Name
|
|
||||||
};
|
|
||||||
_logger.LogDebug($"Current user extracted: {currentUser.Login}");
|
|
||||||
return currentUser;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
using GamificationService.Models;
|
|
||||||
|
|
||||||
namespace GamificationService.Services.CurrentUsers;
|
|
||||||
|
|
||||||
public interface ICurrentUserService
|
|
||||||
{
|
|
||||||
UserSession GetCurrentUser();
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
using System.IdentityModel.Tokens.Jwt;
|
|
||||||
using GamificationService.Models.Database;
|
|
||||||
using GamificationService.Models.DTO;
|
|
||||||
|
|
||||||
namespace GamificationService.Services.JWT;
|
|
||||||
|
|
||||||
public interface IJwtService
|
|
||||||
{
|
|
||||||
string GenerateAccessToken(ApplicationUser user);
|
|
||||||
JwtSecurityToken ValidateAccessToken(string token);
|
|
||||||
Task<RefreshToken> GenerateRefreshTokenAsync(ApplicationUser user);
|
|
||||||
Task RevokeRefreshTokenAsync(long userId, string refreshToken, string remoteIpAddress);
|
|
||||||
}
|
|
||||||
@@ -1,144 +0,0 @@
|
|||||||
using System.IdentityModel.Tokens.Jwt;
|
|
||||||
using System.Security.Claims;
|
|
||||||
using System.Security.Cryptography;
|
|
||||||
using System.Text;
|
|
||||||
using GamificationService.Database.Repositories;
|
|
||||||
using GamificationService.Exceptions.Services.JwtService;
|
|
||||||
using GamificationService.Exceptions.UtilServices.JWT;
|
|
||||||
using GamificationService.Models.Database;
|
|
||||||
using GamificationService.Models.DTO;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.IdentityModel.Tokens;
|
|
||||||
|
|
||||||
namespace GamificationService.Services.JWT;
|
|
||||||
|
|
||||||
public class JwtService : IJwtService
|
|
||||||
{
|
|
||||||
#region Fields
|
|
||||||
|
|
||||||
private readonly IConfiguration _configuration;
|
|
||||||
private readonly ILogger<JwtService> _logger;
|
|
||||||
private readonly UnitOfWork _unitOfWork;
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
public JwtService(IConfiguration configuration, ILogger<JwtService> logger, UnitOfWork unitOfWork)
|
|
||||||
{
|
|
||||||
_configuration = configuration;
|
|
||||||
_logger = logger;
|
|
||||||
_unitOfWork = unitOfWork;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GenerateAccessToken(ApplicationUser user)
|
|
||||||
{
|
|
||||||
var jwtSettings = _configuration.GetSection("JwtSettings");
|
|
||||||
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings["Key"]));
|
|
||||||
var issuer = jwtSettings["Issuer"];
|
|
||||||
var audience = jwtSettings["Audience"];
|
|
||||||
|
|
||||||
var claims = new List<Claim>
|
|
||||||
{
|
|
||||||
new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
|
|
||||||
new Claim(ClaimTypes.Name, user.UserName),
|
|
||||||
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
|
|
||||||
};
|
|
||||||
|
|
||||||
var userRoles = _unitOfWork.UserRoleRepository.Get()
|
|
||||||
.Where(ur => ur.UserId == user.Id)
|
|
||||||
.Select(ur => ur.Role)
|
|
||||||
.Include(rr => rr.RoleRights)
|
|
||||||
.ThenInclude(rr=>rr.Right)
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
foreach (var role in userRoles)
|
|
||||||
{
|
|
||||||
claims.Add(new Claim(ClaimTypes.Role, role.Name));
|
|
||||||
|
|
||||||
foreach (var right in role.RoleRights.Select(rr => rr.Right))
|
|
||||||
{
|
|
||||||
claims.Add(new Claim("Right", right.Name));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var expires = DateTime.UtcNow.AddMinutes(double.Parse(jwtSettings["AccessTokenExpirationMinutes"]));
|
|
||||||
|
|
||||||
var token = new JwtSecurityToken(
|
|
||||||
issuer: issuer,
|
|
||||||
audience: audience,
|
|
||||||
claims: claims,
|
|
||||||
expires: expires,
|
|
||||||
signingCredentials: new SigningCredentials(key, SecurityAlgorithms.HmacSha256)
|
|
||||||
);
|
|
||||||
|
|
||||||
return new JwtSecurityTokenHandler().WriteToken(token);
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GenerateRefreshToken()
|
|
||||||
{
|
|
||||||
var randomNumber = new byte[32];
|
|
||||||
using var rng = RandomNumberGenerator.Create();
|
|
||||||
rng.GetBytes(randomNumber);
|
|
||||||
return Convert.ToBase64String(randomNumber);
|
|
||||||
}
|
|
||||||
|
|
||||||
public JwtSecurityToken ValidateAccessToken(string token)
|
|
||||||
{
|
|
||||||
var jwtSettings = _configuration.GetSection("JwtSettings");
|
|
||||||
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings["Key"]));
|
|
||||||
var issuer = jwtSettings["Issuer"];
|
|
||||||
var audience = jwtSettings["Audience"];
|
|
||||||
|
|
||||||
var tokenHandler = new JwtSecurityTokenHandler();
|
|
||||||
var validationParameters = new TokenValidationParameters
|
|
||||||
{
|
|
||||||
ValidateIssuerSigningKey = true,
|
|
||||||
IssuerSigningKey = key,
|
|
||||||
ValidateIssuer = true,
|
|
||||||
ValidIssuer = issuer,
|
|
||||||
ValidateAudience = true,
|
|
||||||
ValidAudience = audience,
|
|
||||||
ValidateLifetime = true,
|
|
||||||
ClockSkew = TimeSpan.Zero
|
|
||||||
};
|
|
||||||
|
|
||||||
SecurityToken validatedToken;
|
|
||||||
var principal = tokenHandler.ValidateToken(token, validationParameters, out validatedToken);
|
|
||||||
|
|
||||||
return validatedToken as JwtSecurityToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<RefreshToken> GenerateRefreshTokenAsync(ApplicationUser user)
|
|
||||||
{
|
|
||||||
var dbRefreshToken = new RefreshToken
|
|
||||||
{
|
|
||||||
UserId = user.Id,
|
|
||||||
Token = GenerateRefreshToken(),
|
|
||||||
Expires = DateTime.UtcNow.AddDays(double.Parse(_configuration["JwtSettings:RefreshTokenExpirationDays"])),
|
|
||||||
Created = DateTime.UtcNow
|
|
||||||
};
|
|
||||||
|
|
||||||
await _unitOfWork.RefreshTokenRepository.InsertAsync(dbRefreshToken);
|
|
||||||
if (!await _unitOfWork.SaveAsync())
|
|
||||||
{
|
|
||||||
throw new GenerateRefreshTokenException("Failed to generate refresh token");
|
|
||||||
}
|
|
||||||
|
|
||||||
return dbRefreshToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task RevokeRefreshTokenAsync(long userId, string refreshToken, string remoteIpAddress)
|
|
||||||
{
|
|
||||||
var token = await _unitOfWork.RefreshTokenRepository.Get()
|
|
||||||
.FirstOrDefaultAsync(x => x.UserId == userId && x.Token == refreshToken);
|
|
||||||
|
|
||||||
if (token != null)
|
|
||||||
{
|
|
||||||
token.IsRevoked = true;
|
|
||||||
token.RevokedByIp = remoteIpAddress;
|
|
||||||
token.RevokedOn = DateTime.UtcNow;
|
|
||||||
|
|
||||||
await _unitOfWork.SaveAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
using System.Net.Mail;
|
|
||||||
using GamificationService.Models.Database;
|
|
||||||
using GamificationService.Utils;
|
|
||||||
|
|
||||||
namespace GamificationService.Services.NotificationService;
|
|
||||||
|
|
||||||
public interface INotificationService
|
|
||||||
{
|
|
||||||
public Task SendMailNotificationAsync(ApplicationUser user, Notification notification);
|
|
||||||
public Task SendPushNotificationAsync(ApplicationUser user, Notification notification);
|
|
||||||
}
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
using System.Net.Mail;
|
|
||||||
using GamificationService.Models.Database;
|
|
||||||
using GamificationService.Utils;
|
|
||||||
using GamificationService.Utils.Factory;
|
|
||||||
|
|
||||||
namespace GamificationService.Services.NotificationService;
|
|
||||||
|
|
||||||
public class NotificationService : INotificationService
|
|
||||||
{
|
|
||||||
#region Services
|
|
||||||
|
|
||||||
private readonly EmailClient _emailClient;
|
|
||||||
private readonly ILogger<NotificationService> _logger;
|
|
||||||
private readonly PushNotificationsClient _pushNotificationsClient;
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Constructor
|
|
||||||
|
|
||||||
public NotificationService(EmailClient emailClient, PushNotificationsClient pushNotificationsClient, ILogger<NotificationService> logger)
|
|
||||||
{
|
|
||||||
_emailClient = emailClient;
|
|
||||||
_pushNotificationsClient = pushNotificationsClient;
|
|
||||||
_logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
public async Task SendMailNotificationAsync(ApplicationUser user, Notification notification)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await _emailClient.SendEmail(((MailNotification)notification).ConvertToMailMessage(), user.Email);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
_logger.LogError(e,e.Message);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO: Refactor, add reg.ru notifications
|
|
||||||
public async Task SendPushNotificationAsync(ApplicationUser user, Notification notification)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await _emailClient.SendEmail(((MailNotification)notification).ConvertToMailMessage(), user.Email);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
_logger.LogError(e,e.Message);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
using GamificationService.Models.Database;
|
|
||||||
|
|
||||||
namespace GamificationService.Services.Rights;
|
|
||||||
|
|
||||||
public interface IRightsService
|
|
||||||
{
|
|
||||||
Task<Right?> CreateRightAsync(string rightName, string description);
|
|
||||||
Task<bool> UpdateRightAsync(long rightId, string newRightName, string newDescription);
|
|
||||||
Task<bool> DeleteRightAsync(long rightId);
|
|
||||||
Task<Right?> GetRightByIdAsync(long rightId);
|
|
||||||
Task<(List<Right> Rights, int TotalCount)> GetAllRightsAsync(int pageNumber = 1, int pageSize = 10);
|
|
||||||
}
|
|
||||||
@@ -1,103 +0,0 @@
|
|||||||
using GamificationService.Database.Repositories;
|
|
||||||
using GamificationService.Models.Database;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
|
|
||||||
namespace GamificationService.Services.Rights;
|
|
||||||
|
|
||||||
public class RightsService : IRightsService
|
|
||||||
{
|
|
||||||
#region Fields
|
|
||||||
|
|
||||||
private readonly UnitOfWork _unitOfWork;
|
|
||||||
private readonly ILogger<IRightsService> _logger;
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Constructor
|
|
||||||
|
|
||||||
public RightsService(UnitOfWork unitOfWork, ILogger<IRightsService> logger)
|
|
||||||
{
|
|
||||||
_unitOfWork = unitOfWork;
|
|
||||||
_logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Methods
|
|
||||||
|
|
||||||
public async Task<Right?> CreateRightAsync(string rightName, string description)
|
|
||||||
{
|
|
||||||
var right = new Right
|
|
||||||
{
|
|
||||||
Name = rightName,
|
|
||||||
Description = description
|
|
||||||
};
|
|
||||||
|
|
||||||
await _unitOfWork.RightRepository.InsertAsync(right);
|
|
||||||
if (await _unitOfWork.SaveAsync())
|
|
||||||
{
|
|
||||||
return right;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new Exception($"Unable to create right for {rightName}");
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<bool> UpdateRightAsync(long rightId, string newRightName, string newDescription)
|
|
||||||
{
|
|
||||||
var right = await _unitOfWork.RightRepository.GetByIDAsync(rightId);
|
|
||||||
|
|
||||||
if (right == null)
|
|
||||||
{
|
|
||||||
throw new KeyNotFoundException($"Right with ID {rightId} not found");
|
|
||||||
}
|
|
||||||
|
|
||||||
right.Name = newRightName;
|
|
||||||
right.Description = newDescription;
|
|
||||||
|
|
||||||
if (!await _unitOfWork.SaveAsync())
|
|
||||||
{
|
|
||||||
throw new Exception($"Unable to create right for {rightId}");
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<bool> DeleteRightAsync(long rightId)
|
|
||||||
{
|
|
||||||
var right = await _unitOfWork.RightRepository.GetByIDAsync(rightId);
|
|
||||||
|
|
||||||
if (right == null)
|
|
||||||
{
|
|
||||||
throw new KeyNotFoundException($"Right with ID {rightId} not found");
|
|
||||||
}
|
|
||||||
|
|
||||||
_unitOfWork.RightRepository.Delete(right);
|
|
||||||
if (!await _unitOfWork.SaveAsync())
|
|
||||||
{
|
|
||||||
throw new Exception($"Unable to delete right for {rightId}");
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<Right?> GetRightByIdAsync(long rightId)
|
|
||||||
{
|
|
||||||
return await _unitOfWork.RightRepository.GetByIDAsync(rightId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<(List<Right> Rights, int TotalCount)> GetAllRightsAsync(int pageNumber = 1, int pageSize = 10)
|
|
||||||
{
|
|
||||||
var query = _unitOfWork.RightRepository.Get();
|
|
||||||
|
|
||||||
var totalItems = await query.CountAsync();
|
|
||||||
|
|
||||||
var pagedRights = await query
|
|
||||||
.Skip((pageNumber - 1) * pageSize)
|
|
||||||
.Take(pageSize)
|
|
||||||
.ToListAsync();
|
|
||||||
|
|
||||||
return (pagedRights, totalItems);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
using GamificationService.Models.Database;
|
|
||||||
|
|
||||||
namespace GamificationService.Services.Roles;
|
|
||||||
|
|
||||||
public interface IRolesService
|
|
||||||
{
|
|
||||||
Task<ApplicationRole> CreateRoleAsync(string roleName, string description);
|
|
||||||
Task<bool> UpdateRoleAsync(long roleId, string newRoleName, string newDescription);
|
|
||||||
Task<bool> DeleteRoleAsync(long roleId);
|
|
||||||
Task<bool> AddRightToRoleAsync(long roleId, long rightId);
|
|
||||||
Task<bool> RemoveRightFromRoleAsync(long roleId, long rightId);
|
|
||||||
Task<ApplicationRole> GetRoleByIdAsync(long roleId);
|
|
||||||
Task<(List<ApplicationRole> Roles, int TotalCount)> GetAllRolesAsync(int pageNumber = 1, int pageSize = 10);
|
|
||||||
}
|
|
||||||
@@ -1,162 +0,0 @@
|
|||||||
using GamificationService.Database.Repositories;
|
|
||||||
using GamificationService.Models.Database;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
|
|
||||||
namespace GamificationService.Services.Roles;
|
|
||||||
|
|
||||||
public class RolesService : IRolesService
|
|
||||||
{
|
|
||||||
#region Services
|
|
||||||
|
|
||||||
private readonly ILogger<IRolesService> _logger;
|
|
||||||
private readonly UnitOfWork _unitOfWork;
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Constructor
|
|
||||||
|
|
||||||
public RolesService(ILogger<IRolesService> logger, UnitOfWork unitOfWork)
|
|
||||||
{
|
|
||||||
_logger = logger;
|
|
||||||
_unitOfWork = unitOfWork;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Methods
|
|
||||||
//TODO: refactor database work, to be more beautiful
|
|
||||||
//ToDo: make better exception handling
|
|
||||||
public async Task<ApplicationRole> CreateRoleAsync(string roleName, string description)
|
|
||||||
{
|
|
||||||
var role = new ApplicationRole(roleName)
|
|
||||||
{
|
|
||||||
Description = description
|
|
||||||
};
|
|
||||||
|
|
||||||
await _unitOfWork.RoleRepository.InsertAsync(role);
|
|
||||||
if (await _unitOfWork.SaveAsync())
|
|
||||||
{
|
|
||||||
return role;
|
|
||||||
}
|
|
||||||
throw new Exception("Unable to create role");
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<bool> UpdateRoleAsync(long roleId, string newRoleName, string newDescription)
|
|
||||||
{
|
|
||||||
var role = await _unitOfWork.RoleRepository.GetByIDAsync(roleId);
|
|
||||||
|
|
||||||
if (role == null)
|
|
||||||
{
|
|
||||||
throw new KeyNotFoundException($"Role with ID {roleId} not found");
|
|
||||||
}
|
|
||||||
|
|
||||||
role.Name = newRoleName;
|
|
||||||
role.Description = newDescription;
|
|
||||||
|
|
||||||
if (!await _unitOfWork.SaveAsync())
|
|
||||||
{
|
|
||||||
throw new Exception("Unable to create role");
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<bool> DeleteRoleAsync(long roleId)
|
|
||||||
{
|
|
||||||
var role = await _unitOfWork.RoleRepository.GetByIDAsync(roleId);
|
|
||||||
|
|
||||||
if (role == null)
|
|
||||||
{
|
|
||||||
throw new KeyNotFoundException($"Role with ID {roleId} not found");
|
|
||||||
}
|
|
||||||
|
|
||||||
_unitOfWork.RoleRepository.Delete(role);
|
|
||||||
if (!await _unitOfWork.SaveAsync())
|
|
||||||
{
|
|
||||||
throw new Exception("Unable to delete role");
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<bool> AddRightToRoleAsync(long roleId, long rightId)
|
|
||||||
{
|
|
||||||
var role = await _unitOfWork.RoleRepository.Get()
|
|
||||||
.Include(r => r.RoleRights)
|
|
||||||
.FirstOrDefaultAsync(r => r.Id == roleId);
|
|
||||||
|
|
||||||
var right = await _unitOfWork.RightRepository.GetByIDAsync(rightId);
|
|
||||||
|
|
||||||
if (role == null || right == null)
|
|
||||||
{
|
|
||||||
throw new KeyNotFoundException($"Role or Right not found");
|
|
||||||
}
|
|
||||||
|
|
||||||
var existingRight = role.RoleRights.FirstOrDefault(rr => rr.RightId == rightId);
|
|
||||||
|
|
||||||
if (existingRight == null)
|
|
||||||
{
|
|
||||||
role.RoleRights.Add(new RoleRight { RoleId = roleId, RightId = rightId });
|
|
||||||
if (!await _unitOfWork.SaveAsync())
|
|
||||||
{
|
|
||||||
throw new Exception("Unable to add role right");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<bool> RemoveRightFromRoleAsync(long roleId, long rightId)
|
|
||||||
{
|
|
||||||
var roleRight = await _unitOfWork.RoleRightRepository.Get()
|
|
||||||
.FirstOrDefaultAsync(rr => rr.RoleId == roleId && rr.RightId == rightId);
|
|
||||||
|
|
||||||
if (roleRight == null)
|
|
||||||
{
|
|
||||||
throw new KeyNotFoundException($"Right not found for role");
|
|
||||||
}
|
|
||||||
|
|
||||||
_unitOfWork.RoleRightRepository.Delete(roleRight);
|
|
||||||
if (!await _unitOfWork.SaveAsync())
|
|
||||||
{
|
|
||||||
throw new Exception("Unable to remove role right");
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<ApplicationRole> GetRoleByIdAsync(long roleId)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await _unitOfWork.RoleRepository.Get()
|
|
||||||
.Include(r => r.RoleRights)
|
|
||||||
.ThenInclude(rr => rr.Right)
|
|
||||||
.FirstOrDefaultAsync(r => r.Id == roleId);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
_logger.LogError(e, e.Message);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<(List<ApplicationRole> Roles, int TotalCount)> GetAllRolesAsync(int pageNumber = 1, int pageSize = 10)
|
|
||||||
{
|
|
||||||
var query = _unitOfWork.RoleRepository.Get()
|
|
||||||
.Include(r => r.RoleRights)
|
|
||||||
.ThenInclude(rr => rr.Right);
|
|
||||||
|
|
||||||
var totalItems = await query.CountAsync();
|
|
||||||
var pagedRoles = await query
|
|
||||||
.Skip((pageNumber - 1) * pageSize)
|
|
||||||
.Take(pageSize)
|
|
||||||
.ToListAsync();
|
|
||||||
|
|
||||||
return (pagedRoles, totalItems);
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
using GamificationService.Models.Database;
|
|
||||||
using GamificationService.Models.DTO;
|
|
||||||
|
|
||||||
namespace GamificationService.Services.UsersProfile;
|
|
||||||
|
|
||||||
public interface IUserProfileService
|
|
||||||
{
|
|
||||||
public Task<UserProfileDTO> AddUserProfile(long userId, UserProfileCreateDTO userProfile);
|
|
||||||
public Task<UserProfile> AddUserProfile(UserProfile userProfile);
|
|
||||||
public UserProfile? GetUserProfileByUserId(long id);
|
|
||||||
public UserProfile? GetUserProfileById(long id);
|
|
||||||
public Task<bool> UpdateUserProfileByUserId(long userId, UserProfileCreateDTO userProfile);
|
|
||||||
public Task<bool> UpdateUserProfile(UserProfile userProfile);
|
|
||||||
public bool DeleteUserProfile(long id);
|
|
||||||
}
|
|
||||||
@@ -1,121 +0,0 @@
|
|||||||
using AutoMapper;
|
|
||||||
using GamificationService.Database.Repositories;
|
|
||||||
using GamificationService.Exceptions.Services.ProfileService;
|
|
||||||
using GamificationService.Models.Database;
|
|
||||||
using GamificationService.Models.DTO;
|
|
||||||
|
|
||||||
namespace GamificationService.Services.UsersProfile;
|
|
||||||
|
|
||||||
public class UserProfileService : IUserProfileService
|
|
||||||
{
|
|
||||||
private readonly UnitOfWork _unitOfWork;
|
|
||||||
|
|
||||||
# region Services
|
|
||||||
|
|
||||||
private readonly ILogger<UserProfileService> _logger;
|
|
||||||
private readonly IMapper _mapper;
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
|
|
||||||
#region Constructor
|
|
||||||
|
|
||||||
public UserProfileService(UnitOfWork unitOfWork, ILogger<UserProfileService> logger, IMapper mapper)
|
|
||||||
{
|
|
||||||
_unitOfWork = unitOfWork;
|
|
||||||
_logger = logger;
|
|
||||||
_mapper = mapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
# region Methods
|
|
||||||
|
|
||||||
public async Task<UserProfileDTO> AddUserProfile(long userId, UserProfileCreateDTO userProfile)
|
|
||||||
{
|
|
||||||
UserProfile userProfileEntity = _mapper.Map<UserProfile>(userProfile);
|
|
||||||
userProfileEntity.UserId = userId;
|
|
||||||
return _mapper.Map<UserProfileDTO>(await AddUserProfile(userProfileEntity));
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<UserProfile> AddUserProfile(UserProfile userProfile)
|
|
||||||
{
|
|
||||||
UserProfile userProfileEntity = userProfile;
|
|
||||||
|
|
||||||
// Make sure a user profile for the given user does not exist yet
|
|
||||||
if (_unitOfWork.UserProfileRepository.Get(x => x.UserId == userProfile.UserId).Any())
|
|
||||||
{
|
|
||||||
_logger.LogWarning("A user profile already exists for the given user id: {UserId}", userProfile.UserId);
|
|
||||||
throw new ProfileExistsException($"{userProfile.UserId}");
|
|
||||||
}
|
|
||||||
|
|
||||||
await _unitOfWork.UserProfileRepository.InsertAsync(userProfileEntity);
|
|
||||||
if (await _unitOfWork.SaveAsync())
|
|
||||||
{
|
|
||||||
_logger.LogInformation("User profile added for user id: {UserId}", userProfile.UserId);
|
|
||||||
return userProfileEntity;
|
|
||||||
}
|
|
||||||
|
|
||||||
_logger.LogError("Failed to add user profile for user id: {UserId}", userProfile.UserId);
|
|
||||||
throw new ProfileCreationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public UserProfile? GetUserProfileByUserId(long id)
|
|
||||||
{
|
|
||||||
return _unitOfWork.UserProfileRepository.Get(x => x.UserId == id).FirstOrDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
public UserProfile? GetUserProfileById(long id)
|
|
||||||
{
|
|
||||||
return _unitOfWork.UserProfileRepository.GetByID(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<bool> UpdateUserProfileByUserId(long userId, UserProfileCreateDTO userProfile)
|
|
||||||
{
|
|
||||||
var userProfileEntityUpdated = _mapper.Map<UserProfile>(userProfile);
|
|
||||||
var profile = _unitOfWork.UserProfileRepository
|
|
||||||
.Get(x => x.UserId == userId).FirstOrDefault() ?? throw new ProfileNotFoundException($"{userId}");
|
|
||||||
userProfileEntityUpdated.Id = profile.Id;
|
|
||||||
return await UpdateUserProfile(userProfileEntityUpdated);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<bool> UpdateUserProfile(UserProfile userProfile)
|
|
||||||
{
|
|
||||||
var userProfileEntityUpdated = userProfile;
|
|
||||||
var userProfileEntity = await _unitOfWork.UserProfileRepository.GetByIDAsync(userProfileEntityUpdated.Id);
|
|
||||||
|
|
||||||
if (userProfileEntity == null)
|
|
||||||
{
|
|
||||||
throw new ProfileNotFoundException($"{userProfileEntityUpdated.Id}");
|
|
||||||
}
|
|
||||||
|
|
||||||
_mapper.Map(userProfileEntityUpdated, userProfileEntity);
|
|
||||||
|
|
||||||
if (!await _unitOfWork.SaveAsync())
|
|
||||||
{
|
|
||||||
throw new ProfileUpdateException($"Failed to update user profile {userProfileEntityUpdated.Id}");
|
|
||||||
}
|
|
||||||
|
|
||||||
_logger.LogInformation("User profile updated for user id: {UserId}", userProfile.UserId);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool DeleteUserProfile(long id)
|
|
||||||
{
|
|
||||||
var profile = _unitOfWork.UserProfileRepository.GetByID(id);
|
|
||||||
if (profile == null)
|
|
||||||
{
|
|
||||||
throw new ProfileNotFoundException($"{id}");
|
|
||||||
}
|
|
||||||
|
|
||||||
_unitOfWork.UserProfileRepository.Delete(id);
|
|
||||||
if (_unitOfWork.Save())
|
|
||||||
{
|
|
||||||
_logger.LogInformation("User profile deleted: {UserId}", id);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
throw new ProfileDeletionException($"Failed to delete user profile {id}");
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
using System.Net.Mail;
|
|
||||||
using GamificationService.Exceptions.UtilServices.Email;
|
|
||||||
|
|
||||||
namespace GamificationService.Utils;
|
|
||||||
|
|
||||||
public class EmailClient(SmtpClient smtpClient, string emailFrom, ILogger<EmailClient> logger)
|
|
||||||
{
|
|
||||||
#region Fields
|
|
||||||
|
|
||||||
private readonly string _emailFrom = emailFrom;
|
|
||||||
private readonly ILogger<EmailClient> _logger = logger;
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Methods
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sends the email using the SmtpClient instance.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="email">Email to send.</param>
|
|
||||||
/// <exception cref="SendEmailException">If the SmtpClient instance fails to send the email.</exception>
|
|
||||||
/// <returns>Task that represents the asynchronous operation.</returns>
|
|
||||||
public async Task SendEmail(MailMessage email, string emailTo)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
email.To.Add(new MailAddress(emailTo));
|
|
||||||
await smtpClient.SendMailAsync(email);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_logger.LogError(ex, ex.Message);
|
|
||||||
throw new SendEmailException("Failed to send email", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
@@ -1,150 +0,0 @@
|
|||||||
using System.Net;
|
|
||||||
using System.Net.Http.Headers;
|
|
||||||
using System.Text;
|
|
||||||
using System.Text.Json;
|
|
||||||
using GamificationService.Exceptions.UtilServices.Api;
|
|
||||||
|
|
||||||
namespace GamificationService.Utils;
|
|
||||||
|
|
||||||
public class PushNotificationsClient
|
|
||||||
{
|
|
||||||
#region Fields
|
|
||||||
|
|
||||||
private readonly HttpClient _httpClient;
|
|
||||||
private readonly ILogger<PushNotificationsClient> _logger;
|
|
||||||
private readonly string _applicationToken;
|
|
||||||
private readonly string _projectId;
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Constructor
|
|
||||||
|
|
||||||
public PushNotificationsClient(HttpClient httpClient, ILogger<PushNotificationsClient> logger, string applicationToken, string projectId)
|
|
||||||
{
|
|
||||||
_httpClient = httpClient;
|
|
||||||
_logger = logger;
|
|
||||||
_applicationToken = applicationToken;
|
|
||||||
_projectId = projectId;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Methods
|
|
||||||
|
|
||||||
public async Task SendPushNotification(PushNotification pushNotification)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var payload = new
|
|
||||||
{
|
|
||||||
message = new
|
|
||||||
{
|
|
||||||
token = _applicationToken,
|
|
||||||
notification = new
|
|
||||||
{
|
|
||||||
body = pushNotification.Message,
|
|
||||||
title = pushNotification.Title,
|
|
||||||
image = pushNotification.Image
|
|
||||||
},
|
|
||||||
android = new
|
|
||||||
{
|
|
||||||
notification = new
|
|
||||||
{
|
|
||||||
body = pushNotification.Message,
|
|
||||||
title = pushNotification.Title,
|
|
||||||
image = pushNotification.Image,
|
|
||||||
click_action = pushNotification.ClickAction,
|
|
||||||
click_action_type = pushNotification.ClickActionType
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var jsonPayload = JsonSerializer.Serialize(payload);
|
|
||||||
|
|
||||||
var request = new HttpRequestMessage(HttpMethod.Post,$"/{_projectId}/messages")
|
|
||||||
{
|
|
||||||
Content = new StringContent(jsonPayload, Encoding.UTF8, "application/json")
|
|
||||||
};
|
|
||||||
|
|
||||||
var response = await _httpClient.SendAsync(request);
|
|
||||||
|
|
||||||
if (response.StatusCode == HttpStatusCode.BadRequest)
|
|
||||||
{
|
|
||||||
var responseContent = await response.Content.ReadAsStringAsync();
|
|
||||||
_logger.LogError($"Failed to send push notification. Status Code: {response.StatusCode}, Response: {responseContent}");
|
|
||||||
throw new BadRequestException($"Failed to send push notification: {response.StatusCode}");
|
|
||||||
}
|
|
||||||
else if (response.StatusCode == HttpStatusCode.Forbidden)
|
|
||||||
{
|
|
||||||
var responseContent = await response.Content.ReadAsStringAsync();
|
|
||||||
_logger.LogError($"Failed to send push notification: {response.StatusCode}, Response: {responseContent}");
|
|
||||||
throw new ForbiddenException($"Failed to send push notification: {response.StatusCode}");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var responseContent = await response.Content.ReadAsStringAsync();
|
|
||||||
_logger.LogError($"Failed to send push notification: {response.StatusCode}, Response: {responseContent}");
|
|
||||||
throw new Exception($"Failed to send push notification: {response.StatusCode}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
_logger.LogError(e, e.Message);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task SendPushNotification(PushNotification pushNotification, string topic)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var payload = new
|
|
||||||
{
|
|
||||||
message = new
|
|
||||||
{
|
|
||||||
notification = new
|
|
||||||
{
|
|
||||||
body = pushNotification.Message,
|
|
||||||
title = pushNotification.Title,
|
|
||||||
image = pushNotification.Image
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var jsonPayload = JsonSerializer.Serialize(payload);
|
|
||||||
|
|
||||||
var request = new HttpRequestMessage(HttpMethod.Post,$"/{_projectId}/topics/{topic}/publish")
|
|
||||||
{
|
|
||||||
Content = new StringContent(jsonPayload, Encoding.UTF8, "application/json")
|
|
||||||
};
|
|
||||||
|
|
||||||
var response = await _httpClient.SendAsync(request);
|
|
||||||
|
|
||||||
if (response.StatusCode == HttpStatusCode.BadRequest)
|
|
||||||
{
|
|
||||||
var responseContent = await response.Content.ReadAsStringAsync();
|
|
||||||
_logger.LogError($"Failed to send push notification. Status Code: {response.StatusCode}, Response: {responseContent}");
|
|
||||||
throw new BadRequestException($"Failed to send push notification: {response.StatusCode}");
|
|
||||||
}
|
|
||||||
else if (response.StatusCode == HttpStatusCode.Forbidden)
|
|
||||||
{
|
|
||||||
var responseContent = await response.Content.ReadAsStringAsync();
|
|
||||||
_logger.LogError($"Failed to send push notification: {response.StatusCode}, Response: {responseContent}");
|
|
||||||
throw new ForbiddenException($"Failed to send push notification: {response.StatusCode}");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var responseContent = await response.Content.ReadAsStringAsync();
|
|
||||||
_logger.LogError($"Failed to send push notification: {response.StatusCode}, Response: {responseContent}");
|
|
||||||
throw new Exception($"Failed to send push notification: {response.StatusCode}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
_logger.LogError(e, e.Message);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
namespace GamificationService.Utils.Enums;
|
|
||||||
|
|
||||||
public enum Gender
|
|
||||||
{
|
|
||||||
Male,
|
|
||||||
Female
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
namespace GamificationService.Utils.Enums
|
|
||||||
{
|
|
||||||
public enum InstructionTestScoreCalcMethod
|
|
||||||
{
|
|
||||||
AverageGrade,
|
|
||||||
MaxGrade
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
namespace GamificationService.Utils;
|
|
||||||
|
|
||||||
public enum NotificationInformationType
|
|
||||||
{
|
|
||||||
AUTH,
|
|
||||||
INFO,
|
|
||||||
WARNING,
|
|
||||||
ERROR
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
using System.Net.Mail;
|
|
||||||
|
|
||||||
namespace GamificationService.Utils.Factory;
|
|
||||||
|
|
||||||
public class MailNotificationsFactory
|
|
||||||
{
|
|
||||||
public static Notification CreateNotification(NotificationInformationType type,
|
|
||||||
string title,
|
|
||||||
string message,List<Attachment> attachments)
|
|
||||||
{
|
|
||||||
return new MailNotification(type, title, message, attachments);
|
|
||||||
}
|
|
||||||
public Notification CreateNotification(NotificationInformationType type,
|
|
||||||
string title,
|
|
||||||
string message)
|
|
||||||
{
|
|
||||||
|
|
||||||
return new MailNotification(type, title, message);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
namespace GamificationService.Utils.Factory;
|
|
||||||
|
|
||||||
public class PushNotificationsFactory
|
|
||||||
{
|
|
||||||
public Notification CreateNotification(NotificationInformationType type,
|
|
||||||
string title,
|
|
||||||
string message)
|
|
||||||
{
|
|
||||||
return new PushNotification(type, title, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Notification CreateNotification(NotificationInformationType type,
|
|
||||||
string title,
|
|
||||||
string message,
|
|
||||||
string image)
|
|
||||||
{
|
|
||||||
return new PushNotification(type, title, message, image);
|
|
||||||
}
|
|
||||||
public Notification CreateNotification(NotificationInformationType type,
|
|
||||||
string title,
|
|
||||||
string message,
|
|
||||||
string? image,
|
|
||||||
string clickAction,
|
|
||||||
ClickActionType clickActionType)
|
|
||||||
{
|
|
||||||
return new PushNotification(type, title, message, image, clickAction, clickActionType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,111 +0,0 @@
|
|||||||
using System.Net.Mail;
|
|
||||||
|
|
||||||
namespace GamificationService.Utils;
|
|
||||||
|
|
||||||
public class MailNotification : Notification
|
|
||||||
{
|
|
||||||
#region Fields
|
|
||||||
|
|
||||||
private List<Attachment> _attachments;
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Properties
|
|
||||||
public List<Attachment> Attachments { get => _attachments; }
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Constructor
|
|
||||||
|
|
||||||
public MailNotification(NotificationInformationType type, string title, string message, List<Attachment> attachments) : base(type, title, message)
|
|
||||||
{
|
|
||||||
_attachments = attachments;
|
|
||||||
}
|
|
||||||
public MailNotification(NotificationInformationType type, string title, string message) : base(type, title, message)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Methods
|
|
||||||
|
|
||||||
public MailMessage ConvertToMailMessage()
|
|
||||||
{
|
|
||||||
var mailMessage = new MailMessage
|
|
||||||
{
|
|
||||||
Subject = CreateTitle(),
|
|
||||||
Body = CreateBody(),
|
|
||||||
IsBodyHtml = true,
|
|
||||||
Priority = GetPriority()
|
|
||||||
};
|
|
||||||
if (_attachments != null)
|
|
||||||
{
|
|
||||||
mailMessage.Attachments.ToList().AddRange(_attachments);
|
|
||||||
}
|
|
||||||
return mailMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Private Methods
|
|
||||||
private string CreateTitle()
|
|
||||||
{
|
|
||||||
switch (Type)
|
|
||||||
{
|
|
||||||
case NotificationInformationType.AUTH:
|
|
||||||
return "Авторизация " + Title;
|
|
||||||
case NotificationInformationType.INFO:
|
|
||||||
return "Информация "+ Title;
|
|
||||||
case NotificationInformationType.WARNING:
|
|
||||||
return "Предупреждение "+ Title;
|
|
||||||
case NotificationInformationType.ERROR:
|
|
||||||
return "Ошибка "+ Title;
|
|
||||||
default:
|
|
||||||
return "Информация "+ Title;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private string CreateBody()
|
|
||||||
{
|
|
||||||
string formattedMessage;
|
|
||||||
|
|
||||||
switch (Type)
|
|
||||||
{
|
|
||||||
case NotificationInformationType.AUTH:
|
|
||||||
formattedMessage = "Вы успешно авторизовались.";
|
|
||||||
break;
|
|
||||||
case NotificationInformationType.INFO:
|
|
||||||
formattedMessage = "Это информационное сообщение.";
|
|
||||||
break;
|
|
||||||
case NotificationInformationType.WARNING:
|
|
||||||
formattedMessage = "Внимание! Обратите внимание на это предупреждение.";
|
|
||||||
break;
|
|
||||||
case NotificationInformationType.ERROR:
|
|
||||||
formattedMessage = "Произошла ошибка. Пожалуйста, проверьте детали.";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
formattedMessage = "Сообщение не определено.";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $"<p style='font-size: 16px; line-height: 1.5; color: #555;'>{formattedMessage} {Message}</p>";
|
|
||||||
}
|
|
||||||
|
|
||||||
private MailPriority GetPriority()
|
|
||||||
{
|
|
||||||
switch (Type)
|
|
||||||
{
|
|
||||||
case NotificationInformationType.AUTH:
|
|
||||||
return MailPriority.High;
|
|
||||||
case NotificationInformationType.INFO:
|
|
||||||
return MailPriority.Normal;
|
|
||||||
case NotificationInformationType.WARNING:
|
|
||||||
return MailPriority.Low;
|
|
||||||
case NotificationInformationType.ERROR:
|
|
||||||
return MailPriority.High;
|
|
||||||
default:
|
|
||||||
return MailPriority.Normal;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
using System.Net.Mail;
|
|
||||||
|
|
||||||
namespace GamificationService.Utils;
|
|
||||||
|
|
||||||
public abstract class Notification
|
|
||||||
{
|
|
||||||
#region Fields
|
|
||||||
|
|
||||||
private string _title;
|
|
||||||
private string _message;
|
|
||||||
private NotificationInformationType _type;
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Parameters
|
|
||||||
|
|
||||||
public string Title { get => _title;}
|
|
||||||
public string Message { get => _message; }
|
|
||||||
public NotificationInformationType Type { get => _type; }
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Constructor
|
|
||||||
|
|
||||||
public Notification(NotificationInformationType type, string title, string message)
|
|
||||||
{
|
|
||||||
_type = type;
|
|
||||||
_title = title;
|
|
||||||
_message = message;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
namespace GamificationService.Utils;
|
|
||||||
|
|
||||||
public class PushNotification : Notification
|
|
||||||
{
|
|
||||||
#region Fields
|
|
||||||
|
|
||||||
private readonly string? _image;
|
|
||||||
private readonly string? _clickAction;
|
|
||||||
private readonly ClickActionType? _clickActionType;
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Properties
|
|
||||||
|
|
||||||
public string? Image { get => _image; }
|
|
||||||
public string? ClickAction { get => _clickAction; }
|
|
||||||
public int? ClickActionType { get => (int)_clickActionType; }
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Constructor
|
|
||||||
|
|
||||||
public PushNotification(NotificationInformationType type, string title, string message, string image, string clickAction, ClickActionType clickActionType) : base(type, title, message)
|
|
||||||
{
|
|
||||||
_image = image;
|
|
||||||
_clickAction = clickAction;
|
|
||||||
_clickActionType = clickActionType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public PushNotification(NotificationInformationType type, string title, string message, string? image) : base(type, title, message)
|
|
||||||
{
|
|
||||||
_image = image;
|
|
||||||
}
|
|
||||||
|
|
||||||
public PushNotification(NotificationInformationType type, string title, string message) : base(type, title, message)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
namespace GamificationService.Utils;
|
|
||||||
|
|
||||||
public enum TwoFactorProvider
|
|
||||||
{
|
|
||||||
NONE,
|
|
||||||
EMAIL,
|
|
||||||
PHONE,
|
|
||||||
PUSH,
|
|
||||||
AUTHENTICATOR
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user