using Application.Abstractions.Data; using Application.Abstractions.Messaging; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using SharedKernel.Results; namespace Application.Features.Api.Auth.Logout; internal sealed class Handler(IAppDbContext db, ILogger logger) : ICommandHandler { public async Task Handle(Command request, CancellationToken ct) { if (string.IsNullOrWhiteSpace(request.RefreshToken)) { return Result.Failure(Error.Problem("Auth.TokenRequired", "리프레시 토큰은 필수입니다.")); } var refreshToken = await db.RefreshToken.FirstOrDefaultAsync(t => t.Token == request.RefreshToken && t.MemberID == request.MemberID, ct); if (refreshToken is null) { return Result.Failure(Error.NotFound("Auth.TokenNotFound", "유효하지 않은 리프레시 토큰입니다.")); } if (refreshToken.IsRevoked) { return Result.Success(); } refreshToken.Revoke(); await db.SaveChangesAsync(ct); logger.LogInformation("로그아웃 완료"); return Result.Success(); } }