Skip to content

Commit b6627e2

Browse files
iammukeshmclaude
andcommitted
fix(build): add domain event handlers to satisfy Mediator source generator
The Mediator source generator (MSG0005) requires every INotification message to have at least one registered handler. Added INotificationHandler<T> implementations for all 6 Identity domain events. UserRegisteredHandler also bridges to the integration event pipeline. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent e12336b commit b6627e2

6 files changed

Lines changed: 186 additions & 0 deletions

File tree

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using FSH.Modules.Identity.Domain.Events;
2+
using Mediator;
3+
using Microsoft.Extensions.Logging;
4+
5+
namespace FSH.Modules.Identity.Events;
6+
7+
/// <summary>
8+
/// Handles the PasswordChangedEvent domain event.
9+
/// </summary>
10+
public sealed class PasswordChangedHandler(
11+
ILogger<PasswordChangedHandler> logger)
12+
: INotificationHandler<PasswordChangedEvent>
13+
{
14+
public ValueTask Handle(PasswordChangedEvent notification, CancellationToken cancellationToken)
15+
{
16+
ArgumentNullException.ThrowIfNull(notification);
17+
18+
if (logger.IsEnabled(LogLevel.Information))
19+
{
20+
logger.LogInformation(
21+
"Password changed for user {UserId} (reset: {WasReset})",
22+
notification.UserId,
23+
notification.WasReset);
24+
}
25+
26+
return ValueTask.CompletedTask;
27+
}
28+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
using FSH.Modules.Identity.Domain.Events;
2+
using Mediator;
3+
using Microsoft.Extensions.Logging;
4+
5+
namespace FSH.Modules.Identity.Events;
6+
7+
/// <summary>
8+
/// Handles the SessionRevokedEvent domain event.
9+
/// </summary>
10+
public sealed class SessionRevokedHandler(
11+
ILogger<SessionRevokedHandler> logger)
12+
: INotificationHandler<SessionRevokedEvent>
13+
{
14+
public ValueTask Handle(SessionRevokedEvent notification, CancellationToken cancellationToken)
15+
{
16+
ArgumentNullException.ThrowIfNull(notification);
17+
18+
if (logger.IsEnabled(LogLevel.Information))
19+
{
20+
logger.LogInformation(
21+
"Session {SessionId} revoked for user {UserId} by {RevokedBy}: {Reason}",
22+
notification.SessionId,
23+
notification.UserId,
24+
notification.RevokedBy,
25+
notification.Reason);
26+
}
27+
28+
return ValueTask.CompletedTask;
29+
}
30+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using FSH.Modules.Identity.Domain.Events;
2+
using Mediator;
3+
using Microsoft.Extensions.Logging;
4+
5+
namespace FSH.Modules.Identity.Events;
6+
7+
/// <summary>
8+
/// Handles the UserActivatedEvent domain event.
9+
/// </summary>
10+
public sealed class UserActivatedHandler(
11+
ILogger<UserActivatedHandler> logger)
12+
: INotificationHandler<UserActivatedEvent>
13+
{
14+
public ValueTask Handle(UserActivatedEvent notification, CancellationToken cancellationToken)
15+
{
16+
ArgumentNullException.ThrowIfNull(notification);
17+
18+
if (logger.IsEnabled(LogLevel.Information))
19+
{
20+
logger.LogInformation(
21+
"User {UserId} activated by {ActivatedBy}",
22+
notification.UserId,
23+
notification.ActivatedBy);
24+
}
25+
26+
return ValueTask.CompletedTask;
27+
}
28+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
using FSH.Modules.Identity.Domain.Events;
2+
using Mediator;
3+
using Microsoft.Extensions.Logging;
4+
5+
namespace FSH.Modules.Identity.Events;
6+
7+
/// <summary>
8+
/// Handles the UserDeactivatedEvent domain event.
9+
/// </summary>
10+
public sealed class UserDeactivatedHandler(
11+
ILogger<UserDeactivatedHandler> logger)
12+
: INotificationHandler<UserDeactivatedEvent>
13+
{
14+
public ValueTask Handle(UserDeactivatedEvent notification, CancellationToken cancellationToken)
15+
{
16+
ArgumentNullException.ThrowIfNull(notification);
17+
18+
if (logger.IsEnabled(LogLevel.Information))
19+
{
20+
logger.LogInformation(
21+
"User {UserId} deactivated by {DeactivatedBy}: {Reason}",
22+
notification.UserId,
23+
notification.DeactivatedBy,
24+
notification.Reason);
25+
}
26+
27+
return ValueTask.CompletedTask;
28+
}
29+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
using FSH.Framework.Eventing.Abstractions;
2+
using FSH.Modules.Identity.Contracts.Events;
3+
using FSH.Modules.Identity.Domain.Events;
4+
using Mediator;
5+
using Microsoft.Extensions.Logging;
6+
7+
namespace FSH.Modules.Identity.Events;
8+
9+
/// <summary>
10+
/// Handles the UserRegisteredEvent domain event by publishing an integration event
11+
/// so other modules can react to new user registrations.
12+
/// </summary>
13+
public sealed class UserRegisteredHandler(
14+
IEventBus eventBus,
15+
ILogger<UserRegisteredHandler> logger)
16+
: INotificationHandler<UserRegisteredEvent>
17+
{
18+
public async ValueTask Handle(UserRegisteredEvent notification, CancellationToken cancellationToken)
19+
{
20+
ArgumentNullException.ThrowIfNull(notification);
21+
22+
if (logger.IsEnabled(LogLevel.Information))
23+
{
24+
logger.LogInformation(
25+
"User registered: {UserId} ({Email})",
26+
notification.UserId,
27+
notification.Email);
28+
}
29+
30+
var integrationEvent = new UserRegisteredIntegrationEvent(
31+
Id: notification.EventId,
32+
OccurredOnUtc: notification.OccurredOnUtc.UtcDateTime,
33+
TenantId: notification.TenantId,
34+
CorrelationId: notification.CorrelationId ?? notification.EventId.ToString(),
35+
Source: nameof(UserRegisteredHandler),
36+
UserId: notification.UserId,
37+
Email: notification.Email,
38+
FirstName: notification.FirstName ?? string.Empty,
39+
LastName: notification.LastName ?? string.Empty);
40+
41+
await eventBus.PublishAsync(integrationEvent, cancellationToken).ConfigureAwait(false);
42+
}
43+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using FSH.Modules.Identity.Domain.Events;
2+
using Mediator;
3+
using Microsoft.Extensions.Logging;
4+
5+
namespace FSH.Modules.Identity.Events;
6+
7+
/// <summary>
8+
/// Handles the UserRoleAssignedEvent domain event.
9+
/// </summary>
10+
public sealed class UserRoleAssignedHandler(
11+
ILogger<UserRoleAssignedHandler> logger)
12+
: INotificationHandler<UserRoleAssignedEvent>
13+
{
14+
public ValueTask Handle(UserRoleAssignedEvent notification, CancellationToken cancellationToken)
15+
{
16+
ArgumentNullException.ThrowIfNull(notification);
17+
18+
if (logger.IsEnabled(LogLevel.Information))
19+
{
20+
logger.LogInformation(
21+
"Roles assigned to user {UserId}: {Roles}",
22+
notification.UserId,
23+
string.Join(", ", notification.AssignedRoles));
24+
}
25+
26+
return ValueTask.CompletedTask;
27+
}
28+
}

0 commit comments

Comments
 (0)