Creado apartir del commit b888de6c92056de294456f581a56e25e734d4ab7 de develop
This commit is contained in:
@@ -0,0 +1,647 @@
|
||||
using System.Diagnostics;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Security.Claims;
|
||||
using System.Text;
|
||||
using adas_core.Application.Exceptions;
|
||||
using adas_core.Application.Repositories.Interfaces;
|
||||
using adas_core.Application.Services.Interfaces;
|
||||
using adas_core.Authentication.Interfaces;
|
||||
using adas_core.Authentication.Models;
|
||||
using adas_core.Domain.Enums;
|
||||
using adas_core.Domain.Exceptions;
|
||||
using adas_core.Domain.Models.AppSettings;
|
||||
using adas_core.Domain.Models.DTO;
|
||||
using adas_core.Domain.Models.Filter;
|
||||
using adas_core.Domain.Models.MongoModels;
|
||||
using adas_core.Domain.Models.Responses;
|
||||
using adas_core.Domain.Utils;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Driver;
|
||||
using static System.Enum;
|
||||
|
||||
namespace adas_core.Authentication;
|
||||
|
||||
public class UserService : IUserService
|
||||
{
|
||||
private readonly ILocalAuditService _auditService;
|
||||
private readonly IAuthorityService _authorityService;
|
||||
private readonly IEnumerable<ILoginService> _availableLoginServices;
|
||||
private readonly Lazy<IDisplayService> _displayService;
|
||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||
private readonly JwtConfig _jwtConfig;
|
||||
private readonly ILogger<UserService> _logger;
|
||||
private readonly IUserRepository _userRepository;
|
||||
private readonly UsersWhiteListConfig _usersWhiteList;
|
||||
private readonly ValidGroupsConfig _validGroups;
|
||||
private readonly List<string> _validLoginMethods;
|
||||
private readonly ISubscribersService _subscribersService;
|
||||
private readonly IClientMessageService _clientMessageService;
|
||||
private readonly Lazy<IPermissionService> _permissionService;
|
||||
public UserService(
|
||||
IEnumerable<ILoginService> loginServices,
|
||||
IOptions<AuthSettings> configuration,
|
||||
IOptions<ValidGroupsConfig> validGroups,
|
||||
IOptions<AuthSettings> usersWhiteList,
|
||||
IOptions<AuthSettings> jwt,
|
||||
IHttpContextAccessor httpContextAccessor,
|
||||
IUserRepository userRepository,
|
||||
IAuthorityService authorityService,
|
||||
ILocalAuditService auditService,
|
||||
Lazy<IDisplayService> displayService,
|
||||
ILogger<UserService> logger,
|
||||
ISubscribersService subscribersService,
|
||||
IClientMessageService clientMessageService, Lazy<IPermissionService> permissionService)
|
||||
{
|
||||
_availableLoginServices = loginServices;
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
_validGroups = validGroups.Value;
|
||||
_usersWhiteList = usersWhiteList.Value.UsersWhiteListConfig;
|
||||
_jwtConfig = jwt.Value.JwtConfig ?? throw new Exception("JWT NOT CONFIGURED");
|
||||
var loginMethods = configuration.Value.LoginMethods;
|
||||
_validLoginMethods = loginMethods;
|
||||
_userRepository = userRepository;
|
||||
_authorityService = authorityService;
|
||||
_auditService = auditService;
|
||||
_displayService = displayService;
|
||||
_logger = logger;
|
||||
_subscribersService = subscribersService;
|
||||
_clientMessageService = clientMessageService;
|
||||
_permissionService = permissionService;
|
||||
}
|
||||
|
||||
|
||||
public async Task<TokenResult> Login(string username, string password)
|
||||
{
|
||||
var user = await GetUser(username, password);
|
||||
_logger.LogInformation("[UserService] Login user {u}", user.ToString());
|
||||
|
||||
if (user == null) throw new UnauthorizedException(HttpEnum.ErrorMessage.UnauthorizedInvalidCredentials);
|
||||
if (!user.IsEnabled || (user.LockExpirationDate != null && user.LockExpirationDate > DateTime.UtcNow))
|
||||
throw new ForbbidenException(HttpEnum.ErrorMessage.ForbiddenUserBlocked);
|
||||
if (!_usersWhiteList.IsValid(user) && !_validGroups.IsValid(user))
|
||||
throw new UnauthorizedException(HttpEnum.ErrorMessage.UnauthorizedNoPermission);
|
||||
|
||||
if (user.LockExpirationDate < DateTime.UtcNow) user.LockExpirationDate = null;
|
||||
user.LastLogin = DateTime.UtcNow;
|
||||
await UpdateUsersByRequest(user, false);
|
||||
return await GenerateJwt(user);
|
||||
}
|
||||
|
||||
public void ValidateToken(string token, string tokenType, out SecurityToken validatedToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
var tokenValidationParameters = new TokenValidationParameters
|
||||
{
|
||||
ValidateAudience = _jwtConfig.ValidateAudience,
|
||||
ValidateIssuer = _jwtConfig.ValidateIssuer,
|
||||
ValidAudience = _jwtConfig.Audience,
|
||||
ValidIssuer = _jwtConfig.Issuer,
|
||||
ValidateIssuerSigningKey = true,
|
||||
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwtConfig.Key ?? string.Empty)),
|
||||
ValidateLifetime = false
|
||||
};
|
||||
|
||||
var tokenHandler = new JwtSecurityTokenHandler();
|
||||
tokenHandler.ValidateToken(token, tokenValidationParameters, out var securityToken);
|
||||
if (securityToken is not JwtSecurityToken jwtSecurityToken ||
|
||||
!jwtSecurityToken.Header.Alg.Equals(SecurityAlgorithms.HmacSha256,
|
||||
StringComparison.InvariantCultureIgnoreCase))
|
||||
throw new SecurityTokenException("Invalid token");
|
||||
validatedToken = securityToken;
|
||||
}
|
||||
catch (SecurityTokenException a)
|
||||
{
|
||||
_logger.LogError("Error validating token, {msg}", a.Message);
|
||||
throw new TokenException(a.Message);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogError("Error validating token, {msg}", e.Message);
|
||||
throw new TokenException("Error validating token");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<User?> GetUserByToken(JwtSecurityToken? jwtToken)
|
||||
{
|
||||
User? user = null;
|
||||
if (jwtToken == null)
|
||||
return user;
|
||||
|
||||
var userName = jwtToken.Claims.First(x => x.Type == ClaimTypes.Name).Value;
|
||||
|
||||
user = await _userRepository.GetByUserName(userName);
|
||||
if (user == null)
|
||||
return user;
|
||||
|
||||
//Eliminamos la contraseña
|
||||
user.Password = string.Empty;
|
||||
if (user.Authorization == null || user.Authorization.Count == 0)
|
||||
user.Authorization = await _authorityService.GetUserAuthorities(user.Id);
|
||||
return user;
|
||||
}
|
||||
|
||||
public async Task<User?> GetUserByCasTicket(string serviceUrl, string ticket)
|
||||
{
|
||||
var service = _availableLoginServices.FirstOrDefault(s => s.Method == UserEnum.LoginMethod.Cas);
|
||||
if (service == null) throw new LoginServicesException("CAS login method not available");
|
||||
|
||||
try
|
||||
{
|
||||
var user = await service.Login(_httpContextAccessor.HttpContext!);
|
||||
if (!_usersWhiteList.IsValid(user) && !_validGroups.IsValid(user))
|
||||
throw new UnauthorizedAccessException("You don't have sufficient permissions");
|
||||
return user;
|
||||
}
|
||||
catch (BusinessException)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
catch (UnauthorizedAccessException)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
var message = e.Message;
|
||||
if (e.InnerException != null && e.Message != e.InnerException?.Message)
|
||||
message += $", {e.InnerException?.Message}";
|
||||
Debug.WriteLine($"Error while login: {message} ");
|
||||
throw new LoginServicesException(message, e);
|
||||
}
|
||||
////////////////////////
|
||||
/*
|
||||
if (!_validLoginMethods.Contains(LoginMethod.CAS.ToString()))
|
||||
{
|
||||
Log.Warning("CAS login method not enabled");
|
||||
return null;
|
||||
}
|
||||
_casLoginService = new
|
||||
Log.Information("CAS ticket received: '{CasTicket}'", ticket);
|
||||
return string.IsNullOrEmpty(ticket) ? null : _casLoginService.GetUser(serviceUrl, ticket, context);
|
||||
*/
|
||||
}
|
||||
|
||||
public async Task<TokenResult> RefreshToken(string refreshToken)
|
||||
{
|
||||
ValidateToken(refreshToken, IUserService.TokenTypeRefresh, out var validatedToken);
|
||||
var user = await GetUserByToken((JwtSecurityToken)validatedToken);
|
||||
if (user == null)
|
||||
return new TokenResult();
|
||||
return await GenerateJwt(user);
|
||||
}
|
||||
|
||||
|
||||
public async Task<User> GetUser(string username, string password)
|
||||
{
|
||||
//BusinessException? loginException = null;
|
||||
foreach (var m in _validLoginMethods)
|
||||
{
|
||||
if (!TryParse(m, out UserEnum.LoginMethod method)) continue;
|
||||
var service = _availableLoginServices.FirstOrDefault(s => s.Method == method && s.AllowPassword);
|
||||
if (service == null) continue;
|
||||
try
|
||||
{
|
||||
_logger.LogInformation("[UserService] Trying login with method {method}", method);
|
||||
return await service.Login(username, password);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogError("[UserService] Error while trying method {method}, err {err}", method, e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
throw new LoginServicesNotFoundException();
|
||||
}
|
||||
|
||||
public async Task<User?> GetUserById(ObjectId id)
|
||||
{
|
||||
try
|
||||
{
|
||||
var u = await _userRepository.GetById(id);
|
||||
if (u != null) u.Authorization = await _authorityService.GetUserAuthorities(u.Id);
|
||||
return u;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<User?> GetUserByUserName(string name)
|
||||
{
|
||||
var u = await _userRepository.GetByUserName(name);
|
||||
if (u == null) return u;
|
||||
u.Authorization = await _authorityService.GetUserAuthorities(u.Id);
|
||||
return u;
|
||||
}
|
||||
|
||||
public async Task<User?> GetUserByName(string name)
|
||||
{
|
||||
try
|
||||
{
|
||||
var u = await _userRepository.GetByName(name);
|
||||
if (u != null) u.Authorization = await _authorityService.GetUserAuthorities(u.Id);
|
||||
return u;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<User?> CreateUser(User userEntryLdap)
|
||||
{
|
||||
CheckIfUserNameExists(userEntryLdap.UserName);
|
||||
CheckIfEmailExists(userEntryLdap.Email);
|
||||
await _userRepository.InsertOneAsync(userEntryLdap);
|
||||
var result = await GetUserByUserName(userEntryLdap.UserName);
|
||||
await _auditService.CreateAuditLogAsync(_httpContextAccessor.HttpContext?.User, null, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<User?> CreateNewUserByRequest(User user)
|
||||
{
|
||||
CheckIfEmailExists(user.Email);
|
||||
CheckIfUserNameExists(user.UserName);
|
||||
if (user.Type == UserEnum.Type.Local)
|
||||
{
|
||||
if (!CryptoAdas.IsStrongPassword(user.Password))
|
||||
throw new UnprocessableEntityException(HttpEnum.ErrorMessage.UnprocessableEntityInvalidPassword);
|
||||
user.Password = CryptoAdas.CreateBCrypt(user.Password);
|
||||
}
|
||||
|
||||
await _userRepository.InsertOneAsync(user);
|
||||
var result = await GetUserByUserName(user.UserName) ??
|
||||
throw new NotFoundException(HttpEnum.ErrorMessage.NotFoundResourceMissing);
|
||||
await _auditService.CreateAuditLogAsync(_httpContextAccessor.HttpContext?.User, null, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<User?> CreateNewUserWithAuthorities(CreateUserWithAuthDto createUserWithAuthDto)
|
||||
{
|
||||
var user = createUserWithAuthDto.User;
|
||||
var newUser = await CreateNewUserByRequest(user) ??
|
||||
throw new NotFoundException(HttpEnum.ErrorMessage.NotFoundResourceMissing);
|
||||
var auths = createUserWithAuthDto.Authorizations;
|
||||
foreach (var auth in auths)
|
||||
{
|
||||
auth.UserId = newUser.Id;
|
||||
await CreateNewAuthority(auth);
|
||||
}
|
||||
|
||||
return newUser;
|
||||
}
|
||||
|
||||
public async Task<User?> UpdateUsersByRequest(User user, bool updatePass)
|
||||
{
|
||||
var oldUser = await _userRepository.GetByUserName(user.UserName);
|
||||
var logoutHasBeenSent = false;
|
||||
if (updatePass && !CryptoAdas.IsStrongPassword(user.Password))
|
||||
throw new UnprocessableEntityException(HttpEnum.ErrorMessage.UnprocessableEntityInvalidPassword);
|
||||
if (updatePass)
|
||||
{
|
||||
user.Password = CryptoAdas.CreateBCrypt(user.Password);
|
||||
await SendBroadcastUser(user, user.UserName, OperationType.UpdatePassword);
|
||||
logoutHasBeenSent = true;
|
||||
}
|
||||
|
||||
var result = await _userRepository.UpdateUser(user, updatePass);
|
||||
if(!logoutHasBeenSent && oldUser != null && result != null && oldUser.IsEnabled && !result.IsEnabled)
|
||||
{
|
||||
await SendBroadcastUser(result, user.UserName, OperationType.DisableUser);
|
||||
logoutHasBeenSent = true;
|
||||
}
|
||||
if(!logoutHasBeenSent && result != null && result.LockExpirationDate != null && result.LockExpirationDate>DateTime.UtcNow) await SendBroadcastUser(result, user.UserName, OperationType.LockUser);
|
||||
await _auditService.CreateAuditLogAsync(_httpContextAccessor.HttpContext?.User, oldUser, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
private async Task SendBroadcastUser(object elementUpdated, string userName, OperationType operation)
|
||||
{
|
||||
var subscribers = _subscribersService.GetSubscribers().Where(s =>
|
||||
s.UserName == userName).ToList();
|
||||
foreach (var subscriber in subscribers)
|
||||
{
|
||||
await _clientMessageService.SendAsync(subscriber.Id, operation, elementUpdated);
|
||||
}
|
||||
}
|
||||
private async Task SendBroadcastPermissions(object elementUpdated, string userName, OperationType operation)
|
||||
{
|
||||
var subscribers = _subscribersService.GetSubscribers().Where(s =>
|
||||
s.UserName == userName).ToList();
|
||||
foreach (var subscriber in subscribers)
|
||||
{
|
||||
if (subscriber.SubscriptionType == SubscriptionEnum.WsType.Admin)
|
||||
{
|
||||
try
|
||||
{
|
||||
var permissionsForPanel = await _permissionService.Value.GetPermissionsForPanel(userName);
|
||||
_ = _clientMessageService.SendAsync(subscriber.Id, operation, permissionsForPanel);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
_ = _clientMessageService.SendAsync(subscriber.Id, operation, null);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
_ = _clientMessageService.SendAsync(subscriber.Id, operation, elementUpdated);
|
||||
}
|
||||
}
|
||||
}
|
||||
public async Task<User?> UpdateUserWithAuthorities(UpdateUserWithAuthDto updateUserWithAuthDto, bool updatePass)
|
||||
{
|
||||
var u = updateUserWithAuthDto.User;
|
||||
CheckIfEmailExists(u.Email, u.Id);
|
||||
CheckIfUserNameExists(u.UserName, u.Id);
|
||||
var userUpdated = await UpdateUsersByRequest(u, updatePass) ??
|
||||
throw new ConflictException(HttpEnum.ErrorMessage.ConflictUpdateFailed);
|
||||
|
||||
foreach (var id in updateUserWithAuthDto.AuthsToDelete) await DeleteAuthority(id);
|
||||
foreach (var auth in updateUserWithAuthDto.Authorizations) await UpdateAuthority(auth);
|
||||
foreach (var auth in updateUserWithAuthDto.NewAuthorizations)
|
||||
{
|
||||
auth.UserId = userUpdated.Id;
|
||||
await CreateNewAuthority(auth);
|
||||
}
|
||||
if(updateUserWithAuthDto.AuthsToDelete.Any() || updateUserWithAuthDto.NewAuthorizations.Any() || updateUserWithAuthDto.Authorizations.Any())
|
||||
{
|
||||
var allPermissionsForDisplay = await _displayService.Value.GetAllByUser(u.UserName);
|
||||
|
||||
await SendBroadcastPermissions(allPermissionsForDisplay, u.UserName, OperationType.UpdateAuthorities);
|
||||
}
|
||||
return userUpdated;
|
||||
}
|
||||
|
||||
public async Task<bool> UpdateUserPassword(ObjectId id, string oldPassword, string newPassword)
|
||||
{
|
||||
if (oldPassword == newPassword)
|
||||
throw new BadRequestException("New password must be different");
|
||||
|
||||
var user = await _userRepository.GetById(id) ??
|
||||
throw new NotFoundException(HttpEnum.ErrorMessage.NotFoundResourceMissing);
|
||||
|
||||
|
||||
if (!CryptoAdas.VerifyPassword(oldPassword, user.Password))
|
||||
throw new UnprocessableEntityException("Invalid current password");
|
||||
|
||||
if (!CryptoAdas.IsStrongPassword(newPassword))
|
||||
throw new UnprocessableEntityException("Weak password");
|
||||
|
||||
user.Password = CryptoAdas.CreateBCrypt(newPassword);
|
||||
var result = await _userRepository.UpdateUser(user, true);
|
||||
if (result != null)
|
||||
{
|
||||
_logger.LogInformation("Password updated for user {UserId}", id);
|
||||
|
||||
await _auditService.CreateAuditLogAsync(_httpContextAccessor.HttpContext?.User, user, result);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public async Task<bool> DeleteUser(ObjectId id)
|
||||
{
|
||||
try
|
||||
{
|
||||
var user = await _userRepository.GetById(id);
|
||||
await _userRepository.DeleteAsync(id);
|
||||
await _auditService.CreateAuditLogAsync(_httpContextAccessor.HttpContext?.User, user, null);
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogError("Error deleting user. Exception: {e}", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<PaginationResponse<User>> GetPaginatedUsers(PaginationFilter filter)
|
||||
{
|
||||
var result = _userRepository.GetPaginatedUsers(filter);
|
||||
|
||||
var count = await result.CountDocumentsAsync();
|
||||
|
||||
var data = await result.Skip((filter.PageNumber - 1) * filter.PageSize)
|
||||
.Limit(filter.PageSize)
|
||||
.ToCursorAsync();
|
||||
|
||||
|
||||
var dataList = await data.ToListAsync();
|
||||
|
||||
return new PaginationResponse<User>(dataList, filter.PageNumber, filter.PageSize, count);
|
||||
}
|
||||
|
||||
public async Task<TokenResult> GenerateJwt(User user)
|
||||
{
|
||||
var claims = new List<Claim>
|
||||
{
|
||||
new(ClaimTypes.Name, user.UserName),
|
||||
new(ClaimTypes.Email, user.Email),
|
||||
new("IpAddress", user.IpAddress)
|
||||
};
|
||||
|
||||
// Agregar claims de autorizaciones utilizando ClaimsFromAuthorities
|
||||
if (user.Authorization != null)
|
||||
claims.AddRange(await ClaimsFromAuthorities(user.Authorization));
|
||||
|
||||
var accessToken = JwtHelper.GetJwtToken(
|
||||
user.UserName,
|
||||
_jwtConfig.Key ?? string.Empty,
|
||||
_jwtConfig.Issuer ?? string.Empty,
|
||||
_jwtConfig.Audience ?? string.Empty,
|
||||
_jwtConfig.TokenValidityInMinutes,
|
||||
claims.ToArray());
|
||||
|
||||
var refreshToken = JwtHelper.GetJwtToken(
|
||||
user.UserName,
|
||||
_jwtConfig.Key ?? string.Empty,
|
||||
_jwtConfig.Issuer ?? string.Empty,
|
||||
_jwtConfig.Audience ?? string.Empty,
|
||||
_jwtConfig.RefreshTokenValidityInMinutes,
|
||||
claims.ToArray());
|
||||
|
||||
return new TokenResult
|
||||
{
|
||||
AccessToken = new JwtSecurityTokenHandler().WriteToken(accessToken),
|
||||
RefreshToken = new JwtSecurityTokenHandler().WriteToken(refreshToken),
|
||||
AccessTokenExpiryTime = accessToken.ValidTo,
|
||||
RefreshTokenExpiryTime = refreshToken.ValidTo,
|
||||
User = user
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<List<User>> GetAll()
|
||||
{
|
||||
BusinessException? loginException = null;
|
||||
foreach (var m in _validLoginMethods)
|
||||
{
|
||||
if (!TryParse(m, out UserEnum.LoginMethod method)) continue;
|
||||
var service = _availableLoginServices.FirstOrDefault(s => s.Method == method && s.AllowPassword);
|
||||
if (service == null) continue;
|
||||
try
|
||||
{
|
||||
return await service.GetAllUsers();
|
||||
}
|
||||
catch (BusinessException e)
|
||||
{
|
||||
loginException = e;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
var message = e.Message;
|
||||
if (e.Message != e.InnerException?.Message) message += $", {e.InnerException?.Message}";
|
||||
Debug.WriteLine($"Error Getting all users: {message} ");
|
||||
loginException = new LoginServicesException(message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (loginException != null) throw loginException;
|
||||
|
||||
throw new LoginServicesNotFoundException();
|
||||
}
|
||||
|
||||
public async Task<TokenResult> LoginWithGivenAccessToken(string token)
|
||||
{
|
||||
ValidateToken(token, IUserService.TokenTypeUser, out var validatedToken);
|
||||
var jwtToken = (JwtSecurityToken)validatedToken;
|
||||
var user = await GetUserByToken(jwtToken) ??
|
||||
throw new NotFoundException(HttpEnum.ErrorMessage.NotFoundResourceMissing);
|
||||
user.Authorization ??= await _authorityService.GetUserAuthorities(user.Id);
|
||||
|
||||
if (jwtToken.ValidTo < DateTime.UtcNow)
|
||||
return await GenerateJwt(user);
|
||||
|
||||
|
||||
var claims = new List<Claim>
|
||||
{
|
||||
new(ClaimTypes.Name, user.UserName),
|
||||
new(ClaimTypes.Email, user.Email),
|
||||
new("IpAddress", user.IpAddress)
|
||||
};
|
||||
|
||||
// Agregar claims de autorizaciones utilizando ClaimsFromAuthorities
|
||||
claims.AddRange(await ClaimsFromAuthorities(user.Authorization));
|
||||
var dif = jwtToken.ValidTo > DateTime.Now ? jwtToken.ValidTo - DateTime.Now : DateTime.Now - jwtToken.ValidTo;
|
||||
var accessToken = JwtHelper.GetJwtToken(
|
||||
user.UserName,
|
||||
_jwtConfig.Key ?? string.Empty,
|
||||
_jwtConfig.Issuer ?? string.Empty,
|
||||
_jwtConfig.Audience ?? string.Empty,
|
||||
(int)dif.TotalMinutes,
|
||||
claims.ToArray());
|
||||
var refreshToken = JwtHelper.GetJwtToken(
|
||||
user.UserName,
|
||||
_jwtConfig.Key ?? string.Empty,
|
||||
_jwtConfig.Issuer ?? string.Empty,
|
||||
_jwtConfig.Audience ?? string.Empty,
|
||||
(int)dif.TotalMinutes + _jwtConfig.RefreshTokenValidityInMinutes,
|
||||
claims.ToArray());
|
||||
|
||||
return new TokenResult
|
||||
{
|
||||
AccessToken = new JwtSecurityTokenHandler().WriteToken(accessToken),
|
||||
RefreshToken = new JwtSecurityTokenHandler().WriteToken(refreshToken),
|
||||
AccessTokenExpiryTime = accessToken.ValidTo,
|
||||
RefreshTokenExpiryTime = refreshToken.ValidTo,
|
||||
User = user
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<TokenResult> LoginWithAccessToken(string token)
|
||||
{
|
||||
ValidateToken(token, IUserService.TokenTypeUser, out var validatedToken);
|
||||
var jwtToken = (JwtSecurityToken)validatedToken;
|
||||
var user = await GetUserByToken(jwtToken) ??
|
||||
throw new NotFoundException(HttpEnum.ErrorMessage.NotFoundResourceMissing);
|
||||
user.Authorization ??= await _authorityService.GetUserAuthorities(user.Id);
|
||||
|
||||
return await GenerateJwt(user);
|
||||
}
|
||||
|
||||
public async Task<Authorization> CreateNewAuthority(Authorization auth)
|
||||
{
|
||||
var newUserAuthority = await _authorityService.CreateNewUserAuthority(auth) ??
|
||||
throw new ConflictException(HttpEnum.ErrorMessage.ConflictCreationFailed);
|
||||
return newUserAuthority;
|
||||
}
|
||||
|
||||
public async Task<bool> DeleteAuthority(string id)
|
||||
{
|
||||
if (!ObjectId.TryParse(id, out var userAuthorityIdParsed))
|
||||
throw new BadRequestException(HttpEnum.ErrorMessage.BadRequestInvalidFormat);
|
||||
var isDeleted = await _authorityService.DeleteUserAuthority(userAuthorityIdParsed);
|
||||
|
||||
return !isDeleted ? throw new ConflictException(HttpEnum.ErrorMessage.ConflictDeleteFailed) : isDeleted;
|
||||
}
|
||||
|
||||
public async Task<bool> UpdateAuthority(Authorization authorization)
|
||||
{
|
||||
_ = await _authorityService.EditUserAuthority(authorization) ??
|
||||
throw new ConflictException(HttpEnum.ErrorMessage.ConflictUpdateFailed);
|
||||
return true;
|
||||
}
|
||||
|
||||
public async Task<List<Claim>> ClaimsFromAuthorities(List<Authorization> authorities)
|
||||
{
|
||||
var claims = new List<Claim>();
|
||||
foreach (var auth in authorities)
|
||||
if (auth.UnitId != null)
|
||||
{
|
||||
var dis = await
|
||||
_displayService.Value.GetByUnitId(ObjectId.Parse(auth.UnitId));
|
||||
foreach (var claim in dis)
|
||||
{
|
||||
auth.DisplayId = claim.Id.ToString();
|
||||
AddClaim(auth, claims);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AddClaim(auth, claims);
|
||||
}
|
||||
|
||||
return claims;
|
||||
}
|
||||
|
||||
private static void AddClaim(Authorization auth, List<Claim> claims)
|
||||
{
|
||||
var newClaim = new Claim(ClaimTypes.Role,
|
||||
auth.Rol + (string.IsNullOrEmpty(auth.DisplayId) ? "" : "_" + auth.DisplayId));
|
||||
if (claims.Any(c => c.Value == newClaim.Value)) return;
|
||||
|
||||
//newClaim.Properties.Add("DisplayId", auth.DisplayId ?? "");
|
||||
claims.Add(newClaim);
|
||||
}
|
||||
|
||||
private void CheckIfUserNameExists(string userName, ObjectId? userId = null)
|
||||
{
|
||||
var users = GetAll().Result;
|
||||
var userNameExists = userId.HasValue
|
||||
? users.Any(user => user.Id != userId.Value && user.UserName == userName)
|
||||
: users.Any(user => user.UserName == userName);
|
||||
|
||||
if (userNameExists) throw new BadRequestException(HttpEnum.ErrorMessage.BadRequestIncorrectEmailOrUsername);
|
||||
}
|
||||
|
||||
private void CheckIfEmailExists(string email, ObjectId? userId = null)
|
||||
{
|
||||
var users = GetAll().Result;
|
||||
var emailExists = userId.HasValue
|
||||
? users.Any(user => user.Id != userId.Value && user.Email == email)
|
||||
: users.Any(user => user.Email == email);
|
||||
|
||||
if (emailExists && !string.IsNullOrEmpty(email))
|
||||
throw new BadRequestException(HttpEnum.ErrorMessage.BadRequestIncorrectEmailOrUsername);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user