Backend: .NET 10 Clean Architecture + LiteCqrs.Net + EF Core/PostgreSQL + Identity/JWT. Frontend: React 19 + Vite + TanStack Query/Router + Tailwind v4 with a retro CRT theme. Docker/compose deployment mirroring PnvPanel's conventions, scoped down to the current base feature set.
51 lines
1.7 KiB
C#
51 lines
1.7 KiB
C#
using LiteCqrs;
|
|
using TeleWave.Application.Common.Interfaces;
|
|
using TeleWave.Application.Common.Models;
|
|
|
|
namespace TeleWave.Application.Auth.Login;
|
|
|
|
public sealed class LoginCommandHandler(
|
|
IIdentityService identityService,
|
|
IJwtTokenService jwtTokenService,
|
|
IRefreshTokenService refreshTokenService
|
|
) : ICommandHandler<LoginCommand, Result<AuthResult>>
|
|
{
|
|
public async Task<Result<AuthResult>> Handle(
|
|
LoginCommand command,
|
|
CancellationToken cancellationToken
|
|
)
|
|
{
|
|
var credentialsResult = await identityService.ValidateCredentialsAsync(
|
|
command.UserName,
|
|
command.Password,
|
|
cancellationToken
|
|
);
|
|
if (!credentialsResult.IsSuccess)
|
|
return Result.Failure<AuthResult>(credentialsResult.Error);
|
|
|
|
var user = credentialsResult.Value;
|
|
var profile = await identityService.GetProfileAsync(user.Id, cancellationToken);
|
|
if (profile is null)
|
|
return Result.Failure<AuthResult>(AuthErrors.InvalidCredentials);
|
|
|
|
if (profile.IsBlocked)
|
|
return Result.Failure<AuthResult>(AuthErrors.Blocked);
|
|
|
|
var (accessToken, accessExpiresAt) = jwtTokenService.GenerateAccessToken(
|
|
new AuthenticatedUser(profile.Id, profile.UserName, profile.Role)
|
|
);
|
|
var refreshToken = await refreshTokenService.IssueAsync(profile.Id, cancellationToken);
|
|
|
|
var dto = new CurrentUserDto(profile.Id, profile.UserName, profile.Role);
|
|
return Result.Success(
|
|
new AuthResult(
|
|
accessToken,
|
|
accessExpiresAt,
|
|
refreshToken.RawToken,
|
|
refreshToken.ExpiresAt,
|
|
dto
|
|
)
|
|
);
|
|
}
|
|
}
|