Backend: - Cookie + OIDC + API Key authentication schemes - ApiKeyAuthenticationHandler with SHA-256 validation and 24h cache - AuthController with login/logout/profile endpoints - API Key domain model (EventFlow aggregate, events, commands) - ApiKeyReadModel and repository for key validation - Database migration 002_ApiKeys.sql - CORS configuration for frontend Frontend: - authService.ts for login/logout/profile API calls - authStore.ts (Zustand) for user context state - ProtectedRoute component for route guards - Header updated with user display and logout - GraphQL client with credentials: include 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
30 lines
871 B
C#
30 lines
871 B
C#
using Books.Api.Domain.ApiKeys;
|
|
using EventFlow.Commands;
|
|
|
|
namespace Books.Api.Commands.ApiKeys;
|
|
|
|
public class CreateApiKeyCommandHandler
|
|
: CommandHandler<ApiKeyAggregate, ApiKeyId, CreateApiKeyCommand>
|
|
{
|
|
public override Task ExecuteAsync(
|
|
ApiKeyAggregate aggregate,
|
|
CreateApiKeyCommand command,
|
|
CancellationToken cancellationToken)
|
|
{
|
|
aggregate.Create(command.Name, command.KeyHash, command.CompanyId, command.CreatedBy);
|
|
return Task.CompletedTask;
|
|
}
|
|
}
|
|
|
|
public class RevokeApiKeyCommandHandler
|
|
: CommandHandler<ApiKeyAggregate, ApiKeyId, RevokeApiKeyCommand>
|
|
{
|
|
public override Task ExecuteAsync(
|
|
ApiKeyAggregate aggregate,
|
|
RevokeApiKeyCommand command,
|
|
CancellationToken cancellationToken)
|
|
{
|
|
aggregate.Revoke(command.RevokedBy);
|
|
return Task.CompletedTask;
|
|
}
|
|
}
|