diff --git a/src/Api/Controllers/Payload/Requests/Users/UpdateUserRequest.cs b/src/Api/Controllers/Payload/Requests/Users/UpdateUserRequest.cs index d162c28a..c30e9871 100644 --- a/src/Api/Controllers/Payload/Requests/Users/UpdateUserRequest.cs +++ b/src/Api/Controllers/Payload/Requests/Users/UpdateUserRequest.cs @@ -14,10 +14,6 @@ public class UpdateUserRequest /// public string? LastName { get; set; } /// - /// New role of the user to be updated - /// - public string Role { get; set; } = null!; - /// /// New position of the user to be updated /// public string? Position { get; set; } diff --git a/src/Api/Controllers/UsersController.cs b/src/Api/Controllers/UsersController.cs index dc2b406e..cc0c4ccc 100644 --- a/src/Api/Controllers/UsersController.cs +++ b/src/Api/Controllers/UsersController.cs @@ -141,7 +141,6 @@ public async Task>> Update([FromRoute] Guid userId, UserId = userId, FirstName = request.FirstName, LastName = request.LastName, - Role = request.Role, Position = request.Position, }; var result = await Mediator.Send(command); diff --git a/src/Application/Users/Commands/UpdateUser.cs b/src/Application/Users/Commands/UpdateUser.cs index 4d894cc0..00b27531 100644 --- a/src/Application/Users/Commands/UpdateUser.cs +++ b/src/Application/Users/Commands/UpdateUser.cs @@ -1,16 +1,66 @@ +using Application.Common.Interfaces; using Application.Users.Queries; +using AutoMapper; +using FluentValidation; using MediatR; +using Microsoft.EntityFrameworkCore; namespace Application.Users.Commands; public class UpdateUser { + public class Validator : AbstractValidator + { + public Validator() + { + RuleLevelCascadeMode = CascadeMode.Stop; + + RuleFor(x => x.FirstName) + .MaximumLength(50).WithMessage("FirstName can not exceed 50 characters."); + + RuleFor(x => x.LastName) + .MaximumLength(50).WithMessage("LastName can not exceed 50 characters."); + + RuleFor(x => x.Position) + .MaximumLength(64).WithMessage("Position can not exceed 64 characters."); + } + } public record Command : IRequest { public Guid UserId { get; init; } public string? FirstName { get; init; } public string? LastName { get; init; } - public string Role { get; init; } = null!; public string? Position { get; init; } } + + public class CommandHandler : IRequestHandler + { + private readonly IApplicationDbContext _context; + private readonly IMapper _mapper; + + public CommandHandler(IApplicationDbContext context, IMapper mapper) + { + _context = context; + _mapper = mapper; + } + + public async Task Handle(Command request, CancellationToken cancellationToken) + { + var user = await _context.Users + .FirstOrDefaultAsync(x => x.Id.Equals(request.UserId), cancellationToken: cancellationToken); + + if (user is null) + { + throw new KeyNotFoundException("User does not exist."); + } + + user.FirstName = request.FirstName; + user.LastName = request.LastName; + user.Position = request.Position; + + var result = _context.Users.Update(user); + await _context.SaveChangesAsync(cancellationToken); + return _mapper.Map(result.Entity); + } + } } \ No newline at end of file diff --git a/tests/Application.Tests.Integration/Users/Commands/UpdateUserTests.cs b/tests/Application.Tests.Integration/Users/Commands/UpdateUserTests.cs new file mode 100644 index 00000000..3214a6bd --- /dev/null +++ b/tests/Application.Tests.Integration/Users/Commands/UpdateUserTests.cs @@ -0,0 +1,60 @@ +using Application.Identity; +using Application.Users.Commands; +using FluentAssertions; +using Xunit; + +namespace Application.Tests.Integration.Users.Commands; + +public class UpdateUserTests : BaseClassFixture +{ + public UpdateUserTests(CustomApiFactory apiFactory) : base(apiFactory) + { + } + + [Fact] + public async Task ShouldUpdateUser_WhenUpdateDetailsAreValid() + { + // Arrange + var user = CreateUser(IdentityData.Roles.Employee, "randompassword"); + await AddAsync(user); + + var command = new UpdateUser.Command() + { + UserId = user.Id, + FirstName = "khoa", + LastName = "ngu", + Position = "IDK", + }; + + // Act + var result = await SendAsync(command); + + // Assert + result.FirstName.Should().Be(command.FirstName); + result.LastName.Should().Be(command.LastName); + result.Position.Should().Be(command.Position); + + // Cleanup + Remove(user); + } + + [Fact] + public async Task ShouldThrowKeyNotFoundException_WhenThatUserDoesNotExist() + { + // Arrange + var command = new UpdateUser.Command() + { + UserId = Guid.NewGuid(), + FirstName = "khoa", + LastName = "ngu", + Position = "IDK", + }; + + // Act + var action = async () => await SendAsync(command); + + // Assert + await action.Should().ThrowAsync() + .WithMessage("User does not exist."); + } +} \ No newline at end of file