using MediatR; using Microsoft.AspNetCore.Http; using Modules.User.Application.Errors; using Modules.User.Application.Gateways; using Modules.User.Application.Models; namespace Modules.User.Application.Commands; public class RefreshTokensCommand : IRequest { public string? Ip { get; set; } public HttpResponse Response { get; set; } = default!; public string? CookiePath { get; set; } } public class RefreshTokensCommandHandler(UserContext userContext, IUserRepository userRepository, IAccountAccessQueries accessQueries, IUnitOfWork unitOfWork) : IRequestHandler { public async Task Handle(RefreshTokensCommand request, CancellationToken cancellationToken) { var accountId = userContext.GetAccountId(); if (!accountId.HasValue) return null; var oldRefreshToken = userContext.GetRefreshToken(); var user = await userRepository.GetByAccountIdAsync(accountId.Value, cancellationToken) ?? throw new AccountException(); var now = DateTime.UtcNow; var status = user.Account.GetBanStatus(now); if (status.IsBanned) throw new AccountBannedException(status.ReleaseDate); var jwtSettings = userContext.GetJwtSettings(); var userAgent = userContext.GetUserAgent(); var location = await userContext.GetLocation(request.Ip); var newRefreshToken = TokenGenerator.GenerateRefreshToken(); var expiresAt = now.Add(jwtSettings.RefreshTokenExpireTime); var clientInfo = Domain.Entities.User.ClientInfo.Create(userAgent, location?.Country, location?.Region); var session = user.AddOrUpdateSession(oldRefreshToken, newRefreshToken, expiresAt, clientInfo); await userRepository.SaveAsync(user, cancellationToken); await unitOfWork.SaveChangesAsync(cancellationToken); var roleNames = await accessQueries.GetRoleNamesAsync(user.Account.Id, cancellationToken); var permissionNames = await accessQueries.GetPermissionNamesAsync(user.Account.Id, cancellationToken); var permissionCodes = await accessQueries.GetEffectivePermissionCodesAsync(user.Account.Id, cancellationToken); var newAccessToken = TokenGenerator.GenerateAccessToken(user, session, jwtSettings, roleNames, permissionNames, permissionCodes); return new AuthenticationResult { AccessToken = newAccessToken, SessionExpireDate = session.ExpiredDateUtc, }; } }