new event queue adding, register endpoint finished

This commit is contained in:
2026-01-19 03:15:01 +01:00
Unverified
parent 44eb5801fa
commit a01e8666a3
9 changed files with 54 additions and 55 deletions

View File

@@ -0,0 +1,6 @@
namespace TimetableDesigner.Backend.Services.Authentication.DTO.Events;
public record RegisterEvent(
long Id,
string Email
);

View File

@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View File

@@ -1,4 +1,5 @@
<Solution>
<Project Path="TimetableDesigner.Backend.Services.Authentication.DTO.Events/TimetableDesigner.Backend.Services.Authentication.DTO.Events.csproj" />
<Project Path="TimetableDesigner.Backend.Services.Authentication.DTO.WebAPI/TimetableDesigner.Backend.Services.Authentication.DTO.WebAPI.csproj" />
<Project Path="TimetableDesigner.Backend.Services.Authentication/TimetableDesigner.Backend.Services.Authentication.csproj" />
</Solution>

View File

@@ -1,7 +1,9 @@
using MediatR;
using TimetableDesigner.Backend.Events;
using TimetableDesigner.Backend.Services.Authentication.Application.Helpers;
using TimetableDesigner.Backend.Services.Authentication.Database;
using TimetableDesigner.Backend.Services.Authentication.Database.Model;
using TimetableDesigner.Backend.Services.Authentication.DTO.Events;
namespace TimetableDesigner.Backend.Services.Authentication.Application.Commands.Register;
@@ -9,11 +11,13 @@ public class RegisterHandler : IRequestHandler<RegisterCommand, RegisterResult>
{
private readonly DatabaseContext _databaseContext;
private readonly IPasswordHasher _passwordHasher;
private readonly IEventQueuePublisher _eventQueuePublisher;
public RegisterHandler(DatabaseContext databaseContext, IPasswordHasher passwordHasher)
public RegisterHandler(DatabaseContext databaseContext, IPasswordHasher passwordHasher, IEventQueuePublisher eventQueuePublisher)
{
_databaseContext = databaseContext;
_passwordHasher = passwordHasher;
_eventQueuePublisher = eventQueuePublisher;
}
public async Task<RegisterResult> Handle(RegisterCommand command, CancellationToken cancellationToken)
@@ -28,8 +32,9 @@ public class RegisterHandler : IRequestHandler<RegisterCommand, RegisterResult>
};
await _databaseContext.Accounts.AddAsync(account, cancellationToken);
await _databaseContext.SaveChangesAsync(cancellationToken);
// Publish event (probably in transaction)
RegisterEvent eventData = account.ToEvent();
await _eventQueuePublisher.PublishAsync(eventData);
RegisterResult result = account.ToResult();
return result;

View File

@@ -1,4 +1,5 @@
using TimetableDesigner.Backend.Services.Authentication.Database.Model;
using TimetableDesigner.Backend.Services.Authentication.DTO.Events;
using TimetableDesigner.Backend.Services.Authentication.DTO.WebAPI;
namespace TimetableDesigner.Backend.Services.Authentication.Application.Commands.Register;
@@ -13,4 +14,7 @@ public static class RegisterMappers
public static RegisterResponse ToResponse(this RegisterResult result) =>
new RegisterResponse(result.Id, result.Email);
public static RegisterEvent ToEvent(this Account account) =>
new RegisterEvent(account.Id, account.Email);
}

View File

