fronted: login
This commit is contained in:
@@ -1,17 +1,111 @@
|
||||
using back.DataModels;
|
||||
using back.services.Crypto;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Net;
|
||||
|
||||
namespace back.context;
|
||||
|
||||
public class UserContext : DbContext
|
||||
{
|
||||
public DbSet<UserModel> Users { get; set; }
|
||||
public UserContext(DbContextOptions<UserContext> options) : base(options)
|
||||
public record HttpErrorMap(HttpStatusCode Code, string Description);
|
||||
|
||||
public static class Errors
|
||||
{
|
||||
public static readonly HttpErrorMap Unauthorized =
|
||||
new(HttpStatusCode.Unauthorized, "Invalid user data. Email or password are wrong.");
|
||||
public static readonly HttpErrorMap BadRequest =
|
||||
new(HttpStatusCode.BadRequest, "Missing user data.");
|
||||
}
|
||||
|
||||
public DbSet<UserModel> Users { get; set; }
|
||||
private readonly ICryptoService _cryptoService;
|
||||
public UserContext(
|
||||
DbContextOptions<UserContext> options,
|
||||
ICryptoService cryptoService
|
||||
) : base(options)
|
||||
{
|
||||
_cryptoService = cryptoService ?? throw new ArgumentNullException(nameof(cryptoService));
|
||||
// Ensure database is created
|
||||
Database.EnsureCreated();
|
||||
}
|
||||
|
||||
public async Task<UserModel?> Create(string clientId, UserModel user)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(user);
|
||||
|
||||
if (await Exists(user))
|
||||
{
|
||||
return await GetById(Guid.Parse(user.Id)) ?? null;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(user.Id))
|
||||
{
|
||||
user.Id = Guid.NewGuid().ToString();
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(user.Salt))
|
||||
{
|
||||
user.Salt = _cryptoService.Salt();
|
||||
}
|
||||
user.Password = _cryptoService.Decrypt(clientId, user.Password) ?? string.Empty;
|
||||
user.Password = _cryptoService.Hash(user.Password + user.Salt + _cryptoService.Pepper()) ?? string.Empty;
|
||||
|
||||
user.CreatedAt = DateTime.UtcNow;
|
||||
Users.Add(user);
|
||||
await SaveChangesAsync();
|
||||
return user;
|
||||
}
|
||||
|
||||
public async Task<UserModel?> Update(UserModel user)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(user);
|
||||
if (!await Exists(user))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var existingUser = await GetById(Guid.Parse(user.Id));
|
||||
if (existingUser == null) return null;
|
||||
existingUser.Name = user.Name;
|
||||
existingUser.Email = user.Email;
|
||||
existingUser.UpdatedAt = DateTime.UtcNow;
|
||||
Users.Update(existingUser);
|
||||
await SaveChangesAsync();
|
||||
return existingUser;
|
||||
}
|
||||
|
||||
public async Task<bool> Delete(Guid id)
|
||||
{
|
||||
var user = await GetById(id);
|
||||
if (user == null) return false;
|
||||
Users.Remove(user);
|
||||
await SaveChangesAsync();
|
||||
return true;
|
||||
}
|
||||
|
||||
public async Task<UserModel?> GetByEmail(string email)
|
||||
{
|
||||
if (string.IsNullOrEmpty(email)) return null;
|
||||
return await Users.FirstOrDefaultAsync(u => u.Email == email);
|
||||
}
|
||||
|
||||
public async Task<string> GetUserSaltByEmail(string email)
|
||||
{
|
||||
if (string.IsNullOrEmpty(email)) return string.Empty;
|
||||
var user = await Users.FirstOrDefaultAsync(u => u.Email == email);
|
||||
return user?.Salt ?? string.Empty;
|
||||
}
|
||||
|
||||
public async Task<UserModel?> Login(string email, string password, string clientId)
|
||||
{
|
||||
if (string.IsNullOrEmpty(email) || string.IsNullOrEmpty(password)) return null;
|
||||
|
||||
var pass = _cryptoService.Decrypt(clientId, password) + await GetUserSaltByEmail(email) + _cryptoService.Pepper();
|
||||
var hashedPassword = _cryptoService.Hash(pass);
|
||||
var user = await Users
|
||||
.FirstOrDefaultAsync(u => u.Email == email && u.Password == hashedPassword);
|
||||
return user;
|
||||
}
|
||||
|
||||
public async Task<UserModel?> GetById(Guid id)
|
||||
{
|
||||
return await Users.FindAsync(id);
|
||||
|
Reference in New Issue
Block a user