mirror of
https://github.com/aaronpo97/the-biergarten-app.git
synced 2026-07-16 17:47:22 +00:00
Migrate UserManagement to a vertical slice (Features.UserManagement)
Same pattern as the Breweries migration: Service.UserManagement and the UserAccount repository fold into Features.UserManagement, with MediatR queries replacing UserService. UpdateUserCommand/Handler carry forward IUserService.UpdateAsync as-is (it has no HTTP route today, and adding one is a separate decision from this migration). Adds handler/repository test coverage that didn't exist before, since Service.UserManagement had no test project.
This commit is contained in:
@@ -33,8 +33,8 @@
|
||||
<ProjectReference Include="..\..\Infrastructure\Infrastructure.Sql\Infrastructure.Sql.csproj" />
|
||||
<ProjectReference Include="..\..\Infrastructure\Infrastructure.Jwt\Infrastructure.Jwt.csproj" />
|
||||
<ProjectReference Include="..\..\Service\Service.Auth\Service.Auth.csproj" />
|
||||
<ProjectReference Include="..\..\Service\Service.UserManagement\Service.UserManagement.csproj" />
|
||||
<ProjectReference Include="..\..\Features\Features.Breweries\Features.Breweries.csproj" />
|
||||
<ProjectReference Include="..\..\Features\Features.UserManagement\Features.UserManagement.csproj" />
|
||||
<ProjectReference Include="..\..\Shared\Shared.Contracts\Shared.Contracts.csproj" />
|
||||
<ProjectReference Include="..\..\Shared\Shared.Application\Shared.Application.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
using Domain.Entities;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Service.UserManagement.User;
|
||||
|
||||
namespace API.Core.Controllers
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides read-only endpoints for retrieving user accounts.
|
||||
/// </summary>
|
||||
/// <param name="userService">Service used to query user account data.</param>
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
public class UserController(IUserService userService) : ControllerBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Retrieves a paginated list of user accounts.
|
||||
/// </summary>
|
||||
/// <param name="limit">The maximum number of user accounts to return, or <c>null</c> for no limit.</param>
|
||||
/// <param name="offset">The number of user accounts to skip before returning results, or <c>null</c> for no offset.</param>
|
||||
/// <returns>A <c>200 OK</c> result containing the collection of <see cref="UserAccount"/> entities.</returns>
|
||||
[HttpGet]
|
||||
public async Task<ActionResult<IEnumerable<UserAccount>>> GetAll(
|
||||
[FromQuery] int? limit,
|
||||
[FromQuery] int? offset
|
||||
)
|
||||
{
|
||||
var users = await userService.GetAllAsync(limit, offset);
|
||||
return Ok(users);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a single user account by its unique identifier.
|
||||
/// </summary>
|
||||
/// <param name="id">The unique identifier of the user account to retrieve.</param>
|
||||
/// <returns>A <c>200 OK</c> result containing the matching <see cref="UserAccount"/>.</returns>
|
||||
[HttpGet("{id:guid}")]
|
||||
public async Task<ActionResult<UserAccount>> GetById(Guid id)
|
||||
{
|
||||
var user = await userService.GetByIdAsync(id);
|
||||
return Ok(user);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,8 @@ COPY ["Domain/Domain.Entities/Domain.Entities.csproj", "Domain/Domain.Entities/"
|
||||
COPY ["Domain/Domain.Exceptions/Domain.Exceptions.csproj", "Domain/Domain.Exceptions/"]
|
||||
COPY ["Features/Features.Breweries/Features.Breweries.csproj", "Features/Features.Breweries/"]
|
||||
COPY ["Features/Features.Breweries.Tests/Features.Breweries.Tests.csproj", "Features/Features.Breweries.Tests/"]
|
||||
COPY ["Features/Features.UserManagement/Features.UserManagement.csproj", "Features/Features.UserManagement/"]
|
||||
COPY ["Features/Features.UserManagement.Tests/Features.UserManagement.Tests.csproj", "Features/Features.UserManagement.Tests/"]
|
||||
COPY ["Infrastructure/Infrastructure.Email/Infrastructure.Email.csproj", "Infrastructure/Infrastructure.Email/"]
|
||||
COPY ["Infrastructure/Infrastructure.Email.Templates/Infrastructure.Email.Templates.csproj", "Infrastructure/Infrastructure.Email.Templates/"]
|
||||
COPY ["Infrastructure/Infrastructure.Jwt/Infrastructure.Jwt.csproj", "Infrastructure/Infrastructure.Jwt/"]
|
||||
@@ -33,7 +35,6 @@ COPY ["Infrastructure/Infrastructure.Sql/Infrastructure.Sql.csproj", "Infrastruc
|
||||
COPY ["Service/Service.Auth/Service.Auth.csproj", "Service/Service.Auth/"]
|
||||
COPY ["Service/Service.Auth.Tests/Service.Auth.Tests.csproj", "Service/Service.Auth.Tests/"]
|
||||
COPY ["Service/Service.Emails/Service.Emails.csproj", "Service/Service.Emails/"]
|
||||
COPY ["Service/Service.UserManagement/Service.UserManagement.csproj", "Service/Service.UserManagement/"]
|
||||
COPY ["Shared/Shared.Application/Shared.Application.csproj", "Shared/Shared.Application/"]
|
||||
COPY ["Shared/Shared.Contracts/Shared.Contracts.csproj", "Shared/Shared.Contracts/"]
|
||||
RUN dotnet restore "Core.slnx"
|
||||
|
||||
@@ -2,6 +2,8 @@ using API.Core;
|
||||
using API.Core.Authentication;
|
||||
using Features.Breweries.Controllers;
|
||||
using Features.Breweries.DependencyInjection;
|
||||
using Features.UserManagement.Controllers;
|
||||
using Features.UserManagement.DependencyInjection;
|
||||
using FluentValidation;
|
||||
using FluentValidation.AspNetCore;
|
||||
using Infrastructure.Email;
|
||||
@@ -9,11 +11,9 @@ using Infrastructure.Email.Templates.Rendering;
|
||||
using Infrastructure.Jwt;
|
||||
using Infrastructure.PasswordHashing;
|
||||
using Infrastructure.Repository.Auth;
|
||||
using Infrastructure.Repository.UserAccount;
|
||||
using Infrastructure.Sql;
|
||||
using Service.Auth;
|
||||
using Service.Emails;
|
||||
using Service.UserManagement.User;
|
||||
using Shared.Application.Behaviors;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
@@ -23,7 +23,8 @@ builder.Services.AddControllers(options =>
|
||||
{
|
||||
options.Filters.Add<GlobalExceptionFilter>();
|
||||
})
|
||||
.AddApplicationPart(typeof(BreweryController).Assembly);
|
||||
.AddApplicationPart(typeof(BreweryController).Assembly)
|
||||
.AddApplicationPart(typeof(UserController).Assembly);
|
||||
|
||||
builder.Services.AddEndpointsApiExplorer();
|
||||
builder.Services.AddSwaggerGen();
|
||||
@@ -32,6 +33,7 @@ builder.Services.AddOpenApi();
|
||||
// Add FluentValidation
|
||||
builder.Services.AddValidatorsFromAssemblyContaining<Program>();
|
||||
builder.Services.AddValidatorsFromAssembly(typeof(BreweryController).Assembly);
|
||||
builder.Services.AddValidatorsFromAssembly(typeof(UserController).Assembly);
|
||||
builder.Services.AddFluentValidationAutoValidation();
|
||||
|
||||
// Add MediatR. Each Features.* slice's assembly is registered here as it's introduced;
|
||||
@@ -40,6 +42,7 @@ builder.Services.AddMediatR(cfg =>
|
||||
{
|
||||
cfg.RegisterServicesFromAssemblyContaining<Program>();
|
||||
cfg.RegisterServicesFromAssembly(typeof(BreweryController).Assembly);
|
||||
cfg.RegisterServicesFromAssembly(typeof(UserController).Assembly);
|
||||
cfg.AddOpenBehavior(typeof(ValidationBehavior<,>));
|
||||
});
|
||||
|
||||
@@ -61,11 +64,10 @@ builder.Services.AddSingleton<
|
||||
DefaultSqlConnectionFactory
|
||||
>();
|
||||
|
||||
builder.Services.AddScoped<IUserAccountRepository, UserAccountRepository>();
|
||||
builder.Services.AddScoped<IAuthRepository, AuthRepository>();
|
||||
builder.Services.AddFeaturesBreweries();
|
||||
builder.Services.AddFeaturesUserManagement();
|
||||
|
||||
builder.Services.AddScoped<IUserService, UserService>();
|
||||
builder.Services.AddScoped<ILoginService, LoginService>();
|
||||
builder.Services.AddScoped<IRegisterService, RegisterService>();
|
||||
builder.Services.AddScoped<ITokenService, TokenService>();
|
||||
|
||||
Reference in New Issue
Block a user