{{tag> topic module notifications sms email notification idm-ntf }}
====== Modules - Notification [ntf] ======
This is a **paid** module. If you're interested, please contact your consultant.
The notification module contains a **simplified mechanism for notification configuration.** It helps the administrator with:
* **define events** that should trigger a notification (for example, changes on a user),
* **define rules** when the notification should be sent (for example, change of user state),
* **edit the topic** for individual notifications,
* **easily disable or enable** individual configurations,
* **define multiple types of notifications** for one event and one rule.
The notification module is **in the first development phase**. The module **does not have** its own configuration agenda. Configuration is done only using code list values.
Initialization of the notification module [''idm-ntf''] is **fully automated**. After correct installation of the module into IdM, the initial module configuration is done and all settings are applied without the need for administrator action.
{{ .:ntf-module-001.drawio.png }}
===== Version =====
^Version ^Compatible with product |**Notes** |
|12.0.0 |12.3.4 |First module implementation for 12.x.x IdM |
|14.0.0 |14.10.0 |First module implementation for 14.x.x IdM |
|14.0.1 |14.10.0 |Bug fixing |
//"Compatible with the product" means that this is the recommended product version.//
===== Supported notification types =====
Currently, the notification module supports notifications only for the following object/entity types:
* **Users** (''IdmIdentityDto'').
* **Provisioning operations** (''SysProvisioningOperationDto'').
**Support for other object types is not only a configuration change**. It also **needs** an implementation of the mechanism in the application backend.
For each supported object type, a notification can react to any attribute change for that object. Examples:
* (''IdmIdentityDto'') when the user state changes,
* (''IdmIdentityDto'') when the username changes,
* (''SysProvisioningOperationDto'') when the description value is written to the system,
* (''SysProvisioningOperationDto'') when groups are written to the system.
===== Lifecycle of sending notification =====
In the current version, **notifications are sent only when an object change is triggered**, and **always for each object separately**.
For example, if a synchronization/HR process changes the user state from ''VALID'' to ''LEFT'', the notification is sent **at the moment of the change**, not in advance.
**Notifications are not grouped!** For each change, one notification is sent even if the recipient is the same.
The notification module **does not support** advance notifications – for example, XY days before a change.
==== Example of sending a notification on state change ====
The following example describes a notification for a change of a user attribute and notifying, for example, the user's manager.
In the notification code list, we have a configuration that means:
when the user state changes from Valid (''VALID'') to Excluded from evidence count (''EXCLUDED''), an email notification is sent to the user's manager.
* From the HR system, information arrives about a state change of a single contract (''IdmIdentityContractDto'') for the user,
* the contract change means a change of the contract ''STATE'' from NULL to Excluded from evidence count (''EXCLUDED''),
* {{.:f39u82vt.png?600 }}
* the HR process in IdM (''HrContractExclusionProcess'') automatically recalculates the user state and detects a change of the ''STATE'' attribute for the user (''IdmIdentityDto''),
* {{.:4wdmywgt.png?600 }}
* the HR process evaluates a change of ''STATE'' from Valid (''VALID'') to Excluded from evidence count (DISABLED) and also deactivates the user (''DISABLED'') from ''FALSE'' to ''TRUE'',
* {{.:emm0mdda.png?600 }}
* after the user with the new state is successfully saved, this event is caught by the notification module,
* the notification module evaluates all valid notification configurations for this event, and if the rule match, sends the notification according to the configuration.
* {{.:8rrgsow9.png?600 }}
{{ .:ntf-module-002.drawio.png }}
⚠️⚠️ If you have multiple configurations in the code list for one object/entity, and during evaluation more than one configuration matches the rules,
the same number of notifications will be sent as the number of matched configurations/rules.
==== Example of sending a notification on attribute change during provisioning ====
The following example describes a notification for an attribute change on an end system. The notification is, for example, sent to users with a defined role.
In the notification code list, we have a configuration that means:
when the value of the attribute Description (description) changes on the end system, an email notification is sent to users with the assigned role.
* On the end system, IdM manages the description attribute. This attribute is also mapped 1:1 to the standard user attribute Description (''description''),
* {{.:zd9av1ft.png?600 }}
* in IdM, the Description attribute on the user is changed,
* this attribute change triggers a write to the end system,
* the notification module catches the successfully executed provisioning operation and then sends the notification.
* {{.:teqbokur.png?600 }}
==== Installation ====
This section describes the installation process of the Notification ''idm-ntf'' module, including its activation, required prerequisites, access rights configuration, and integration with target systems. It serves as a starting point for administrators when introducing the module into the IdM environment.
==== Configuration ====
The notification module **does not require any specific configuration** after installation (for example, configuration items, creating code lists, etc.).
=== Code list: Entity types [ntf-entity-type] ===
{{ .:hph9gxsw.png?500}}
This code list is **automatically created at application startup** based on the presence of the ''idm-ntf'' module.
Do not edit this code list manually!
The code list contains all objects/entities for which it is possible to configure notifications using the notification module.
Currently, the module supports the following objects/entities:
* Users (''IdmIdentityDto''),
* Provisioning operations (''SysProvisioningOperationDto'').
=== Code list: Entity events [ntf-entity-event] ===
{{ .:ikpiavdb.png?500}}
This code list is **automatically created at application startup** based on the presence of the ''idm-ntf'' module.
Do not edit this code list manually!
The code list contains all event types that can be checked/caught by the notification module.
Currently, the following event types are supported:
* **Create** (''CREATE''),
* **Delete** (''DELETE''),
* **Update** (''UPDATE'').
=== Code list: Notification code list [ntf-notification] ===
{{ .:uqor38jj.png?500}}
This code list is **automatically created at application startup** based on the presence of the ''idm-ntf'' module.
The code list contains the main definition of notifications.
It is the only configuration part of the module that can be edited/modified by the administrator.
Each code list value contains the following attributes:
* **Entity type**
* Defines for which object/entity type this notification configuration will be sent.
* **Event type **
* Event type for which this configuration will be evaluated.
* **Form projection**
* Form projection / user type. Currently, it can only be used for the ''IdmIdentityDto'' object/entity. Limits for which user type the notification configuration will be evaluated.
* **System**
* System definition – restriction only for the defined system. Currently, it can only be used for the ''SysProvisioningOperationDto'' object/entity.
* **Rules**
* Definition of rules for this configuration. Currently, only one rule per configuration is supported. More about rules is described in a separate section.
* **Rules by script**
* Definition of rules using a script. Instead of the rules above, you can configure the condition using a script. //More about the script is in a separate section.//
* **Topic**
* Standard notification configuration – the code of the script to which the notification will be sent if the conditions are met.
* **Level**
* Standard notification configuration – the "level" defines whether the notification will be ''SUCCESS'', ''WARNING'', etc.
* **Send to identity itself**
* Defines whether, if conditions are met, the notification will be sent **to the identity itself**.
* **Send to manager**
* Defines whether, if conditions are met, the notification will be sent **to the user’s manager**.
* **Send to identities**
* Defines whether, if conditions are met, the notification will be sent to the **multi-value list of identities** specified here from IdM.
* **Send to roles**
* Defines whether, if conditions are met, the notification will be sent to the **multi-value list of roles** specified here from IdM.
* **Recipients by script**
* Defines whether, if conditions are met, the notification will be sent **to the list of users returned by a script**. //More about scripts is in a separate section.//
* **Disable**
* Defines whether this configuration will be evaluated or not.
==== Rules ====
The following section describes how to evaluate rules using a script and using **pseudo syntax**.
The current way of defining rules in the notification module is a **preparation for a full-featured notification configuration agenda**.
=== Rules ===
In the current module version 14.x.x, **only one rule** per configuration is supported.
EAV:myProjectEavCode:valueA->valueB //The example above shows a rule that is evaluated for the EAV attribute with the code `myProjectEavCode`, only when it changes from value `valueA` to value `valueB`//
The rules can contain the following parts:
* Attribute type definition.
* Attribute code
* Separator.
* Value from which the rule is evaluated.
* Change separator.
* Value to which the rule is evaluated.
The following modifiers can also be used in the rules:
* **Wild card** - *,
* allows defining a change from any value, or to any value.
* null,
* means that the value was not filled before, or the value was deleted.
* Always - !
* means that the notification is sent every time without checking for changes.
* Change - CHANGED
* means that the attribute changed. It does not check from which value to which value.
== Rule examples in practice ==
^Rule ^Rule type^Description |
|firstName:John->Johny|Standard identity attribute|Rule describes a change of the user’s standard attribute `firstName` from value `John` to `Johny`. Other changes of `firstName` will not be evaluated as matched.|
|EAV:clinicCode:100->200|EAV identity attribute|Rule describes a change of the EAV attribute with code `clinicCode` from value `100` to `200`. For all other changes, the rule will not match.|
|EAV:alternateEmail:john@example.tld->johny@externist_example.tld|EAV identity attribute|Rule describes a change of the EAV attribute with code `alternateEmail` from value `john@example.tld` to `johny@externist_example.tld`.|
|EAV:supervisor:*->true|EAV identity attribute|Rule describes a change of the EAV attribute with code `supervisor` from any value ("*") to the value `"true"`.|
|email:*->null|Standard identity attribute|Rule describes a change of the standard attribute `email` from any value to an empty (null) value – i.e., attribute deletion.|
|externalCode:CHANGED|Standard identity attribute|Rule describes a change of the standard attribute `externalCode` (personnel number) to any value.|
=== Rules by script ===
For more complex rules, it is possible to use evaluation by **script**. **This script always has priority over standard rule evaluation.**
If both rules and a script are defined, **only the script will be evaluated**.
The script is defined through the standard IdM configuration agenda: //Configuration → Script definitions//.
Scripts can be written and selected only from the category **System**.
Script permissions are handled by the standard IdM mechanism. It is also allowed to call scripts from other scripts.
The script return value must always be of type ''Boolean.TRUE'' or ''Boolean.FALSE''.
For any other return type, the rule will be skipped! In the IdM log, an error message will be available saying that the script did not return the required type.
The input parameters of the script are different for the objects/entities ''IdmIdentityDto'' and ''SysProvisioningOperationDto''.
== IdmIdentityDto ==
The input parameters for the ''IdmIdentityDto'' object are:
* **oldDto**,
* the original ''IdmIdentityDto'' object for which the rule is evaluated,
* **the value can be null** – for example, on creation,
* **newDto**,
* the newly updated `IdmIdentityDto` object for which the rule is evaluated,
* **oldEavs**,
* the original list of EAV values,
* the collection contains items of type ''IdmFormValueDto'',
* **the value can be null**,
* **newEavs**,
* the new list of EAV values,
* the collection contains items of type ''IdmFormValueDto'',
* **the value can be null**,
* **scriptEvaluator**,
* the standard script evaluator,
* can be used to run other scripts.
An example script for the ''IdmIdentityDto'' object can be as follows:
// Check email if is null or empty rule will pass
if (oldDto.getEmail() == null || oldDto.getEmail().isEmpty) {
return Boolean.TRUE;
}
// Check form projection if is same as external. External form projection is defined by UUID not code.
if (oldDto.getFormProjection() != null && oldDto.getFormProjection().equals(UUID.fromString('8a02783b-c4a8-4ed8-84a5-808ae3c69657'))) {
return Boolean.TRUE;
}
// For all another state return false;
return Boolean.FALSE;
== SysProvisioningOperationDto ==
The input parameters for the ''SysProvisioningOperationDto'' object are:
* **entity**,
* the currently processed provisioning operation,
* an object of type ''SysProvisioningOperationDto'',
* **scriptEvaluator**,
* the standard script evaluator,
* can be used to run other scripts.
An example script for the ''SysProvisioningOperationDto'' object can be as follows:
import eu.bcvsolutions.idm.acc.dto.SysProvisioningOperationDto;
SysProvisioningOperationDto provisioningOperation = (SysProvisioningOperationDto) entity;
if (provisioningOperation.getProvisioningContext().getConnectorObject().getAttributes().size() != 1) {
return Boolean.FALSE;
}
if (provisioningOperation.getProvisioningContext().getConnectorObject().getAttributes().getFirst().getName().equals('__ENABLE__')) {
return Boolean.TRUE;
}
return Boolean.FALSE;
==== Templates ====
The notification module by default **does not contain any templates** or text for notifications.
**All templates must be created by the IdM administrator.**
For each type of monitored object/entity, there are different template parameters that can be used in notifications.
=== Template parameters for IdmIdentityDto ===
For ''IdmIdentityDto'', the following parameters can be used:
* **rule** (''NtfConfigurationItemCacheDto''),
* the matched rule sent to the notification, mainly to get the old and new value from the rule,
* **entity** (''IdmIdentityDto''),
* the updated ''IdmIdentityDto'' object that matched the above rules.
=== Template parameters for SysProvisioningOperationDto ===
For ''SysProvisioningOperationDto'', the following parameters can be used:
* **rule** (''NtfConfigurationItemCacheDto''),
* the matched rule sent to the notification, mainly to get the old and new value from the rule,
* **entity** (''SysProvisioningOperationDto''),
* the full provisioning operation containing information about the executed provisioning,
* **identity** (''IdmIdentityDto''),
* the user for whom the operation was performed,
* if the provisioning is for a type other than ''IDENTITY'', this value will be null,
* **system** (''SysSystemDto''),
* the system for which the provisioning operation was performed,
* **account** (''String''),
* note: this is the UID of the system entity (`getSystemEntityUid`), not the account UID,
* **changes** (''List>''),
* the complete list of changed attributes sent by the provisioning.
==== Recipients ====
Recipients can be configured differently for each managed object/entity.
The following sections describe the recipients for each object/entity.
**If the final recipient list is empty, it is automatically filled with IdM Administrators (users with the `SuperAdminRole`)**.
=== Recipients for IdmIdentity ===
For a configuration monitoring the ''IdmIdentityDto'' object/entity, the following recipient options are available:
* **the user itself**,
* the notification will be sent to the user,
* **the user’s manager**,
* a **combination of managers** from the organizational structure and those specifically assigned to contracts,
* if the user has multiple contracts, the result is the union of their managers,
* if the user has no managers, **the recipient list is replaced with IdM Administrators (users with the `SuperAdminRole`)**.
=== Recipients for SysProvisioningOperation ===
For a configuration monitoring the ''SysProvisioningOperationDto'' object/entity, the following recipient options are available:
* **the user itself**,
* the notification will be sent to the user,
* **the user’s manager**,
* a combination of managers from the organizational structure and those specifically assigned to contracts,
* if the user has multiple contracts, the result is the union of their managers,
* if the user has no managers, the recipient list is replaced with IdM Administrators (users with the `SuperAdminRole`).
Note: If the provisioning operation is for an object type other than ''IDENTITY'', the above behavior is not available. Please use recipients defined by script.
=== Recipients by script ===
If none of the above recipient definition options are suitable, it is possible to define recipients by script.
Recipients defined by script **do not replace** the original recipients, **they only add to them**.
Scripts can be written and selected only from the **System** category.
Scripts can also call other scripts (only from the same category).
The following parameters are sent to the script that evaluates recipients:
* **entity**,
* a DTO (currently ''IdmIdentityDto'' and ''SysProvisioningOperationDto'') for which the rule was evaluated,
* **scriptEvaluator**,
* the standard system script evaluator,
* can be used to run other scripts.
The script must return an object of type ''List''.
For all other object types, processing will end with an error.
The return value can also be empty or null. In these cases, the recipient list will be filled with IdM Administrators (users with the `SuperAdminRole`).
==== Configuration ====
The notification module ''idm-ntf'' contains several configuration items that do not need to be configured manually – they are set automatically on the first application startup.
Changing these configuration items may cause the module to stop working correctly and break rule evaluation!
# Configuration property that holds the ID of the code list containing notification configurations for identities.
idm.sec.ntf.codeListId=
# Codelist with saved all supported entity types.
idm.sec.ntf.entityType.codeListId=
# Codelist with saved all available entity events.
idm.sec.ntf.entityEvent.codeListId=
# Configuration property specifying for which entity is this configuration used.
idm.sec.ntf.codeList.eav.entityTypeId=
# Configuration property specifying for which {@link eu.bcvsolutions.idm.core.api.event.EventType} the notification configuration is used.
idm.sec.ntf.codeList.eav.eventTypeId=
# Configuration property specifying for which system the rule is used. Currently, this configuration is used only for {@link eu.bcvsolutions.idm.acc.dto.SysProvisioningOperationDto}.
idm.sec.ntf.codeList.eav.systemId=
# Configuration property for the EAV attribute of the code list that stores all rules required for sending notifications.
idm.sec.ntf.codeList.eav.ruleId=
# Configuration property for the EAV attribute containing a script. The script is evaluated with its own rule-checking logic.
idm.sec.ntf.codeList.eav.scriptRuleId=
# Configuration property for the topic code used to search for notification configurations.
idm.sec.ntf.codeList.eav.topicId=
# Configuration property for the notification level used to search for notification configurations.
idm.sec.ntf.codeList.eav.levelId=
# Configuration property indicating whether to send notifications to the currently processed {@link eu.bcvsolutions.idm.core.api.dto.IdmIdentityDto}.
idm.sec.ntf.codeList.eav.sendIdentityItselfId=
# Configuration property indicating whether to send notifications to the manager of the given {@link eu.bcvsolutions.idm.core.api.dto.IdmIdentityDto}. Used only for this type.
idm.sec.ntf.codeList.eav.sendManagerId=
# Configuration property indicating whether to send notifications to static identities list.
idm.sec.ntf.codeList.eav.sendIdentityId=
# Configuration property indicating whether to send notifications to identities assigned to a specific role.
idm.sec.ntf.codeList.eav.sendRoleId=
# Configuration property specifying script that returns notification recipients.
idm.sec.ntf.codeList.eav.sendScriptId=
# Configuration property that enables or disables the current notification configuration.
idm.sec.ntf.codeList.eav.disabledId=
==== Developer guide ====
The following section describes a simplified mechanism of how the notification module works.
=== Executor ===
Currently, the notification module supports only the following executors that catch events in IdM, evaluate rules, and send notifications. These executors are:
* ''NtfNotificationProvisioningOperationExecutor''
* Evaluates changes on ''IdmIdentityDto'' and their EAV attributes.
* ''NtfNotificationIdentityExecutor''
* Evaluates changes on ''SysProvisioningOperationDto'' (write/provisioning to the system).
=== Implementing a new executor ===
If, in a new project (which depends on the ''idm-ntf'' module) or directly in the ''idm-ntf'' module, we decide to implement a new notification for a new type of monitored object/entity, it is necessary to create a new executor that extends the abstract class ''AbstractNtfNotificationExecutor'' with the generic type we are interested in.
For example:
@Component("notificationProvisioningOperationExecutor")
public class NtfNotificationTreeNodeExecutor extends AbstractNtfNotificationExecutor {
...
}
Add all required methods that the abstract class asks you to implement. You can use finished implementations here:
* ''/idm-ntf/src/main/java/eu/bcvsolutions/idm/ntf/service/impl/NtfNotificationProvisioningOperationExecutor.java''
* ''/idm-ntf/src/main/java/eu/bcvsolutions/idm/ntf/service/impl/NtfNotificationIdentityExecutor.java''
Creating an executor is only one part. Next, you must add capture points in the application. These are standard processors that, from the standard values of the given event, call the ''DefaultNtfNotificationManager'', which decides which executor to call. For our example on IdmTreeNodeDto, this can be implemented like this:
* A processor before saving the given object, which evaluates changes and stores which notification rules matched:
@Component(NtfBeforeTreeNodeProcessor.PROCESSOR_NAME)
public class NtfBeforeTreeNodeProcessor extends AbstractNtfNotificationProcessor {
public static final String PROCESSOR_NAME = "ntf-before-identity-processor";
public NtfBeforeTreeNodeProcessor() {
super();
}
@Override
public EventResult process(EntityEvent entityEvent) {
IdmTreeNodeDto oldDto = entityEvent.getOriginalSource();
IdmTreeNodeDto newDto = entityEvent.getContent();
List oldEavs = Lists.newArrayList();
if (oldDto != null) {
oldEavs = getValues(oldDto.getEavs());
}
List newEavs = Lists.newArrayList();
if (newEavs != null) {
newEavs = getValues(newDto.getEavs());
}
List passed = notificationManager.checkCachedNotifications(
entityEvent.getType(),
oldDto,
newDto,
oldEavs,
newEavs,
newDto);
if (CollectionUtils.isNotEmpty(passed)) {
Map properties = entityEvent.getProperties();
// TODO set whole cached object or just IDs?
properties.put(PASSED_RULES, new NtfWrapperCacheDto(passed));
}
return new DefaultEventResult<>(entityEvent, this);
}
@Override
public int getOrder() {
// Before save
return -5;
}
* A processor after saving the given object, which checks the number of matched rules and performs the sending:
@Component(NtfAfterTreeNodeProcessor.PROCESSOR_NAME)
public class NtfAfterTreeNodeProcessor extends AbstractNtfNotificationProcessor {
public static final String PROCESSOR_NAME = "ntf-after-tree-node-processor";
public NtfAfterTreeNodeProcessor() {
super();
}
@Override
public EventResult process(EntityEvent entityEvent) {
Map properties = entityEvent.getProperties();
NtfWrapperCacheDto wrapper = (NtfWrapperCacheDto) properties.get(PASSED_RULES);
if (wrapper != null) {
IdmTreeNodeDto entity = entityEvent.getContent();
List items = wrapper.getItems();
if (CollectionUtils.isNotEmpty(items)) {
notificationManager.sendNotification(items, entity);
}
}
return new DefaultEventResult<>(entityEvent, this);
}
@Override
public int getOrder() {
// After save
return 5;
}
=== Cache ===
@since 12.0.0
When evaluating rules during the saving of objects/entities, rules may be checked and evaluated frequently.
Rules are now stored in ''IdmCodeListItemDto'' entities, and retrieving them from the database and then transforming them into rules (''NtfConfigurationRuleTypeCacheDto'') can be a costly operation when used often.
In the notification module (''idm-ntf''), a standard cache implementation named ''notification-cache'' has been introduced in IdM.
This cache is managed and initialized by the notification module and contains pre-prepared rules from all configurations.
The default validity of this cache is 12 hours. It is also automatically reset when any value in the notification code list is modified/added/deleted (this state is not checked for other code lists).