new app server and database + added hub and controller of user profile

This commit is contained in:
Artemy
2025-11-04 11:41:06 +07:00
parent 1d442d037c
commit a5a5fc4758
62 changed files with 1760 additions and 2543 deletions
@@ -31,7 +31,7 @@ public class AccesserToDownloadMediaServiceTests
_groupId = Guid.NewGuid();
_mediaFileId = Guid.NewGuid();
// Seed message from user to other user
// Áàçîâîå ñîîáùåíèå è ìåäèà
var message = new Message
{
Id = Guid.NewGuid(),
@@ -40,7 +40,6 @@ public class AccesserToDownloadMediaServiceTests
RecipientType = RecipientType.User
};
var media = new MediaFile
{
Id = _mediaFileId,
@@ -48,7 +47,9 @@ public class AccesserToDownloadMediaServiceTests
MineType = "image/png",
MediaType = MediaType.Image,
UploaderId = _userId,
DateCreated = DateTime.UtcNow
DateCreated = DateTime.UtcNow,
OwnerType = MediaOwnerType.Message,
OwnerId = message.Id
};
var attachment = new MediaAttachments
@@ -108,7 +109,9 @@ public class AccesserToDownloadMediaServiceTests
MineType = "image/png",
MediaType = MediaType.Image,
UploaderId = _userId,
DateCreated = DateTime.UtcNow
DateCreated = DateTime.UtcNow,
OwnerType = MediaOwnerType.Message,
OwnerId = groupMessage.Id
};
var attachment = new MediaAttachments
@@ -144,9 +147,148 @@ public class AccesserToDownloadMediaServiceTests
Assert.That(result, Is.False);
}
[Test]
public async Task HasAccessAsync_ReturnsTrue_ForUserAvatar()
{
var avatarMedia = new MediaFile
{
Id = Guid.NewGuid(),
Url = "/media/avatar.png",
MineType = "image/png",
MediaType = MediaType.Image,
UploaderId = _userId,
OwnerType = MediaOwnerType.Avatar,
OwnerId = _userId,
DateCreated = DateTime.UtcNow
};
await _dbContext.MediaFiles.AddAsync(avatarMedia);
await _dbContext.SaveChangesAsync();
var result = await _accesser.HasAccessAsync(avatarMedia.Id, _userId);
Assert.That(result, Is.True);
}
[Test]
public async Task HasAccessAsync_ReturnsFalse_ForOtherUserAvatar()
{
var avatarMedia = new MediaFile
{
Id = Guid.NewGuid(),
Url = "/media/avatar2.png",
MineType = "image/png",
MediaType = MediaType.Image,
UploaderId = _otherUserId,
OwnerType = MediaOwnerType.Avatar,
OwnerId = _otherUserId,
DateCreated = DateTime.UtcNow
};
await _dbContext.MediaFiles.AddAsync(avatarMedia);
await _dbContext.SaveChangesAsync();
var result = await _accesser.HasAccessAsync(avatarMedia.Id, _userId);
Assert.That(result, Is.False);
}
[Test]
public async Task HasAccessAsync_ReturnsTrue_ForGroupAvatarMember()
{
var groupAvatar = new MediaFile
{
Id = Guid.NewGuid(),
Url = "/media/group_avatar.png",
MineType = "image/png",
MediaType = MediaType.Image,
UploaderId = _userId,
OwnerType = MediaOwnerType.GroupAvatar,
OwnerId = _groupId,
DateCreated = DateTime.UtcNow
};
var membership = new GroupMembership
{
Id = Guid.NewGuid(),
GroupId = _groupId,
UserId = _otherUserId
};
await _dbContext.MediaFiles.AddAsync(groupAvatar);
await _dbContext.GroupMemberships.AddAsync(membership);
await _dbContext.SaveChangesAsync();
var result = await _accesser.HasAccessAsync(groupAvatar.Id, _otherUserId);
Assert.That(result, Is.True);
}
[Test]
public async Task HasAccessAsync_ReturnsFalse_ForGroupAvatarNonMember()
{
var groupAvatar = new MediaFile
{
Id = Guid.NewGuid(),
Url = "/media/group_avatar2.png",
MineType = "image/png",
MediaType = MediaType.Image,
UploaderId = _userId,
OwnerType = MediaOwnerType.GroupAvatar,
OwnerId = _groupId,
DateCreated = DateTime.UtcNow
};
await _dbContext.MediaFiles.AddAsync(groupAvatar);
await _dbContext.SaveChangesAsync();
var unrelatedUserId = Guid.NewGuid();
var result = await _accesser.HasAccessAsync(groupAvatar.Id, unrelatedUserId);
Assert.That(result, Is.False);
}
[Test]
public async Task HasAccessAsync_ReturnsTrue_ForSystemMedia()
{
var systemMedia = new MediaFile
{
Id = Guid.NewGuid(),
Url = "/media/system.png",
MineType = "image/png",
MediaType = MediaType.Image,
UploaderId = _userId,
OwnerType = MediaOwnerType.System,
DateCreated = DateTime.UtcNow
};
await _dbContext.MediaFiles.AddAsync(systemMedia);
await _dbContext.SaveChangesAsync();
var result = await _accesser.HasAccessAsync(systemMedia.Id, Guid.NewGuid());
Assert.That(result, Is.True);
}
[Test]
public async Task HasAccessAsync_ReturnsFalse_ForUnknownOwnerType()
{
var unknownMedia = new MediaFile
{
Id = Guid.NewGuid(),
Url = "/media/unknown.png",
MineType = "image/png",
MediaType = MediaType.Image,
UploaderId = _userId,
OwnerType = (MediaOwnerType)999, // íåèçâåñòíûé òèï
DateCreated = DateTime.UtcNow
};
await _dbContext.MediaFiles.AddAsync(unknownMedia);
await _dbContext.SaveChangesAsync();
var result = await _accesser.HasAccessAsync(unknownMedia.Id, _userId);
Assert.That(result, Is.False);
}
[TearDown]
public void TearDown()
{
_dbContext.Dispose();
}
}
}
@@ -1,5 +1,6 @@
using Govor.Application.Exceptions.VerifyFriendship;
using Govor.Application.Exceptions.VerifyFriendship;
using Govor.Application.Interfaces;
using Govor.Application.Interfaces.Medias;
using Govor.Application.Interfaces.Messages.Parameters;
using Govor.Application.Services.Messages;
using Govor.Core.Models;
@@ -22,6 +23,7 @@ public class MessageCommandServiceTests
private Mock<IGroupsRepository> _mockGroupsRepo;
private Mock<IVerifyFriendship> _mockVerifyFriendship;
private Mock<IPrivateChatsRepository> _mockPrivateChats;
private Mock<IMediaService> _mockMediaService;
private Mock<ILogger<MessageCommandService>> _mockLogger;
private MessageCommandService _messageService;
@@ -33,6 +35,7 @@ public class MessageCommandServiceTests
_mockGroupsRepo = new Mock<IGroupsRepository>();
_mockVerifyFriendship = new Mock<IVerifyFriendship>();
_mockPrivateChats = new Mock<IPrivateChatsRepository>();
_mockMediaService = new Mock<IMediaService>();
_mockLogger = new Mock<ILogger<MessageCommandService>>();
_messageService = new MessageCommandService(
@@ -41,6 +44,7 @@ public class MessageCommandServiceTests
_mockGroupsRepo.Object,
_mockVerifyFriendship.Object,
_mockPrivateChats.Object,
_mockMediaService.Object,
_mockLogger.Object);
}
@@ -52,7 +56,6 @@ public class MessageCommandServiceTests
// Arrange
var senderId = Guid.NewGuid();
var recipientId = Guid.NewGuid();
var sendMessageParams = new SendMessage("Hello",
null,
recipientId,
@@ -66,6 +69,7 @@ public class MessageCommandServiceTests
_mockMessagesRepo.Setup(r => r.AddAsync(It.IsAny<Message>())).Returns(Task.CompletedTask);
_mockPrivateChats.Setup(c => c.Exist(senderId, recipientId)).Returns(true);
_mockPrivateChats.Setup(c => c.GetByMembersAsync(senderId, recipientId)).ReturnsAsync(new PrivateChat(){Id = recipientId});
// Act
var result = await _messageService.SendMessageAsync(sendMessageParams);
// Assert
@@ -79,7 +83,53 @@ public class MessageCommandServiceTests
m.RecipientType == RecipientType.User &&
m.EncryptedContent == "Hello")), Times.Once);
}
[Test]
public async Task SendMessageAsync_ToUser_When_AttachMediaThrowsException_ReturnsFailure()
{
// Arrange
var senderId = Guid.NewGuid();
var recipientId = Guid.NewGuid();
var sendMediaId = Guid.NewGuid();
var sendMessageParams = new SendMessage(
"Hello",
null,
recipientId,
RecipientType.User,
senderId,
DateTime.UtcNow,
new List<SendMedia> { new SendMedia(sendMediaId, string.Empty) });
_mockUsersRepo.Setup(r => r.ExistsByIdAsync(recipientId)).ReturnsAsync(true);
_mockVerifyFriendship.Setup(v => v.VerifyAsync(senderId, recipientId)).Returns(Task.CompletedTask);
_mockMessagesRepo.Setup(r => r.AddAsync(It.IsAny<Message>())).Returns(Task.CompletedTask);
_mockPrivateChats.Setup(c => c.Exist(senderId, recipientId)).Returns(true);
_mockPrivateChats.Setup(c => c.GetByMembersAsync(senderId, recipientId))
.ReturnsAsync(new PrivateChat { Id = recipientId });
// !
_mockMediaService
.Setup(m => m.AttachToMessageAsync(sendMediaId, It.IsAny<Guid>()))
.ThrowsAsync(new Exception("Unexpected DB error"));
// Act
var result = await _messageService.SendMessageAsync(sendMessageParams);
// Assert
Assert.That(result, Is.Not.Null);
Assert.That(result.IsSuccess, Is.False);
Assert.That(result.Exception, Is.Not.Null);
Assert.That(result.Exception.Message, Is.EqualTo("Unexpected DB error"));
// Проверяем, что сообщение не было сохранено
_mockMessagesRepo.Verify(r => r.AddAsync(It.IsAny<Message>()), Times.Never);
// Проверяем, что метод прикрепления медиа вызывался
_mockMediaService.Verify(m => m.AttachToMessageAsync(sendMediaId, It.IsAny<Guid>()), Times.Once);
}
[Test]
public async Task SendMessageAsync_ToGroup_Success()
{
@@ -0,0 +1,131 @@
using Govor.Application.Services;
using Govor.Core.Models.Users;
using Govor.Core.Repositories.Users;
using Microsoft.Extensions.Logging;
using Moq;
namespace Govor.Application.Tests.Services;
[TestFixture]
public class ProfileServiceTests
{
private Mock<IUsersRepository> _mockUsersRepo = null!;
private Mock<ILogger<ProfileService>> _mockLogger = null!;
private ProfileService _service = null!;
private User _testUser = null!;
[SetUp]
public void SetUp()
{
_mockUsersRepo = new Mock<IUsersRepository>();
_mockLogger = new Mock<ILogger<ProfileService>>();
_service = new ProfileService(_mockUsersRepo.Object, _mockLogger.Object);
_testUser = new User
{
Id = Guid.NewGuid(),
Username = "testuser",
Description = "old description",
IconId = Guid.NewGuid()
};
}
// ---------- GetUserProfileAsync ----------
[Test]
public async Task GetUserProfileAsync_ReturnsCorrectData()
{
// Arrange
_mockUsersRepo.Setup(r => r.FindByIdAsync(_testUser.Id))
.ReturnsAsync(_testUser);
// Act
var result = await _service.GetUserProfileAsync(_testUser.Id);
// Assert
Assert.That(result, Is.Not.Null);
Assert.That(result.Id, Is.EqualTo(_testUser.Id));
Assert.That(result.Username, Is.EqualTo("testuser"));
Assert.That(result.Description, Is.EqualTo("old description"));
Assert.That(result.IconId, Is.EqualTo(_testUser.IconId));
_mockUsersRepo.Verify(r => r.FindByIdAsync(_testUser.Id), Times.Once);
}
[Test]
public void GetUserProfileAsync_Throws_WhenUserNotFound()
{
// Arrange
_mockUsersRepo.Setup(r => r.FindByIdAsync(It.IsAny<Guid>()))
.ReturnsAsync((User)null!);
// Act + Assert
Assert.ThrowsAsync<NullReferenceException>(() =>
_service.GetUserProfileAsync(Guid.NewGuid()));
}
// ---------- SetDescription ----------
[Test]
public async Task SetDescription_UpdatesUserDescription()
{
// Arrange
var newDescription = "new cool description";
_mockUsersRepo.Setup(r => r.FindByIdAsync(_testUser.Id))
.ReturnsAsync(_testUser);
_mockUsersRepo.Setup(r => r.UpdateAsync(It.IsAny<User>()))
.Returns(Task.CompletedTask);
// Act
await _service.SetDescription(newDescription, _testUser.Id);
// Assert
Assert.That(_testUser.Description, Is.EqualTo(newDescription));
_mockUsersRepo.Verify(r => r.UpdateAsync(It.Is<User>(u => u.Description == newDescription)), Times.Once);
}
[Test]
public void SetDescription_Throws_WhenUserNotFound()
{
// Arrange
_mockUsersRepo.Setup(r => r.FindByIdAsync(It.IsAny<Guid>()))
.ReturnsAsync((User)null!);
// Act + Assert
Assert.ThrowsAsync<NullReferenceException>(() =>
_service.SetDescription("desc", Guid.NewGuid()));
}
// ---------- SetNewIcon ----------
[Test]
public async Task SetNewIcon_UpdatesUserIconId()
{
// Arrange
var newIconId = Guid.NewGuid();
_mockUsersRepo.Setup(r => r.FindByIdAsync(_testUser.Id))
.ReturnsAsync(_testUser);
_mockUsersRepo.Setup(r => r.UpdateAsync(It.IsAny<User>()))
.Returns(Task.CompletedTask);
// Act
await _service.SetNewIcon(_testUser.Id, newIconId);
// Assert
Assert.That(_testUser.IconId, Is.EqualTo(newIconId));
_mockUsersRepo.Verify(r => r.UpdateAsync(It.Is<User>(u => u.IconId == newIconId)), Times.Once);
}
[Test]
public void SetNewIcon_Throws_WhenUserNotFound()
{
// Arrange
_mockUsersRepo.Setup(r => r.FindByIdAsync(It.IsAny<Guid>()))
.ReturnsAsync((User)null!);
// Act + Assert
Assert.ThrowsAsync<NullReferenceException>(() =>
_service.SetNewIcon(Guid.NewGuid(), Guid.NewGuid()));
}
}
@@ -23,7 +23,12 @@ public class UserSessionReaderTests
public void SetUp()
{
_fixture = new Fixture();
_fixture.Behaviors.OfType<ThrowingRecursionBehavior>()
.ToList()
.ForEach(b => _fixture.Behaviors.Remove(b));
_fixture.Behaviors.Add(new OmitOnRecursionBehavior());
_mockUserSessionsRepository = new Mock<IUserSessionsRepository>();
_mockLogger = new Mock<ILogger<UserSessionReader>>();