using IO.Swagger.Models.db;
using IO.Swagger.Models.RequestDto;
using IO.Swagger.Services;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using System;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace IO.Swagger.Repositories
{
///
/// The EF implementation of this interface
///
///
public class UserRepository : IUserRepository
{
private readonly BankDbContext bankDbContext;
///
/// Initializes a new instance of the class.
///
/// The bank database context.
public UserRepository(BankDbContext bankDbContext)
{
this.bankDbContext = bankDbContext;
}
///
public async Task RegisterUser(AuthRegisterBody request)
{
request.Email = request.Email.ToLower();
if (await bankDbContext.Users.CountAsync((User u) => u.Email == request.Email) > 0)
return null;
// Generate a random salt
byte[] saltBytes = RandomNumberGenerator.GetBytes(16);
string salt = Convert.ToBase64String(saltBytes);
// Hash the password along with the salt
string hashedPassword = HashPassword(salt, request.Password);
// Create and insert the user
User newUser = new()
{
PasswordHash = hashedPassword,
Salt = salt,
Email = request.Email,
FirstName = request.FirstName,
LastName = request.LastName
};
_ = await bankDbContext.Users.AddAsync(newUser);
_ = await bankDbContext.SaveChangesAsync();
return newUser;
}
///
public async Task LoginUser(AuthLoginBody request)
{
request.Email = request.Email.ToLower();
User user = await bankDbContext.Users.FirstOrDefaultAsync(u => u.Email.Equals(request.Email));
if (user == null)
return null;
string hashedPassword = HashPassword(user.Salt, request.Password);
return hashedPassword != user.PasswordHash ? null : user;
}
///
public async Task RetrieveUser(int userId)
{
return await bankDbContext.Users.FirstOrDefaultAsync(u => u.Id == userId);
}
///
/// Hashes the password.
///
/// The salt to apply.
/// The password to hash.
/// The hashed and salted password
private static string HashPassword(string salt, string password)
{
string saltedPassword = password + salt;
byte[] passwordBytes = Encoding.UTF8.GetBytes(saltedPassword);
byte[] hashedBytes = SHA256.HashData(passwordBytes);
string hashedPassword = Convert.ToBase64String(hashedBytes);
return hashedPassword;
}
}
}