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:
Aaron Po
2026-06-20 00:02:27 -04:00
parent a8c1b17095
commit 6db004066f
24 changed files with 267 additions and 118 deletions

View File

@@ -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>();