Notification Manager configuration
The Notification Manager needs some configuration in order to be used effectively.
CRUD collections
To use the Notification Manager you need to create the following CRUD collections:
users
: a CRUD containing the users;templates
: a CRUD containing the notification templates;event settings
: a CRUD containing the event settings;events
: a CRUD containing events (used to store details about unknown events);notifications
: a CRUD containing the notifications sent;notification settings
: a CRUD containing the notification settings.
Users CRUD
Since version v2.3.0 the users collection is no longer required if the USERS_API_ENDPOINT
is specified and it points to an external service that handles users.
This CRUD collection contains the data of the users you want to send messages to. The collection is required and
can be named however you want (we suggest users
) as long as you specify the name in the USERS_CRUD_NAME
environment variable.
The CRUD collection must have the properties listed in the following table.
Name | Type | Required | Description |
---|---|---|---|
id | string | No | The user's unique identifier. |
clusters | Array of strings | No | A list of clusters the user belongs to (used to decide if the user should be included as a recipient when sending a message to a particular cluster). |
groups | Array of strings | No | A list of groups the user belongs to (used to decide if the user should be included as a recipient when sending a message to a particular group). |
roles | Array of strings | No | A list of roles associated to the user. |
emailAddress | string | For email notifications | A valid e-mail address. |
phoneNumber | string | For SMS notifications | A phone number in E.164 formatformat. |
deviceToken | string | For push notifications | A Firebase devices token. |
The naming of these properties is up to you. By default, the service will look for the names listed above, but if
you prefer using other names you just need to map them correctly in the userFields
properties of the
service configuration.
None of these properties are required. If the service does not find a value for a user, it will simply not send messages to that user over the missing channel(s).
The collection can have any number of additional properties, the service will ignore them.
Templates CRUD
The templates collection contains all the information needed to create standardized messages.
v2.0.0. Since version 2.0.0 this collection is required both for sending automatic notifications based on events and whatsapp messaging service. Also, the name
field is now required.
v1.5.0. Since version 1.5.0 the pushTitle
and pushMessage
fields are no longer required, since you can use pushData
to provide a custom payload for push notifications.
This CRUD collection contains the message templates for sending notifications, both manually (optional) and automatically (required).
Like for the users
collection, it does not matter how the CRUD is named (we suggest message_templates
) as long as
you specify the name in the TEMPLATES_CRUD_NAME
environment variable.
The CRUD collection must have the properties listed in the following table.
Name | Type | Required | Description |
---|---|---|---|
name | string | Yes | A human-readable name of the template. Required since v2.0.0. |
emailTitle | string | For email notifications | Email title. It supports interpolation. |
emailMessage | string | For email notifications | Email plain-text body. Required if htmlMessage is not defined. It will be ignored if emailHtmlMessage is set and supports interpolation. |
emailHtmlMessage | string | For email notifications | Email HTML body. Required if emailMessage is not defined; if both are defined, only emailHtmlMessage is used. It supports interpolation. |
emailAttachments | Array of object | For email notifications | List of objects with the same interface given by File Service. The only compulsory field is the file attribute. |
smsMessage | string | For SMS notifications | SMS body. It supports interpolation. |
voiceMessage | string | For voice notifications | Voice message body. It supports interpolation. |
pushTitle | string | For push notifications | Optional since v1.5.0. Push notification title. It supports interpolation. |
pushSubtitle | string | For push notifications | Push notification subtitle. It supports interpolation. |
pushMessage | string | For push notifications | Optional since v1.5.0. Push notification message. It supports interpolation. |
pushData | string | For push notifications | JSON payload of the notification. It supports interpolation. |
whatsappTemplateName | string | For whatsapp notifications | Whatsapp template name. |
whatsappTemplateParameters | string | For whatsapp notifications | A comma-separated list of values to pass as parameters (see TEMPLATE_PARAMETERS in Kaleyra API documentation). It supports interpolation. |
Since version 1.5.0, the pushData
field is available to customize the push notifications, for example to provide localized messages, and takes precedence over the other fields - pushTitle
, pushSubtitle
and pushMessage
. The field accepts as value a JSON object with the following fields:
- android -
object
: android-specific information to be included in the message. The object must conform the shape described here. - apns -
object
: information specific to APNS (Apple Push Notification Service). The object must conform the shape described here.
The fields relative to a channel are required only if plan to use templates, and you want to send messages through that channel (this applies also to the fields marked as required in the list above).
Event settings CRUD
v2.0.0. This CRUD collection was introduced and is required since version 2.0.0.
This CRUD collection contains the settings for each class of events.
The collection is required and can be named however you want (we suggest event_settings
) as long as you specify the name in the EVENTS_SETTINGS_CRUD_NAME
environment variable.
The CRUD collection must have the properties listed in the following table.
Name | Type | Required | Description |
---|---|---|---|
eventName | string | Yes | Name of the event the settings refer. |
userGroups | Array of string | No | List of groups the event is visible to (all by default if the field is not set). |
supportedChannels | Array of string | No | List of channels supported by the event, must be a subset of the channels enabled at the service level. |
eventSchema | Object | No | JSON schema to validate the received event. |
handlerName | string | No | Name of the custom handler to use to process the event. |
handlerConfig | Object | No | An arbitrary configuration for the event handler. |
The handlerConfig
is not currently used, but it has been introduced in anticipation of new features planned for future releases.
Events CRUD
v2.0.0. This CRUD collection was added and is required since version 2.0.0.
This CRUD collection contains details about events, in particular unknown events, that were received.
The collection is required and can be named however you want (we suggest events
) as long as you specify the name in the EVENTS_CRUD_NAME
environment variable.
The CRUD collection must have the properties listed in the following table.
Name | Type | Required | Description |
---|---|---|---|
id | string | Yes | Event identifier (must be unique across the system). |
key | string | No | Event key (ID of the main resource associated to the event, like an appointment or plan). |
name | string | Yes | Event name. |
metadata | Object | No | Event metdata, to provide additional details to the event handler. |
payload | Object | No | Event payload |
source | Object | Yes | Event source (HTTP request) |
status | string | Yes | Event status (RECEIVED , PROCESSED , ERROR ) |
errors | Array of object | No | List of errors occurred processing the event |
Notifications CRUD
v2.0.0. This CRUD collection was added and is required since version 2.0.0.
This CRUD collection contains details about the notifications sent in response to events.
The collection is required and can be named however you want (we suggest notifications
)
as long as you specify the name in the NOTIFICATIONS_CRUD_NAME
environment variable.
The CRUD collection must have the properties listed in the following table.
Name | Type | Required | Description |
---|---|---|---|
event | Object | Yes | The event the notification is about, as in the events CRUD. |
recipient | string | No | ID of the user the notification was sent to. |
messages | Array of object | No | List of messages processed. |
reminders | Array of object | No | List of reminders processed. |
failures | Array of object | No | List of generic errors occurred processing the notification. |
Notification messages
Each message in the messages
field represents a single message sent to the recipient using the given template on a specific channel.
Each message has the properties illustrated in the following table.
Name | Type | Required | Description |
---|---|---|---|
status | string | Yes | If the message was processed correctly (SUCCESS ) or not (FAILURE ). |
channel | string | Yes | Name of the channel the message was sent on. |
templateName | string | Yes | Name of the template used to send the message on the channel. |
attachments | Array of object | No | List of custom attachments sent (available since version 2.3.0). |
service | Object | No | An object containing information about the notification processed by a service provider. |
error | Object | No | In case of errors, it contains additional information about the error. |
So, for example, if you configure a notification settings with the following reminders:
{
"user": "auth0|john.doe",
"channel": "email",
"templateName": "create-appointment-patient",
"attachments": [{"file" :"patient-medical-record.pdf"}]
}
in the notification you could find something like this:
{
"messages": [
{
"status": "SUCCESS",
"channel": "email",
"templateName": "create-appointment-patient",
"attachments": [{"file" :"patient-medical-record.pdf"}],
"service": {
"message": {
"sender": "noreply@example.com",
"recipient": "patient0@example.com",
"subject": "New appointment confirmed on 2023/12/15 at 09:30",
"htmlMessage": "Dear patient, we confirm your appointment on 2023/12/15 at 09:30."
}
}
},
{
"status": "FAILURE",
"channel": "sms",
"templateName": "create-appointment-patient",
"service": {
"message": {
"sender": "St.Claire Hospital",
"receiver": "+391234567890",
"body": "Dear patient, we confirm your appointment on 2023/12/15 at 09:30.",
}
},
"error": { "statusCode": 401, "error": "Unauthorized", "message": "..." }
},
{
"status": "SUCCESS",
"channel": "voice",
"templateName": "create-appointment-patient",
"service": {
"message": {
"receiver": "+391234567890",
"body": "Dear patient, we confirm your appointment on 2023/12/15 at 09:30.",
}
}
},
{
"status": "FAILURE",
"channel": "whatsapp",
"templateName": "create-appointment-patient",
"service": {
"message": {
"sender": "St.Claire Hospital",
"receiver": "+391234567890",
"templateName": "whatsapp-create-appointment-patient",
"params": "John,Doe,2023-12-15T09:30:00",
}
},
"error": { "statusCode": 503, "error": "Service Unavailable", "message": "..." }
}
]
}
Notification reminders
Each reminder in the reminders
field matches the corresponding reminder in the notification settings field with the same name.
Each reminder has the properties illustrated in the following table.
Name | Type | Required | Description |
---|---|---|---|
status | string | Yes | If the reminder was processed correctly (ACTIVE or ABORTED ) or not (ERROR ). |
expirationDate | string | Yes | When the reminder expires, as an ISO 8601 date-time string. |
expirationId | string | No | The ID of the job scheduled on the Timer Service (if the reminder was processed correctly). |
schedule | string | No | The reminder schedule, as an ISO 8601 duration string. |
triggers | Array of string | No | The IDs of the notification settings that triggered this notification. |
error | Object | No | In case of errors, it contains additional information about the error, like the response received by the Timer Service. |
So, for example, if you configure a notification settings with the following reminders:
{
"reminders": ["P1D", "PT2H"]
}
in the notification you could find something like this:
{
"reminders": [
{
"status": "ACTIVE",
"expirationDate": "2023-08-12T09:30:00Z",
"schedule": "P1D",
"expirationId": "4b5f068c-5f8b-4f0b-ba69-1b0025633edc"
},
{
"status": "ERROR",
"expirationDate": "2023-08-13T07:30:00Z",
"schedule": "PT2H",
"error": {
"statusCode": 503,
"error": "Service Unavailable",
"message": "..."
}
}
]
}
Notification settings CRUD
v2.0.0. This CRUD collection was introduced with version 2.0.0.
This CRUD collection contains the notification settings. The collection is required and
can be named however you want (we suggest notifications_settings
) as long as you specify the name in the NOTIFICATIONS_SETTINGS_CRUD_NAME
environment variable.
The properties used by the service are the following.
Name | Type | Required | Description |
---|---|---|---|
eventName | string | Yes | Name of the event for which notifications are sent. |
user | string | No | ID of a user who can receive notifications. |
group | string | No | Group of users who can receive notifications. |
cluster | string | No | Cluster who can receive notifications. |
role | string | No | Role who can receive notifications. |
channels | Array of string | Yes | List of channels to send notifications on. |
hours | Array of string | No | List of time slots when notifications can be sent. Each time value must be expressed in ISO 8601 time format (for example, 09:00-18:00 ). |
templateName | string | Yes | Template name from the templates CRUD to use. |
rule | string | No | If the given users, groups and/or cluster should receive (SEND ) or not (IGNORE ) notifications. |
emitters | Array of string | No | List of emitters that should trigger the sending of notifications. |
reminders | Array of string | No | List of reminders to set, expressed as ISO 8601 duration strings (for example, P1D for one day and PT1H for an hour before). |
Views
Notification messages view
This view is required by the following endpoints and must be enabled explicitly by setting the NOTIFICATIONS_MESSAGES_VIEW_NAME
environment variable:
By default, the view is not enabled and these endpoints are not available.
This MongoDB view runs an aggregation pipeline on the notifications CRUD collection to return a distinct document for each message sent, i.e. each element in the notification messages
array field.
The MongoDB view must have the properties listed in the following table.
Name | Type | Required | Description |
---|---|---|---|
notificationId | String | No | CRUD _id of the notification. |
recipient | String | No | ID of the user the message was sent to. |
event | String | No | The name of the event. |
date | Date | No | When the message was sent. |
status | String | No | If the message was processed correctly (SUCCESS ) or not (FAILURE ). |
channel | String | No | Name of the channel the message was sent on. |
templateName | String | No | Name of the template used to send the message on the channel. |
message | Object | No | The details about the message sent (title, subtitle, body, etc.) |
This is the aggregation pipeline, that you can customize for example by adding additional fields.
[
{
"$match": {
"__STATE__": "PUBLIC"
}
},
{
"$unwind": {
"path": "$messages"
}
},
{
"$project": {
"_id": {
"$concat": [
{
"$toString": "$_id"
},
"-",
"$messages.channel",
"-",
"$messages.templateName"
]
},
"creatorId": "$creatorId",
"createdAt": "$createdAt",
"updaterId": "$updaterId",
"updatedAt": "$updatedAt",
"__STATE__": "$__STATE__",
"notificationId": {
"$toString": "$_id"
},
"recipient": "$recipient",
"event": "$event.name",
"date": "$createdAt",
"status": "$messages.status",
"channel": "$messages.channel",
"templateName": "$messages.templateName",
"message": "$messages.service.message"
}
}
]
The _id
field is computed dinamically based on the notification _id
and is unique across all messages.
Environment variables
v2.3.0. Since version 2.3.0 the USERS_API_ENDPOINT
environment variable is available, to configure the base URL of an API providing users data with a CRUD-like interface.
If USERS_API_ENDPOINT
is not set, the users data is retrieved as in previous versions from a CRUD collection using the CRUD_SERVICE_URL
and USERS_CRUD_NAME
environment variables.
v2.3.0. Since version 2.3.0 the DEFAULT_LOCALE
environment variable is available, to configure the default locale to use with toLocale
custom helper.
v2.2.0. Since version 2.2.0 the GOOGLE_APPLICATION_CREDENTIALS
environment variable is available, to send push notifications directly to Firebase, without needing Kafka.
v2.0.0. Since version 2.0.0 the following environment variables are no longer available, so if you are upgrading from version 1.x you need to update the service configuration first:
CRUD_SERVICE_NAME
(useCRUD_SERVICE_URL
instead).
Name | Required | Default | Version | Description |
---|---|---|---|---|
SERVICE_NAME | Yes | - | * | The name of the Notification Manager microservice. |
CONFIGURATION_PATH | Yes | - | * | Path of the config map file containing the service configuration. |
CRUD_SERVICE_URL | Yes | - | >= 2.0.0 | The HTTP(S) URL of the CRUD service. This environment variable replaces CRUD_SERVICE_NAME since version 2.0.0. |
USERS_CRUD_NAME | Yes | - | * | Name of the CRUD collection containing users data. |
TEMPLATES_CRUD_NAME | Yes | - | * | Name of the CRUD collection containing messaging templates. |
EVENTS_CRUD_NAME | Yes | - | * | Name of the CRUD collection containing events. |
EVENTS_SETTINGS_CRUD_NAME | Yes | - | * | Name of the CRUD collection containing event settings. |
NOTIFICATIONS_CRUD_NAME | Yes | - | * | Name of the CRUD collection containing statistics about notifications sent. |
NOTIFICATIONS_SETTINGS_CRUD_NAME | Yes | - | * | Name of the CRUD collection containing the notifications settings. |
NOTIFICATIONS_MESSAGES_VIEW_NAME | No | - | >= 2.4.0 | Name of the MongoDB view containing the notification messages. |
MAIL_SERVICE_URL | Email notifications | - | * | URL of the SES Mail Notification Service. Required if you want to send e-mails. |
SMS_SERVICE_URL | SMS notifications | - | * | URL of the SMS Service. Required if you want to send SMS. |
FILE_SERVICE_URL | Email attachments | - | * | URL of the File Service. Required if you want to send emails with attachments. |
TIMER_SERVICE_URL | Reminders | - | * | The HTTP(S) URL of the Timer Service. |
KAFKA_CLIENT_ID | Push notifications | - | * | Required if you want to send push notifications. |
KAFKA_BROKERS | Push notifications | - | * | List of comma separated brokers address. Required if you want to send push notifications. |
KAFKA_TOPICS | Push notifications | - | * | List of comma separated topics. Required if you want to send push notifications. |
KAFKA_AUTH_MECHANISM | Push notifications | PLAIN | * | Authentication mechanism, used only if KAFKA_USERNAME and KAFKA_PASSWORD have a value. |
KAFKA_USERNAME | Push notifications | - | * | |
KAFKA_PASSWORD | Push notifications | - | * | |
KAFKA_CONNECTION_TIMEOUT | Push notifications | 1000 | * | Time in milliseconds to wait for a successful connection. |
KAFKA_AUTHENTICATION_TIMEOUT | Push notifications | 1000 | * | Time in milliseconds to wait for a successful authentication. |
KAFKA_EVENTS_TOPIC_NAME | No | - | * | Name of the Kafka topic for incoming events. If not set, automatic notifications via Kafka are disabled. |
KAFKA_ERRORS_TOPIC_NAME | No | - | * | Name of the Kafka topic for unknown events. If not set, automatic notifications via Kafka are disabled. |
KAFKA_CONSUMER_GROUP | No | - | * | Name of the Kafka consumer group for Kafka topic for incoming events. |
KALEYRA_API_BASE_URL | No | - | * | Kaleyra API base URL for the whatsapp and outbound calling services. |
KALEYRA_API_KEY | No | - | * | Kaleyra API key for the whatsapp and outbound calling services. |
KALEYRA_API_SID | No | - | * | Kaleyra SID for the whatsapp and outbound calling services. |
CUSTOM_HANDLERS_FOLDER | Custom handlers | - | * | The path to the directory containing the definitions (i.e. the configmaps) of the custom handlers. |
GOOGLE_APPLICATION_CREDENTIALS | Push notifications | - | >= 2.2.0 | The application credentials given by Firebase. Must be loaded from a secret. |
DEFAULT_LOCALE | No | - | >= 2.3.0 | A BCP 47 language tag used as default locale by toLocale custom helper in message templates. |
USERS_API_ENDPOINT | No | - | >= 2.3.0 | The url of the API queried to fetch users data. |
Channels configuration
Kaleyra integration
The outbound calling and the whatsapp services will need the Kaleyra integration to work properly. In order to setup the Kaleyra integration, you will need, firstly, to create a Kaleyra account and create an API Key. To successfully set up your Kaleyra account, please refer to the Getting Started section of the official Kaleyra documentation. The obtained Kaleyra API Key and SID will be provided to the notification-manager
via environment variables, namely KALEYRA_API_KEY
and KALEYRA_API_SID
.
Outbound calls
In order to use the outbound calls service, you will then need to setup a valid bridge number, that will be provided to the notification-manager
in the service configuration map, as stated in the next section.
Whatsapp messaging
In order to use the Whatsapp messaging service, you need firstly to enable the Whatsapp channel on your Kaleyra account. When setting up the Whatsapp channel, you will need to create a WhatsApp Business account on the Meta developer platform. This account will be then linked to your Kaleyra account. You will also need a valid phone number to associate to your Whatsapp business account, which will be the number that will appear to users who will receive your messages. This number will be provided to the notification-manager
in the service configuration map, as stated in the next section.
In order to set up a correct configuration, we kindly recommend to follow the official Kaleyra documentation for Whatsapp integration.
Service configuration
The service needs a configuration file in JSON format, that can be provided to it as a configmap. You can choose the
name and mounting point of the map, as long as you specify the correct path in the CONFIGURATION_PATH
environment variable.
It follows a description of the fields of the map.
- userFields -
object
: if you have given a different name to any of the properties listed in the Users CRUD section, you can use this map to tell the service how to find them.- id -
string
: the name of the property in the Users CRUD containing the user's unique identifier. It will be matched with the values specified in therecipients
field. If not set, the service will use_id
as default. - emailAddress -
string
: the name of the property in the Users CRUD containing the user's e-mail address. - phoneNumber -
string
: the name of the property in the Users CRUD containing the user's phone number. - deviceToken -
string
: the name of the property in the Users CRUD containing the user's device token. - clusters -
string
: the name of the property in the Users CRUD containing the user's clusters list. - groups -
string
: the name of the property in the Users CRUD containing the user's groups list. - roles -
string
: the name of the property in the Users CRUD containing the user's roles list.
- id -
- activeChannels (required) -
string array
: the list of active channels over which each message will be delivered. Possible values areemail
,sms
,push
,voice
andwhatsapp
.
Keep in mind that even if a channel is active, a user will not receive messages over that channel if the correspondent property in the Users CRUD does not have a value.
- sender -
object
: the senders for the various channels. Required if at least one amongemail
,sms
andwhatsapp
channels are enabled.- email -
string
: the e-mail address that will appear as the sender of e-mail messages. Required if theemail
channel is enabled. - sms -
string
: the sender of the SMS messages. Required if thesms
channel is enabled. It can be one of the following:- a phone number in E.164 format
- an alphanumeric sender ID
- voice -
string
: the caller phone number of the voice messages. Required if thevoice
channel is enabled. The phone number must be registered in the Kaleyra console. - whatsappPhoneNumberId -
string
: Required when usingwhatsapp
. It is the phone number id of the phone number registered in your whatsapp business account. It can be retrieved from the dashboard of the application created inside your whatsapp business account or, alternatively, in the management section of the Whatsapp channel of your Kaleyra account.
- email -
If you use an alphanumeric sender ID please avoid generic names (e.g. SMS, Info...), otherwise the SMS provider may return an error like Invalid 'From' Number. Please check the SMS Service documentation for more details about supported providers.
voice -
object
: the configuration for the outbound calls used for voice notifications.- retryCount -
integer
: the number of retries that can be made until a timeout is reached if the initial call fails to connect. The default retry count is 0 and the maximum count is 2. Any value higher than 2 will be considered 2. - speechSpeed -
string
: the speed of the text-to-speech. The available options are:slow
,medium
,fast
,x-slow
andx-fast
. For further info, you must refer to Kaleyra official documentation. If not provided, the default speed is set tomedium
. - speechLanguage -
string
: the language of the text-to-speech. The available options are:en-IN
,en-US
,es-ES
andit-IT
. For further info, you must refer to Kaleyra official documentation. If not provided, the default language is set toit-IT
.
- retryCount -
push -
object
: the configuration for push notifications.- provider -
string
: the provider used to deliver push notifications. The available options are:firebase
,kafka
(default).
- provider -
androidIntentAction -
string
: the Android intent action that is triggered by the notification (the default value is an empty string).flowManagerConfiguration -
object
: required if you want to enable the/saga/send
API and the Flow Manager direct interaction.- metadataSchema -
object
: defines the path where to find the body fields, with exactly the same meaning, inside the Flow Manager metadata object.- channels (required) -
string
orstring array
- recipients -
string
orstring array
- clusters -
string
orstring array
- messageTitle -
string
- messageContent -
string
- templateId -
string
: It will be ignored ifgetTemplateIdFilePath
is defined. - emailAttachments -
string
orstring array
- emailCarbonCopies -
string
orstring array
- emailBlindCarbonCopies -
string
orstring array
- emailSender -
string
- channels (required) -
- serviceUrl -
string
: URL of the Flow Manager Service. Required if you want to send events back. - successEventLabel -
string
: event label. Required if you want to send an event in case of successful notification. - failEventLabel -
string
: event label. Required if you want to send an event in case of failed notification. - getTemplateIdFilePath -
string
: path of the config map file containing the custom function that retrieves a templateId based on the command received. The function must have the following signature:function getTemplateId: (event: FlowManagerEvent) => string
. It follows an example of a valid file.module.exports = function getTemplateId(event) {
return event.value.messageLabel
} - getDataFilePath -
string
: path of the config map file containing the custom function that retrieves an object used as data body field, based on the command received. The function must have the following signature:function getData: (event: FlowManagerEvent) => Record<string, any>
. If not defined the Flow Manager command is used as is. It follows an example of a valid file.module.exports = function getData(event) {
return {
...event,
value: {
...event.value,
messagePayload: {
...event.value.messagePayload,
amount: event.value.messagePayload.amount.toFixed(2),
},
},
}
}
- metadataSchema -
It follows an example of a valid configuration file.
{
"userFields": {
"id": "fiscalCode",
"emailAddress": "mail",
"phoneNumber": "phone",
"clusters": "departments",
"groups": "teams",
},
"activeChannels": [
"email",
"push",
"sms",
"voice",
"whatsapp"
],
"sender": {
"email": "email@test.com",
"voice": "+39123456789",
"sms": "Mia Care",
"whatsappPhoneNumberId": "+39123456789"
},
"voice": {
"retryCount": 0,
"speechSpeed": "medium",
"speechLanguage": "it-IT"
},
"push": {
"provider": "kafka"
},
"androidIntentAction": "eu.miaplatform.fakeactivity",
"flowManagerConfiguration": {
"serviceUrl": "http://flow-manager-service",
"successEventLabel": "notificationSent",
"failEventLabel": "notificationFailed",
"metadataSchema": {
"channels": "notifications.channels",
"recipients": "buyer.name",
"templateId": "notification.channel",
}
}
}
Custom event handlers
To register custom handlers, first you need to create a new configuration with an arbitrary name, for example /home/node/app/custom-handlers
, and assign its path to the CUSTOM_HANDLERS_FOLDER env var.
Then, to register a custom handler, simply add a new file to the configuration - like acme-shipping-handler.js
in the snippet above - containing the JavaScript code implementing and exporting your handler, i.e. the function to be executed when a new HTTP request is received notifying a new event to process.
Finally, to get the custom handler loaded at application startup, add or update a record in the event settings CRUD collection by calling the PATCH /event-settings/:id
endpoint with the name of the chosen event, the name of the handler, and optionally a JSON schema for the event validation.
Here's an example of an event settings specifying a custom handler, defined in the acme-shipping-handler.js
config map, to process ACME/OrderShipped/v1
custom events.
{
"eventName": "ACME/OrderShipped/v1",
"handlerName": "acme-shipping-handler.js",
"eventSchema": {
"type": "object",
"description": "AM/AppointmentCreated/v1 notification event",
"properties": {
"id": {
"type": "string",
},
"key": {
"type": "string",
"description": "Event key (affected resource, etc.)",
},
"name": {
"type": "string",
"description": "Event name",
"value": "ACME/OrderShipped/v1",
},
"metadata": {"...": "..."},
"payload": {"...": "..."},
},
"required": ["name"],
"additionalProperties": false,
}
}
The routing table, that specifies which custom or default handler is used to process each type of event, is built once at startup and is updated automatically if you update the [event settings CRUD][crud-event-settings] using one of the following endpoints:
Any other change requires a service restart to takes effect.
The JavaScript file must export a function with two arguments:
- service: a decorated Fastify instance, to access the logger, CRUD proxy, …;
- event: the event details;
{
"id": "event12345",
"key": "order-12345",
"name": "ACME/OrderCreated/v1",
"payload": {
"...": "..."
}
}
- utils: several utility functions to send notifications, retrieve users, set reminders, … .
You can find more details about the API accessible inside a custom handler in the Usage section.
Your JavaScript module should therefore look like this:
// lodash and luxon libraries can be accessed inside the custom handler
const _ = require('lodash')
const luxon = require('luxon')
module.exports = async function handler(service, event, utils) {
// Your code to handle the event, this is an example using some of the provided utils
// Let's imagine we have a single recipient with the ID stored in the userId field of the event payload
const {payload} = event
const {userId, startDate} = payload
const recipients = await utils.getRecipients(service, {_id: userId})
return recipients.map(async recipient => {
const notificationSettings = await utils.getNotificationSettings(service, event, recipient)
const mergedNotificationSettings = utils.mergeNotificationSettings(service, notificationSettings)
const messages = utils.buildMessages(service, mergedNotificationSettings)
const messagesNotification = await utils.sendMessages(service, event, recipient, messages)
const reminders = utils.buildReminders(service, recipient, notificationSettings, startDate)
const remindersNotification = await utils.setReminders(service, reminderEvent, recipient, reminders)
const userNotifications = [messagesNotification, remindersNotification]
return mergeNotifications(event, recipient, userNotifications)
})
}
Be careful with the implementation of your handler, since any error raised during its execution would interrupt the processing of the notification event, whose status would be set to ERROR
.
Users configuration
Since version v2.3.0 users can be handled by an external service if the USERS_API_ENDPOINT
is defined. This external service must be compatible with the Crud service interface.
If the external api endpoint is not defined the USERS_CRUD_NAME
must be specified, and the Notification Manager fetches users from the Crud service as usual.
When both environment variables are specified, the USERS_API_ENDPOINT
takes precedence and the external service is used for users.
Security configuration
General recommendations about endpoint authorization are summarized in the following table.
Endpoint | Recommended authorization level |
---|---|
/user-notification-settings | Accessible to all who can change their notification settings. |
/notification-settings | Accessible to users with admin roles. |
/notifications | Accessible to users that monitor anomalies in sending messages and reminders. |
Event ACLs
If you want to allow certain events to be visible only to certain user groups, you can build a custom solution or you can use Rönd to enforce such security policies.
First, you need to configure, for each event type, which user groups have access to it by settings the corresponding userGroups
field in the event settings CRUD collection. If the field is not set, the service assumes the event is visible to all users. For example, if you want the AM/AppointmentCreated/v1
event to be visible only to users belonging to the doctors
and/or admins
group, you should configure a CRUD record like this:
{
"eventName": "AM/AppointmentCreated/v1",
"userGroups": ["admins", "doctors"]
}
If you want to build a custom solution, you can use the GET /user/events
endpoint to retrieve the list of events accessible to the logged user. If you are using Rönd, you can write a policy fetching directly this information from the event settings CRUD collection.
The following table provides some default policies you can use or extend to protect the most relevant endpoints.
Endpoint | Rönd policy |
---|---|
DELETE /notification-settings/:id | nm_update_notification_settings |
PATCH /notification-settings/:id | nm_update_notification_settings |
POST /notification-settings/ | nm_create_notification_settings |
Rönd policies and their tests are downloadable from the following links:
Make sure that the collections written in the policies match the crud collections name specified in the corresponding environment variables.
Notification settings
This section illustrates with examples how you can leverage notification settings to send messages and reminders to users.
Let's start with an example to break down the notification settings data model:
{
"eventName": "AM/AppointmentCreated/v1",
"emitters": ["sarah.cohen", "julie.cross"],
"group": "doctors",
"cluster": "st.mary.hospital",
"channels": ["email", "sms"],
"hours": ["09:00-18:00"],
"templateName": "doctor-new-appointment",
"reminders": ["P1D", "PT6H"],
"rule": "SEND"
}
The eventName
field targets the AM/AppointmentCreated/v1
, which is generated when a new appointment is created in the Appointment Manager, while the emitters
field specifies that the notification setting applies only to event emitted by sarah.cohen
or julie.cross
; the actual semantic of the emitters
field value (being a patient ID or something entirely different) depends on the specific event.
The group
and cluster
fields, together with user
and role
, target a subset of users that belong to the given group and cluster, in the example all the doctors of the fictional St. Mary Hospital.
The channels
, hours
and templateName
determine which messages are sent on which channels, in particular the doctors are going to receive an email and a sms message based on the doctor-new-appointment
template, but only if the event occurs in the 9-18 time slot, which could be their working hours.
The reminders
field specifies how many and when reminders will be sent, in the example one day (P1D
) and six hours earlier (PT6H
); each string represent a duration expressed in ISO 8601 format and the event handler is responsible for the type of event associated to the reminder (you can check the event handlers documentation to find out). Also, the exact moment when the reminders will be sent depends on which date/time the handlers applies the specified durations: in the example, we will send the first reminder one day before the appointment starts, the second one six hours before the appointment starts.
Reminders
When a handler designed to process a reminder receives the appropriate reminder event (for example the AM/AppointmentReminder/v1
event, from the example above), the handler receives two key information in the event metadata:
- the
schedule
, which is the notification settings reminder that triggered the event (P1D
orPT6H
from the example above); - the
recipients
, which are the ID of users that should received the messages (it could be a doctor or patient from the appointment or someone from the hospital administration).
These kind of handlers typically fetch the notification settings that apply to the given reminder event, schedule and recipients, assigning a double semantic to the reminders
field of the notification settings:
- when fetching them, will filter the notification settings containing the given
schedule
in thereminders
field; - after the reminders are sent, the handler could set new reminders according to the notification settings
reminders
.
Which of these two semantics are applied depends entirely on the specific behavior of the event handler, could be none or both. We recommend to always check the event handlers documentation to find out which is the case for each default event handler.
Let's see with an example how we can configure the notification settings to take advantage of these semantics for the TMM/MonitoringCreated/v1
event, which is triggered when a monitoring plan is created in the Therapy & Monitoring Manager.
{
"eventName": "TMM/MonitoringCreated/v1",
"group": "patients",
"channels": ["email"],
"templateName": "patient-monitoring-plan-created",
"reminders": ["P1D", "PT1H"],
"rule": "SEND"
}
So, when a new monitoring plan is created, the patient receives an email confirmation and two reminders - one day and one hour before the day the monitoring plan starts - are scheduled for the TMM/MonitoringReminder/v1
. So, let's see how we can configure two different notification settings with different templates for each reminder if the notification settings are filtered according to the reminder schedule:
{
"eventName": "TMM/MonitoringReminder/v1",
"group": "patients",
"channels": ["email"],
"templateName": "patient-monitoring-plan-reminder-1d",
"reminders": ["P1D"],
"rule": "SEND"
}
{
"eventName": "TMM/MonitoringCreated/v1",
"group": "patients",
"channels": ["sms"],
"templateName": "patient-monitoring-plan-reminder-1h",
"reminders": ["PT1H"],
"rule": "SEND"
}
In the example, we are sending the first reminder one day earlier via email and the second reminder one hour earlier via sms, using different templates.
If the handler is configured to send recurring reminders, for example to send to the patient a reminder each day he or she has to measure the blood pressure, after the current reminder has been processed, it will schedule new reminders according the reminders
field of the notification settings.
The following default reminder event handlers filter the notification settings according to the reminders
field:
AM/AppointmentReminder/v1
The following default reminder event handlers both filter the notification settings and set recurring reminders, until the event is considered expired, according to the reminders
field:
TMM/MonitoringReminder/v1
TMM/TherapyReminder/v1