improvements, fixes, etc...

This commit is contained in:
jozsef.b@aycode.com 2024-04-24 17:58:38 +02:00
parent 7360291242
commit cba3b9f8d6
4 changed files with 50 additions and 27 deletions

View File

@ -8,8 +8,10 @@ namespace AyCode.Core.Helpers
{
public class PasswordHasher
{
public static string HashPassword(string password, string? dynamicSalt = null)
public static string HashPassword(string? password, string? dynamicSalt = null)
{
if (string.IsNullOrWhiteSpace(password)) throw new ArgumentNullException(nameof(password));
// Generate a random salt
var salt = new byte[16];
using (var rng = RandomNumberGenerator.Create()) rng.GetBytes(salt);
@ -29,6 +31,9 @@ namespace AyCode.Core.Helpers
// Extract the salt and hashed password from the combined hash
var parts = hashedPassword.Split('$');
if (parts.Length != 5) return false;
var salt = Convert.FromBase64String(parts[3].Replace("salt=", string.Empty));
var storedHash = parts[4].Replace("hash=", string.Empty);

View File

@ -21,7 +21,7 @@ namespace AyCode.Database.Tests.Users
protected TUser AcBase_GetUserById_ReturnsUser_WhenUserExists(string userIdString)
{
var userId = Guid.Parse(userIdString);
var user = Dal.GetUserById(userId);
var user = Dal.GetUserById(userId, false);
Assert.IsNotNull(user, "User is null");
Assert.IsNotNull(user.Profile, "Profile is null");
@ -34,7 +34,7 @@ namespace AyCode.Database.Tests.Users
protected TUser AcBase_GetUserByEmail_ReturnsUser_WhenUserExists(string email)
{
var user = Dal.GetUserByEmail(email);
var user = Dal.GetUserByEmail(email, false);
Assert.IsNotNull(user, "User is null");
Assert.IsNotNull(user.Profile, "Profile is null");
@ -49,7 +49,7 @@ namespace AyCode.Database.Tests.Users
{
TUser? user = null;
user = await Dal.GetUserByEmailAsync(email).ConfigureAwait(false);
user = await Dal.GetUserByEmailAsync(email, false).ConfigureAwait(false);
//user = await Dal.SessionAsync(ctx => ctx.Users.FirstOrDefault(x => x.EmailAddress == email)).ConfigureAwait(false);

View File

@ -27,11 +27,11 @@ namespace AyCode.Database.DataLayers.Users
where TUserToServiceProvider : class, IAcUserToServiceProviderBase
where TProfileAddress : class, IAcAddress
{
public TUser? GetUserById(Guid userId) => Session(x => x.GetUserById(userId));
public Task<TUser?> GetUserByIdAsync(Guid userId) => SessionAsync(x => x.GetUserById(userId));
public TUser? GetUserById(Guid userId, bool onlyConfirmed) => Session(x => x.GetUserById(userId, onlyConfirmed));
public Task<TUser?> GetUserByIdAsync(Guid userId, bool onlyConfirmed) => SessionAsync(x => x.GetUserById(userId, onlyConfirmed));
public TUser? GetUserByEmail(string? email) => Session(x => x.GetUserByEmail(email));
public Task<TUser?> GetUserByEmailAsync(string? email) => SessionAsync(x => x.GetUserByEmail(email));
public TUser? GetUserByEmail(string? email, bool onlyConfirmed) => Session(x => x.GetUserByEmail(email, onlyConfirmed));
public Task<TUser?> GetUserByEmailAsync(string? email, bool onlyConfirmed) => SessionAsync(x => x.GetUserByEmail(email, onlyConfirmed));
public Task<bool> AddUserAsync(TUser user)
{
@ -72,18 +72,19 @@ namespace AyCode.Database.DataLayers.Users
profile.Address = address;
profile.AddressId = address.Id;
return profile;
}
public Task<bool> RemoveUserAsync(TUser? user) => TransactionAsync(ctx => RemoveUserTransactionBody(user, ctx));
public Task<bool> RemoveUserAsync(Guid userId) => TransactionAsync(ctx =>
{
var user = ctx.GetUserById(userId);
var user = ctx.GetUserById(userId, false);
return RemoveUserTransactionBody(user, ctx);
});
protected bool RemoveUserTransactionBody(TUser? user, TDbContext ctx)
protected virtual bool RemoveUserTransactionBody(TUser? user, TDbContext ctx)
{
if (user == null) return false;
@ -106,7 +107,11 @@ namespace AyCode.Database.DataLayers.Users
var result = Transaction(ctx =>
{
user = ctx.GetUserByEmail(email);
try
{
//var passwordHash = PasswordHasher.HashPassword(password, PasswordHasher.GenerateDynamicSalt(userId));
user = ctx.GetUserByEmail(email, true);
if (user is { EmailConfirmed: true } && string.Equals(user.EmailAddress, email, StringComparison.CurrentCultureIgnoreCase)
&& PasswordHasher.VerifyPassword(password, user.Password, PasswordHasher.GenerateDynamicSalt(user.Id)))
{
@ -115,6 +120,11 @@ namespace AyCode.Database.DataLayers.Users
errorCodeInner = AcErrorCode.RefreshTokenUpdateError;
}
else errorCodeInner = AcErrorCode.WrongLoginData;
}
catch (Exception ex)
{
errorCodeInner = AcErrorCode.UnknownError;
}
return false;
});

View File

@ -9,23 +9,31 @@ namespace AyCode.Database.DbSets.Users;
public static class AcUserDbSetExtensions
{
public static TUser? GetUserById<TUser>(this IAcUserDbSetBase<TUser> ctx, Guid userId) where TUser : class, IAcUserBase
=> ctx.GetUsersById(userId).FirstOrDefault();
public static TUser? GetUserByEmail<TUser>(this IAcUserDbSetBase<TUser> ctx, string? email) where TUser : class, IAcUserBase
public static TUser? AuthenticateUser<TUser>(this IAcUserDbSetBase<TUser> ctx, string? email, string? passwordHash, bool onlyConfirmed) where TUser : class, IAcUserBase
{
return string.IsNullOrWhiteSpace(email) ? null : ctx.GetUsersByEmail(email).FirstOrDefault();
if (string.IsNullOrWhiteSpace(email) || string.IsNullOrWhiteSpace(passwordHash))
return null;
return ctx.GetUsersByEmail(email, onlyConfirmed).SingleOrDefault(u => u.Password == passwordHash);
}
public static IQueryable<TUser> GetUsersById<TUser>(this IAcUserDbSetBase<TUser> ctx, Guid userId) where TUser : class, IAcUserBase
=> ctx.Users.Where(u => u.Id == userId);
public static TUser? GetUserById<TUser>(this IAcUserDbSetBase<TUser> ctx, Guid userId, bool onlyConfirmed) where TUser : class, IAcUserBase
=> ctx.GetUsersById(userId, onlyConfirmed).FirstOrDefault();
public static IQueryable<TUser> GetUsersByEmail<TUser>(this IAcUserDbSetBase<TUser> ctx, string email) where TUser : class, IAcUserBase
public static TUser? GetUserByEmail<TUser>(this IAcUserDbSetBase<TUser> ctx, string? email, bool onlyConfirmed) where TUser : class, IAcUserBase
{
return string.IsNullOrWhiteSpace(email) ? null : ctx.GetUsersByEmail(email, onlyConfirmed).FirstOrDefault();
}
public static IQueryable<TUser> GetUsersById<TUser>(this IAcUserDbSetBase<TUser> ctx, Guid userId, bool onlyConfirmed) where TUser : class, IAcUserBase
=> ctx.Users.Where(u => u.Id == userId && (!onlyConfirmed || u.EmailConfirmed));
public static IQueryable<TUser> GetUsersByEmail<TUser>(this IAcUserDbSetBase<TUser> ctx, string email, bool onlyConfirmed) where TUser : class, IAcUserBase
{
Logger.Info($"GetUserByEmail: {email}");
var emailLower = email.ToLower();
return ctx.Users.Where(u => u.EmailAddress == emailLower);
return ctx.Users.Where(u => u.EmailAddress == emailLower && (!onlyConfirmed || u.EmailConfirmed));
}
public static bool AddUser<TUser>(this IAcUserDbSetBase<TUser> ctx, TUser user) where TUser : class, IAcUserBase
@ -42,7 +50,7 @@ public static class AcUserDbSetExtensions
public static bool RemoveUser<TUser>(this IAcUserDbSetBase<TUser> ctx, Guid userId) where TUser : class, IAcUserBase
{
var user = ctx.GetUserById(userId);
var user = ctx.GetUserById(userId, false);
if (user == null) return false;
@ -65,7 +73,7 @@ public static class AcUserDbSetExtensions
if (string.IsNullOrWhiteSpace(refreshToken)) return null;
var existingUser = ctx.GetUserByEmail(email);
var existingUser = ctx.GetUserByEmail(email, true);
if (existingUser == null) return null;
existingUser.RefreshToken = refreshToken;