diff --git a/AyCode.Core.sln b/AyCode.Core.sln index 7ef3cbf..f2f9000 100644 --- a/AyCode.Core.sln +++ b/AyCode.Core.sln @@ -33,7 +33,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AyCode.Models.Server", "AyC EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AyCode.Services.Server", "AyCode.Services.Server\AyCode.Services.Server.csproj", "{3C74C94F-2FEB-47F7-ABB3-B0C9CBCCC876}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AyCode.Services.Server.Tests", "AyCode.Services.Server.Tests\AyCode.Services.Server.Tests.csproj", "{9AC9AF60-280A-4871-A7FA-69AB4D0C858A}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AyCode.Services.Server.Tests", "AyCode.Services.Server.Tests\AyCode.Services.Server.Tests.csproj", "{9AC9AF60-280A-4871-A7FA-69AB4D0C858A}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -80,11 +80,9 @@ Global {15272F57-771E-47BE-A960-AD75935254D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {15272F57-771E-47BE-A960-AD75935254D0}.Debug|Any CPU.Build.0 = Debug|Any CPU {15272F57-771E-47BE-A960-AD75935254D0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {15272F57-771E-47BE-A960-AD75935254D0}.Release|Any CPU.Build.0 = Release|Any CPU {320A245F-6731-476D-A9D8-77888E6B5D9C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {320A245F-6731-476D-A9D8-77888E6B5D9C}.Debug|Any CPU.Build.0 = Debug|Any CPU {320A245F-6731-476D-A9D8-77888E6B5D9C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {320A245F-6731-476D-A9D8-77888E6B5D9C}.Release|Any CPU.Build.0 = Release|Any CPU {21392620-7D0E-44B6-9485-93C57F944C20}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {21392620-7D0E-44B6-9485-93C57F944C20}.Debug|Any CPU.Build.0 = Debug|Any CPU {21392620-7D0E-44B6-9485-93C57F944C20}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -104,7 +102,6 @@ Global {9AC9AF60-280A-4871-A7FA-69AB4D0C858A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {9AC9AF60-280A-4871-A7FA-69AB4D0C858A}.Debug|Any CPU.Build.0 = Debug|Any CPU {9AC9AF60-280A-4871-A7FA-69AB4D0C858A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9AC9AF60-280A-4871-A7FA-69AB4D0C858A}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/AyCode.Core/Consts/AcErrorCode.cs b/AyCode.Core/Consts/AcErrorCode.cs index c414fa0..0bcb72d 100644 --- a/AyCode.Core/Consts/AcErrorCode.cs +++ b/AyCode.Core/Consts/AcErrorCode.cs @@ -54,5 +54,6 @@ DisableAddUser = 44, PhoneNumberFormatIsNotValid = 45, + RefreshTokenUpdateError = 50, } } diff --git a/AyCode.Core/Consts/AcValidate.cs b/AyCode.Core/Consts/AcValidate.cs index d3ba4ea..f7c6b05 100644 --- a/AyCode.Core/Consts/AcValidate.cs +++ b/AyCode.Core/Consts/AcValidate.cs @@ -6,7 +6,7 @@ namespace AyCode.Core.Consts { public static class AcValidate { - public static bool IsValidEmailAndPasswordFormat(string email, string password, out AcErrorCode acErrorCode) + public static bool IsValidEmailAndPasswordFormat(string? email, string? password, out AcErrorCode acErrorCode) { return IsValidEmailFormat(email, out acErrorCode) && IsValidPasswordFormat(password, out acErrorCode); } @@ -36,23 +36,23 @@ namespace AyCode.Core.Consts return isValid; } - public static bool IsValidPasswordFormat(string password, out AcErrorCode acErrorCode) + public static bool IsValidPasswordFormat(string? password, out AcErrorCode acErrorCode) { acErrorCode = AcErrorCode.Unset; - var isValid = !password.IsNullOrWhiteSpace() && password.Length is >= AcConst.MinPasswordLength and <= AcConst.MaxPasswordLength; + var isValid = !string.IsNullOrWhiteSpace(password) && password.Length is >= AcConst.MinPasswordLength and <= AcConst.MaxPasswordLength; if (!isValid) acErrorCode = AcErrorCode.PasswordIsTooShort; return isValid; } - public static bool IsValidEmailFormat(string email, out AcErrorCode acErrorCode) + public static bool IsValidEmailFormat(string? email, out AcErrorCode acErrorCode) { acErrorCode = AcErrorCode.Unset; //a@a.a -> length == 5 //var isValid = !email.IsNullOrWhiteSpace() && email.Length >= 5 && email.Contains('@') && email.Contains('.') && !email.Contains(' '); - var isValid = AcRegExpression.EmailRegex().IsMatch(email); + var isValid = !string.IsNullOrWhiteSpace(email) && AcRegExpression.EmailRegex().IsMatch(email); if (!isValid) acErrorCode = AcErrorCode.EmailFormatIsNotValid; return isValid; diff --git a/AyCode.Utils/Helpers/PasswordHasher.cs b/AyCode.Core/Helpers/PasswordHasher.cs similarity index 75% rename from AyCode.Utils/Helpers/PasswordHasher.cs rename to AyCode.Core/Helpers/PasswordHasher.cs index 71a5924..5d8fcfb 100644 --- a/AyCode.Utils/Helpers/PasswordHasher.cs +++ b/AyCode.Core/Helpers/PasswordHasher.cs @@ -1,10 +1,10 @@ -using Microsoft.AspNetCore.Cryptography.KeyDerivation; -using System.Security.Cryptography; +using System.Security.Cryptography; using System.Text; +using AyCode.Core.Consts; using AyCode.Core.Extensions; -using AyCode.Utils.Extensions; +using Microsoft.AspNetCore.Cryptography.KeyDerivation; -namespace AyCode.Utils.Helpers +namespace AyCode.Core.Helpers { public class PasswordHasher { @@ -23,8 +23,10 @@ namespace AyCode.Utils.Helpers return combinedHash; } - public static bool VerifyPassword(string password, string hashedPassword, string? dynamicSalt = null) + public static bool VerifyPassword(string? password, string hashedPassword, string? dynamicSalt = null) { + if (string.IsNullOrWhiteSpace(password)) return false; + // Extract the salt and hashed password from the combined hash var parts = hashedPassword.Split('$'); var salt = Convert.FromBase64String(parts[3].Replace("salt=", string.Empty)); @@ -41,6 +43,10 @@ namespace AyCode.Utils.Helpers iterationCount: 10000, numBytesRequested: 32)); + //SEMMILYEN KÖRÜLMÉNYEK KÖZÖTT SE VÁLTOZTASD MEG METÓDUS LOGIKÁJÁT!!! Különben senki sem fog tudni Login-olni! - J. + public static string GenerateDynamicSalt(Guid userId) + => userId.ToString("N").ToLower().Reverse().MixCharacters(AcConst.ProjectSalt); + //SEMMILYEN KÖRÜLMÉNYEK KÖZÖTT SE VÁLTOZTASD MEG METÓDUS LOGIKÁJÁT!!! Különben senki sem fog tudni Login-olni! - J. private static byte[] GenerateFinallySalt(byte[] salt, string? dynamicSalt) => SHA256.HashData(string.IsNullOrWhiteSpace(dynamicSalt) ? salt : Encoding.ASCII.GetBytes(Convert.ToBase64String(salt).Reverse().MixCharacters(dynamicSalt))).Take(16).ToArray(); diff --git a/AyCode.Database/DataLayers/Users/AcUserDalBase.cs b/AyCode.Database/DataLayers/Users/AcUserDalBase.cs index d58903c..576152d 100644 --- a/AyCode.Database/DataLayers/Users/AcUserDalBase.cs +++ b/AyCode.Database/DataLayers/Users/AcUserDalBase.cs @@ -10,6 +10,7 @@ using AyCode.Interfaces.Users; using Microsoft.EntityFrameworkCore; using AyCode.Database.Extensions; using AyCode.Core.Consts; +using AyCode.Core.Helpers; using AyCode.Database.DbSets.Users; using AyCode.Interfaces.Addresses; using AyCode.Interfaces.Profiles; @@ -29,8 +30,8 @@ namespace AyCode.Database.DataLayers.Users public TUser? GetUserById(Guid userId) => Session(x => x.GetUserById(userId)); public Task GetUserByIdAsync(Guid userId) => SessionAsync(x => x.GetUserById(userId)); - public TUser? GetUserByEmail(string email) => Session(x => x.GetUserByEmail(email)); - public Task GetUserByEmailAsync(string email) => SessionAsync(x => x.GetUserByEmail(email)); + public TUser? GetUserByEmail(string? email) => Session(x => x.GetUserByEmail(email)); + public Task GetUserByEmailAsync(string? email) => SessionAsync(x => x.GetUserByEmail(email)); public Task AddUserAsync(TUser user) { @@ -74,8 +75,47 @@ namespace AyCode.Database.DataLayers.Users return profile; } - public Task RemoveUserAsync(TUser user) => TransactionAsync(ctx => ctx.RemoveUserAsync(user)); - public Task RemoveUserAsync(Guid userId) => TransactionAsync(ctx => ctx.RemoveUserAsync(userId)); + public Task RemoveUserAsync(TUser user) => TransactionAsync(ctx => ctx.RemoveUser(user)); + public Task RemoveUserAsync(Guid userId) => TransactionAsync(ctx => ctx.RemoveUser(userId)); + + public TUser? AuthenticateUser(string? email, string? password, string refreshToken, out AcErrorCode errorCode) + { + TUser? user = null; + var errorCodeInner = AcErrorCode.Unset; + + var result = Transaction(ctx => + { + user = ctx.GetUserByEmail(email); + if (user is { EmailConfirmed: true } && string.Equals(user.EmailAddress, email, StringComparison.CurrentCultureIgnoreCase) + && PasswordHasher.VerifyPassword(password, user.Password, PasswordHasher.GenerateDynamicSalt(user.Id))) + { + if (ctx.UpdateJwtRefreshToken(user, refreshToken)) return true; + + errorCodeInner = AcErrorCode.RefreshTokenUpdateError; + } + else errorCodeInner = AcErrorCode.WrongLoginData; + + return false; + }); + + errorCode = errorCodeInner; + + return result ? user : null; + } + + public async Task UpdateJwtRefreshTokenAsync(string email, string refreshToken) + { + TUser? user = null; + + return await TransactionAsync(ctx => (user = ctx.UpdateJwtRefreshToken(email, refreshToken)) != null) ? user : null; + } + + public TUser? UpdateJwtRefreshToken(string email, string refreshToken) + { + TUser? user = null; + + return Transaction(ctx => (user = ctx.UpdateJwtRefreshToken(email, refreshToken)) != null) ? user : null; + } //public UserToken CreateUserToken(Guid userId, string verificationToken) //{ diff --git a/AyCode.Database/DbSets/Users/AcUserDbSetExtensions.cs b/AyCode.Database/DbSets/Users/AcUserDbSetExtensions.cs index e64b367..49fb333 100644 --- a/AyCode.Database/DbSets/Users/AcUserDbSetExtensions.cs +++ b/AyCode.Database/DbSets/Users/AcUserDbSetExtensions.cs @@ -1,4 +1,5 @@ -using AyCode.Core.Logger; +using AyCode.Core.Extensions; +using AyCode.Core.Logger; using AyCode.Entities.Users; using AyCode.Interfaces.Entities; using AyCode.Interfaces.Profiles; @@ -11,8 +12,10 @@ public static class AcUserDbSetExtensions public static TUser? GetUserById(this IAcUserDbSetBase ctx, Guid userId) where TUser : class, IAcUserBase => ctx.GetUsersById(userId).FirstOrDefault(); - public static TUser? GetUserByEmail(this IAcUserDbSetBase ctx, string email) where TUser : class, IAcUserBase - => ctx.GetUsersByEmail(email).FirstOrDefault(); + public static TUser? GetUserByEmail(this IAcUserDbSetBase ctx, string? email) where TUser : class, IAcUserBase + { + return string.IsNullOrWhiteSpace(email) ? null : ctx.GetUsersByEmail(email).FirstOrDefault(); + } public static IQueryable GetUsersById(this IAcUserDbSetBase ctx, Guid userId) where TUser : class, IAcUserBase => ctx.Users.Where(u => u.Id == userId); @@ -34,15 +37,40 @@ public static class AcUserDbSetExtensions return ctx.Users.Add(user).State == Microsoft.EntityFrameworkCore.EntityState.Added; } - public static bool RemoveUserAsync(this IAcUserDbSetBase ctx, TUser user) where TUser : class, IAcUserBase + public static bool RemoveUser(this IAcUserDbSetBase ctx, TUser user) where TUser : class, IAcUserBase => ctx.Users.Remove(user).State == Microsoft.EntityFrameworkCore.EntityState.Deleted; - public static bool RemoveUserAsync(this IAcUserDbSetBase ctx, Guid userId) where TUser : class, IAcUserBase + public static bool RemoveUser(this IAcUserDbSetBase ctx, Guid userId) where TUser : class, IAcUserBase { var user = ctx.GetUserById(userId); if (user == null) return false; - return ctx.RemoveUserAsync(user); + return ctx.RemoveUser(user); + } + + public static bool UpdateJwtRefreshToken(this IAcUserDbSetBase ctx, TUser user, string refreshToken) where TUser : class, IAcUserBase + { + if (string.IsNullOrWhiteSpace(refreshToken)) return false; + + user.RefreshToken = refreshToken; + ctx.Users.Update(user); + + return true; + } + + public static TUser? UpdateJwtRefreshToken(this IAcUserDbSetBase ctx, string email, string refreshToken) where TUser : class, IAcUserBase + { + Console.WriteLine(@"UserDal Update refresh token"); + + if (string.IsNullOrWhiteSpace(refreshToken)) return null; + + var existingUser = ctx.GetUserByEmail(email); + if (existingUser == null) return null; + + existingUser.RefreshToken = refreshToken; + ctx.Users.Update(existingUser); + + return existingUser; } } \ No newline at end of file diff --git a/AyCode.Interfaces.Server/AyCode.Interfaces.Server.csproj b/AyCode.Interfaces.Server/AyCode.Interfaces.Server.csproj index f7f8798..8bb0da8 100644 --- a/AyCode.Interfaces.Server/AyCode.Interfaces.Server.csproj +++ b/AyCode.Interfaces.Server/AyCode.Interfaces.Server.csproj @@ -6,10 +6,6 @@ enable - - - - diff --git a/AyCode.Interfaces.Server/Logins/IAcLoggedInModelBase.cs b/AyCode.Interfaces.Server/Logins/IAcLoggedInModelBase.cs new file mode 100644 index 0000000..8b12064 --- /dev/null +++ b/AyCode.Interfaces.Server/Logins/IAcLoggedInModelBase.cs @@ -0,0 +1,25 @@ +using AyCode.Core.Consts; +using AyCode.Interfaces.Addresses; +using AyCode.Interfaces.Profiles; +using AyCode.Interfaces.ServiceProviders; +using AyCode.Interfaces.Users; + +namespace AyCode.Interfaces.Server.Logins; + +public interface IAcLoggedInModelBase : IAcLoginDtoBase + + where TUser : class, IAcUser + where TUserToken : class, IAcUserTokenBase + where TProfile : class, IAcProfile + where TServiceProvider : class, IAcServiceProviderBase + where TUserToServiceProvider : class, IAcUserToServiceProviderBase + where TProfileAddress : class, IAcAddress +{ + bool IsLoggedIn { get; } + TUser LoggedInUser { get; } + string AccessToken { get; } + AcErrorCode LoginErrorCode { get; set; } + + void AddLoggedInUser(TUser user, string accessToken); + void Logout(); +} \ No newline at end of file diff --git a/AyCode.Interfaces.Server/Logins/IAcLoginDtoBase.cs b/AyCode.Interfaces.Server/Logins/IAcLoginDtoBase.cs new file mode 100644 index 0000000..2ec6076 --- /dev/null +++ b/AyCode.Interfaces.Server/Logins/IAcLoginDtoBase.cs @@ -0,0 +1,6 @@ +namespace AyCode.Interfaces.Server.Logins; + +public interface IAcLoginDtoBase +{ + +} \ No newline at end of file diff --git a/AyCode.Interfaces.Server/Logins/IAcLoginServiceServer.cs b/AyCode.Interfaces.Server/Logins/IAcLoginServiceServer.cs index 946545d..f9c6054 100644 --- a/AyCode.Interfaces.Server/Logins/IAcLoginServiceServer.cs +++ b/AyCode.Interfaces.Server/Logins/IAcLoginServiceServer.cs @@ -7,7 +7,8 @@ using AyCode.Interfaces.Users; namespace AyCode.Interfaces.Server.Logins; -public interface IAcLoginServiceServer : IAcLoginServiceCommon +public interface IAcLoginServiceServer : IAcLoginServiceCommon + where TResultLoggedInModel: class, IAcLoggedInModelBase where TUser : class, IAcUser where TUserToken : class, IAcUserTokenBase @@ -16,5 +17,8 @@ public interface IAcLoginServiceServer LoginAsync(string? email, string password); } \ No newline at end of file diff --git a/AyCode.Interfaces/Logins/IAcLoginServiceBase.cs b/AyCode.Interfaces/Logins/IAcLoginServiceBase.cs index dc7ab32..cac39f7 100644 --- a/AyCode.Interfaces/Logins/IAcLoginServiceBase.cs +++ b/AyCode.Interfaces/Logins/IAcLoginServiceBase.cs @@ -11,5 +11,6 @@ public interface IAcLoginServiceBase LoginAsync(string email, string password); - public bool Logout(); public Task LogoutAsync(); - public TUser? Registration(string email, string password, string? phoneNumber = null); - public TUser? Registration(Guid userId, string email, string password, string? phoneNumber = null); - public Task RegistrationAsync(string email, string password, string? phoneNumber = null); - public Task RegistrationAsync(Guid userId, string email, string password, string? phoneNumber = null); + public AcErrorCode Registration(string email, string password, string? phoneNumber = null); + public AcErrorCode Registration(Guid userId, string email, string password, string? phoneNumber = null); + public Task RegistrationAsync(string email, string password, string? phoneNumber = null); + public Task RegistrationAsync(Guid userId, string email, string password, string? phoneNumber = null); } \ No newline at end of file diff --git a/AyCode.Models.Server/Logins/AcLoggedInModelServer.cs b/AyCode.Models.Server/Logins/AcLoggedInModelServer.cs index cab634a..ea03ca9 100644 --- a/AyCode.Models.Server/Logins/AcLoggedInModelServer.cs +++ b/AyCode.Models.Server/Logins/AcLoggedInModelServer.cs @@ -1,17 +1,38 @@ -using AyCode.Interfaces.Addresses; +using AyCode.Core.Consts; +using AyCode.Interfaces.Addresses; using AyCode.Interfaces.Profiles; using AyCode.Interfaces.ServiceProviders; using AyCode.Interfaces.Users; -using AyCode.Models.Logins; +using AyCode.Interfaces.Server.Logins; namespace AyCode.Models.Server.Logins; -public class AcLoggedInModelServer : IAcLoggedInModelBase +public class AcLoggedInModelServer : IAcLoggedInModelBase + where TUser : class, IAcUser + where TUserToken : class, IAcUserTokenBase where TProfile : class, IAcProfile where TServiceProvider : class, IAcServiceProviderBase where TUserToServiceProvider : class, IAcUserToServiceProviderBase where TProfileAddress : class, IAcAddress { - public TUser? LoggedInUser { get; set; } + public bool IsLoggedIn => LoggedInUser != null; + + public TUser LoggedInUser { get; private set; } + public string AccessToken { get; private set; } + public AcErrorCode LoginErrorCode { get; set; } + + public void AddLoggedInUser(TUser user, string accessToken) + { + LoggedInUser = user; + AccessToken = accessToken; + } + + public void Logout() + { + AccessToken = string.Empty; + LoggedInUser = null; + + LoginErrorCode = AcErrorCode.Unset; + } } \ No newline at end of file diff --git a/AyCode.Models/AyCode.Models.csproj b/AyCode.Models/AyCode.Models.csproj index 086bd2b..86295b3 100644 --- a/AyCode.Models/AyCode.Models.csproj +++ b/AyCode.Models/AyCode.Models.csproj @@ -12,4 +12,8 @@ + + + + diff --git a/AyCode.Models/Logins/IAcLoggedInModelBase.cs b/AyCode.Models/Logins/IAcLoggedInModelBase.cs deleted file mode 100644 index 2dd9bea..0000000 --- a/AyCode.Models/Logins/IAcLoggedInModelBase.cs +++ /dev/null @@ -1,18 +0,0 @@ -using AyCode.Interfaces.Addresses; -using AyCode.Interfaces.Logins; -using AyCode.Interfaces.Profiles; -using AyCode.Interfaces.ServiceProviders; -using AyCode.Interfaces.TimeStampInfo; -using AyCode.Interfaces.Users; - -namespace AyCode.Models.Logins; - -public interface IAcLoggedInModelBase : IAcLoginDtoBase - where TUser : class, IAcUser - where TProfile : class, IAcProfile - where TServiceProvider : class, IAcServiceProviderBase - where TUserToServiceProvider : class, IAcUserToServiceProviderBase - where TProfileAddress : class, IAcAddress -{ - TUser? LoggedInUser { get; set; } -} \ No newline at end of file diff --git a/AyCode.Models/Logins/IAcLoginDtoBase.cs b/AyCode.Models/Logins/IAcLoginDtoBase.cs deleted file mode 100644 index d1d901b..0000000 --- a/AyCode.Models/Logins/IAcLoginDtoBase.cs +++ /dev/null @@ -1,8 +0,0 @@ -using AyCode.Interfaces.Entities; - -namespace AyCode.Models.Logins; - -public interface IAcLoginDtoBase -{ - -} \ No newline at end of file diff --git a/AyCode.Services.Server.Tests/LoginServices/AcLoginServiceServerTestBase.cs b/AyCode.Services.Server.Tests/LoginServices/AcLoginServiceServerTestBase.cs index 1e63548..dba50c2 100644 --- a/AyCode.Services.Server.Tests/LoginServices/AcLoginServiceServerTestBase.cs +++ b/AyCode.Services.Server.Tests/LoginServices/AcLoginServiceServerTestBase.cs @@ -10,10 +10,11 @@ using AyCode.Interfaces.Users; namespace AyCode.Services.Server.Tests.LoginServices { - public abstract class AcLoginServiceServerTestBase : AcDatabaseTestModelBase + public abstract class AcLoginServiceServerTestBase : AcDatabaseTestModelBase where TDal : AcUserDalBase where TDbContext : AcDbContextBase, IAcUserDbContextBase - where TLoginServiceServer : class, IAcLoginServiceServer + where TLoginServiceServer : class, IAcLoginServiceServer + where TResultLoggedInModel: class, IAcLoggedInModelBase where TUser : class, IAcUser where TProfile : class, IAcProfile where TProfileAddress : class, IAcAddress diff --git a/AyCode.Services.Server/Logins/AcLoginServiceServer.cs b/AyCode.Services.Server/Logins/AcLoginServiceServer.cs index 16d8c8a..b22be45 100644 --- a/AyCode.Services.Server/Logins/AcLoginServiceServer.cs +++ b/AyCode.Services.Server/Logins/AcLoginServiceServer.cs @@ -20,18 +20,16 @@ using AyCode.Core.Consts; using AyCode.Core.Extensions; using AyCode.Database.DataLayers.Users; using AyCode.Database.DbContexts.Users; -using AyCode.Models.Logins; using AyCode.Models.Server.Logins; using AyCode.Utils.Extensions; -using AyCode.Utils.Helpers; using Microsoft.Extensions.Configuration; namespace AyCode.Services.Server.Logins; -public class AcLoginServiceServer(TDal userDal, IConfiguration configuration) - : AcLoginServiceBase, IAcLoginServiceServer +public class AcLoginServiceServer(TDal userDal, IConfiguration configuration) + : AcLoginServiceBase, IAcLoginServiceServer - where TResultLoggedInModel: class, IAcLoggedInModelBase + where TResultLoggedInModel : class, IAcLoggedInModelBase where TDal : AcUserDalBase where TDbContext : AcDbContextBase, IAcUserDbContextBase where TUser : class, IAcUser @@ -41,30 +39,37 @@ public class AcLoginServiceServer LoggedInModel?.LoggedInUser; + public override bool IsLoggedIn => LoggedInModel?.IsLoggedIn ?? false; + + public virtual TResultLoggedInModel Login(string? email, string? password) { - accessToken = string.Empty; - //var loginModel = Activator.CreateInstance(); + if (LoggedInModel != null) Logout(); - if (!AcValidate.IsValidEmailAndPasswordFormat(email, password, out var errorCode)) return null;//return loginModel; + LoggedInModel = Activator.CreateInstance(); - var user = userDal.GetUserByEmail(email); - if (user is not { EmailConfirmed: true } || !string.Equals(user.EmailAddress, email, StringComparison.CurrentCultureIgnoreCase) - || !PasswordHasher.VerifyPassword(password, user.Password, GenerateDynamicSalt(user.Id))) return null; + if (AcValidate.IsValidEmailAndPasswordFormat(email, password, out var errorCode)) + { + var user = userDal.AuthenticateUser(email, password, GenerateRefreshToken(), out errorCode); - - //loginModel.LoggedInUser = user; - return LoggedInUser = user; + if (user != null) LoggedInModel.AddLoggedInUser(user, GenerateAccessToken(user)); + } + + LoggedInModel.LoginErrorCode = errorCode; + + return LoggedInModel; } - public virtual Task LoginAsync(string email, string password) + public virtual Task LoginAsync(string? email, string? password) { - return TaskHelper.ToThreadPoolTask(() => Login(email, password, out _)); + return TaskHelper.ToThreadPoolTask(() => Login(email, password)); } public virtual bool Logout() { - LoggedInUser = null; + LoggedInModel?.Logout(); + LoggedInModel = null; return true; } @@ -74,39 +79,41 @@ public class AcLoginServiceServer Registration(Guid.NewGuid(), email, password, phoneNumber); - public virtual TUser? Registration(Guid userId, string email, string password, string? phoneNumber = null) + public virtual AcErrorCode Registration(Guid userId, string email, string password, string? phoneNumber = null) { if ((phoneNumber != null && !AcValidate.IsValidPhoneNumberFormat(phoneNumber, out var errorCode)) || - !AcValidate.IsValidEmailAndPasswordFormat(email, password, out errorCode)) return null; + !AcValidate.IsValidEmailAndPasswordFormat(email, password, out errorCode)) return errorCode; var user = Activator.CreateInstance(); user.Id = userId; user.EmailAddress = email; user.EmailConfirmed = true; - user.Password = PasswordHasher.HashPassword(password, GenerateDynamicSalt(userId)); + user.Password = PasswordHasher.HashPassword(password, PasswordHasher.GenerateDynamicSalt(userId)); var address = Activator.CreateInstance(); address.Id = Guid.NewGuid(); var userName = email.Split('@')[0]; //TODO: generálni egy nevet... - J. - return userDal.AddUser(user, userName, address) ? null : userDal.GetUserById(userId); + + if (!userDal.AddUser(user, userName, address)) errorCode = AcErrorCode.DatabaseError; + + return errorCode; } - public virtual Task RegistrationAsync(string email, string password, string? phoneNumber = null) + + public virtual Task RegistrationAsync(string email, string password, string? phoneNumber = null) => RegistrationAsync(Guid.NewGuid(), email, password, phoneNumber); - public virtual Task RegistrationAsync(Guid userId, string email, string password, string? phoneNumber = null) + + public virtual Task RegistrationAsync(Guid userId, string email, string password, string? phoneNumber = null) { return TaskHelper.ToThreadPoolTask(() => Registration(userId, email, password, phoneNumber)); } - //SEMMILYEN KÖRÜLMÉNYEK KÖZÖTT SE VÁLTOZTASD MEG METÓDUS LOGIKÁJÁT!!! Különben senki sem fog tudni Login-olni! - J. - public virtual string GenerateDynamicSalt(Guid userId) - => userId.ToString("N").ToLower().Reverse().MixCharacters(AcConst.ProjectSalt); - - private string GenerateAccessToken(TUser user) + //public Task SendConfirmationToken(string email) + public string GenerateAccessToken(TUser user) { var tokenHandler = new JwtSecurityTokenHandler(); Console.WriteLine("----------------------------------------------------------"); @@ -139,7 +146,7 @@ public class AcLoginServiceServer LoggedInUser != null; + public virtual TUser? LoggedInUser { get; protected set; } } \ No newline at end of file diff --git a/AyCode.Services/Logins/AcLoginServiceClient.cs b/AyCode.Services/Logins/AcLoginServiceClient.cs index 4de231a..e290e5d 100644 --- a/AyCode.Services/Logins/AcLoginServiceClient.cs +++ b/AyCode.Services/Logins/AcLoginServiceClient.cs @@ -1,4 +1,5 @@ -using AyCode.Core.Helpers; +using AyCode.Core.Consts; +using AyCode.Core.Helpers; using AyCode.Interfaces.Addresses; using AyCode.Interfaces.Logins; using AyCode.Interfaces.Profiles; @@ -36,22 +37,22 @@ public class AcLoginServiceClient RegistrationAsync(string email, string password, string? phoneNumber = null) + public virtual Task RegistrationAsync(string email, string password, string? phoneNumber = null) { return TaskHelper.ToThreadPoolTask(() => Registration(email, password, phoneNumber)); } - public Task RegistrationAsync(Guid userId, string email, string password, string? phoneNumber = null) + public Task RegistrationAsync(Guid userId, string email, string password, string? phoneNumber = null) { throw new NotImplementedException(); } diff --git a/AyCode.Utils/AyCode.Utils.csproj b/AyCode.Utils/AyCode.Utils.csproj index 115ed45..90a350c 100644 --- a/AyCode.Utils/AyCode.Utils.csproj +++ b/AyCode.Utils/AyCode.Utils.csproj @@ -11,4 +11,8 @@ + + + +