using Isopoh.Cryptography.Argon2; using Microsoft.EntityFrameworkCore; using Mizuki.Database; using Mizuki.Database.Models; namespace Mizuki.Services; /// /// The user service. /// /// The Mizuki database context. public class UserService( MizukiDbContext dbContext) { /// /// Check if a user with the given username exists. /// /// The username. /// Whether they exist. public async Task UsernameTaken( string username) { return await dbContext.Users .AnyAsync(u => u.Username == username); } /// /// Gets a user with the given username. /// /// The username. /// The user model. public async Task GetUserForUsername( string username) { return await dbContext.Users .FirstAsync(u => u.Username == username); } /// /// Check if the password is valid for the given user. /// /// The user's name. /// The password. /// Whether it's valid. public async Task CheckPasswordForUser( string username, string password) { var user = await dbContext.Users .FirstOrDefaultAsync(u => u.Username == username); if (user is null) return false; return Argon2.Verify(user.PasswordHash, password); } /// /// Creates a user with the given username and password. /// /// The username. /// The password. /// Whether the user was created. public async Task CreateUser( string username, string password) { if (await UsernameTaken(username)) return false; var hash = Argon2.Hash(password); var userModel = new User { Id = Guid.NewGuid(), Username = username, PasswordHash = hash }; await dbContext.Users.AddAsync(userModel); await dbContext.SaveChangesAsync(); return true; } }