improvements, fixes, etc...
This commit is contained in:
parent
7360291242
commit
cba3b9f8d6
|
|
@ -8,8 +8,10 @@ namespace AyCode.Core.Helpers
|
||||||
{
|
{
|
||||||
public class PasswordHasher
|
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
|
// Generate a random salt
|
||||||
var salt = new byte[16];
|
var salt = new byte[16];
|
||||||
using (var rng = RandomNumberGenerator.Create()) rng.GetBytes(salt);
|
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
|
// Extract the salt and hashed password from the combined hash
|
||||||
var parts = hashedPassword.Split('$');
|
var parts = hashedPassword.Split('$');
|
||||||
|
|
||||||
|
if (parts.Length != 5) return false;
|
||||||
|
|
||||||
var salt = Convert.FromBase64String(parts[3].Replace("salt=", string.Empty));
|
var salt = Convert.FromBase64String(parts[3].Replace("salt=", string.Empty));
|
||||||
var storedHash = parts[4].Replace("hash=", string.Empty);
|
var storedHash = parts[4].Replace("hash=", string.Empty);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ namespace AyCode.Database.Tests.Users
|
||||||
protected TUser AcBase_GetUserById_ReturnsUser_WhenUserExists(string userIdString)
|
protected TUser AcBase_GetUserById_ReturnsUser_WhenUserExists(string userIdString)
|
||||||
{
|
{
|
||||||
var userId = Guid.Parse(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, "User is null");
|
||||||
Assert.IsNotNull(user.Profile, "Profile 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)
|
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, "User is null");
|
||||||
Assert.IsNotNull(user.Profile, "Profile is null");
|
Assert.IsNotNull(user.Profile, "Profile is null");
|
||||||
|
|
@ -49,7 +49,7 @@ namespace AyCode.Database.Tests.Users
|
||||||
{
|
{
|
||||||
TUser? user = null;
|
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);
|
//user = await Dal.SessionAsync(ctx => ctx.Users.FirstOrDefault(x => x.EmailAddress == email)).ConfigureAwait(false);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,11 +27,11 @@ namespace AyCode.Database.DataLayers.Users
|
||||||
where TUserToServiceProvider : class, IAcUserToServiceProviderBase
|
where TUserToServiceProvider : class, IAcUserToServiceProviderBase
|
||||||
where TProfileAddress : class, IAcAddress
|
where TProfileAddress : class, IAcAddress
|
||||||
{
|
{
|
||||||
public TUser? GetUserById(Guid userId) => Session(x => x.GetUserById(userId));
|
public TUser? GetUserById(Guid userId, bool onlyConfirmed) => Session(x => x.GetUserById(userId, onlyConfirmed));
|
||||||
public Task<TUser?> GetUserByIdAsync(Guid userId) => SessionAsync(x => x.GetUserById(userId));
|
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 TUser? GetUserByEmail(string? email, bool onlyConfirmed) => Session(x => x.GetUserByEmail(email, onlyConfirmed));
|
||||||
public Task<TUser?> GetUserByEmailAsync(string? email) => SessionAsync(x => x.GetUserByEmail(email));
|
public Task<TUser?> GetUserByEmailAsync(string? email, bool onlyConfirmed) => SessionAsync(x => x.GetUserByEmail(email, onlyConfirmed));
|
||||||
|
|
||||||
public Task<bool> AddUserAsync(TUser user)
|
public Task<bool> AddUserAsync(TUser user)
|
||||||
{
|
{
|
||||||
|
|
@ -72,18 +72,19 @@ namespace AyCode.Database.DataLayers.Users
|
||||||
|
|
||||||
profile.Address = address;
|
profile.Address = address;
|
||||||
profile.AddressId = address.Id;
|
profile.AddressId = address.Id;
|
||||||
|
|
||||||
return profile;
|
return profile;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<bool> RemoveUserAsync(TUser? user) => TransactionAsync(ctx => RemoveUserTransactionBody(user, ctx));
|
public Task<bool> RemoveUserAsync(TUser? user) => TransactionAsync(ctx => RemoveUserTransactionBody(user, ctx));
|
||||||
public Task<bool> RemoveUserAsync(Guid userId) => TransactionAsync(ctx =>
|
public Task<bool> RemoveUserAsync(Guid userId) => TransactionAsync(ctx =>
|
||||||
{
|
{
|
||||||
var user = ctx.GetUserById(userId);
|
var user = ctx.GetUserById(userId, false);
|
||||||
|
|
||||||
return RemoveUserTransactionBody(user, ctx);
|
return RemoveUserTransactionBody(user, ctx);
|
||||||
});
|
});
|
||||||
|
|
||||||
protected bool RemoveUserTransactionBody(TUser? user, TDbContext ctx)
|
protected virtual bool RemoveUserTransactionBody(TUser? user, TDbContext ctx)
|
||||||
{
|
{
|
||||||
if (user == null) return false;
|
if (user == null) return false;
|
||||||
|
|
||||||
|
|
@ -106,7 +107,11 @@ namespace AyCode.Database.DataLayers.Users
|
||||||
|
|
||||||
var result = Transaction(ctx =>
|
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)
|
if (user is { EmailConfirmed: true } && string.Equals(user.EmailAddress, email, StringComparison.CurrentCultureIgnoreCase)
|
||||||
&& PasswordHasher.VerifyPassword(password, user.Password, PasswordHasher.GenerateDynamicSalt(user.Id)))
|
&& PasswordHasher.VerifyPassword(password, user.Password, PasswordHasher.GenerateDynamicSalt(user.Id)))
|
||||||
{
|
{
|
||||||
|
|
@ -115,6 +120,11 @@ namespace AyCode.Database.DataLayers.Users
|
||||||
errorCodeInner = AcErrorCode.RefreshTokenUpdateError;
|
errorCodeInner = AcErrorCode.RefreshTokenUpdateError;
|
||||||
}
|
}
|
||||||
else errorCodeInner = AcErrorCode.WrongLoginData;
|
else errorCodeInner = AcErrorCode.WrongLoginData;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
errorCodeInner = AcErrorCode.UnknownError;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -9,23 +9,31 @@ namespace AyCode.Database.DbSets.Users;
|
||||||
|
|
||||||
public static class AcUserDbSetExtensions
|
public static class AcUserDbSetExtensions
|
||||||
{
|
{
|
||||||
public static TUser? GetUserById<TUser>(this IAcUserDbSetBase<TUser> ctx, Guid userId) where TUser : class, IAcUserBase
|
public static TUser? AuthenticateUser<TUser>(this IAcUserDbSetBase<TUser> ctx, string? email, string? passwordHash, bool onlyConfirmed) where TUser : class, IAcUserBase
|
||||||
=> ctx.GetUsersById(userId).FirstOrDefault();
|
|
||||||
|
|
||||||
public static TUser? GetUserByEmail<TUser>(this IAcUserDbSetBase<TUser> ctx, string? email) 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
|
public static TUser? GetUserById<TUser>(this IAcUserDbSetBase<TUser> ctx, Guid userId, bool onlyConfirmed) where TUser : class, IAcUserBase
|
||||||
=> ctx.Users.Where(u => u.Id == userId);
|
=> 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}");
|
Logger.Info($"GetUserByEmail: {email}");
|
||||||
|
|
||||||
var emailLower = email.ToLower();
|
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
|
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
|
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;
|
if (user == null) return false;
|
||||||
|
|
||||||
|
|
@ -65,7 +73,7 @@ public static class AcUserDbSetExtensions
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(refreshToken)) return null;
|
if (string.IsNullOrWhiteSpace(refreshToken)) return null;
|
||||||
|
|
||||||
var existingUser = ctx.GetUserByEmail(email);
|
var existingUser = ctx.GetUserByEmail(email, true);
|
||||||
if (existingUser == null) return null;
|
if (existingUser == null) return null;
|
||||||
|
|
||||||
existingUser.RefreshToken = refreshToken;
|
existingUser.RefreshToken = refreshToken;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue