Skip to content

Cross-Module Recipes — Workflow, Authorization & Encryption Integration

These recipes show how to combine Granit.Notifications with other framework modules for common real-world scenarios.

Workflow + Notifications: notify on state transition

Section titled “Workflow + Notifications: notify on state transition”

When an entity transitions in a workflow, publish a notification automatically. The WorkflowStateChangedEvent is published by Wolverine — handle it in a notification handler:

public static class InvoiceApprovalNotificationHandler
{
public static async Task Handle(
WorkflowStateChangedEvent @event,
INotificationPublisher publisher,
CancellationToken ct)
{
if (@event.NewState != nameof(InvoiceStatus.PendingApproval))
return;
await publisher.PublishAsync(new NotificationRequest(
Type: "InvoiceApprovalRequired",
EntityType: "Invoice",
EntityId: @event.EntityId,
Recipients: [@event.Properties["ApproverId"]],
Data: new { InvoiceNumber = @event.Properties["Number"] }), ct)
.ConfigureAwait(false);
}
}

Authorization + Notifications: permission-gated channels

Section titled “Authorization + Notifications: permission-gated channels”

Use IPermissionChecker to restrict notification channels based on the sender’s permissions (e.g., only managers can trigger SMS notifications):

public class SmsPermissionFilter(IPermissionChecker permissionChecker)
: INotificationChannelFilter
{
public async Task<bool> ShouldSendAsync(
NotificationContext context, CancellationToken ct)
{
return await permissionChecker
.IsGrantedAsync("Notifications.Sms.Send")
.ConfigureAwait(false);
}
}

Encryption + Notifications: protect PII in notification payloads

Section titled “Encryption + Notifications: protect PII in notification payloads”

When notification data contains PII (patient names, account numbers), encrypt the Data dictionary before persisting. The InApp channel stores the notification in the database — combine with IStringEncryptionService:

public class EncryptedNotificationEnricher(IStringEncryptionService encryption)
: INotificationDataEnricher
{
public Task EnrichAsync(NotificationContext context, CancellationToken ct)
{
if (context.Data.TryGetValue("PatientName", out var name))
context.Data["PatientName"] = encryption.Encrypt(name?.ToString() ?? "");
return Task.CompletedTask;
}
}
CategoryKey typesPackage
ModuleGranitNotificationsModule, GranitNotificationsEntityFrameworkCoreModule, GranitNotificationsWolverineModule
PublisherINotificationPublisher, NotificationType<TData>Granit.Notifications
ChannelsINotificationChannel, NotificationChannels, NotificationDeliveryContextGranit.Notifications
DefinitionsNotificationDefinition, INotificationDefinitionProvider, INotificationDefinitionContext, INotificationDefinitionStoreGranit.Notifications
EntitiesUserNotification, NotificationDeliveryAttempt, NotificationPreference, NotificationSubscription, UserNotificationStateGranit.Notifications
CQRSIUserNotificationReader, IUserNotificationWriter, INotificationPreferenceReader, INotificationPreferenceWriter, INotificationSubscriptionReader, INotificationSubscriptionWriter, INotificationDeliveryWriterGranit.Notifications
RecipientIRecipientResolver, RecipientInfoGranit.Notifications
Entity trackingITrackedEntity, TrackedPropertyConfig, EntityStateChangedData, EntityReferenceGranit.Notifications
MessagesNotificationTrigger, DeliverNotificationCommandGranit.Notifications
HandlersNotificationFanoutHandler, NotificationDeliveryHandlerGranit.Notifications
OptionsNotificationsOptions, EmailChannelOptions, SmtpOptions, BrevoOptions, ScalewayEmailOptions, SendGridEmailOptions, AcsEmailOptions, SmsChannelOptions, AcsSmsOptions, AwsSnsSmsOptions, TwilioOptions, MobilePushChannelOptions, GoogleFcmOptions, AzureNotificationHubsOptions, AwsSnsMobilePushOptions, SignalRChannelOptions, PushChannelOptions, SseChannelOptions, ZulipChannelOptions, ZulipBotOptionsvarious
EmailIEmailSender, EmailMessageGranit.Notifications.Email, Granit.Notifications.Email.AzureCommunicationServices, Granit.Notifications.Email.Scaleway, Granit.Notifications.Email.SendGrid
SMSISmsSender, SmsMessageGranit.Notifications.Sms, Granit.Notifications.Sms.AwsSns, Granit.Notifications.Twilio
WhatsAppIWhatsAppSender, WhatsAppMessageGranit.Notifications.WhatsApp, Granit.Notifications.Twilio
Mobile PushIMobilePushSender, MobilePushMessage, IMobilePushTokenReader, IMobilePushTokenWriter, MobilePushTokenInfo, MobilePlatformGranit.Notifications.MobilePush, Granit.Notifications.MobilePush.AwsSns
SignalRNotificationHub, SignalRNotificationMessageGranit.Notifications.SignalR
Web PushIPushSubscriptionReader, IPushSubscriptionWriter, PushSubscriptionInfoGranit.Notifications.WebPush
SSEISseConnectionManager, SseConnection, SseNotificationMessageGranit.Notifications.Sse
ZulipIZulipSender, ZulipMessageGranit.Notifications.Zulip
ExceptionsNotificationDeliveryExceptionGranit.Notifications
EndpointsNotificationEndpointsOptions, MobilePushTokenEndpointsGranit.Notifications.Endpoints
ExtensionsAddGranitNotifications(), AddGranitNotificationsEntityFrameworkCore(), AddGranitNotificationsEmail(), AddGranitNotificationsEmailSmtp(), AddGranitNotificationsEmailAcs(), AddGranitNotificationsEmailScaleway(), AddGranitNotificationsEmailSendGrid(), AddGranitNotificationsBrevo(), AddGranitNotificationsSms(), AddGranitNotificationsSmsAcs(), AddGranitNotificationsSmsAwsSns(), AddGranitNotificationsTwilio(), AddGranitNotificationsWhatsApp(), AddGranitNotificationsMobilePush(), AddGranitNotificationsMobilePushGoogleFcm(), AddGranitNotificationsMobilePushAzureNotificationHubs(), AddGranitNotificationsMobilePushAwsSns(), AddGranitNotificationsSignalR(), AddGranitNotificationsPush(), AddGranitNotificationsSse(), AddGranitNotificationsZulip(), AddNotificationDefinitions<T>(), MapGranitNotifications(), MapGranitMobilePushTokens()various