diff --git a/web/backend/API/API.Core/API.Core.csproj b/web/backend/API/API.Core/API.Core.csproj
index 36e47d4c..09478802 100644
--- a/web/backend/API/API.Core/API.Core.csproj
+++ b/web/backend/API/API.Core/API.Core.csproj
@@ -22,8 +22,7 @@
-
-
+
diff --git a/web/backend/API/API.Core/Dockerfile b/web/backend/API/API.Core/Dockerfile
index 21132363..4ba26f84 100644
--- a/web/backend/API/API.Core/Dockerfile
+++ b/web/backend/API/API.Core/Dockerfile
@@ -22,8 +22,6 @@ COPY ["Database/Database.Migrations/Database.Migrations.csproj", "Database/Datab
COPY ["Database/Database.Seed/Database.Seed.csproj", "Database/Database.Seed/"]
COPY ["Domain/Domain.Entities/Domain.Entities.csproj", "Domain/Domain.Entities/"]
COPY ["Domain/Domain.Exceptions/Domain.Exceptions.csproj", "Domain/Domain.Exceptions/"]
-COPY ["Features/Features.Auth/Features.Auth.csproj", "Features/Features.Auth/"]
-COPY ["Features/Features.Auth.Tests/Features.Auth.Tests.csproj", "Features/Features.Auth.Tests/"]
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.Emails/Features.Emails.csproj", "Features/Features.Emails/"]
@@ -32,8 +30,8 @@ COPY ["Features/Features.Locations/Features.Locations.csproj", "Features/Feature
COPY ["Features/Features.Locations.Tests/Features.Locations.Tests.csproj", "Features/Features.Locations.Tests/"]
COPY ["Features/Features.PhotoUpload/Features.PhotoUpload.csproj", "Features/Features.PhotoUpload/"]
COPY ["Features/Features.PhotoUpload.Tests/Features.PhotoUpload.Tests.csproj", "Features/Features.PhotoUpload.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 ["Features/Features.Users/Features.Users.csproj", "Features/Features.Users/"]
+COPY ["Features/Features.Users.Tests/Features.Users.Tests.csproj", "Features/Features.Users.Tests/"]
COPY ["Infrastructure/Infrastructure.Configuration/Infrastructure.Configuration.csproj", "Infrastructure/Infrastructure.Configuration/"]
COPY ["Infrastructure/Infrastructure.Email/Infrastructure.Email.csproj", "Infrastructure/Infrastructure.Email/"]
COPY ["Infrastructure/Infrastructure.Email.Templates/Infrastructure.Email.Templates.csproj", "Infrastructure/Infrastructure.Email.Templates/"]
diff --git a/web/backend/API/API.Core/Program.cs b/web/backend/API/API.Core/Program.cs
index 80912563..9c10bd5b 100644
--- a/web/backend/API/API.Core/Program.cs
+++ b/web/backend/API/API.Core/Program.cs
@@ -9,8 +9,8 @@ using Features.Emails.DependencyInjection;
using Features.Emails.Services;
using Features.ImageUploads.Commands.UploadPhoto;
using Features.ImageUploads.DependencyInjection;
-using Features.UserManagement.Controllers;
-using Features.UserManagement.DependencyInjection;
+using Features.Users.Controllers;
+using Features.Users.DependencyInjection;
using FluentValidation;
using FluentValidation.AspNetCore;
using Infrastructure.FileUpload;
@@ -25,12 +25,8 @@ WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
// Add current controllers to the exception filter
builder
- .Services.AddControllers(options =>
- {
- options.Filters.Add();
- })
+ .Services.AddControllers(options => { options.Filters.Add(); })
.AddApplicationPart(typeof(BreweryController).Assembly)
- .AddApplicationPart(typeof(UserController).Assembly)
.AddApplicationPart(typeof(AuthController).Assembly);
builder.Services.AddEndpointsApiExplorer();
@@ -69,7 +65,6 @@ builder.Services.AddOpenApi();
builder.Services.AddValidatorsFromAssemblyContaining();
builder.Services.AddValidatorsFromAssembly(typeof(BreweryController).Assembly);
-builder.Services.AddValidatorsFromAssembly(typeof(UserController).Assembly);
builder.Services.AddValidatorsFromAssembly(typeof(AuthController).Assembly);
builder.Services.AddValidatorsFromAssembly(typeof(UploadPhotoCommand).Assembly);
builder.Services.AddFluentValidationAutoValidation();
@@ -80,7 +75,6 @@ builder.Services.AddMediatR(cfg =>
{
cfg.RegisterServicesFromAssemblyContaining();
cfg.RegisterServicesFromAssembly(typeof(BreweryController).Assembly);
- cfg.RegisterServicesFromAssembly(typeof(UserController).Assembly);
cfg.RegisterServicesFromAssembly(typeof(AuthController).Assembly);
cfg.RegisterServicesFromAssembly(typeof(UploadPhotoCommand).Assembly);
cfg.RegisterServicesFromAssembly(typeof(IEmailDispatcher).Assembly);
@@ -98,7 +92,6 @@ if (!builder.Environment.IsProduction())
builder.Services.AddDatabaseConnection();
builder.Services.AddFeaturesBreweries();
-builder.Services.AddFeaturesUserManagement();
builder.Services.AddFeaturesAuth();
builder.Services.AddFeaturesEmails();
builder.Services.AddFeaturesPhotoUpload();
@@ -152,4 +145,4 @@ lifetime.ApplicationStopping.Register(() =>
app.Logger.LogInformation("Application is shutting down gracefully...");
});
-app.Run();
+app.Run();
\ No newline at end of file
diff --git a/web/backend/API/API.Specs/Dockerfile b/web/backend/API/API.Specs/Dockerfile
index 4ac4114d..124425d4 100644
--- a/web/backend/API/API.Specs/Dockerfile
+++ b/web/backend/API/API.Specs/Dockerfile
@@ -12,8 +12,6 @@ COPY ["Database/Database.Migrations/Database.Migrations.csproj", "Database/Datab
COPY ["Database/Database.Seed/Database.Seed.csproj", "Database/Database.Seed/"]
COPY ["Domain/Domain.Entities/Domain.Entities.csproj", "Domain/Domain.Entities/"]
COPY ["Domain/Domain.Exceptions/Domain.Exceptions.csproj", "Domain/Domain.Exceptions/"]
-COPY ["Features/Features.Auth/Features.Auth.csproj", "Features/Features.Auth/"]
-COPY ["Features/Features.Auth.Tests/Features.Auth.Tests.csproj", "Features/Features.Auth.Tests/"]
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.Emails/Features.Emails.csproj", "Features/Features.Emails/"]
@@ -22,8 +20,8 @@ COPY ["Features/Features.Locations/Features.Locations.csproj", "Features/Feature
COPY ["Features/Features.Locations.Tests/Features.Locations.Tests.csproj", "Features/Features.Locations.Tests/"]
COPY ["Features/Features.PhotoUpload/Features.PhotoUpload.csproj", "Features/Features.PhotoUpload/"]
COPY ["Features/Features.PhotoUpload.Tests/Features.PhotoUpload.Tests.csproj", "Features/Features.PhotoUpload.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 ["Features/Features.Users/Features.Users.csproj", "Features/Features.Users/"]
+COPY ["Features/Features.Users.Tests/Features.Users.Tests.csproj", "Features/Features.Users.Tests/"]
COPY ["Infrastructure/Infrastructure.Configuration/Infrastructure.Configuration.csproj", "Infrastructure/Infrastructure.Configuration/"]
COPY ["Infrastructure/Infrastructure.Email/Infrastructure.Email.csproj", "Infrastructure/Infrastructure.Email/"]
COPY ["Infrastructure/Infrastructure.Email.Templates/Infrastructure.Email.Templates.csproj", "Infrastructure/Infrastructure.Email.Templates/"]
diff --git a/web/backend/Biergarten.API.slnx b/web/backend/Biergarten.API.slnx
index e62246bc..a7cce055 100644
--- a/web/backend/Biergarten.API.slnx
+++ b/web/backend/Biergarten.API.slnx
@@ -12,6 +12,10 @@
+
+
+
+
@@ -20,22 +24,31 @@
-
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
-
+
\ No newline at end of file
diff --git a/web/backend/Database/Database.Seed/Database.Seed.csproj b/web/backend/Database/Database.Seed/Database.Seed.csproj
index a40bea94..0ce082e9 100644
--- a/web/backend/Database/Database.Seed/Database.Seed.csproj
+++ b/web/backend/Database/Database.Seed/Database.Seed.csproj
@@ -18,7 +18,7 @@
-
+
diff --git a/web/backend/Features/Features.Emails/Commands/SendRegistrationEmail/SendRegistrationEmailHandler.cs b/web/backend/Features/Features.Emails/Commands/SendRegistrationEmail/SendRegistrationEmailHandler.cs
index 31981b69..6bd22d78 100644
--- a/web/backend/Features/Features.Emails/Commands/SendRegistrationEmail/SendRegistrationEmailHandler.cs
+++ b/web/backend/Features/Features.Emails/Commands/SendRegistrationEmail/SendRegistrationEmailHandler.cs
@@ -5,7 +5,7 @@ using Shared.Application.Emails;
namespace Features.Emails.Commands.SendRegistrationEmail;
///
-/// Handles , the cross-slice command sent by Features.Auth
+/// Handles , the cross-slice command sent by Features.Users
/// after a new user registers.
///
public class SendRegistrationEmailHandler(IEmailDispatcher emailDispatcher)
diff --git a/web/backend/Features/Features.Emails/Commands/SendResendConfirmationEmail/SendResendConfirmationEmailHandler.cs b/web/backend/Features/Features.Emails/Commands/SendResendConfirmationEmail/SendResendConfirmationEmailHandler.cs
index d04419b9..c37551e0 100644
--- a/web/backend/Features/Features.Emails/Commands/SendResendConfirmationEmail/SendResendConfirmationEmailHandler.cs
+++ b/web/backend/Features/Features.Emails/Commands/SendResendConfirmationEmail/SendResendConfirmationEmailHandler.cs
@@ -5,7 +5,7 @@ using Shared.Application.Emails;
namespace Features.Emails.Commands.SendResendConfirmationEmail;
///
-/// Handles , the cross-slice command sent by Features.Auth
+/// Handles , the cross-slice command sent by Features.Users
/// when a user requests a fresh confirmation link.
///
public class SendResendConfirmationEmailHandler(IEmailDispatcher emailDispatcher)
diff --git a/web/backend/Features/Features.UserManagement.Tests/Commands/UpdateUserHandlerTests.cs b/web/backend/Features/Features.UserManagement.Tests/Commands/UpdateUserHandlerTests.cs
deleted file mode 100644
index 53f3a800..00000000
--- a/web/backend/Features/Features.UserManagement.Tests/Commands/UpdateUserHandlerTests.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-using Domain.Entities;
-using Features.UserManagement.Commands.UpdateUser;
-using Features.UserManagement.Repository;
-using Moq;
-
-namespace Features.UserManagement.Tests.Commands;
-
-public class UpdateUserHandlerTests
-{
- [Fact]
- public async Task Handle_DelegatesToRepository()
- {
- Mock repoMock = new();
- UpdateUserHandler handler = new(repoMock.Object);
- UserAccount user = new() { UserAccountId = Guid.NewGuid() };
- repoMock.Setup(r => r.UpdateAsync(user)).Returns(Task.CompletedTask);
-
- await handler.Handle(new UpdateUserCommand(user), CancellationToken.None);
-
- repoMock.Verify(r => r.UpdateAsync(user), Times.Once);
- }
-}
diff --git a/web/backend/Features/Features.UserManagement.Tests/Features.UserManagement.Tests.csproj b/web/backend/Features/Features.UserManagement.Tests/Features.UserManagement.Tests.csproj
deleted file mode 100644
index 1777547c..00000000
--- a/web/backend/Features/Features.UserManagement.Tests/Features.UserManagement.Tests.csproj
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
- net10.0
- enable
- enable
- false
- Features.UserManagement.Tests
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/web/backend/Features/Features.UserManagement/Commands/UpdateUser/UpdateUserCommand.cs b/web/backend/Features/Features.UserManagement/Commands/UpdateUser/UpdateUserCommand.cs
deleted file mode 100644
index 73d9c503..00000000
--- a/web/backend/Features/Features.UserManagement/Commands/UpdateUser/UpdateUserCommand.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-using Domain.Entities;
-using MediatR;
-
-namespace Features.UserManagement.Commands.UpdateUser;
-
-///
-/// Updates an existing user account. Not currently exposed via any HTTP route, carried forward
-/// from IUserService.UpdateAsync as-is.
-///
-public record UpdateUserCommand(UserAccount UserAccount) : IRequest;
diff --git a/web/backend/Features/Features.UserManagement/Commands/UpdateUser/UpdateUserHandler.cs b/web/backend/Features/Features.UserManagement/Commands/UpdateUser/UpdateUserHandler.cs
deleted file mode 100644
index 4967b127..00000000
--- a/web/backend/Features/Features.UserManagement/Commands/UpdateUser/UpdateUserHandler.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-using Features.UserManagement.Repository;
-using MediatR;
-
-namespace Features.UserManagement.Commands.UpdateUser;
-
-public class UpdateUserHandler(IUserAccountRepository repository)
- : IRequestHandler
-{
- public Task Handle(UpdateUserCommand request, CancellationToken cancellationToken)
- {
- return repository.UpdateAsync(request.UserAccount);
- }
-}
diff --git a/web/backend/Features/Features.UserManagement/DependencyInjection/FeaturesUserManagementServiceCollectionExtensions.cs b/web/backend/Features/Features.UserManagement/DependencyInjection/FeaturesUserManagementServiceCollectionExtensions.cs
deleted file mode 100644
index caff349d..00000000
--- a/web/backend/Features/Features.UserManagement/DependencyInjection/FeaturesUserManagementServiceCollectionExtensions.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-using Features.UserManagement.Repository;
-using Microsoft.Extensions.DependencyInjection;
-
-namespace Features.UserManagement.DependencyInjection;
-
-///
-/// Registers the services used by the Features.UserManagement slice.
-///
-public static class FeaturesUserManagementServiceCollectionExtensions
-{
- ///
- /// Registers and its Dapper-based implementation.
- ///
- /// The same instance, for chaining.
- public static IServiceCollection AddFeaturesUserManagement(this IServiceCollection services)
- {
- services.AddScoped();
- return services;
- }
-}
diff --git a/web/backend/Features/Features.UserManagement/Features.UserManagement.csproj b/web/backend/Features/Features.UserManagement/Features.UserManagement.csproj
deleted file mode 100644
index 77bfb16b..00000000
--- a/web/backend/Features/Features.UserManagement/Features.UserManagement.csproj
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
- net10.0
- enable
- enable
- Features.UserManagement
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/web/backend/Features/Features.UserManagement/Repository/IUserAccountRepository.cs b/web/backend/Features/Features.UserManagement/Repository/IUserAccountRepository.cs
deleted file mode 100644
index 25ebf13d..00000000
--- a/web/backend/Features/Features.UserManagement/Repository/IUserAccountRepository.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using Domain.Entities;
-using Domain.Exceptions;
-
-namespace Features.UserManagement.Repository;
-
-///
-/// Repository for CRUD operations on user account records.
-///
-public interface IUserAccountRepository
-{
- /// Returns null if no user account exists with the given ID.
- Task GetByIdAsync(Guid id);
-
- /// Returns user accounts ordered by creation date descending.
- /// null for no limit.
- /// null for no offset.
- Task> GetAllAsync(int? limit, int? offset);
-
- /// Updates the mutable fields of an existing user account.
- /// Must have a valid UserAccountId.
- /// Thrown when no user account exists with the given ID.
- Task UpdateAsync(UserAccount userAccount);
-
- /// Deletes the user account with the given ID.
- /// Thrown when no user account exists with the given ID.
- Task DeleteAsync(Guid id);
-
- /// Returns null if no user account exists with the given username.
- Task GetByUsernameAsync(string username);
-
- /// Returns null if no user account exists with the given email address.
- Task GetByEmailAsync(string email);
-}
diff --git a/web/backend/Features/Features.UserManagement/Repository/UserAccountRepository.cs b/web/backend/Features/Features.UserManagement/Repository/UserAccountRepository.cs
deleted file mode 100644
index 13d56011..00000000
--- a/web/backend/Features/Features.UserManagement/Repository/UserAccountRepository.cs
+++ /dev/null
@@ -1,118 +0,0 @@
-using System.Data.Common;
-using Dapper;
-using Database.Connection;
-using Domain.Entities;
-using Domain.Exceptions;
-
-namespace Features.UserManagement.Repository;
-
-///
-/// Dapper-based implementation of .
-///
-public class UserAccountRepository(ISqlConnectionFactory connectionFactory)
- : DapperRepository(connectionFactory),
- IUserAccountRepository
-{
- ///
- public async Task GetByIdAsync(Guid id)
- {
- await using DbConnection connection = await CreateConnection();
- return await connection.QueryFirstOrDefaultAsync(
- """
- SELECT UserAccountID, Username, FirstName, LastName, Email, CreatedAt, UpdatedAt, DateOfBirth, RowVersion
- FROM dbo.UserAccount
- WHERE UserAccountID = @UserAccountId
- """,
- new { UserAccountId = id }
- );
- }
-
- ///
- ///
- /// Always applies pagination via OFFSET/FETCH, ordered by creation date descending.
- /// A null / is treated as "no limit"/"no offset".
- ///
- public async Task> GetAllAsync(int? limit, int? offset)
- {
- await using DbConnection connection = await CreateConnection();
- return await connection.QueryAsync(
- """
- SELECT UserAccountID, Username, FirstName, LastName, Email, CreatedAt, UpdatedAt, DateOfBirth, RowVersion
- FROM dbo.UserAccount
- ORDER BY CreatedAt DESC
- OFFSET @Offset ROWS FETCH NEXT @Limit ROWS ONLY
- """,
- new { Offset = offset ?? 0, Limit = limit ?? int.MaxValue }
- );
- }
-
- ///
- public async Task UpdateAsync(UserAccount userAccount)
- {
- await using DbConnection connection = await CreateConnection();
- int rows = await connection.ExecuteAsync(
- """
- UPDATE dbo.UserAccount
- SET Username = @Username, FirstName = @FirstName, LastName = @LastName,
- DateOfBirth = @DateOfBirth, Email = @Email
- WHERE UserAccountId = @UserAccountId
- """,
- new
- {
- userAccount.UserAccountId,
- userAccount.Username,
- userAccount.FirstName,
- userAccount.LastName,
- userAccount.DateOfBirth,
- userAccount.Email,
- }
- );
-
- if (rows == 0)
- throw new NotFoundException("User account not found.");
- }
-
- ///
- public async Task DeleteAsync(Guid id)
- {
- await using DbConnection connection = await CreateConnection();
- int rows = await connection.ExecuteAsync(
- """
- DELETE FROM dbo.UserAccount
- WHERE UserAccountId = @UserAccountId
- """,
- new { UserAccountId = id }
- );
-
- if (rows == 0)
- throw new NotFoundException("User account not found.");
- }
-
- ///
- public async Task GetByUsernameAsync(string username)
- {
- await using DbConnection connection = await CreateConnection();
- return await connection.QueryFirstOrDefaultAsync(
- """
- SELECT UserAccountID, Username, FirstName, LastName, Email, CreatedAt, UpdatedAt, DateOfBirth, RowVersion
- FROM dbo.UserAccount
- WHERE Username = @Username
- """,
- new { Username = username }
- );
- }
-
- ///
- public async Task GetByEmailAsync(string email)
- {
- await using DbConnection connection = await CreateConnection();
- return await connection.QueryFirstOrDefaultAsync(
- """
- SELECT UserAccountID, Username, FirstName, LastName, Email, CreatedAt, UpdatedAt, DateOfBirth, RowVersion
- FROM dbo.UserAccount
- WHERE Email = @Email
- """,
- new { Email = email }
- );
- }
-}
diff --git a/web/backend/Features/Features.Auth.Tests/Commands/ConfirmUserHandlerTests.cs b/web/backend/Features/Features.Users.Tests/Commands/ConfirmUserHandlerTests.cs
similarity index 100%
rename from web/backend/Features/Features.Auth.Tests/Commands/ConfirmUserHandlerTests.cs
rename to web/backend/Features/Features.Users.Tests/Commands/ConfirmUserHandlerTests.cs
diff --git a/web/backend/Features/Features.Auth.Tests/Commands/DeleteAccountHandlerTests.cs b/web/backend/Features/Features.Users.Tests/Commands/DeleteAccountHandlerTests.cs
similarity index 100%
rename from web/backend/Features/Features.Auth.Tests/Commands/DeleteAccountHandlerTests.cs
rename to web/backend/Features/Features.Users.Tests/Commands/DeleteAccountHandlerTests.cs
diff --git a/web/backend/Features/Features.Auth.Tests/Commands/RefreshTokenHandlerTests.cs b/web/backend/Features/Features.Users.Tests/Commands/RefreshTokenHandlerTests.cs
similarity index 100%
rename from web/backend/Features/Features.Auth.Tests/Commands/RefreshTokenHandlerTests.cs
rename to web/backend/Features/Features.Users.Tests/Commands/RefreshTokenHandlerTests.cs
diff --git a/web/backend/Features/Features.Auth.Tests/Commands/RegisterUserHandlerTests.cs b/web/backend/Features/Features.Users.Tests/Commands/RegisterUserHandlerTests.cs
similarity index 100%
rename from web/backend/Features/Features.Auth.Tests/Commands/RegisterUserHandlerTests.cs
rename to web/backend/Features/Features.Users.Tests/Commands/RegisterUserHandlerTests.cs
diff --git a/web/backend/Features/Features.Auth.Tests/Commands/ResendConfirmationEmailHandlerTests.cs b/web/backend/Features/Features.Users.Tests/Commands/ResendConfirmationEmailHandlerTests.cs
similarity index 100%
rename from web/backend/Features/Features.Auth.Tests/Commands/ResendConfirmationEmailHandlerTests.cs
rename to web/backend/Features/Features.Users.Tests/Commands/ResendConfirmationEmailHandlerTests.cs
diff --git a/web/backend/Features/Features.Auth.Tests/Commands/UpdateEmailHandlerTests.cs b/web/backend/Features/Features.Users.Tests/Commands/UpdateEmailHandlerTests.cs
similarity index 100%
rename from web/backend/Features/Features.Auth.Tests/Commands/UpdateEmailHandlerTests.cs
rename to web/backend/Features/Features.Users.Tests/Commands/UpdateEmailHandlerTests.cs
diff --git a/web/backend/Features/Features.Auth.Tests/Commands/UpdatePasswordHandlerTests.cs b/web/backend/Features/Features.Users.Tests/Commands/UpdatePasswordHandlerTests.cs
similarity index 100%
rename from web/backend/Features/Features.Auth.Tests/Commands/UpdatePasswordHandlerTests.cs
rename to web/backend/Features/Features.Users.Tests/Commands/UpdatePasswordHandlerTests.cs
diff --git a/web/backend/Features/Features.Auth.Tests/Commands/UpdateProfileHandlerTests.cs b/web/backend/Features/Features.Users.Tests/Commands/UpdateProfileHandlerTests.cs
similarity index 100%
rename from web/backend/Features/Features.Auth.Tests/Commands/UpdateProfileHandlerTests.cs
rename to web/backend/Features/Features.Users.Tests/Commands/UpdateProfileHandlerTests.cs
diff --git a/web/backend/Features/Features.Auth.Tests/Commands/UpdateUsernameHandlerTests.cs b/web/backend/Features/Features.Users.Tests/Commands/UpdateUsernameHandlerTests.cs
similarity index 100%
rename from web/backend/Features/Features.Auth.Tests/Commands/UpdateUsernameHandlerTests.cs
rename to web/backend/Features/Features.Users.Tests/Commands/UpdateUsernameHandlerTests.cs
diff --git a/web/backend/Features/Features.Auth.Tests/Features.Auth.Tests.csproj b/web/backend/Features/Features.Users.Tests/Features.Users.Tests.csproj
similarity index 92%
rename from web/backend/Features/Features.Auth.Tests/Features.Auth.Tests.csproj
rename to web/backend/Features/Features.Users.Tests/Features.Users.Tests.csproj
index aa3c8bff..53d61628 100644
--- a/web/backend/Features/Features.Auth.Tests/Features.Auth.Tests.csproj
+++ b/web/backend/Features/Features.Users.Tests/Features.Users.Tests.csproj
@@ -20,7 +20,7 @@
-
+
diff --git a/web/backend/Features/Features.UserManagement.Tests/Queries/GetAllUsersHandlerTests.cs b/web/backend/Features/Features.Users.Tests/Queries/GetAllUsersHandlerTests.cs
similarity index 75%
rename from web/backend/Features/Features.UserManagement.Tests/Queries/GetAllUsersHandlerTests.cs
rename to web/backend/Features/Features.Users.Tests/Queries/GetAllUsersHandlerTests.cs
index 83b42d1c..4f2aeb06 100644
--- a/web/backend/Features/Features.UserManagement.Tests/Queries/GetAllUsersHandlerTests.cs
+++ b/web/backend/Features/Features.Users.Tests/Queries/GetAllUsersHandlerTests.cs
@@ -1,17 +1,17 @@
using Domain.Entities;
-using Features.UserManagement.Queries.GetAllUsers;
-using Features.UserManagement.Repository;
+using Features.Auth.Queries.GetAllUsers;
+using Features.Auth.Repository;
using FluentAssertions;
using Moq;
-namespace Features.UserManagement.Tests.Queries;
+namespace Features.Auth.Tests.Queries;
public class GetAllUsersHandlerTests
{
[Fact]
public async Task Handle_PassesLimitAndOffset_ToRepository()
{
- Mock repoMock = new();
+ Mock repoMock = new();
GetAllUsersHandler handler = new(repoMock.Object);
repoMock.Setup(r => r.GetAllAsync(10, 5)).ReturnsAsync(Array.Empty());
diff --git a/web/backend/Features/Features.UserManagement.Tests/Queries/GetUserByIdHandlerTests.cs b/web/backend/Features/Features.Users.Tests/Queries/GetUserByIdHandlerTests.cs
similarity index 84%
rename from web/backend/Features/Features.UserManagement.Tests/Queries/GetUserByIdHandlerTests.cs
rename to web/backend/Features/Features.Users.Tests/Queries/GetUserByIdHandlerTests.cs
index e79b05b4..d3d7fbdf 100644
--- a/web/backend/Features/Features.UserManagement.Tests/Queries/GetUserByIdHandlerTests.cs
+++ b/web/backend/Features/Features.Users.Tests/Queries/GetUserByIdHandlerTests.cs
@@ -1,16 +1,16 @@
using Domain.Entities;
using Domain.Exceptions;
-using Features.UserManagement.Queries.GetUserById;
-using Features.UserManagement.Repository;
+using Features.Auth.Queries.GetUserById;
+using Features.Auth.Repository;
using FluentAssertions;
using Moq;
-namespace Features.UserManagement.Tests.Queries;
+namespace Features.Auth.Tests.Queries;
public class GetUserByIdHandlerTests
{
private readonly GetUserByIdHandler _handler;
- private readonly Mock _repoMock = new();
+ private readonly Mock _repoMock = new();
public GetUserByIdHandlerTests()
{
diff --git a/web/backend/Features/Features.Auth.Tests/Queries/LoginHandlerTests.cs b/web/backend/Features/Features.Users.Tests/Queries/LoginHandlerTests.cs
similarity index 100%
rename from web/backend/Features/Features.Auth.Tests/Queries/LoginHandlerTests.cs
rename to web/backend/Features/Features.Users.Tests/Queries/LoginHandlerTests.cs
diff --git a/web/backend/Features/Features.Auth.Tests/Services/TokenServiceRefreshTests.cs b/web/backend/Features/Features.Users.Tests/Services/TokenServiceRefreshTests.cs
similarity index 100%
rename from web/backend/Features/Features.Auth.Tests/Services/TokenServiceRefreshTests.cs
rename to web/backend/Features/Features.Users.Tests/Services/TokenServiceRefreshTests.cs
diff --git a/web/backend/Features/Features.Auth.Tests/Services/TokenServiceValidationTests.cs b/web/backend/Features/Features.Users.Tests/Services/TokenServiceValidationTests.cs
similarity index 100%
rename from web/backend/Features/Features.Auth.Tests/Services/TokenServiceValidationTests.cs
rename to web/backend/Features/Features.Users.Tests/Services/TokenServiceValidationTests.cs
diff --git a/web/backend/Features/Features.Auth.Tests/TestSupport/UserManagerMockFactory.cs b/web/backend/Features/Features.Users.Tests/TestSupport/UserManagerMockFactory.cs
similarity index 100%
rename from web/backend/Features/Features.Auth.Tests/TestSupport/UserManagerMockFactory.cs
rename to web/backend/Features/Features.Users.Tests/TestSupport/UserManagerMockFactory.cs
diff --git a/web/backend/Features/Features.Auth/Commands/ConfirmUser/ConfirmUserCommand.cs b/web/backend/Features/Features.Users/Commands/ConfirmUser/ConfirmUserCommand.cs
similarity index 100%
rename from web/backend/Features/Features.Auth/Commands/ConfirmUser/ConfirmUserCommand.cs
rename to web/backend/Features/Features.Users/Commands/ConfirmUser/ConfirmUserCommand.cs
diff --git a/web/backend/Features/Features.Auth/Commands/ConfirmUser/ConfirmUserHandler.cs b/web/backend/Features/Features.Users/Commands/ConfirmUser/ConfirmUserHandler.cs
similarity index 100%
rename from web/backend/Features/Features.Auth/Commands/ConfirmUser/ConfirmUserHandler.cs
rename to web/backend/Features/Features.Users/Commands/ConfirmUser/ConfirmUserHandler.cs
diff --git a/web/backend/Features/Features.Auth/Commands/DeleteAccount/DeleteAccountCommand.cs b/web/backend/Features/Features.Users/Commands/DeleteAccount/DeleteAccountCommand.cs
similarity index 100%
rename from web/backend/Features/Features.Auth/Commands/DeleteAccount/DeleteAccountCommand.cs
rename to web/backend/Features/Features.Users/Commands/DeleteAccount/DeleteAccountCommand.cs
diff --git a/web/backend/Features/Features.Auth/Commands/DeleteAccount/DeleteAccountHandler.cs b/web/backend/Features/Features.Users/Commands/DeleteAccount/DeleteAccountHandler.cs
similarity index 100%
rename from web/backend/Features/Features.Auth/Commands/DeleteAccount/DeleteAccountHandler.cs
rename to web/backend/Features/Features.Users/Commands/DeleteAccount/DeleteAccountHandler.cs
diff --git a/web/backend/Features/Features.Auth/Commands/Login/LoginCommand.cs b/web/backend/Features/Features.Users/Commands/Login/LoginCommand.cs
similarity index 100%
rename from web/backend/Features/Features.Auth/Commands/Login/LoginCommand.cs
rename to web/backend/Features/Features.Users/Commands/Login/LoginCommand.cs
diff --git a/web/backend/Features/Features.Auth/Commands/Login/LoginHandler.cs b/web/backend/Features/Features.Users/Commands/Login/LoginHandler.cs
similarity index 100%
rename from web/backend/Features/Features.Auth/Commands/Login/LoginHandler.cs
rename to web/backend/Features/Features.Users/Commands/Login/LoginHandler.cs
diff --git a/web/backend/Features/Features.Auth/Commands/Login/LoginValidator.cs b/web/backend/Features/Features.Users/Commands/Login/LoginValidator.cs
similarity index 100%
rename from web/backend/Features/Features.Auth/Commands/Login/LoginValidator.cs
rename to web/backend/Features/Features.Users/Commands/Login/LoginValidator.cs
diff --git a/web/backend/Features/Features.Auth/Commands/RefreshToken/RefreshTokenCommand.cs b/web/backend/Features/Features.Users/Commands/RefreshToken/RefreshTokenCommand.cs
similarity index 100%
rename from web/backend/Features/Features.Auth/Commands/RefreshToken/RefreshTokenCommand.cs
rename to web/backend/Features/Features.Users/Commands/RefreshToken/RefreshTokenCommand.cs
diff --git a/web/backend/Features/Features.Auth/Commands/RefreshToken/RefreshTokenHandler.cs b/web/backend/Features/Features.Users/Commands/RefreshToken/RefreshTokenHandler.cs
similarity index 100%
rename from web/backend/Features/Features.Auth/Commands/RefreshToken/RefreshTokenHandler.cs
rename to web/backend/Features/Features.Users/Commands/RefreshToken/RefreshTokenHandler.cs
diff --git a/web/backend/Features/Features.Auth/Commands/RefreshToken/RefreshTokenValidator.cs b/web/backend/Features/Features.Users/Commands/RefreshToken/RefreshTokenValidator.cs
similarity index 100%
rename from web/backend/Features/Features.Auth/Commands/RefreshToken/RefreshTokenValidator.cs
rename to web/backend/Features/Features.Users/Commands/RefreshToken/RefreshTokenValidator.cs
diff --git a/web/backend/Features/Features.Auth/Commands/RegisterUser/RegisterUserCommand.cs b/web/backend/Features/Features.Users/Commands/RegisterUser/RegisterUserCommand.cs
similarity index 100%
rename from web/backend/Features/Features.Auth/Commands/RegisterUser/RegisterUserCommand.cs
rename to web/backend/Features/Features.Users/Commands/RegisterUser/RegisterUserCommand.cs
diff --git a/web/backend/Features/Features.Auth/Commands/RegisterUser/RegisterUserHandler.cs b/web/backend/Features/Features.Users/Commands/RegisterUser/RegisterUserHandler.cs
similarity index 100%
rename from web/backend/Features/Features.Auth/Commands/RegisterUser/RegisterUserHandler.cs
rename to web/backend/Features/Features.Users/Commands/RegisterUser/RegisterUserHandler.cs
diff --git a/web/backend/Features/Features.Auth/Commands/RegisterUser/RegisterUserValidator.cs b/web/backend/Features/Features.Users/Commands/RegisterUser/RegisterUserValidator.cs
similarity index 100%
rename from web/backend/Features/Features.Auth/Commands/RegisterUser/RegisterUserValidator.cs
rename to web/backend/Features/Features.Users/Commands/RegisterUser/RegisterUserValidator.cs
diff --git a/web/backend/Features/Features.Auth/Commands/ResendConfirmationEmail/ResendConfirmationEmailCommand.cs b/web/backend/Features/Features.Users/Commands/ResendConfirmationEmail/ResendConfirmationEmailCommand.cs
similarity index 100%
rename from web/backend/Features/Features.Auth/Commands/ResendConfirmationEmail/ResendConfirmationEmailCommand.cs
rename to web/backend/Features/Features.Users/Commands/ResendConfirmationEmail/ResendConfirmationEmailCommand.cs
diff --git a/web/backend/Features/Features.Auth/Commands/ResendConfirmationEmail/ResendConfirmationEmailHandler.cs b/web/backend/Features/Features.Users/Commands/ResendConfirmationEmail/ResendConfirmationEmailHandler.cs
similarity index 100%
rename from web/backend/Features/Features.Auth/Commands/ResendConfirmationEmail/ResendConfirmationEmailHandler.cs
rename to web/backend/Features/Features.Users/Commands/ResendConfirmationEmail/ResendConfirmationEmailHandler.cs
diff --git a/web/backend/Features/Features.Auth/Commands/UpdateEmail/UpdateEmailCommand.cs b/web/backend/Features/Features.Users/Commands/UpdateEmail/UpdateEmailCommand.cs
similarity index 100%
rename from web/backend/Features/Features.Auth/Commands/UpdateEmail/UpdateEmailCommand.cs
rename to web/backend/Features/Features.Users/Commands/UpdateEmail/UpdateEmailCommand.cs
diff --git a/web/backend/Features/Features.Auth/Commands/UpdateEmail/UpdateEmailHandler.cs b/web/backend/Features/Features.Users/Commands/UpdateEmail/UpdateEmailHandler.cs
similarity index 96%
rename from web/backend/Features/Features.Auth/Commands/UpdateEmail/UpdateEmailHandler.cs
rename to web/backend/Features/Features.Users/Commands/UpdateEmail/UpdateEmailHandler.cs
index 8ef0613d..5cc03d34 100644
--- a/web/backend/Features/Features.Auth/Commands/UpdateEmail/UpdateEmailHandler.cs
+++ b/web/backend/Features/Features.Users/Commands/UpdateEmail/UpdateEmailHandler.cs
@@ -10,7 +10,7 @@ namespace Features.Auth.Commands.UpdateEmail;
/// Handles via .
/// also resets EmailConfirmed to
/// , so the user must re-confirm the new address (see
-/// Features.Auth.Commands.ResendConfirmationEmail).
+/// Features.Users.Commands.ResendConfirmationEmail).
///
public class UpdateEmailHandler(UserManager userManager)
: IRequestHandler
diff --git a/web/backend/Features/Features.Auth/Commands/UpdateEmail/UpdateEmailValidator.cs b/web/backend/Features/Features.Users/Commands/UpdateEmail/UpdateEmailValidator.cs
similarity index 100%
rename from web/backend/Features/Features.Auth/Commands/UpdateEmail/UpdateEmailValidator.cs
rename to web/backend/Features/Features.Users/Commands/UpdateEmail/UpdateEmailValidator.cs
diff --git a/web/backend/Features/Features.Auth/Commands/UpdatePassword/UpdatePasswordCommand.cs b/web/backend/Features/Features.Users/Commands/UpdatePassword/UpdatePasswordCommand.cs
similarity index 100%
rename from web/backend/Features/Features.Auth/Commands/UpdatePassword/UpdatePasswordCommand.cs
rename to web/backend/Features/Features.Users/Commands/UpdatePassword/UpdatePasswordCommand.cs
diff --git a/web/backend/Features/Features.Auth/Commands/UpdatePassword/UpdatePasswordHandler.cs b/web/backend/Features/Features.Users/Commands/UpdatePassword/UpdatePasswordHandler.cs
similarity index 100%
rename from web/backend/Features/Features.Auth/Commands/UpdatePassword/UpdatePasswordHandler.cs
rename to web/backend/Features/Features.Users/Commands/UpdatePassword/UpdatePasswordHandler.cs
diff --git a/web/backend/Features/Features.Auth/Commands/UpdatePassword/UpdatePasswordValidator.cs b/web/backend/Features/Features.Users/Commands/UpdatePassword/UpdatePasswordValidator.cs
similarity index 100%
rename from web/backend/Features/Features.Auth/Commands/UpdatePassword/UpdatePasswordValidator.cs
rename to web/backend/Features/Features.Users/Commands/UpdatePassword/UpdatePasswordValidator.cs
diff --git a/web/backend/Features/Features.Auth/Commands/UpdateProfile/UpdateProfileCommand.cs b/web/backend/Features/Features.Users/Commands/UpdateProfile/UpdateProfileCommand.cs
similarity index 100%
rename from web/backend/Features/Features.Auth/Commands/UpdateProfile/UpdateProfileCommand.cs
rename to web/backend/Features/Features.Users/Commands/UpdateProfile/UpdateProfileCommand.cs
diff --git a/web/backend/Features/Features.Auth/Commands/UpdateProfile/UpdateProfileHandler.cs b/web/backend/Features/Features.Users/Commands/UpdateProfile/UpdateProfileHandler.cs
similarity index 100%
rename from web/backend/Features/Features.Auth/Commands/UpdateProfile/UpdateProfileHandler.cs
rename to web/backend/Features/Features.Users/Commands/UpdateProfile/UpdateProfileHandler.cs
diff --git a/web/backend/Features/Features.Auth/Commands/UpdateProfile/UpdateProfileValidator.cs b/web/backend/Features/Features.Users/Commands/UpdateProfile/UpdateProfileValidator.cs
similarity index 100%
rename from web/backend/Features/Features.Auth/Commands/UpdateProfile/UpdateProfileValidator.cs
rename to web/backend/Features/Features.Users/Commands/UpdateProfile/UpdateProfileValidator.cs
diff --git a/web/backend/Features/Features.Auth/Commands/UpdateUsername/UpdateUsernameCommand.cs b/web/backend/Features/Features.Users/Commands/UpdateUsername/UpdateUsernameCommand.cs
similarity index 100%
rename from web/backend/Features/Features.Auth/Commands/UpdateUsername/UpdateUsernameCommand.cs
rename to web/backend/Features/Features.Users/Commands/UpdateUsername/UpdateUsernameCommand.cs
diff --git a/web/backend/Features/Features.Auth/Commands/UpdateUsername/UpdateUsernameHandler.cs b/web/backend/Features/Features.Users/Commands/UpdateUsername/UpdateUsernameHandler.cs
similarity index 100%
rename from web/backend/Features/Features.Auth/Commands/UpdateUsername/UpdateUsernameHandler.cs
rename to web/backend/Features/Features.Users/Commands/UpdateUsername/UpdateUsernameHandler.cs
diff --git a/web/backend/Features/Features.Auth/Commands/UpdateUsername/UpdateUsernameValidator.cs b/web/backend/Features/Features.Users/Commands/UpdateUsername/UpdateUsernameValidator.cs
similarity index 100%
rename from web/backend/Features/Features.Auth/Commands/UpdateUsername/UpdateUsernameValidator.cs
rename to web/backend/Features/Features.Users/Commands/UpdateUsername/UpdateUsernameValidator.cs
diff --git a/web/backend/Features/Features.Auth/Controllers/AuthController.cs b/web/backend/Features/Features.Users/Controllers/AuthController.cs
similarity index 100%
rename from web/backend/Features/Features.Auth/Controllers/AuthController.cs
rename to web/backend/Features/Features.Users/Controllers/AuthController.cs
diff --git a/web/backend/Features/Features.UserManagement/Controllers/UserController.cs b/web/backend/Features/Features.Users/Controllers/UserController.cs
similarity index 89%
rename from web/backend/Features/Features.UserManagement/Controllers/UserController.cs
rename to web/backend/Features/Features.Users/Controllers/UserController.cs
index 669d4f5e..86d4827c 100644
--- a/web/backend/Features/Features.UserManagement/Controllers/UserController.cs
+++ b/web/backend/Features/Features.Users/Controllers/UserController.cs
@@ -1,11 +1,11 @@
using Domain.Entities;
using Domain.Exceptions;
-using Features.UserManagement.Queries.GetAllUsers;
-using Features.UserManagement.Queries.GetUserById;
+using Features.Auth.Queries.GetAllUsers;
+using Features.Auth.Queries.GetUserById;
using MediatR;
using Microsoft.AspNetCore.Mvc;
-namespace Features.UserManagement.Controllers;
+namespace Features.Auth.Controllers;
///
/// Exposes read endpoints for user accounts.
diff --git a/web/backend/Features/Features.Auth/DependencyInjection/FeaturesAuthServiceCollectionExtensions.cs b/web/backend/Features/Features.Users/DependencyInjection/FeaturesAuthServiceCollectionExtensions.cs
similarity index 81%
rename from web/backend/Features/Features.Auth/DependencyInjection/FeaturesAuthServiceCollectionExtensions.cs
rename to web/backend/Features/Features.Users/DependencyInjection/FeaturesAuthServiceCollectionExtensions.cs
index 97d632a0..89dec851 100644
--- a/web/backend/Features/Features.Auth/DependencyInjection/FeaturesAuthServiceCollectionExtensions.cs
+++ b/web/backend/Features/Features.Users/DependencyInjection/FeaturesAuthServiceCollectionExtensions.cs
@@ -1,4 +1,5 @@
using Features.Auth.Identity;
+using Features.Auth.Repository;
using Features.Auth.Services;
using Infrastructure.PasswordHashing;
using Microsoft.AspNetCore.Identity;
@@ -6,17 +7,19 @@ using Microsoft.Extensions.DependencyInjection;
namespace Features.Auth.DependencyInjection;
-/// Registers the services required by Features.Auth with the dependency injection container.
+/// Registers the services required by Features.Users with the dependency injection container.
public static class FeaturesAuthServiceCollectionExtensions
{
///
- /// Adds and ASP.NET Core Identity (
- /// backed by and ) as scoped services.
+ /// Adds , , and ASP.NET Core
+ /// Identity ( backed by and
+ /// ) as scoped services.
///
public static IServiceCollection AddFeaturesAuth(this IServiceCollection services)
{
services.AddScoped();
services.AddScoped();
+ services.AddScoped();
// AddDefaultTokenProviders() is deliberately not called: it registers
// DataProtectorTokenProvider, which UserManager's constructor resolves eagerly and which
diff --git a/web/backend/Features/Features.Auth/Dtos/AuthPayloads.cs b/web/backend/Features/Features.Users/Dtos/AuthPayloads.cs
similarity index 100%
rename from web/backend/Features/Features.Auth/Dtos/AuthPayloads.cs
rename to web/backend/Features/Features.Users/Dtos/AuthPayloads.cs
diff --git a/web/backend/Features/Features.Auth/Features.Auth.csproj b/web/backend/Features/Features.Users/Features.Users.csproj
similarity index 93%
rename from web/backend/Features/Features.Auth/Features.Auth.csproj
rename to web/backend/Features/Features.Users/Features.Users.csproj
index 53379c51..b7439890 100644
--- a/web/backend/Features/Features.Auth/Features.Auth.csproj
+++ b/web/backend/Features/Features.Users/Features.Users.csproj
@@ -18,11 +18,8 @@
+
-
-
-
-
diff --git a/web/backend/Features/Features.Auth/Identity/ApplicationUser.cs b/web/backend/Features/Features.Users/Identity/ApplicationUser.cs
similarity index 88%
rename from web/backend/Features/Features.Auth/Identity/ApplicationUser.cs
rename to web/backend/Features/Features.Users/Identity/ApplicationUser.cs
index e0dd41d5..9b015bc6 100644
--- a/web/backend/Features/Features.Auth/Identity/ApplicationUser.cs
+++ b/web/backend/Features/Features.Users/Identity/ApplicationUser.cs
@@ -2,7 +2,7 @@ namespace Features.Auth.Identity;
///
/// The user type driving for
-/// Features.Auth. A plain POCO (not IdentityUser<TKey>) backed by
+/// Features.Users. A plain POCO (not IdentityUser<TKey>) backed by
/// rather than EF Core, matching the rest of the solution's Dapper-only persistence.
///
public sealed class ApplicationUser
diff --git a/web/backend/Features/Features.Auth/Identity/Argon2PasswordHasher.cs b/web/backend/Features/Features.Users/Identity/Argon2PasswordHasher.cs
similarity index 100%
rename from web/backend/Features/Features.Auth/Identity/Argon2PasswordHasher.cs
rename to web/backend/Features/Features.Users/Identity/Argon2PasswordHasher.cs
diff --git a/web/backend/Features/Features.Auth/Identity/DapperUserStore.cs b/web/backend/Features/Features.Users/Identity/DapperUserStore.cs
similarity index 98%
rename from web/backend/Features/Features.Auth/Identity/DapperUserStore.cs
rename to web/backend/Features/Features.Users/Identity/DapperUserStore.cs
index fb2780a9..1e8965cb 100644
--- a/web/backend/Features/Features.Auth/Identity/DapperUserStore.cs
+++ b/web/backend/Features/Features.Users/Identity/DapperUserStore.cs
@@ -186,8 +186,9 @@ public sealed class DapperUserStore(ISqlConnectionFactory connectionFactory)
///
///
/// A plain DELETE against dbo.UserAccount: its foreign keys from
- /// dbo.UserCredential, dbo.UserVerification, and dbo.UserAvatar cascade, so no
- /// manual child cleanup is needed. Other tables (posts, comments, photos, follows) reference the
+ /// dbo.UserCredential, dbo.UserVerification, and dbo.UserProfile cascade
+ /// (dbo.UserAvatar cascades transitively through dbo.UserProfile), so no manual
+ /// child cleanup is needed. Other tables (posts, comments, photos, follows) reference the
/// account with ON DELETE NO ACTION by design; deleting an account that still has any of
/// those fails with a foreign key violation, which is surfaced as a failed
/// rather than an unhandled .
diff --git a/web/backend/Features/Features.Auth/Identity/UserAccountExtensions.cs b/web/backend/Features/Features.Users/Identity/UserAccountExtensions.cs
similarity index 87%
rename from web/backend/Features/Features.Auth/Identity/UserAccountExtensions.cs
rename to web/backend/Features/Features.Users/Identity/UserAccountExtensions.cs
index 67c270bb..24c11c5a 100644
--- a/web/backend/Features/Features.Auth/Identity/UserAccountExtensions.cs
+++ b/web/backend/Features/Features.Users/Identity/UserAccountExtensions.cs
@@ -5,7 +5,7 @@ namespace Features.Auth.Identity;
///
/// Converts the persistence-agnostic domain entity into the
/// shape required by .
-/// Kept here, in Features.Auth, rather than on itself so the domain layer has
+/// Kept here, in Features.Users, rather than on itself so the domain layer has
/// no dependency on ASP.NET Core Identity.
///
public static class UserAccountExtensions
diff --git a/web/backend/Features/Features.UserManagement/Queries/GetAllUsers/GetAllUsersHandler.cs b/web/backend/Features/Features.Users/Queries/GetAllUsers/GetAllUsersHandler.cs
similarity index 66%
rename from web/backend/Features/Features.UserManagement/Queries/GetAllUsers/GetAllUsersHandler.cs
rename to web/backend/Features/Features.Users/Queries/GetAllUsers/GetAllUsersHandler.cs
index 4e8afe82..201c35be 100644
--- a/web/backend/Features/Features.UserManagement/Queries/GetAllUsers/GetAllUsersHandler.cs
+++ b/web/backend/Features/Features.Users/Queries/GetAllUsers/GetAllUsersHandler.cs
@@ -1,10 +1,10 @@
using Domain.Entities;
-using Features.UserManagement.Repository;
+using Features.Auth.Repository;
using MediatR;
-namespace Features.UserManagement.Queries.GetAllUsers;
+namespace Features.Auth.Queries.GetAllUsers;
-public class GetAllUsersHandler(IUserAccountRepository repository)
+public class GetAllUsersHandler(IUserListRepository repository)
: IRequestHandler>
{
public Task> Handle(
diff --git a/web/backend/Features/Features.UserManagement/Queries/GetAllUsers/GetAllUsersQuery.cs b/web/backend/Features/Features.Users/Queries/GetAllUsers/GetAllUsersQuery.cs
similarity index 86%
rename from web/backend/Features/Features.UserManagement/Queries/GetAllUsers/GetAllUsersQuery.cs
rename to web/backend/Features/Features.Users/Queries/GetAllUsers/GetAllUsersQuery.cs
index 54e8d4cf..e000063e 100644
--- a/web/backend/Features/Features.UserManagement/Queries/GetAllUsers/GetAllUsersQuery.cs
+++ b/web/backend/Features/Features.Users/Queries/GetAllUsers/GetAllUsersQuery.cs
@@ -1,7 +1,7 @@
using Domain.Entities;
using MediatR;
-namespace Features.UserManagement.Queries.GetAllUsers;
+namespace Features.Auth.Queries.GetAllUsers;
///
/// Requests a page of user accounts, ordered by creation date descending.
diff --git a/web/backend/Features/Features.UserManagement/Queries/GetUserById/GetUserByIdHandler.cs b/web/backend/Features/Features.Users/Queries/GetUserById/GetUserByIdHandler.cs
similarity index 78%
rename from web/backend/Features/Features.UserManagement/Queries/GetUserById/GetUserByIdHandler.cs
rename to web/backend/Features/Features.Users/Queries/GetUserById/GetUserByIdHandler.cs
index d664310e..8d83c112 100644
--- a/web/backend/Features/Features.UserManagement/Queries/GetUserById/GetUserByIdHandler.cs
+++ b/web/backend/Features/Features.Users/Queries/GetUserById/GetUserByIdHandler.cs
@@ -1,11 +1,11 @@
using Domain.Entities;
using Domain.Exceptions;
-using Features.UserManagement.Repository;
+using Features.Auth.Repository;
using MediatR;
-namespace Features.UserManagement.Queries.GetUserById;
+namespace Features.Auth.Queries.GetUserById;
-public class GetUserByIdHandler(IUserAccountRepository repository)
+public class GetUserByIdHandler(IUserListRepository repository)
: IRequestHandler
{
/// Thrown when no user account exists with the given ID.
diff --git a/web/backend/Features/Features.UserManagement/Queries/GetUserById/GetUserByIdQuery.cs b/web/backend/Features/Features.Users/Queries/GetUserById/GetUserByIdQuery.cs
similarity index 67%
rename from web/backend/Features/Features.UserManagement/Queries/GetUserById/GetUserByIdQuery.cs
rename to web/backend/Features/Features.Users/Queries/GetUserById/GetUserByIdQuery.cs
index 8337b7a9..80328852 100644
--- a/web/backend/Features/Features.UserManagement/Queries/GetUserById/GetUserByIdQuery.cs
+++ b/web/backend/Features/Features.Users/Queries/GetUserById/GetUserByIdQuery.cs
@@ -1,6 +1,6 @@
using Domain.Entities;
using MediatR;
-namespace Features.UserManagement.Queries.GetUserById;
+namespace Features.Auth.Queries.GetUserById;
public record GetUserByIdQuery(Guid UserAccountId) : IRequest;
diff --git a/web/backend/Features/Features.Users/Repository/IUserListRepository.cs b/web/backend/Features/Features.Users/Repository/IUserListRepository.cs
new file mode 100644
index 00000000..954d37ab
--- /dev/null
+++ b/web/backend/Features/Features.Users/Repository/IUserListRepository.cs
@@ -0,0 +1,21 @@
+using Domain.Entities;
+
+namespace Features.Auth.Repository;
+
+///
+/// Read access for user account listing. Everything else on user accounts (lookup by
+/// username/email, create/update/delete) already goes through
+/// ; this repository only covers
+/// what IUserStore has no equivalent for: fetching by ID with full audit fields, and
+/// paginated listing.
+///
+public interface IUserListRepository
+{
+ /// Returns null if no user account exists with the given ID.
+ Task GetByIdAsync(Guid id);
+
+ /// Returns user accounts ordered by creation date descending.
+ /// null for no limit.
+ /// null for no offset.
+ Task> GetAllAsync(int? limit, int? offset);
+}
diff --git a/web/backend/Features/Features.Users/Repository/UserListRepository.cs b/web/backend/Features/Features.Users/Repository/UserListRepository.cs
new file mode 100644
index 00000000..8f90054a
--- /dev/null
+++ b/web/backend/Features/Features.Users/Repository/UserListRepository.cs
@@ -0,0 +1,50 @@
+using System.Data.Common;
+using Dapper;
+using Database.Connection;
+using Domain.Entities;
+
+namespace Features.Auth.Repository;
+
+///
+/// Dapper-based implementation of .
+///
+public class UserListRepository(ISqlConnectionFactory connectionFactory)
+ : DapperRepository(connectionFactory),
+ IUserListRepository
+{
+ ///
+ public async Task GetByIdAsync(Guid id)
+ {
+ await using DbConnection connection = await CreateConnection();
+ return await connection.QueryFirstOrDefaultAsync(
+ """
+ SELECT
+ UserAccountID,
+ Username,
+ FirstName, LastName, Email, CreatedAt, UpdatedAt, DateOfBirth, RowVersion
+ FROM dbo.UserAccount
+ WHERE UserAccountID = @UserAccountId
+ """,
+ new { UserAccountId = id }
+ );
+ }
+
+ ///
+ ///
+ /// Always applies pagination via OFFSET/FETCH, ordered by creation date descending.
+ /// A null / is treated as "no limit"/"no offset".
+ ///
+ public async Task> GetAllAsync(int? limit, int? offset)
+ {
+ await using DbConnection connection = await CreateConnection();
+ return await connection.QueryAsync(
+ """
+ SELECT UserAccountID, Username, FirstName, LastName, Email, CreatedAt, UpdatedAt, DateOfBirth, RowVersion
+ FROM dbo.UserAccount
+ ORDER BY CreatedAt DESC
+ OFFSET @Offset ROWS FETCH NEXT @Limit ROWS ONLY
+ """,
+ new { Offset = offset ?? 0, Limit = limit ?? int.MaxValue }
+ );
+ }
+}
diff --git a/web/backend/Features/Features.Auth/Services/ITokenService.cs b/web/backend/Features/Features.Users/Services/ITokenService.cs
similarity index 100%
rename from web/backend/Features/Features.Auth/Services/ITokenService.cs
rename to web/backend/Features/Features.Users/Services/ITokenService.cs
diff --git a/web/backend/Features/Features.Auth/Services/TokenService.cs b/web/backend/Features/Features.Users/Services/TokenService.cs
similarity index 100%
rename from web/backend/Features/Features.Auth/Services/TokenService.cs
rename to web/backend/Features/Features.Users/Services/TokenService.cs
diff --git a/web/backend/Shared/Shared.Application/Emails/SendRegistrationEmailCommand.cs b/web/backend/Shared/Shared.Application/Emails/SendRegistrationEmailCommand.cs
index 5c573245..80e1133e 100644
--- a/web/backend/Shared/Shared.Application/Emails/SendRegistrationEmailCommand.cs
+++ b/web/backend/Shared/Shared.Application/Emails/SendRegistrationEmailCommand.cs
@@ -3,7 +3,7 @@ using MediatR;
namespace Shared.Application.Emails;
///
-/// Cross-slice command sent by Features.Auth and handled by Features.Emails to dispatch a
+/// Cross-slice command sent by Features.Users and handled by Features.Emails to dispatch a
/// registration confirmation email, without either slice taking a project reference on the other.
///
public record SendRegistrationEmailCommand(string FirstName, string Email, string ConfirmationToken)
diff --git a/web/backend/Shared/Shared.Application/Emails/SendResendConfirmationEmailCommand.cs b/web/backend/Shared/Shared.Application/Emails/SendResendConfirmationEmailCommand.cs
index 0831d8c2..af2fa75b 100644
--- a/web/backend/Shared/Shared.Application/Emails/SendResendConfirmationEmailCommand.cs
+++ b/web/backend/Shared/Shared.Application/Emails/SendResendConfirmationEmailCommand.cs
@@ -3,7 +3,7 @@ using MediatR;
namespace Shared.Application.Emails;
///
-/// Cross-slice command sent by Features.Auth and handled by Features.Emails to dispatch a
+/// Cross-slice command sent by Features.Users and handled by Features.Emails to dispatch a
/// fresh confirmation-link email, without either slice taking a project reference on the other.
///
public record SendResendConfirmationEmailCommand(