using Application.Abstractions.Messaging; using Application.Abstractions.Data; using Application.Abstractions.Forum; using Domain.Entities.Forum.Logs; using SharedKernel.Results; using Microsoft.EntityFrameworkCore; namespace Application.Features.Api.Forum.PostFile.Download; public sealed class Handler(IAppDbContext db, IBoardPermissionService permissionService) : ICommandHandler> { public async Task> Handle(Command request, CancellationToken ct) { var file = await db.PostFile.FirstOrDefaultAsync(x => x.UUID == request.PostFileUUID && !x.IsDisabled, ct); if (file is null) { return Result.Failure(Error.NotFound("PostFile.NotFound", "파일을 찾을 수 없습니다.")); } // 파일 다운로드 권한 확인 var boardMeta = await db.BoardMeta.AsNoTracking().FirstOrDefaultAsync(x => x.BoardID == file.BoardID, ct); if (boardMeta is not null && boardMeta.Permission.FileDownload > -1) { if (!request.MemberID.HasValue) { return Result.Failure(Error.Forbidden("PostFile.PermissionDenied", "파일 다운로드 권한이 없습니다.")); } var member = await db.Member.AsNoTracking().FirstOrDefaultAsync(x => x.ID == request.MemberID.Value, ct); if (member is null || !await permissionService.HasPermissionAsync(member, file.BoardID, boardMeta.Permission.FileDownload, ct)) { return Result.Failure(Error.Forbidden("PostFile.PermissionDenied", "파일 다운로드 권한이 없습니다.")); } } file.Downloads++; var log = new PostFileDownLog { PostID = file.PostID, PostFileID = file.ID, MemberID = request.MemberID, IpAddress = request.IpAddress, UserAgent = request.UserAgent }; await db.PostFileDownLog.AddAsync(log, ct); await db.SaveChangesAsync(ct); return new Response(file.Url, file.FileName); } }