0
0
mirror of https://github.com/alex289/CleanArchitecture.git synced 2025-06-30 02:31:08 +00:00

feat: Check for tenant when updating users tenant

This commit is contained in:
alex289 2023-08-31 11:46:01 +02:00
parent 61bcab6d77
commit 3969db2bba
No known key found for this signature in database
GPG Key ID: 573F77CD2D87F863
9 changed files with 126 additions and 13 deletions

View File

@ -17,7 +17,7 @@ public sealed class CreateTenantCommandHandlerTests
Guid.NewGuid(),
"Test Tenant");
_fixture.CommandHandler.Handle(command, default!).Wait();
_fixture.CommandHandler.Handle(command, default).Wait();
_fixture
.VerifyNoDomainNotification()
@ -36,7 +36,7 @@ public sealed class CreateTenantCommandHandlerTests
Guid.NewGuid(),
"Test Tenant");
_fixture.CommandHandler.Handle(command, default!).Wait();
_fixture.CommandHandler.Handle(command, default).Wait();
_fixture
.VerifyNoCommit()
@ -56,7 +56,7 @@ public sealed class CreateTenantCommandHandlerTests
_fixture.SetupExistingTenant(command.AggregateId);
_fixture.CommandHandler.Handle(command, default!).Wait();
_fixture.CommandHandler.Handle(command, default).Wait();
_fixture
.VerifyNoCommit()

View File

@ -42,4 +42,23 @@ public sealed class DeleteTenantCommandHandlerTests
ErrorCodes.ObjectNotFound,
$"There is no tenant with Id {command.AggregateId}");
}
[Fact]
public void Should_Not_Delete_Tenant_Insufficient_Permissions()
{
var tenant = _fixture.SetupTenant();
_fixture.SetupUser();
var command = new DeleteTenantCommand(tenant.Id);
_fixture.CommandHandler.Handle(command, default).Wait();
_fixture
.VerifyNoCommit()
.VerifyNoRaisedEvent<TenantDeletedEvent>()
.VerifyAnyDomainNotification()
.VerifyExistingNotification(
ErrorCodes.InsufficientPermissions,
$"No permission to delete tenant {command.AggregateId}");
}
}

View File

@ -1,5 +1,6 @@
using System;
using CleanArchitecture.Domain.Commands.Tenants.DeleteTenant;
using CleanArchitecture.Domain.Enums;
using CleanArchitecture.Domain.Interfaces.Repositories;
using NSubstitute;
@ -36,4 +37,9 @@ public sealed class DeleteTenantCommandTestFixture : CommandHandlerFixtureBase
return tenant;
}
public void SetupUser()
{
User.GetUserRole().Returns(UserRole.User);
}
}

View File

@ -19,7 +19,7 @@ public sealed class UpdateTenantCommandHandlerTests
_fixture.SetupExistingTenant(command.AggregateId);
_fixture.CommandHandler.Handle(command, default!).Wait();
_fixture.CommandHandler.Handle(command, default).Wait();
_fixture
.VerifyCommit()
@ -38,7 +38,7 @@ public sealed class UpdateTenantCommandHandlerTests
_fixture.SetupUser();
_fixture.CommandHandler.Handle(command, default!).Wait();
_fixture.CommandHandler.Handle(command, default).Wait();
_fixture
.VerifyNoCommit()
@ -56,7 +56,7 @@ public sealed class UpdateTenantCommandHandlerTests
Guid.NewGuid(),
"Tenant Name");
_fixture.CommandHandler.Handle(command, default!).Wait();
_fixture.CommandHandler.Handle(command, default).Wait();
_fixture
.VerifyNoCommit()

View File

