199 lines
8.1 KiB
C#
199 lines
8.1 KiB
C#
using System.IdentityModel.Tokens.Jwt;
|
|
using AyCode.Core.Helpers;
|
|
using AyCode.Interfaces.Addresses;
|
|
using AyCode.Interfaces.Logins;
|
|
using AyCode.Interfaces.Profiles;
|
|
using AyCode.Interfaces.Server.Logins;
|
|
using AyCode.Interfaces.ServiceProviders;
|
|
using AyCode.Interfaces.Users;
|
|
using AyCode.Services.Logins;
|
|
using System.Runtime.InteropServices;
|
|
using System.Security;
|
|
using System.Security.Claims;
|
|
using System.Security.Cryptography;
|
|
using System.Text;
|
|
using Microsoft.IdentityModel.Tokens;
|
|
using AyCode.Database.DataLayers;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using AyCode.Database.DbContexts;
|
|
using AyCode.Core.Consts;
|
|
using AyCode.Core.Extensions;
|
|
using AyCode.Core.Loggers;
|
|
using AyCode.Core.Server.Loggers;
|
|
using AyCode.Database.DataLayers.Users;
|
|
using AyCode.Database.DbContexts.Users;
|
|
using AyCode.Interfaces.Messages;
|
|
using AyCode.Models.Server.Logins;
|
|
using AyCode.Utils.Extensions;
|
|
using Microsoft.Extensions.Configuration;
|
|
|
|
namespace AyCode.Services.Server.Logins;
|
|
|
|
public class AcLoginServiceServer<TResultLoggedInModel, TDal, TDbContext, TUser, TUserToken, TProfile, TCompany, TUserToServiceProvider, TProfileAddress, TEmailMessage>(TDal userDal, IConfiguration configuration)
|
|
: AcLoginServiceBase<TUser, TProfile, TCompany, TUserToServiceProvider, TProfileAddress>, IAcLoginServiceServer<TResultLoggedInModel, TUser, TUserToken, TProfile, TCompany, TUserToServiceProvider, TProfileAddress>
|
|
|
|
where TResultLoggedInModel : class, IAcLoggedInModelBase<TUser, TUserToken, TProfile, TCompany, TUserToServiceProvider, TProfileAddress>
|
|
where TDal : AcUserDalBase<TDbContext, TUser, TProfile, TUserToken, TCompany, TUserToServiceProvider, TProfileAddress, TEmailMessage>
|
|
where TDbContext : AcDbContextBase, IAcUserDbContextBase<TUser, TProfile, TUserToken, TCompany, TUserToServiceProvider, TProfileAddress, TEmailMessage>
|
|
where TUser : class, IAcUser<TProfile, TCompany, TUserToServiceProvider, TProfileAddress>
|
|
where TUserToken : class, IAcUserTokenBase
|
|
where TProfile : class, IAcProfile<TProfileAddress>
|
|
where TCompany : class, IAcCompanyBase
|
|
where TUserToServiceProvider : class, IAcUserToCompanyBase
|
|
where TProfileAddress : class, IAcAddress
|
|
where TEmailMessage : class, IAcEmailMessageBase
|
|
{
|
|
public TResultLoggedInModel? LoggedInModel { get; private set; }
|
|
public override TUser? LoggedInUser => LoggedInModel?.LoggedInUser;
|
|
public override bool IsLoggedIn => LoggedInModel?.IsLoggedIn ?? false;
|
|
|
|
public virtual TResultLoggedInModel Login(string? email, string? password)
|
|
{
|
|
if (LoggedInModel != null) Logout();
|
|
|
|
LoggedInModel = Activator.CreateInstance<TResultLoggedInModel>();
|
|
|
|
if (AcValidate.IsValidEmailAndPasswordFormat(email, password, out var errorCode))
|
|
{
|
|
var user = userDal.AuthenticateUser(email, password, GenerateRefreshToken(), out errorCode);
|
|
|
|
if (user != null) LoggedInModel.AddLoggedInUser(user, GenerateAccessToken(user));
|
|
}
|
|
|
|
LoggedInModel.LoginErrorCode = errorCode;
|
|
|
|
return LoggedInModel;
|
|
}
|
|
|
|
public virtual Task<TResultLoggedInModel> LoginAsync(string? email, string? password)
|
|
{
|
|
return TaskHelper.ToThreadPoolTask(() => Login(email, password));
|
|
}
|
|
|
|
public virtual bool Logout()
|
|
{
|
|
LoggedInModel?.Logout();
|
|
LoggedInModel = null;
|
|
|
|
return true;
|
|
}
|
|
|
|
public virtual Task<bool> LogoutAsync()
|
|
{
|
|
return TaskHelper.ToThreadPoolTask(Logout);
|
|
}
|
|
|
|
public virtual AcErrorCode Registration(string email, string password, string? phoneNumber = null, Guid? referralId = null)
|
|
=> Registration(Guid.NewGuid(), email, password, phoneNumber, referralId);
|
|
|
|
public virtual AcErrorCode Registration(Guid userId, string email, string password, string? phoneNumber = null, Guid? referralId = null)
|
|
{
|
|
email = email.ToLower();
|
|
|
|
if ((phoneNumber != null && !AcValidate.IsValidPhoneNumberFormat(phoneNumber, out var errorCode)) ||
|
|
!AcValidate.IsValidEmailAndPasswordFormat(email, password, out errorCode)) return errorCode;
|
|
|
|
var user = Activator.CreateInstance<TUser>();
|
|
user.Id = userId;
|
|
user.EmailAddress = email;
|
|
user.EmailConfirmed = true;
|
|
user.Password = PasswordHasher.HashPassword(password, PasswordHasher.GenerateDynamicSalt(userId));
|
|
if(referralId != null)
|
|
user.RefferalId = referralId;
|
|
var address = Activator.CreateInstance<TProfileAddress>();
|
|
address.Id = Guid.NewGuid();
|
|
|
|
var userName = email.Split('@')[0]; //TODO: generálni egy nevet... - J.
|
|
|
|
if (!userDal.AddUser(user, userName, address)) errorCode = AcErrorCode.DatabaseError;
|
|
|
|
return errorCode;
|
|
}
|
|
|
|
|
|
public virtual Task<AcErrorCode> RegistrationAsync(string email, string password, string? phoneNumber = null, Guid? referralId = null)
|
|
=> RegistrationAsync(Guid.NewGuid(), email, password, phoneNumber, referralId);
|
|
|
|
public virtual Task<AcErrorCode> RegistrationAsync(Guid userId, string email, string password, string? phoneNumber = null, Guid? referralId = null)
|
|
=> TaskHelper.ToThreadPoolTask(() => Registration(userId, email, password, phoneNumber, referralId));
|
|
|
|
public virtual bool SendConfirmationToken(string? email, string confirmationToken)
|
|
{
|
|
//var sendGrid = SendGrid.SendGridClient();
|
|
return true;
|
|
}
|
|
|
|
public virtual Task<bool> SendConfirmationTokenAsync(string email, string confirmationToken)
|
|
=> TaskHelper.ToThreadPoolTask(() => SendConfirmationToken(email, confirmationToken));
|
|
|
|
public string GenerateAccessToken(TUser user)
|
|
{
|
|
var tokenHandler = new JwtSecurityTokenHandler();
|
|
GlobalLogger.Info("----------------------------------------------------------");
|
|
|
|
if (configuration["JWT:Key"] == null)
|
|
throw new SecurityTokenException("Token is null");
|
|
|
|
var keyDetail = Encoding.UTF8.GetBytes(configuration["JWT:Key"] ?? string.Empty);
|
|
GlobalLogger.Info(configuration["JWT:Key"]);
|
|
|
|
var claims = new List<Claim>
|
|
{
|
|
new(ClaimTypes.NameIdentifier, user.Id.ToString()),
|
|
new(ClaimTypes.Email, user.EmailAddress)
|
|
};
|
|
|
|
var tokenDescriptor = new SecurityTokenDescriptor
|
|
{
|
|
Audience = configuration["JWT:Audience"],
|
|
Issuer = configuration["JWT:Issuer"],
|
|
Expires = DateTime.UtcNow.AddMinutes(30),
|
|
Subject = new ClaimsIdentity(claims),
|
|
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(keyDetail), SecurityAlgorithms.HmacSha256Signature)
|
|
};
|
|
|
|
var token = tokenHandler.CreateToken(tokenDescriptor) as JwtSecurityToken;
|
|
var writtenToken = tokenHandler.WriteToken(token);
|
|
GlobalLogger.Info(writtenToken);
|
|
|
|
return writtenToken;
|
|
}
|
|
|
|
public ClaimsPrincipal GetPrincipalFromExpiredToken(string token)
|
|
{
|
|
var tokenHandler = new JwtSecurityTokenHandler();
|
|
|
|
if (configuration["JWT:Key"] == null)
|
|
throw new SecurityTokenException("Token is null");
|
|
|
|
var keyDetail = Encoding.UTF8.GetBytes(configuration["JWT:Key"] ?? string.Empty);
|
|
|
|
var tokenValidationParameter = new TokenValidationParameters
|
|
{
|
|
ValidateIssuer = false,
|
|
ValidateAudience = false,
|
|
ValidateLifetime = false,
|
|
ValidateIssuerSigningKey = true,
|
|
ValidIssuer = configuration["JWT:Issuer"],
|
|
ValidAudience = configuration["JWT:Audience"],
|
|
IssuerSigningKey = new SymmetricSecurityKey(keyDetail),
|
|
};
|
|
|
|
var principal = tokenHandler.ValidateToken(token, tokenValidationParameter, out var securityToken);
|
|
|
|
if (securityToken is not JwtSecurityToken jwtSecurityToken || !jwtSecurityToken.Header.Alg.Equals(SecurityAlgorithms.HmacSha256, StringComparison.InvariantCultureIgnoreCase))
|
|
throw new SecurityTokenException("Invalid token");
|
|
|
|
return principal;
|
|
}
|
|
|
|
public string GenerateRefreshToken()
|
|
{
|
|
var randomNumber = new byte[32];
|
|
|
|
using var rng = RandomNumberGenerator.Create();
|
|
rng.GetBytes(randomNumber);
|
|
|
|
return Convert.ToBase64String(randomNumber);
|
|
}
|
|
} |