Фиксы
This commit is contained in:
@@ -11,8 +11,11 @@ using MediatR;
|
||||
using Host.Application.Admin.Queries;
|
||||
using Host.Application.Admin.Commands;
|
||||
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
||||
namespace Host.Controllers;
|
||||
|
||||
[Authorize]
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
public class AdminController : ControllerBase
|
||||
|
||||
@@ -52,7 +52,7 @@ public sealed class ChatsController : ControllerBase
|
||||
var result = await _sender.Send(command, ct);
|
||||
if (result.IsFailure) return BadRequest(result.Error.Description);
|
||||
|
||||
var chatResult = await _sender.Send(new GetChatByIdQuery(result.Value), ct);
|
||||
var chatResult = await _sender.Send(new GetChatByIdQuery(_userContext.UserId, result.Value), ct);
|
||||
return Ok(chatResult.Value);
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ public sealed class ChatsController : ControllerBase
|
||||
var result = await _sender.Send(command, ct);
|
||||
if (result.IsFailure) return BadRequest(result.Error.Description);
|
||||
|
||||
var chatResult = await _sender.Send(new GetChatByIdQuery(result.Value), ct);
|
||||
var chatResult = await _sender.Send(new GetChatByIdQuery(_userContext.UserId, result.Value), ct);
|
||||
return Ok(chatResult.Value);
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ public sealed class ChatsController : ControllerBase
|
||||
var result = await _sender.Send(command, ct);
|
||||
if (result.IsFailure) return BadRequest(result.Error.Description);
|
||||
|
||||
var chatResult = await _sender.Send(new GetChatByIdQuery(result.Value), ct);
|
||||
var chatResult = await _sender.Send(new GetChatByIdQuery(_userContext.UserId, result.Value), ct);
|
||||
return Ok(chatResult.Value);
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ public sealed class ChatsController : ControllerBase
|
||||
var result = await _sender.Send(new GetOrCreateFavoritesCommand(_userContext.UserId), ct);
|
||||
if (result.IsFailure) return BadRequest(result.Error.Description);
|
||||
|
||||
var chatResult = await _sender.Send(new GetChatByIdQuery(result.Value), ct);
|
||||
var chatResult = await _sender.Send(new GetChatByIdQuery(_userContext.UserId, result.Value), ct);
|
||||
return Ok(chatResult.Value);
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ public sealed class ChatsController : ControllerBase
|
||||
var result = await _sender.Send(new UpdateChatCommand(id, _userContext.UserId, request.Name, request.Description), ct);
|
||||
if (result.IsFailure) return NotFound();
|
||||
|
||||
var chatResult = await _sender.Send(new GetChatByIdQuery(result.Value), ct);
|
||||
var chatResult = await _sender.Send(new GetChatByIdQuery(_userContext.UserId, result.Value), ct);
|
||||
return Ok(chatResult.Value);
|
||||
}
|
||||
|
||||
@@ -139,7 +139,7 @@ public sealed class ChatsController : ControllerBase
|
||||
var result = await _sender.Send(new AddMembersCommand(id, _userContext.UserId, request.UserIds.ToList()), ct);
|
||||
if (result.IsFailure) return NotFound();
|
||||
|
||||
var chatResult = await _sender.Send(new GetChatByIdQuery(result.Value), ct);
|
||||
var chatResult = await _sender.Send(new GetChatByIdQuery(_userContext.UserId, result.Value), ct);
|
||||
return Ok(chatResult.Value);
|
||||
}
|
||||
|
||||
@@ -149,7 +149,7 @@ public sealed class ChatsController : ControllerBase
|
||||
var result = await _sender.Send(new RemoveMemberCommand(id, _userContext.UserId, userId), ct);
|
||||
if (result.IsFailure) return NotFound();
|
||||
|
||||
var chatResult = await _sender.Send(new GetChatByIdQuery(result.Value), ct);
|
||||
var chatResult = await _sender.Send(new GetChatByIdQuery(_userContext.UserId, result.Value), ct);
|
||||
return Ok(chatResult.Value);
|
||||
}
|
||||
|
||||
@@ -163,7 +163,7 @@ public sealed class ChatsController : ControllerBase
|
||||
|
||||
if (result.IsFailure) return NotFound();
|
||||
|
||||
var chatResult = await _sender.Send(new GetChatByIdQuery(result.Value), ct);
|
||||
var chatResult = await _sender.Send(new GetChatByIdQuery(_userContext.UserId, result.Value), ct);
|
||||
return Ok(chatResult.Value);
|
||||
}
|
||||
|
||||
@@ -177,7 +177,7 @@ public sealed class ChatsController : ControllerBase
|
||||
|
||||
if (result.IsFailure) return NotFound();
|
||||
|
||||
var chatResult = await _sender.Send(new GetChatByIdQuery(result.Value), ct);
|
||||
var chatResult = await _sender.Send(new GetChatByIdQuery(_userContext.UserId, result.Value), ct);
|
||||
return Ok(chatResult.Value);
|
||||
}
|
||||
|
||||
@@ -187,7 +187,7 @@ public sealed class ChatsController : ControllerBase
|
||||
var result = await _sender.Send(new RemoveGroupAvatarCommand(id, _userContext.UserId), ct);
|
||||
if (result.IsFailure) return NotFound();
|
||||
|
||||
var chatResult = await _sender.Send(new GetChatByIdQuery(result.Value), ct);
|
||||
var chatResult = await _sender.Send(new GetChatByIdQuery(_userContext.UserId, result.Value), ct);
|
||||
return Ok(chatResult.Value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ using Knot.Shared.Kernel.Storage;
|
||||
|
||||
namespace Host.Controllers;
|
||||
|
||||
[Authorize]
|
||||
[ApiController]
|
||||
[Route("api/files")]
|
||||
public sealed class FilesController : ControllerBase
|
||||
|
||||
@@ -11,7 +11,7 @@ using Knot.Modules.Chats.Application.Abstractions;
|
||||
|
||||
namespace Knot.Modules.Chats.Application.Chats.GetChatById;
|
||||
|
||||
public record GetChatByIdQuery(Guid ChatId) : IQuery<ChatDto?>;
|
||||
public record GetChatByIdQuery(Guid UserId, Guid ChatId) : IQuery<ChatDto?>;
|
||||
|
||||
internal sealed class GetChatByIdQueryHandler : IQueryHandler<GetChatByIdQuery, ChatDto?>
|
||||
{
|
||||
@@ -31,6 +31,11 @@ internal sealed class GetChatByIdQueryHandler : IQueryHandler<GetChatByIdQuery,
|
||||
var chat = await _chatRepository.GetByIdAsync(request.ChatId, cancellationToken);
|
||||
if (chat == null) return Result.Success<ChatDto?>(null);
|
||||
|
||||
if (!chat.Members.Any(m => m.UserId == request.UserId))
|
||||
{
|
||||
return Result.Failure<ChatDto?>(new Error("Chats.Forbidden", "Вы не являетесь участником этого чата."));
|
||||
}
|
||||
|
||||
var userIdsToFetch = new HashSet<Guid>();
|
||||
foreach (var m in chat.Members) userIdsToFetch.Add(m.UserId);
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@ using Knot.Shared.Kernel;
|
||||
using Knot.Modules.Chats.Application.DTOs;
|
||||
using Knot.Modules.Chats.Domain;
|
||||
|
||||
using Knot.Modules.Chats.Application.Abstractions;
|
||||
|
||||
namespace Knot.Modules.Chats.Application.Messages.GetMessages;
|
||||
|
||||
public record GetMessagesQuery(Guid UserId, Guid ChatId, string? Cursor) : IQuery<List<MessageDetailDto>>;
|
||||
@@ -16,15 +18,23 @@ internal sealed class GetMessagesQueryHandler : IQueryHandler<GetMessagesQuery,
|
||||
{
|
||||
private readonly IMessageRepository _messageRepository;
|
||||
private readonly IUserDisplayNameProvider _userProvider;
|
||||
private readonly IChatRepository _chatRepository;
|
||||
|
||||
public GetMessagesQueryHandler(IMessageRepository messageRepository, IUserDisplayNameProvider userProvider)
|
||||
public GetMessagesQueryHandler(IMessageRepository messageRepository, IUserDisplayNameProvider userProvider, IChatRepository chatRepository)
|
||||
{
|
||||
_messageRepository = messageRepository;
|
||||
_userProvider = userProvider;
|
||||
_chatRepository = chatRepository;
|
||||
}
|
||||
|
||||
public async Task<Result<List<MessageDetailDto>>> Handle(GetMessagesQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
var chat = await _chatRepository.GetByIdAsync(request.ChatId, cancellationToken);
|
||||
if (chat == null || !chat.Members.Any(m => m.UserId == request.UserId))
|
||||
{
|
||||
return Result.Failure<List<MessageDetailDto>>(new Error("Chats.Forbidden", "Вы не являетесь участником этого чата."));
|
||||
}
|
||||
|
||||
DateTime? cursorDate = null;
|
||||
if (!string.IsNullOrEmpty(request.Cursor) && DateTime.TryParse(request.Cursor, null, System.Globalization.DateTimeStyles.RoundtripKind, out var parsed))
|
||||
{
|
||||
|
||||
@@ -9,6 +9,8 @@ using Knot.Shared.Kernel;
|
||||
using Knot.Modules.Chats.Application.DTOs;
|
||||
using Knot.Modules.Chats.Domain;
|
||||
|
||||
using Knot.Modules.Chats.Application.Abstractions;
|
||||
|
||||
namespace Knot.Modules.Chats.Application.Messages.GetSharedMedia;
|
||||
|
||||
public record GetSharedMediaQuery(Guid UserId, Guid ChatId, string? Type) : IQuery<List<SharedMediaDto>>;
|
||||
@@ -17,15 +19,23 @@ internal sealed class GetSharedMediaQueryHandler : IQueryHandler<GetSharedMediaQ
|
||||
{
|
||||
private readonly IMessageRepository _messageRepository;
|
||||
private readonly IUserDisplayNameProvider _userProvider;
|
||||
private readonly IChatRepository _chatRepository;
|
||||
|
||||
public GetSharedMediaQueryHandler(IMessageRepository messageRepository, IUserDisplayNameProvider userProvider)
|
||||
public GetSharedMediaQueryHandler(IMessageRepository messageRepository, IUserDisplayNameProvider userProvider, IChatRepository chatRepository)
|
||||
{
|
||||
_messageRepository = messageRepository;
|
||||
_userProvider = userProvider;
|
||||
_chatRepository = chatRepository;
|
||||
}
|
||||
|
||||
public async Task<Result<List<SharedMediaDto>>> Handle(GetSharedMediaQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
var chat = await _chatRepository.GetByIdAsync(request.ChatId, cancellationToken);
|
||||
if (chat == null || !chat.Members.Any(m => m.UserId == request.UserId))
|
||||
{
|
||||
return Result.Failure<List<SharedMediaDto>>(new Error("Chats.Forbidden", "Вы не являетесь участником этого чата."));
|
||||
}
|
||||
|
||||
var messages = await _messageRepository.GetChatMessagesAsync(request.ChatId, 300, 0, cancellationToken);
|
||||
messages = messages.Where(m => !m.IsDeleted && !m.DeletedByUsers.Contains(request.UserId)).ToList();
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ internal sealed class SearchMessagesQueryHandler : IQueryHandler<SearchMessagesQ
|
||||
|
||||
public async Task<Result<List<SearchMessageDto>>> Handle(SearchMessagesQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
var messages = await _messageRepository.SearchMessagesAsync(request.Query, request.ChatId, cancellationToken);
|
||||
var messages = await _messageRepository.SearchMessagesAsync(request.Query, request.ChatId, request.UserId, cancellationToken);
|
||||
messages = messages.Where(m => !m.DeletedByUsers.Contains(request.UserId)).ToList();
|
||||
|
||||
var userIds = messages.Select(m => m.SenderId).ToList();
|
||||
|
||||
@@ -47,8 +47,11 @@ public sealed class SendMessageCommandHandler : ICommandHandler<SendMessageComma
|
||||
return Result.Failure<Guid>(new Error("Chats.NotFound", "Чат не найден."));
|
||||
}
|
||||
|
||||
// 2. Проверяем, является ли отправитель участником (в будущем)
|
||||
// if (!chat.Members.Any(m => m.UserId == request.SenderId)) ...
|
||||
// 2. Проверяем, является ли отправитель участником
|
||||
if (!chat.Members.Any(m => m.UserId == request.SenderId))
|
||||
{
|
||||
return Result.Failure<Guid>(new Error("Chats.Forbidden", "Вы не являетесь участником этого чата."));
|
||||
}
|
||||
|
||||
// 3. Создаем сообщение
|
||||
var message = Message.Create(
|
||||
|
||||
@@ -7,7 +7,7 @@ public interface IMessageRepository
|
||||
void Add(Message message);
|
||||
Task<Message?> GetByIdAsync(Guid id, CancellationToken cancellationToken);
|
||||
Task<List<Message>> GetChatMessagesAsync(Guid chatId, int limit, int offset, CancellationToken cancellationToken);
|
||||
Task<List<Message>> SearchMessagesAsync(string query, Guid? chatId, CancellationToken cancellationToken);
|
||||
Task<List<Message>> SearchMessagesAsync(string query, Guid? chatId, Guid requestingUserId, CancellationToken cancellationToken);
|
||||
Task AddReadReceiptsAsync(Guid userId, List<Guid> messageIds, CancellationToken cancellationToken);
|
||||
Task<bool> AddReactionAsync(Guid messageId, Guid userId, string emoji, CancellationToken cancellationToken);
|
||||
Task<bool> RemoveReactionAsync(Guid messageId, Guid userId, string emoji, CancellationToken cancellationToken);
|
||||
|
||||
@@ -58,6 +58,8 @@ public sealed class ChatsDbContext : DbContext, IChatsUnitOfWork
|
||||
{
|
||||
builder.ToTable("Messages");
|
||||
builder.HasKey(m => m.Id);
|
||||
builder.HasIndex(m => m.ChatId);
|
||||
builder.HasIndex(m => new { m.ChatId, m.CreatedAt });
|
||||
|
||||
builder.Property(m => m.Content)
|
||||
.HasConversion(
|
||||
|
||||
@@ -58,9 +58,14 @@ public sealed class MessageRepository : IMessageRepository
|
||||
.ToListAsync(cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<List<Message>> SearchMessagesAsync(string query, Guid? chatId, CancellationToken cancellationToken)
|
||||
public async Task<List<Message>> SearchMessagesAsync(string query, Guid? chatId, Guid requestingUserId, CancellationToken cancellationToken)
|
||||
{
|
||||
var q = _dbContext.Messages.AsQueryable();
|
||||
var validChatIdsQuery = _dbContext.Chats
|
||||
.Where(c => c.Members.Any(m => m.UserId == requestingUserId))
|
||||
.Select(c => c.Id);
|
||||
|
||||
var q = _dbContext.Messages.Where(m => validChatIdsQuery.Contains(m.ChatId));
|
||||
|
||||
if (chatId.HasValue)
|
||||
{
|
||||
q = q.Where(m => m.ChatId == chatId.Value);
|
||||
|
||||
Reference in New Issue
Block a user