@@ -17,14 +17,19 @@ public static class Program
{
public static void Main(string[] args)
{
WebApplication app = WebApplication.CreateBuilder(args)
.SetupOpenApi()
.SetupSecurity()
.SetupDatabase()
.SetupHelpers()
.SetupValidation()
.SetupMediatR()
.Build();
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
string databaseConnectionString = builder.Configuration.GetConnectionString("Database")!;
string eventQueueConnectionString = builder.Configuration.GetConnectionString("EventQueue")!;
builder.Services.AddOpenApi();
builder.Services.AddDbContext<DatabaseContext>(x => x.UseNpgsql(databaseConnectionString), ServiceLifetime.Transient);
builder.Services.AddEventQueue<RabbitMQEventQueue>(eventQueueConnectionString);
builder.Services.AddHelpers();
builder.Services.AddValidators();
builder.Services.AddMediatR(x => x.RegisterServicesFromAssembly(typeof(Program).Assembly));
WebApplication app = builder.Build();
if (app.Environment.IsDevelopment())
app.MapOpenApi();
@@ -35,50 +40,17 @@ public static class Program
app.Run();
}
private static WebApplicationBuilder SetupOpenApi(this WebApplicationBuilder builder)
{
builder.Services.AddEventQueue<RabbitMQEventQueue>(cfg =>
{
cfg.Hostname = "localhost";
cfg.Port = 5672;
cfg.Username = "user";
cfg.Password = "l4JxOIuSoyod86N";
cfg.ExchangeName = "events";
cfg.QueuePrefix = "authentication";
});
builder.Services.AddOpenApi();
return builder;
}
private static WebApplicationBuilder SetupSecurity(this WebApplicationBuilder builder)
private static IServiceCollection AddHelpers(this IServiceCollection services)
{
//builder.Services.AddAuthorization();
return builder;
services.AddSingleton<IPasswordHasher, PasswordHasher>();
return services;
}
private static WebApplicationBuilder SetupDatabase(this WebApplicationBuilder builder)
private static IServiceCollection AddValidators(this IServiceCollection services)
{
builder.Services.AddDbContext<DatabaseContext>(x => x.UseNpgsql(builder.Configuration.GetConnectionString("Database")), ServiceLifetime.Transient);
return builder;
}
private static WebApplicationBuilder SetupHelpers(this WebApplicationBuilder builder)
{
builder.Services.AddSingleton<IPasswordHasher, PasswordHasher>();
return builder;
}
private static WebApplicationBuilder SetupValidation(this WebApplicationBuilder builder)
{
builder.Services.AddScoped<IValidator<TimetableDesigner.Backend.Services.Authentication.DTO.WebAPI.RegisterRequest>, RegisterRequestValidator>();
return builder;
}
private static WebApplicationBuilder SetupMediatR(this WebApplicationBuilder builder)
{
builder.Services.AddMediatR(x => x.RegisterServicesFromAssembly(typeof(Program).Assembly));
return builder;
services.AddScoped<IValidator<TimetableDesigner.Backend.Services.Authentication.DTO.WebAPI.RegisterRequest>, RegisterRequestValidator>();
return services;
}
private static WebApplication InitializeDatabase(this WebApplication app)

View File

@@ -18,11 +18,12 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="10.0.0" />
<PackageReference Include="timetabledesigner.backend.events.extensions.aspnetcore.openapi" Version="1.0.0" />
<PackageReference Include="TimetableDesigner.Backend.Events.Providers.RabbitMQ" Version="1.0.1" />
<PackageReference Include="timetabledesigner.backend.events.extensions.aspnetcore.openapi" Version="1.0.1" />
<PackageReference Include="TimetableDesigner.Backend.Events.Providers.RabbitMQ" Version="1.0.4" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\TimetableDesigner.Backend.Services.Authentication.DTO.Events\TimetableDesigner.Backend.Services.Authentication.DTO.Events.csproj" />
<ProjectReference Include="..\TimetableDesigner.Backend.Services.Authentication.DTO.WebAPI\TimetableDesigner.Backend.Services.Authentication.DTO.WebAPI.csproj" />
</ItemGroup>

View File

@@ -29,7 +29,7 @@ public static class Endpoints
return app;
}
private static async Task<Results<Created<RegisterResponse>, ValidationProblem>> Register(IMediator mediator, IValidator<RegisterRequest> validator, RegisterRequest request)
private static async Task<Results<Created<RegisterResponse>, ValidationProblem>> Register(IMediator mediator, IValidator<RegisterRequest> validator, RegisterRequest request, CancellationToken cancellationToken)
{
ValidationResult validationResult = await validator.ValidateAsync(request);
if (!validationResult.IsValid)
@@ -38,7 +38,7 @@ public static class Endpoints
}
RegisterCommand registerCommand = request.ToCommand();
RegisterResult result = await mediator.Send(registerCommand);
RegisterResult result = await mediator.Send(registerCommand, cancellationToken);
RegisterResponse response = result.ToResponse();
return TypedResults.Created($"accounts/{response.Id}", response);

View File

@@ -7,6 +7,7 @@
},
"AllowedHosts": "*",
"ConnectionStrings": {
"Database": "Host=localhost;Port=5433;Database=ttd_authentication;Username=postgres;Password=l4JxOIuSoyod86N;Include Error Detail=True"
"Database": "Host=localhost;Port=5433;Database=ttd_authentication;Username=postgres;Password=l4JxOIuSoyod86N;Include Error Detail=True",
"EventQueue": "Hostname=localhost;Port=5672;Username=user;Password=l4JxOIuSoyod86N;ExchangeName=events;QueuePrefix=authentication"
}
}