using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; using Tiku.Application.Auth; using Tiku.Domain.Identity; using Tiku.Domain.Tenancy; namespace Tiku.Infrastructure.Auth; internal sealed class PasswordLoginService(AuthServiceDependencies dependencies) : AuthServiceBase(dependencies), IPasswordLoginService { public async Task LoginWithPasswordAsync( PasswordLoginRequest request, CancellationToken cancellationToken = default) { var identifier = request.Phone.Trim(); var normalizedEmail = userManager.NormalizeEmail(identifier); var normalizedUserName = userManager.NormalizeName(identifier); var user = await identityPersistence.Users .SingleOrDefaultAsync(entity => entity.Phone == identifier || entity.NormalizedEmail == normalizedEmail || entity.NormalizedUserName == normalizedUserName, cancellationToken); var passwordResult = user is null || user.Status != UserStatus.Active ? SignInResult.Failed : await signInManager.CheckPasswordSignInAsync(user, request.Password, true); if (!passwordResult.Succeeded) { var loginResult = passwordResult.IsLockedOut ? AuthLoginResult.Blocked : AuthLoginResult.Failed; var failureCode = passwordResult.IsLockedOut ? "account_locked" : "invalid_credentials"; await AddLoginEventAsync( request.TenantId, user?.Id, PasswordProvider, identifier, loginResult, failureCode, request.IpAddress, request.UserAgent, cancellationToken); throw new InvalidCredentialsException(); } return await CompleteSuccessfulLoginAsync( request.Realm, request.TenantId, user!, PasswordProvider, identifier, request.IpAddress, request.UserAgent, cancellationToken); } }