@ -26,6 +26,8 @@ public sealed class UpdateUserCommandHandlerTests
UserRole.User,
Guid.NewGuid());
_fixture.SetupTenant(command.TenantId);
await _fixture.CommandHandler.Handle(command, default);
_fixture
@ -46,6 +48,8 @@ public sealed class UpdateUserCommandHandlerTests
"Email",
UserRole.User,
Guid.NewGuid());
_fixture.SetupTenant(command.TenantId);
await _fixture.CommandHandler.Handle(command, default);
@ -70,6 +74,8 @@ public sealed class UpdateUserCommandHandlerTests
"Email",
UserRole.User,
Guid.NewGuid());
_fixture.SetupTenant(command.TenantId);
_fixture.UserRepository
.GetByEmailAsync(command.Email)
@ -92,4 +98,59 @@ public sealed class UpdateUserCommandHandlerTests
DomainErrorCodes.User.UserAlreadyExists,
$"There is already a user with email {command.Email}");
}
[Fact]
public async Task Should_Not_Update_Non_Existing_Tenant()
{
var user = _fixture.SetupUser();
var command = new UpdateUserCommand(
user.Id,
"test@email.com",
"Test",
"Email",
UserRole.User,
Guid.NewGuid());
await _fixture.CommandHandler.Handle(command, default);
_fixture
.VerifyNoCommit()
.VerifyNoRaisedEvent<UserUpdatedEvent>()
.VerifyAnyDomainNotification()
.VerifyExistingNotification(
ErrorCodes.ObjectNotFound,
$"There is no tenant with Id {command.TenantId}");
}
[Fact]
public async Task Should_Not_Update_Admin_Properties()
{
var user = _fixture.SetupUser();
_fixture.SetupCurrentUser(user.Id);
var command = new UpdateUserCommand(
user.Id,
"test@email.com",
"Test",
"Email",
UserRole.Admin,
Guid.NewGuid());
_fixture.SetupTenant(command.TenantId);
await _fixture.CommandHandler.Handle(command, default);
_fixture.UserRepository.Received(1).Update(Arg.Is<Entities.User>(u =>
u.TenantId == user.TenantId &&
u.Role == user.Role &&
u.Id == command.UserId &&
u.Email == command.Email &&
u.FirstName == command.FirstName));
_fixture
.VerifyNoDomainNotification()
.VerifyCommit()
.VerifyRaisedEvent<UserUpdatedEvent>(x => x.AggregateId == command.UserId);
}
}

View File

@ -11,17 +11,20 @@ public sealed class UpdateUserCommandTestFixture : CommandHandlerFixtureBase
public UpdateUserCommandTestFixture()
{
UserRepository = Substitute.For<IUserRepository>();
TenantRepository = Substitute.For<ITenantRepository>();
CommandHandler = new UpdateUserCommandHandler(
Bus,
UnitOfWork,
NotificationHandler,
UserRepository,
User);
User,
TenantRepository);
}
public UpdateUserCommandHandler CommandHandler { get; }
public IUserRepository UserRepository { get; }
private ITenantRepository TenantRepository { get; }
public Entities.User SetupUser()
{
@ -40,4 +43,21 @@ public sealed class UpdateUserCommandTestFixture : CommandHandlerFixtureBase
return user;
}
public Entities.Tenant SetupTenant(Guid tenantId)
{
var tenant = new Entities.Tenant(tenantId, "Name");
TenantRepository
.ExistsAsync(Arg.Is<Guid>(y => y == tenant.Id))
.Returns(true);
return tenant;
}
public void SetupCurrentUser(Guid userId)
{
User.GetUserId().Returns(userId);
User.GetUserRole().Returns(UserRole.User);
}
}

View File

@ -38,8 +38,6 @@ public sealed class DeleteTenantCommandHandler : CommandHandlerBase,
return;
}
// Todo: Test following
if (_user.GetUserRole() != UserRole.Admin)
{
await NotifyAsync(

View File

@ -15,16 +15,19 @@ public sealed class UpdateUserCommandHandler : CommandHandlerBase,
{
private readonly IUser _user;
private readonly IUserRepository _userRepository;
private readonly ITenantRepository _tenantRepository;
public UpdateUserCommandHandler(
IMediatorHandler bus,
IUnitOfWork unitOfWork,
INotificationHandler<DomainNotification> notifications,
IUserRepository userRepository,
IUser user) : base(bus, unitOfWork, notifications)
IUser user,
ITenantRepository tenantRepository) : base(bus, unitOfWork, notifications)
{
_userRepository = userRepository;
_user = user;
_tenantRepository = tenantRepository;
}
public async Task Handle(UpdateUserCommand request, CancellationToken cancellationToken)
@ -76,8 +79,15 @@ public sealed class UpdateUserCommandHandler : CommandHandlerBase,
{
user.SetRole(request.Role);
// Todo: Test
// Todo: Check if tenant exists first
if (!await _tenantRepository.ExistsAsync(request.TenantId))
{
await NotifyAsync(
new DomainNotification(
request.MessageType,
$"There is no tenant with Id {request.TenantId}",
ErrorCodes.ObjectNotFound));
return;
}
user.SetTenant(request.TenantId);
}

View File

@ -40,7 +40,6 @@ public sealed class GetUsersByIdsTests : IClassFixture<UserTestFixture>
ids.Add(nonExistingId);
// Todo: Use default instead of null everywhere
var result = await _fixture.UsersApiImplementation.GetByIds(
SetupRequest(ids),
default!);