From 66819a015a318ddb9ae5a150e00e5137eb8aea0e Mon Sep 17 00:00:00 2001 From: Artemy <109195690+stalcker2288969@users.noreply.github.com> Date: Sun, 6 Jul 2025 21:09:12 +0700 Subject: [PATCH] Refactor media attachments to use MediaFile entity This commit introduces the MediaFile entity and updates the media attachments model, repositories, and related logic to reference MediaFile instead of storing file metadata directly in MediaAttachments. Controller, service, and SignalR request/response contracts are updated to support the new structure. Database configurations and validators are also adjusted accordingly. This refactor improves media management and normalization in the data model. --- .../UnitTests/Services/FriendsServiceTests.cs | 8 ++--- Govor.API/Controllers/MediaController.cs | 18 ++++++------ Govor.API/Hubs/ChatsHub.cs | 26 ++++++++--------- .../Interfaces/Medias/IMediaService.cs | 14 +++++++++ .../Interfaces/Messages/IMessageService.cs | 4 +-- .../Messages/Parameters/SendMedia.cs | 2 +- Govor.Application/Services/FriendsService.cs | 3 +- Govor.Application/Services/MediaService.cs | 29 +++++++++++++++++++ Govor.Application/Services/MessageService.cs | 29 +++++++++---------- .../Requests/SignalR/EditMessageRequest.cs | 7 +++++ .../Requests/SignalR/MediaReference.cs | 2 -- .../Requests/SignalR/RemoveMessageRequest.cs | 6 ++++ .../Responses/SignalR/UserMessageResponse.cs | 2 +- .../Validators/MediaAttachmentsValidator.cs | 4 +-- Govor.Core/Models/MediaAttachments.cs | 14 +++------ Govor.Core/Models/MediaFile.cs | 10 +++++++ Govor.Core/Models/Message.cs | 1 - .../MediaAttachmentsConfiguration.cs | 19 +++++------- .../Configurations/MediaFileConfiguration.cs | 27 +++++++++++++++++ .../Configurations/MessagesConfiguration.cs | 5 ---- Govor.Data/GovorDbContext.cs | 2 ++ .../MediaAttachmentsRepository.cs | 9 ++---- Govor.Data/Repositories/MessagesRepository.cs | 18 +++++++----- 23 files changed, 166 insertions(+), 93 deletions(-) create mode 100644 Govor.Application/Interfaces/Medias/IMediaService.cs create mode 100644 Govor.Application/Services/MediaService.cs create mode 100644 Govor.Contracts/Requests/SignalR/EditMessageRequest.cs create mode 100644 Govor.Contracts/Requests/SignalR/RemoveMessageRequest.cs create mode 100644 Govor.Core/Models/MediaFile.cs create mode 100644 Govor.Data/Configurations/MediaFileConfiguration.cs diff --git a/Govor.API.Tests/UnitTests/Services/FriendsServiceTests.cs b/Govor.API.Tests/UnitTests/Services/FriendsServiceTests.cs index e1e77b7..79f6a6f 100644 --- a/Govor.API.Tests/UnitTests/Services/FriendsServiceTests.cs +++ b/Govor.API.Tests/UnitTests/Services/FriendsServiceTests.cs @@ -329,8 +329,8 @@ public class FriendsServiceTests f.Status = FriendshipStatus.Pending; }); - _usersRepositoryMock.Setup(f => f.FindByIdAsync(userId)) - .ReturnsAsync(user); + _friendshipsRepositoryMock.Setup(f => f.FindByUserIdAsync(userId)) + .ReturnsAsync(friendships); // Act var result = await _service.GetIncomingRequestsAsync(userId); @@ -346,8 +346,8 @@ public class FriendsServiceTests // Arrange var userId = Guid.NewGuid(); - _usersRepositoryMock - .Setup(r => r.FindByIdAsync(userId)) + _friendshipsRepositoryMock + .Setup(r => r.FindByUserIdAsync(userId)) .ThrowsAsync(new NotFoundByKeyException(userId)); // Act & Assert diff --git a/Govor.API/Controllers/MediaController.cs b/Govor.API/Controllers/MediaController.cs index 4aece1b..b7f00d8 100644 --- a/Govor.API/Controllers/MediaController.cs +++ b/Govor.API/Controllers/MediaController.cs @@ -1,4 +1,5 @@ using Govor.Application.Interfaces; +using Govor.Application.Interfaces.Medias; using Govor.Contracts.Requests; using Govor.Core.Models; using Govor.Core.Repositories.MediasAttachments; @@ -13,12 +14,12 @@ namespace Govor.API.Controllers; public class MediaController : Controller { private readonly ILogger _logger; - private readonly IStorageService _storageService; - - public MediaController(ILogger logger, IStorageService storageService) + private readonly IMediaService _mediaService; + + public MediaController(ILogger logger, IMediaService mediaService) { _logger = logger; - _storageService = storageService; + _mediaService = mediaService; } [HttpPost("upload")] @@ -27,11 +28,10 @@ public class MediaController : Controller { try { - var url = await _storageService.SaveAsync(request.Data,request.FileName); - var mediaId = Guid.NewGuid(); - - - return Ok(mediaId); + var result = await _mediaService.UploadMediaAsync(new Media(request.Data, request.FileName, request.Type, + request.MimeType, request.EncryptedKey)); + + return Ok(result); } catch (Exception ex) { diff --git a/Govor.API/Hubs/ChatsHub.cs b/Govor.API/Hubs/ChatsHub.cs index aad3501..8c5eb3e 100644 --- a/Govor.API/Hubs/ChatsHub.cs +++ b/Govor.API/Hubs/ChatsHub.cs @@ -92,14 +92,14 @@ public class ChatsHub : Hub RecipientType: request.RecipientType, SendAt: DateTime.UtcNow, Media: request.MediaAttachments?.Select(f => new SendMedia( - f.MediaId, f.EncryptedKey, f.Type, f.MimeType)) ?? Array.Empty() + f.MediaId, f.EncryptedKey)) ?? Array.Empty() ); try { var result = await _messageService.SendMessageAsync(sendMessageParams); - if (!result.IsSuccess || result.MessageId == Guid.Empty) + if (!result.IsSuccess || result.Message.Id == Guid.Empty) { _logger.LogError(result.Exception, "Failed to send message from {SenderId} to {RecipientId}. Error: {ErrorMessage}", senderId, request.RecipientId, result.Exception?.Message ?? "Unknown error"); if (result.Exception != null) throw result.Exception; @@ -108,14 +108,15 @@ public class ChatsHub : Hub var messageResponse = new UserMessageResponse // Assuming a response DTO { - MessageId = result.MessageId, - SenderId = senderId, - RecipientId = request.RecipientId, - RecipientType = request.RecipientType, - EncryptedContent = request.EncryptedContent, - SentAt = sendMessageParams.SendAt, + MessageId = result.Message.Id, + SenderId = result.Message.SenderId, + RecipientId = result.Message.RecipientId, + RecipientType = result.Message.RecipientType, + EncryptedContent = result.Message.EncryptedContent, + SentAt = result.Message.SentAt, IsEdited = false, - MediaAttachments = request.MediaAttachments, + MediaAttachments = result.Message.MediaAttachments + .Select(m => m.MediaFile).ToList(), ReplyToMessageId = request.ReplyToMessageId }; @@ -134,7 +135,7 @@ public class ChatsHub : Hub // Notify sender (confirmation) on their connection await Clients.Caller.SendAsync("MessageSent", messageResponse); // Or use "ReceiveMessage" if the sender should also just get it like anyone else - _logger.LogInformation("Message {MessageId} sent successfully from {SenderId} to {RecipientId} ({RecipientType})", result.MessageId, senderId, request.RecipientId, request.RecipientType); + _logger.LogInformation("Message {MessageId} sent successfully from {SenderId} to {RecipientId} ({RecipientType})", result.Message.Id, senderId, request.RecipientId, request.RecipientType); } catch (Exception ex) { @@ -145,18 +146,17 @@ public class ChatsHub : Hub } } - public async Task Remove(Guid recipientId, Guid messageId) + public async Task Remove(RemoveMessageRequest request) { } - public async Task Edit(string newMessage, Guid messageId) + public async Task Edit(EditMessageRequest request) { } - private Guid GetUserId(bool suppressException = false) { var userIdClaim = Context.User?.FindFirst("userId")?.Value; diff --git a/Govor.Application/Interfaces/Medias/IMediaService.cs b/Govor.Application/Interfaces/Medias/IMediaService.cs new file mode 100644 index 0000000..ec3e707 --- /dev/null +++ b/Govor.Application/Interfaces/Medias/IMediaService.cs @@ -0,0 +1,14 @@ +using Govor.Core.Models; + +namespace Govor.Application.Interfaces.Medias; + +public interface IMediaService +{ + public Task UploadMediaAsync(Media file); + public Task DeleteMediaAsync(Guid fileId); + public Task GetMediaAsync(string url); +} + +public record Media(byte[] Data, string FileName, MediaType Type, string MineType, string EncryptedKey); + +public record MediaUploadResult(Guid? MediaId, string Url); \ No newline at end of file diff --git a/Govor.Application/Interfaces/Messages/IMessageService.cs b/Govor.Application/Interfaces/Messages/IMessageService.cs index 850afcb..5493bbf 100644 --- a/Govor.Application/Interfaces/Messages/IMessageService.cs +++ b/Govor.Application/Interfaces/Messages/IMessageService.cs @@ -17,8 +17,8 @@ public interface IMessageService // Define specific result types for clarity, including original message for notifications if needed -public record SendMessageResult(bool IsSuccess, Exception? Exception, Guid MessageId) - : Result(IsSuccess, Exception, MessageId); +public record SendMessageResult(bool IsSuccess, Exception? Exception, Message Message) + : Result(IsSuccess, Exception, Message.Id); public record EditMessageResult(bool IsSuccess, Exception? Exception, Message? OriginalMessage) : Result(IsSuccess, Exception, OriginalMessage?.Id ?? Guid.Empty) diff --git a/Govor.Application/Interfaces/Messages/Parameters/SendMedia.cs b/Govor.Application/Interfaces/Messages/Parameters/SendMedia.cs index 1d87a71..e07b452 100644 --- a/Govor.Application/Interfaces/Messages/Parameters/SendMedia.cs +++ b/Govor.Application/Interfaces/Messages/Parameters/SendMedia.cs @@ -2,4 +2,4 @@ using Govor.Core.Models; namespace Govor.Application.Interfaces.Messages.Parameters; -public record SendMedia(Guid MediaId, string EncryptedKey, MediaType Type, string MimeType); \ No newline at end of file +public record SendMedia(Guid MediaId, string EncryptedKey); \ No newline at end of file diff --git a/Govor.Application/Services/FriendsService.cs b/Govor.Application/Services/FriendsService.cs index e24dcd4..45b0de8 100644 --- a/Govor.Application/Services/FriendsService.cs +++ b/Govor.Application/Services/FriendsService.cs @@ -105,7 +105,8 @@ public class FriendsService : IFriendsService try { var friendships = await _friendshipsRepository.FindByUserIdAsync(userId); - return friendships.Where(f => f.AddresseeId == userId && f.Status == FriendshipStatus.Pending).ToList(); + return friendships.Where(f => f.AddresseeId == userId && f.Status == FriendshipStatus.Pending).ToList() + ?? new List(); } catch (NotFoundByKeyException ex) { diff --git a/Govor.Application/Services/MediaService.cs b/Govor.Application/Services/MediaService.cs new file mode 100644 index 0000000..178c364 --- /dev/null +++ b/Govor.Application/Services/MediaService.cs @@ -0,0 +1,29 @@ +using Govor.Application.Interfaces; +using Govor.Application.Interfaces.Medias; + +namespace Govor.Application.Services; + +public class MediaService : IMediaService +{ + private IStorageService _storageService; + + public MediaService(IStorageService storageService) + { + _storageService = storageService; + } + + public Task UploadMediaAsync(Media file) + { + throw new NotImplementedException(); + } + + public Task DeleteMediaAsync(Guid fileId) + { + throw new NotImplementedException(); + } + + public Task GetMediaAsync(string url) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/Govor.Application/Services/MessageService.cs b/Govor.Application/Services/MessageService.cs index d423fdb..cf4469e 100644 --- a/Govor.Application/Services/MessageService.cs +++ b/Govor.Application/Services/MessageService.cs @@ -38,10 +38,10 @@ public class MessageService : IMessageService // Validate recipient if (sendParams.RecipientType == RecipientType.User) { - if (!await _usersRepository.ExistsByIdAsync(sendParams.RecipientId)) // Changed to ExistsByIdAsync + if (!await _usersRepository.ExistsByIdAsync(sendParams.RecipientId)) { _logger.LogWarning("Attempt to send message to non-existent user {RecipientId}", sendParams.RecipientId); - return new SendMessageResult(false, new KeyNotFoundException($"Recipient user {sendParams.RecipientId} not found."), Guid.Empty); + return new SendMessageResult(false, new KeyNotFoundException($"Recipient user {sendParams.RecipientId} not found."), default); } // Verify friendship for private messages await _verifyFriendship.VerifyAsync(sendParams.FromUserId, sendParams.RecipientId); @@ -51,7 +51,7 @@ public class MessageService : IMessageService if (!_groupsRepository.Exists(sendParams.RecipientId)) { _logger.LogWarning("Attempt to send message to non-existent group {GroupId}", sendParams.RecipientId); - return new SendMessageResult(false, new KeyNotFoundException($"Recipient group {sendParams.RecipientId} not found."), Guid.Empty); + return new SendMessageResult(false, new KeyNotFoundException($"Recipient group {sendParams.RecipientId} not found."), default); } // TODO: Optionally, verify if sender is a member of the group // bool isMember = await _groupsRepository.IsUserMemberOfGroupAsync(sendParams.FromUserId, sendParams.RecipientId); @@ -64,7 +64,7 @@ public class MessageService : IMessageService else { _logger.LogError("Invalid recipient type specified: {RecipientType}", sendParams.RecipientType); - return new SendMessageResult(false, new ArgumentException("Invalid recipient type."), Guid.Empty); + return new SendMessageResult(false, new ArgumentException("Invalid recipient type."), default); } var messageId = Guid.NewGuid(); @@ -80,23 +80,20 @@ public class MessageService : IMessageService ReplyToMessageId = sendParams.ReplyToMessageId, MediaAttachments = sendParams.Media?.Select(m => new MediaAttachments { - Id = m.MediaId, // Assuming SendMedia provides Id or it's generated here/by repo + Id = Guid.NewGuid(), MessageId = messageId, - Type = m.Type, - MimeType = m.MimeType, - EncryptedKey = m.EncryptedKey, - // FilePath will be set by storage service or handled by repository if media ID is pre-generated + MediaFileId = m.MediaId }).ToList() ?? new List() }; await _messagesRepository.AddAsync(message); _logger.LogInformation("Message {MessageId} from {SenderId} to {RecipientId} ({RecipientType}) saved successfully.", messageId, sendParams.FromUserId, sendParams.RecipientId, sendParams.RecipientType); - return new SendMessageResult(true, null, messageId); + return new SendMessageResult(true, null, message); } catch (Exception ex) { _logger.LogError(ex, "Error sending message from {SenderId} to {RecipientId} ({RecipientType})", sendParams.FromUserId, sendParams.RecipientId, sendParams.RecipientType); - return new SendMessageResult(false, ex, Guid.Empty); + return new SendMessageResult(false, ex, default); } } @@ -133,12 +130,12 @@ public class MessageService : IMessageService await _messagesRepository.UpdateAsync(message); _logger.LogInformation("Message {MessageId} edited successfully by user {EditorId}", editParams.MessageId, editParams.EditorId); - return new EditMessageResult(true, null, originalMessageForNotification); + return new EditMessageResult(true, default, originalMessageForNotification); } catch (Exception ex) { _logger.LogError(ex, "Error editing message {MessageId} by user {EditorId}", editParams.MessageId, editParams.EditorId); - return new EditMessageResult(false, ex, null); + return new EditMessageResult(false, ex, default); } } @@ -159,7 +156,7 @@ public class MessageService : IMessageService // } // } else { _logger.LogWarning("User {DeleterId} attempted to delete message {MessageId} not sent by them (sender was {SenderId})", deleteParams.DeleterId, deleteParams.MessageId, message.SenderId); - return new DeleteMessageResult(false, new UnauthorizedAccessException("User is not authorized to delete this message."), null); + return new DeleteMessageResult(false, new UnauthorizedAccessException("User is not authorized to delete this message."), default); // } } @@ -174,12 +171,12 @@ public class MessageService : IMessageService await _messagesRepository.RemoveAsync(deleteParams.MessageId); _logger.LogInformation("Message {MessageId} deleted successfully by user {DeleterId}", deleteParams.MessageId, deleteParams.DeleterId); - return new DeleteMessageResult(true, null, originalMessageForNotification); + return new DeleteMessageResult(true, default, originalMessageForNotification); } catch (Exception ex) { _logger.LogError(ex, "Error deleting message {MessageId} by user {DeleterId}", deleteParams.MessageId, deleteParams.DeleterId); - return new DeleteMessageResult(false, ex, null); + return new DeleteMessageResult(false, ex, default); } } } \ No newline at end of file diff --git a/Govor.Contracts/Requests/SignalR/EditMessageRequest.cs b/Govor.Contracts/Requests/SignalR/EditMessageRequest.cs new file mode 100644 index 0000000..6d8fc70 --- /dev/null +++ b/Govor.Contracts/Requests/SignalR/EditMessageRequest.cs @@ -0,0 +1,7 @@ +namespace Govor.Contracts.Requests.SignalR; + +public class EditMessageRequest +{ + public Guid MessageId { get; set; } + public string NewEncryptedContent { get; set; } = string.Empty; +} \ No newline at end of file diff --git a/Govor.Contracts/Requests/SignalR/MediaReference.cs b/Govor.Contracts/Requests/SignalR/MediaReference.cs index f5faef9..d2b9a1b 100644 --- a/Govor.Contracts/Requests/SignalR/MediaReference.cs +++ b/Govor.Contracts/Requests/SignalR/MediaReference.cs @@ -6,6 +6,4 @@ public record MediaReference { public Guid MediaId { get; init; } public string EncryptedKey { get; init; } = string.Empty; - public MediaType Type { get; init; } - public string MimeType { get; init; } = string.Empty; } \ No newline at end of file diff --git a/Govor.Contracts/Requests/SignalR/RemoveMessageRequest.cs b/Govor.Contracts/Requests/SignalR/RemoveMessageRequest.cs new file mode 100644 index 0000000..4948b75 --- /dev/null +++ b/Govor.Contracts/Requests/SignalR/RemoveMessageRequest.cs @@ -0,0 +1,6 @@ +namespace Govor.Contracts.Requests.SignalR; + +public class RemoveMessageRequest +{ + public Guid MessageId { get; set; } +} \ No newline at end of file diff --git a/Govor.Contracts/Responses/SignalR/UserMessageResponse.cs b/Govor.Contracts/Responses/SignalR/UserMessageResponse.cs index 6380a05..20a33fd 100644 --- a/Govor.Contracts/Responses/SignalR/UserMessageResponse.cs +++ b/Govor.Contracts/Responses/SignalR/UserMessageResponse.cs @@ -13,5 +13,5 @@ public record UserMessageResponse public Guid? ReplyToMessageId { get; init; } public DateTime SentAt { get; init; } public bool IsEdited { get; init; } = false; - public List MediaAttachments { get; init; } = new List(); + public List MediaAttachments { get; init; } = new List(); } \ No newline at end of file diff --git a/Govor.Core/Infrastructure/Validators/MediaAttachmentsValidator.cs b/Govor.Core/Infrastructure/Validators/MediaAttachmentsValidator.cs index fc20e82..aa598f7 100644 --- a/Govor.Core/Infrastructure/Validators/MediaAttachmentsValidator.cs +++ b/Govor.Core/Infrastructure/Validators/MediaAttachmentsValidator.cs @@ -15,10 +15,8 @@ public class MediaAttachmentsValidator : IObjectValidator throw new ArgumentException("Id cannot be empty", nameof(attachments)); if(attachments.MessageId == Guid.Empty) throw new ArgumentException("MessageId cannot be empty", nameof(attachments)); - if(string.IsNullOrWhiteSpace(attachments.FilePath)) + if(string.IsNullOrWhiteSpace(attachments.MediaFile.Url)) throw new ArgumentException("File path cannot be empty", nameof(attachments)); - if(string.IsNullOrWhiteSpace(attachments.EncryptedKey)) - throw new ArgumentException("Encrypted key cannot be empty", nameof(attachments)); } catch (Exception ex) { diff --git a/Govor.Core/Models/MediaAttachments.cs b/Govor.Core/Models/MediaAttachments.cs index 43da672..947d458 100644 --- a/Govor.Core/Models/MediaAttachments.cs +++ b/Govor.Core/Models/MediaAttachments.cs @@ -4,22 +4,16 @@ public class MediaAttachments { public Guid Id { get; set; } public Guid MessageId { get; set; } - public MediaType Type { get; set; } - public string FilePath { get; set; } = string.Empty; // local path in filesystem - public string MimeType { get; set; } = string.Empty; - public string? EncryptedKey { get; set; } - public Message Message { get; set; } = null!; - + public Guid MediaFileId { get; set; } + public Message Message { get; set; } + public MediaFile MediaFile { get; set; } public override bool Equals(object? obj) { if (obj is not MediaAttachments other) return false; return Id == other.Id && MessageId == other.MessageId && - EncryptedKey == other.EncryptedKey && - Type == other.Type && - FilePath == other.FilePath && - MimeType == other.MimeType; + MediaFileId == other.MediaFileId; } } diff --git a/Govor.Core/Models/MediaFile.cs b/Govor.Core/Models/MediaFile.cs new file mode 100644 index 0000000..038f00f --- /dev/null +++ b/Govor.Core/Models/MediaFile.cs @@ -0,0 +1,10 @@ +namespace Govor.Core.Models; + +public class MediaFile +{ + public Guid Id { get; set; } + public string Url { get; set; } + public MediaType MediaType { get; set; } + public string MineType { get; set; } + public DateTime DateCreated { get; set; } +} \ No newline at end of file diff --git a/Govor.Core/Models/Message.cs b/Govor.Core/Models/Message.cs index b1bac31..6b72852 100644 --- a/Govor.Core/Models/Message.cs +++ b/Govor.Core/Models/Message.cs @@ -15,7 +15,6 @@ public class Message public List MessageViews { get; set; } = new List(); public Guid? ReplyToMessageId { get; set; } - public Message? ReplyToMessage { get; set; } // navigation public override bool Equals(object? obj) { diff --git a/Govor.Data/Configurations/MediaAttachmentsConfiguration.cs b/Govor.Data/Configurations/MediaAttachmentsConfiguration.cs index d9c6bc4..b0ad220 100644 --- a/Govor.Data/Configurations/MediaAttachmentsConfiguration.cs +++ b/Govor.Data/Configurations/MediaAttachmentsConfiguration.cs @@ -10,17 +10,14 @@ public class MediaAttachmentsConfiguration : IEntityTypeConfiguration ma.Id); - builder.Property(ma => ma.FilePath) - .IsRequired(); + builder.HasOne(ma => ma.Message) + .WithMany(m => m.MediaAttachments) + .HasForeignKey(ma => ma.MessageId) + .OnDelete(DeleteBehavior.Cascade); - builder.Property(ma => ma.MimeType) - .IsRequired(); - - builder.Property(ma => ma.EncryptedKey) - .HasMaxLength(512); // зависит от шифра - - builder.Property(ma => ma.Type) - .HasConversion() // enum as string (e.g., "Image") - .IsRequired(); + builder.HasOne(ma => ma.MediaFile) + .WithMany() + .HasForeignKey(ma => ma.MediaFileId) + .OnDelete(DeleteBehavior.Restrict); } } \ No newline at end of file diff --git a/Govor.Data/Configurations/MediaFileConfiguration.cs b/Govor.Data/Configurations/MediaFileConfiguration.cs new file mode 100644 index 0000000..452587f --- /dev/null +++ b/Govor.Data/Configurations/MediaFileConfiguration.cs @@ -0,0 +1,27 @@ +using Govor.Core.Models; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace Govor.Data.Configurations; + +public class MediaFileConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.HasKey(ma => ma.Id); + + builder.Property(mf => mf.Url) + .IsRequired(); + + builder.Property(mf => mf.MediaType) + .HasConversion() // enum as string (e.g., "Image") + .IsRequired(); + + builder.Property(ma => ma.MineType) + .HasMaxLength(128) + .IsRequired(); + + builder.Property(mf => mf.DateCreated) + .IsRequired(); + } +} \ No newline at end of file diff --git a/Govor.Data/Configurations/MessagesConfiguration.cs b/Govor.Data/Configurations/MessagesConfiguration.cs index 39f8adb..f1a973d 100644 --- a/Govor.Data/Configurations/MessagesConfiguration.cs +++ b/Govor.Data/Configurations/MessagesConfiguration.cs @@ -25,11 +25,6 @@ public class MessagesConfiguration : IEntityTypeConfiguration .HasForeignKey(mv => mv.MessageId) .OnDelete(DeleteBehavior.Cascade); - builder.HasOne(m => m.ReplyToMessage) - .WithMany() - .HasForeignKey(m => m.ReplyToMessageId) - .OnDelete(DeleteBehavior.Restrict); - builder.Property(m => m.EncryptedContent) .IsRequired(); } diff --git a/Govor.Data/GovorDbContext.cs b/Govor.Data/GovorDbContext.cs index dea43e1..c07d72a 100644 --- a/Govor.Data/GovorDbContext.cs +++ b/Govor.Data/GovorDbContext.cs @@ -18,6 +18,7 @@ public class GovorDbContext(DbContextOptions options) : DbContex public virtual DbSet MessageViews { get; set; } public virtual DbSet MessageReactions { get; set; } public virtual DbSet MediaAttachments { get; set; } + public virtual DbSet MediaFiles { get; set; } public virtual DbSet ChatGroups { get; set; } public virtual DbSet GroupMemberships { get; set; } @@ -33,6 +34,7 @@ public class GovorDbContext(DbContextOptions options) : DbContex modelBuilder.ApplyConfiguration(new MessageReactionConfiguration()); modelBuilder.ApplyConfiguration(new MediaAttachmentsConfiguration()); modelBuilder.ApplyConfiguration(new MessageViewConfiguration()); + modelBuilder.ApplyConfiguration(new MediaFileConfiguration()); base.OnModelCreating(modelBuilder); } diff --git a/Govor.Data/Repositories/MediaAttachmentsRepository.cs b/Govor.Data/Repositories/MediaAttachmentsRepository.cs index 391c18c..e60a3b4 100644 --- a/Govor.Data/Repositories/MediaAttachmentsRepository.cs +++ b/Govor.Data/Repositories/MediaAttachmentsRepository.cs @@ -77,9 +77,7 @@ public class MediaAttachmentsRepository : IMediaAttachmentsRepository .ExecuteUpdateAsync(u => u .SetProperty(m => m.MessageId, attachments.MessageId) .SetProperty(m => m.Message, attachments.Message) - .SetProperty(m => m.FilePath, attachments.FilePath) - .SetProperty(m => m.MimeType, attachments.MimeType) - .SetProperty(m => m.EncryptedKey, attachments.EncryptedKey) + .SetProperty(m => m.MediaFileId, attachments.MediaFileId) ); if (rowsAffected == 0) @@ -121,11 +119,8 @@ public class MediaAttachmentsRepository : IMediaAttachmentsRepository return _context.MediaAttachments.Any( e => e.Id == attachments.Id && - e.EncryptedKey == attachments.EncryptedKey && - e.MimeType == attachments.MimeType && - e.FilePath == attachments.FilePath && e.MessageId == attachments.MessageId && - e.Type == attachments.Type + e.MediaFileId == attachments.MediaFileId ); } } \ No newline at end of file diff --git a/Govor.Data/Repositories/MessagesRepository.cs b/Govor.Data/Repositories/MessagesRepository.cs index 2ef4755..a6c0a16 100644 --- a/Govor.Data/Repositories/MessagesRepository.cs +++ b/Govor.Data/Repositories/MessagesRepository.cs @@ -21,7 +21,8 @@ public class MessagesRepository : IMessagesRepository { return await _context.Messages .AsNoTracking() - .Include(m => m.ReplyToMessage) + .Include(m => m.MediaAttachments) + .ThenInclude(m => m.MediaFile) .AsSplitQuery() .ToListOrThrowIfEmpty(new NotFoundException("No messages found in the database")); } @@ -30,7 +31,6 @@ public class MessagesRepository : IMessagesRepository { return await _context.Messages .AsNoTracking() - .Include(m => m.ReplyToMessage) .AsSplitQuery() .FirstOrDefaultAsync(m => m.Id == messageId) ?? throw new NotFoundByKeyException(messageId, "Message with given id does not exist"); @@ -40,7 +40,8 @@ public class MessagesRepository : IMessagesRepository { return await _context.Messages .AsNoTracking() - .Include(m => m.ReplyToMessage) + .Include(m => m.MediaAttachments) + .ThenInclude(m => m.MediaFile) .AsSplitQuery() .Where(m => m.SenderId == senderId) .ToListOrThrowIfEmpty(new NotFoundByKeyException(senderId, "Messages with given sender id do not exist")); @@ -50,7 +51,8 @@ public class MessagesRepository : IMessagesRepository { return await _context.Messages .AsNoTracking() - .Include(m => m.ReplyToMessage) + .Include(m => m.MediaAttachments) + .ThenInclude(m => m.MediaFile) .AsSplitQuery() .Where(m => m.RecipientId == receiverId) .ToListOrThrowIfEmpty(new NotFoundByKeyException(receiverId, "Messages with given recipient id do not exist")); @@ -60,7 +62,8 @@ public class MessagesRepository : IMessagesRepository { return await _context.Messages .AsNoTracking() - .Include(m => m.ReplyToMessage) + .Include(m => m.MediaAttachments) + .ThenInclude(m => m.MediaFile) .AsSplitQuery() .Where(m => m.SenderId == senderId && m.RecipientId == receiverId @@ -72,7 +75,8 @@ public class MessagesRepository : IMessagesRepository { return await _context.Messages .AsNoTracking() - .Include(m => m.ReplyToMessage) + .Include(m => m.MediaAttachments) + .ThenInclude(m => m.MediaFile) .AsSplitQuery() .Where(m => m.SentAt == date) .ToListOrThrowIfEmpty(new NotFoundByKeyException(date, "Messages sent at date do not exist")); @@ -161,7 +165,7 @@ public class MessagesRepository : IMessagesRepository m.EditedAt == message.EditedAt && m.IsEdited == message.IsEdited && m.SentAt == message.SentAt && - m.ReplyToMessageId == message.ReplyToMessageId + m.ReplyToMessageId == message.ReplyToMessageId ); }