using MediatR; using Microsoft.EntityFrameworkCore; using SequenceAuth.Example.Domain; using SequenceAuth.Example.Infrastructure; using SequenceAuth.Lib; namespace SequenceAuth.Example.Features.Auth; public record LoginCommand(string Username) : IRequest; public record LoginResult(User User, string InitialSequence); public class LoginCommandHandler(AppDbContext dbContext, ISequenceStore sequenceStore, Microsoft.AspNetCore.Http.IHttpContextAccessor httpContextAccessor, Microsoft.Extensions.Options.IOptions options) : IRequestHandler { public async Task Handle(LoginCommand request, CancellationToken cancellationToken) { var userOpt = await dbContext.Users.FirstOrDefaultAsync(u => u.Username == request.Username, cancellationToken); var user = userOpt switch { null => await CreateUser(request.Username, cancellationToken), _ => userOpt }; var initialSequenceId = Guid.NewGuid().ToString("N"); var sequenceData = new SequenceData(UserId: user.Id.ToString(), RequestsRemaining: 1000, State: SequenceState.Initialized, NextSequenceId: initialSequenceId); await sequenceStore.SaveSequenceAsync(initialSequenceId, sequenceData); httpContextAccessor.HttpContext?.Response.Headers.Append(options.Value.NextHeaderName, initialSequenceId); httpContextAccessor.HttpContext?.Response.Headers.Append(options.Value.RequestsRemainingHeaderName, "1000"); return new LoginResult(user, initialSequenceId); } private async Task CreateUser(string username, CancellationToken cancellationToken) { var user = new User(Guid.NewGuid(), username); dbContext.Users.Add(user); await dbContext.SaveChangesAsync(cancellationToken); return user; } }