Browse Source

Default notification configs; improvements

pull/7911/head
ViacheslavKlimov 4 years ago
parent
commit
c34b6623ce
  1. 9
      application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java
  2. 19
      application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java
  3. 2
      application/src/main/java/org/thingsboard/server/service/install/update/DefaultDataUpdateService.java
  4. 5
      application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/AlarmAssignmentTriggerProcessor.java
  5. 2
      application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/AlarmCommentTriggerProcessor.java
  6. 2
      application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/EntityActionTriggerProcessor.java
  7. 3
      application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/RuleEngineComponentLifecycleEventTriggerProcessor.java
  8. 6
      common/data/src/main/java/org/thingsboard/server/common/data/id/TenantId.java
  9. 18
      common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationProcessingContext.java
  10. 2
      common/data/src/main/java/org/thingsboard/server/common/data/notification/info/AlarmAssignmentNotificationInfo.java
  11. 2
      common/data/src/main/java/org/thingsboard/server/common/data/notification/info/AlarmCommentNotificationInfo.java
  12. 2
      common/data/src/main/java/org/thingsboard/server/common/data/notification/info/AlarmNotificationInfo.java
  13. 1
      common/data/src/main/java/org/thingsboard/server/common/data/notification/info/DeviceInactivityNotificationInfo.java
  14. 2
      common/data/src/main/java/org/thingsboard/server/common/data/notification/info/RuleEngineComponentLifecycleEventNotificationInfo.java
  15. 2
      common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/NotificationRule.java
  16. 9
      common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/trigger/AlarmAssignmentNotificationRuleTriggerConfig.java
  17. 2
      common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/trigger/EntitiesLimitNotificationRuleTriggerConfig.java
  18. 2
      common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/trigger/NewPlatformVersionNotificationRuleTriggerConfig.java
  19. 4
      common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/trigger/RuleEngineComponentLifecycleEventNotificationRuleTriggerConfig.java
  20. 2
      common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/NotificationTargetConfig.java
  21. 231
      dao/src/main/java/org/thingsboard/server/dao/notification/DefaultNotificationSettingsService.java
  22. 6
      dao/src/main/java/org/thingsboard/server/dao/tenant/TenantServiceImpl.java

9
application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java

@ -34,6 +34,9 @@ import org.thingsboard.server.service.install.migrate.EntitiesMigrateService;
import org.thingsboard.server.service.install.migrate.TsLatestMigrateService;
import org.thingsboard.server.service.install.update.CacheCleanupService;
import org.thingsboard.server.service.install.update.DataUpdateService;
import org.thingsboard.server.service.install.update.DefaultDataUpdateService;
import static org.thingsboard.server.service.install.update.DefaultDataUpdateService.getEnv;
@Service
@Profile("install")
@ -242,7 +245,11 @@ public class ThingsboardInstallService {
databaseEntitiesUpgradeService.upgradeDatabase("3.4.4");
log.info("Updating system data...");
systemDataLoaderService.updateSystemWidgets();
systemDataLoaderService.createDefaultNotificationConfigs();
if (!getEnv("SKIP_DEFAULT_NOTIFICATION_CONFIGS_CREATION", false)) {
systemDataLoaderService.createDefaultNotificationConfigs();
} else {
log.info("Skipping default notification configs creation");
}
break;
//TODO update CacheCleanupService on the next version upgrade
default:

19
application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java

@ -22,6 +22,7 @@ import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
@ -678,13 +679,27 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService {
@Override
public void createDefaultNotificationConfigs() {
notificationSettingsService.createDefaultNotificationConfigs(TenantId.SYS_TENANT_ID);
try {
log.info("Creating default notification configs for system admin");
notificationSettingsService.createDefaultNotificationConfigs(TenantId.SYS_TENANT_ID);
} catch (Exception e) {
if (StringUtils.contains(e.getMessage(), "already exists")) {
log.info("Default notification configs are already present for system admin, skipping");
} else {
throw e;
}
}
PageDataIterable<TenantId> tenants = new PageDataIterable<>(tenantService::findTenantsIds, 500);
log.info("Creating default notification configs for all tenants");
for (TenantId tenantId : tenants) {
try {
notificationSettingsService.createDefaultNotificationConfigs(tenantId);
} catch (Exception e) {
log.warn("Failed to create default notification configs for tenant {}: {}", tenantId, e.getMessage());
if (StringUtils.contains(e.getMessage(), "already exists")) {
log.info("Default notification configs are already present for tenant {}, skipping", tenantId);
} else {
throw e;
}
}
}
}

2
application/src/main/java/org/thingsboard/server/service/install/update/DefaultDataUpdateService.java

@ -672,7 +672,7 @@ public class DefaultDataUpdateService implements DataUpdateService {
return mainQueueConfiguration;
}
private boolean getEnv(String name, boolean defaultValue) {
public static boolean getEnv(String name, boolean defaultValue) {
String env = System.getenv(name);
if (env == null) {
return defaultValue;

5
application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/AlarmAssignmentTriggerProcessor.java

@ -25,6 +25,7 @@ import org.thingsboard.server.common.data.alarm.AlarmStatusFilter;
import org.thingsboard.server.common.data.notification.info.AlarmAssignmentNotificationInfo;
import org.thingsboard.server.common.data.notification.info.NotificationInfo;
import org.thingsboard.server.common.data.notification.rule.trigger.AlarmAssignmentNotificationRuleTriggerConfig;
import org.thingsboard.server.common.data.notification.rule.trigger.AlarmAssignmentNotificationRuleTriggerConfig.Action;
import org.thingsboard.server.common.data.notification.rule.trigger.NotificationRuleTriggerType;
import org.thingsboard.server.common.msg.TbMsg;
@ -37,8 +38,8 @@ public class AlarmAssignmentTriggerProcessor implements RuleEngineMsgNotificatio
@Override
public boolean matchesFilter(TbMsg ruleEngineMsg, AlarmAssignmentNotificationRuleTriggerConfig triggerConfig) {
if ((ruleEngineMsg.getType().equals(DataConstants.ALARM_ASSIGN) && !triggerConfig.isNotifyOnAssign())
|| (ruleEngineMsg.getType().equals(DataConstants.ALARM_UNASSIGN) && !triggerConfig.isNotifyOnUnassign())) {
Action action = ruleEngineMsg.getType().equals(DataConstants.ALARM_ASSIGN) ? Action.ASSIGNED : Action.UNASSIGNED;
if (!triggerConfig.getNotifyOn().contains(action)) {
return false;
}
Alarm alarm = JacksonUtil.fromString(ruleEngineMsg.getData(), Alarm.class);

2
application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/AlarmCommentTriggerProcessor.java

@ -62,7 +62,7 @@ public class AlarmCommentTriggerProcessor implements RuleEngineMsgNotificationRu
AlarmInfo alarmInfo = JacksonUtil.fromString(ruleEngineMsg.getData(), AlarmInfo.class);
return AlarmCommentNotificationInfo.builder()
.comment(comment.getComment().get("text").asText())
.action(ruleEngineMsg.getType().equals(DataConstants.COMMENT_CREATED) ? "created" : "updated")
.action(ruleEngineMsg.getType().equals(DataConstants.COMMENT_CREATED) ? "added" : "updated")
.userName(ruleEngineMsg.getMetaData().getValue("userName"))
.alarmId(alarmInfo.getUuidId())
.alarmType(alarmInfo.getType())

2
application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/EntityActionTriggerProcessor.java

@ -60,7 +60,7 @@ public class EntityActionTriggerProcessor implements RuleEngineMsgNotificationRu
msgType.equals(DataConstants.ENTITY_UPDATED) ? ActionType.UPDATED :
msgType.equals(DataConstants.ENTITY_DELETED) ? ActionType.DELETED : null;
return EntityActionNotificationInfo.builder()
.entityId(entityId)
.entityId(actionType != ActionType.DELETED ? entityId : null)
.entityName(ruleEngineMsg.getMetaData().getValue("entityName"))
.actionType(actionType)
.originatorUserId(UUID.fromString(ruleEngineMsg.getMetaData().getValue("userId")))

3
application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/RuleEngineComponentLifecycleEventTriggerProcessor.java

@ -76,6 +76,9 @@ public class RuleEngineComponentLifecycleEventTriggerProcessor implements Notifi
.ruleChainName(triggerObject.getRuleChainName())
.componentId(triggerObject.getComponentId())
.componentName(triggerObject.getComponentName())
.action(triggerObject.getEventType() == ComponentLifecycleEvent.STARTED ? "start" :
triggerObject.getEventType() == ComponentLifecycleEvent.UPDATED ? "update" :
triggerObject.getEventType() == ComponentLifecycleEvent.STOPPED ? "stop" : null)
.eventType(triggerObject.getEventType())
.error(getErrorMsg(triggerObject.getError()))
.build();

6
common/data/src/main/java/org/thingsboard/server/common/data/id/TenantId.java

@ -45,9 +45,15 @@ public final class TenantId extends UUIDBased implements EntityId {
super(id);
}
@JsonIgnore
public boolean isSysTenantId() {
return this.equals(SYS_TENANT_ID);
}
@ApiModelProperty(position = 2, required = true, value = "string", example = "TENANT", allowableValues = "TENANT")
@Override
public EntityType getEntityType() {
return EntityType.TENANT;
}
}

18
common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationProcessingContext.java

@ -35,7 +35,6 @@ import org.thingsboard.server.common.data.notification.template.NotificationTemp
import org.thingsboard.server.common.data.notification.template.NotificationTemplateConfig;
import org.thingsboard.server.common.data.notification.template.WebDeliveryMethodNotificationTemplate;
import java.util.Collections;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Map;
@ -114,9 +113,14 @@ public class NotificationProcessingContext {
.map(config -> config.get("actionButtonConfig")).filter(JsonNode::isObject)
.map(config -> (ObjectNode) config);
if (buttonConfig.isPresent()) {
JsonNode text = buttonConfig.get().get("text");
if (text != null && text.isTextual()) {
text = new TextNode(processTemplate(text.asText(), templateContext));
buttonConfig.get().set("text", text);
}
JsonNode link = buttonConfig.get().get("link");
if (link != null && link.isTextual()) {
link = new TextNode(processTemplate(link.asText(), templateContext, info != null ? info.getTemplateData() : Collections.emptyMap()));
link = new TextNode(processTemplate(link.asText(), templateContext).toLowerCase());
buttonConfig.get().set("link", link);
}
}
@ -124,14 +128,12 @@ public class NotificationProcessingContext {
return template;
}
private static String processTemplate(String template, Map<String, String>... contexts) {
private static String processTemplate(String template, Map<String, String> context) {
if (template == null) return null;
String result = template;
for (Map<String, String> context : contexts) {
for (Map.Entry<String, String> kv : context.entrySet()) {
String value = Strings.nullToEmpty(kv.getValue());
result = result.replace("${" + kv.getKey() + '}', value);
}
for (Map.Entry<String, String> kv : context.entrySet()) {
String value = Strings.nullToEmpty(kv.getValue());
result = result.replace("${" + kv.getKey() + '}', value);
}
return result;
}

2
common/data/src/main/java/org/thingsboard/server/common/data/notification/info/AlarmAssignmentNotificationInfo.java

@ -61,7 +61,7 @@ public class AlarmAssignmentNotificationInfo implements RuleOriginatedNotificati
"userName", userName,
"alarmType", alarmType,
"alarmId", alarmId.toString(),
"alarmSeverity", alarmSeverity.toString(),
"alarmSeverity", alarmSeverity.name().toLowerCase(),
"alarmStatus", alarmStatus.toString(),
"alarmOriginatorEntityType", alarmOriginator.getEntityType().normalName(),
"alarmOriginatorId", alarmOriginator.getId().toString(),

2
common/data/src/main/java/org/thingsboard/server/common/data/notification/info/AlarmCommentNotificationInfo.java

@ -54,7 +54,7 @@ public class AlarmCommentNotificationInfo implements RuleOriginatedNotificationI
"userName", userName,
"alarmType", alarmType,
"alarmId", alarmId.toString(),
"alarmSeverity", alarmSeverity.toString(),
"alarmSeverity", alarmSeverity.name().toLowerCase(),
"alarmStatus", alarmStatus.toString(),
"alarmOriginatorEntityType", alarmOriginator.getEntityType().normalName(),
"alarmOriginatorId", alarmOriginator.getId().toString(),

2
common/data/src/main/java/org/thingsboard/server/common/data/notification/info/AlarmNotificationInfo.java

@ -50,7 +50,7 @@ public class AlarmNotificationInfo implements RuleOriginatedNotificationInfo {
"alarmType", alarmType,
"action", action,
"alarmId", alarmId.toString(),
"alarmSeverity", alarmSeverity.toString(),
"alarmSeverity", alarmSeverity.name().toLowerCase(),
"alarmStatus", alarmStatus.toString(),
"alarmOriginatorEntityType", alarmOriginator.getEntityType().normalName(),
"alarmOriginatorName", alarmOriginatorName,

1
common/data/src/main/java/org/thingsboard/server/common/data/notification/info/DeviceInactivityNotificationInfo.java

@ -15,7 +15,6 @@
*/
package org.thingsboard.server.common.data.notification.info;
import com.google.common.base.Strings;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;

2
common/data/src/main/java/org/thingsboard/server/common/data/notification/info/RuleEngineComponentLifecycleEventNotificationInfo.java

@ -37,6 +37,7 @@ public class RuleEngineComponentLifecycleEventNotificationInfo implements Notifi
private String ruleChainName;
private EntityId componentId;
private String componentName;
private String action;
private ComponentLifecycleEvent eventType;
private String error;
@ -48,6 +49,7 @@ public class RuleEngineComponentLifecycleEventNotificationInfo implements Notifi
"componentId", componentId.toString(),
"componentType", componentId.getEntityType().normalName(),
"componentName", componentName,
"action", action,
"eventType", eventType.name().toLowerCase(),
"error", error
);

2
common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/NotificationRule.java

@ -27,6 +27,7 @@ import org.thingsboard.server.common.data.id.NotificationTemplateId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.notification.rule.trigger.NotificationRuleTriggerConfig;
import org.thingsboard.server.common.data.notification.rule.trigger.NotificationRuleTriggerType;
import org.thingsboard.server.common.data.validation.NoXss;
import javax.validation.Valid;
import javax.validation.constraints.AssertTrue;
@ -40,6 +41,7 @@ public class NotificationRule extends BaseData<NotificationRuleId> implements Ha
private TenantId tenantId;
@NotBlank
@NoXss
private String name;
@NotNull
private NotificationTemplateId templateId;

9
common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/trigger/AlarmAssignmentNotificationRuleTriggerConfig.java

@ -19,6 +19,7 @@ import lombok.Data;
import org.thingsboard.server.common.data.alarm.AlarmSearchStatus;
import org.thingsboard.server.common.data.alarm.AlarmSeverity;
import javax.validation.constraints.NotEmpty;
import java.util.Set;
@Data
@ -27,12 +28,16 @@ public class AlarmAssignmentNotificationRuleTriggerConfig implements Notificatio
private Set<String> alarmTypes;
private Set<AlarmSeverity> alarmSeverities;
private Set<AlarmSearchStatus> alarmStatuses;
private boolean notifyOnAssign;
private boolean notifyOnUnassign;
@NotEmpty
private Set<Action> notifyOn;
@Override
public NotificationRuleTriggerType getTriggerType() {
return NotificationRuleTriggerType.ALARM_ASSIGNMENT;
}
public enum Action {
ASSIGNED, UNASSIGNED
}
}

2
common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/trigger/EntitiesLimitNotificationRuleTriggerConfig.java

@ -28,6 +28,8 @@ public class EntitiesLimitNotificationRuleTriggerConfig implements NotificationR
@Max(1)
private float threshold; // in percents,
// TODO: don't forget to create default notification configs
@Override
public NotificationRuleTriggerType getTriggerType() {
return NotificationRuleTriggerType.ENTITIES_LIMIT;

2
common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/trigger/NewPlatformVersionNotificationRuleTriggerConfig.java

@ -20,6 +20,8 @@ import lombok.Data;
@Data
public class NewPlatformVersionNotificationRuleTriggerConfig implements NotificationRuleTriggerConfig {
// TODO: don't forget to create default notification configs
@Override
public NotificationRuleTriggerType getTriggerType() {
return NotificationRuleTriggerType.NEW_PLATFORM_VERSION;

4
common/data/src/main/java/org/thingsboard/server/common/data/notification/rule/trigger/RuleEngineComponentLifecycleEventNotificationRuleTriggerConfig.java

@ -24,6 +24,8 @@ import java.util.UUID;
@Data
public class RuleEngineComponentLifecycleEventNotificationRuleTriggerConfig implements NotificationRuleTriggerConfig {
private Set<UUID> ruleChains; // if empty - all rule chains
private Set<ComponentLifecycleEvent> ruleChainEvents; // available options: STARTED, UPDATED, STOPPED. if empty - all events
private boolean onlyRuleChainLifecycleFailures;
@ -31,8 +33,6 @@ public class RuleEngineComponentLifecycleEventNotificationRuleTriggerConfig impl
private Set<ComponentLifecycleEvent> ruleNodeEvents; // available options: STARTED, UPDATED, STOPPED. if empty - all events
private boolean onlyRuleNodeLifecycleFailures;
private Set<UUID> ruleChains; // if empty - all rule chains
@Override
public NotificationRuleTriggerType getTriggerType() {
return NotificationRuleTriggerType.RULE_ENGINE_COMPONENT_LIFECYCLE_EVENT;

2
common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/NotificationTargetConfig.java

@ -23,6 +23,7 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo;
import lombok.Data;
import org.thingsboard.server.common.data.notification.targets.platform.PlatformUsersNotificationTargetConfig;
import org.thingsboard.server.common.data.notification.targets.slack.SlackNotificationTargetConfig;
import org.thingsboard.server.common.data.validation.NoXss;
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
@ -33,6 +34,7 @@ import org.thingsboard.server.common.data.notification.targets.slack.SlackNotifi
@Data
public abstract class NotificationTargetConfig {
@NoXss
private String description;
@JsonIgnore

231
dao/src/main/java/org/thingsboard/server/dao/notification/DefaultNotificationSettingsService.java

@ -15,21 +15,56 @@
*/
package org.thingsboard.server.dao.notification;
import com.fasterxml.jackson.databind.node.ObjectNode;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.common.data.AdminSettings;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.alarm.AlarmSearchStatus;
import org.thingsboard.server.common.data.alarm.AlarmSeverity;
import org.thingsboard.server.common.data.id.NotificationTargetId;
import org.thingsboard.server.common.data.id.NotificationTemplateId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod;
import org.thingsboard.server.common.data.notification.NotificationType;
import org.thingsboard.server.common.data.notification.rule.DefaultNotificationRuleRecipientsConfig;
import org.thingsboard.server.common.data.notification.rule.EscalatedNotificationRuleRecipientsConfig;
import org.thingsboard.server.common.data.notification.rule.NotificationRule;
import org.thingsboard.server.common.data.notification.rule.NotificationRuleConfig;
import org.thingsboard.server.common.data.notification.rule.trigger.AlarmAssignmentNotificationRuleTriggerConfig;
import org.thingsboard.server.common.data.notification.rule.trigger.AlarmCommentNotificationRuleTriggerConfig;
import org.thingsboard.server.common.data.notification.rule.trigger.AlarmNotificationRuleTriggerConfig;
import org.thingsboard.server.common.data.notification.rule.trigger.AlarmNotificationRuleTriggerConfig.AlarmAction;
import org.thingsboard.server.common.data.notification.rule.trigger.DeviceInactivityNotificationRuleTriggerConfig;
import org.thingsboard.server.common.data.notification.rule.trigger.EntityActionNotificationRuleTriggerConfig;
import org.thingsboard.server.common.data.notification.rule.trigger.NotificationRuleTriggerConfig;
import org.thingsboard.server.common.data.notification.rule.trigger.NotificationRuleTriggerType;
import org.thingsboard.server.common.data.notification.rule.trigger.RuleEngineComponentLifecycleEventNotificationRuleTriggerConfig;
import org.thingsboard.server.common.data.notification.settings.NotificationSettings;
import org.thingsboard.server.common.data.notification.targets.NotificationTarget;
import org.thingsboard.server.common.data.notification.targets.platform.ActionTargetUserFilter;
import org.thingsboard.server.common.data.notification.targets.platform.AllUsersFilter;
import org.thingsboard.server.common.data.notification.targets.platform.OriginatorEntityOwnerUsersFilter;
import org.thingsboard.server.common.data.notification.targets.platform.PlatformUsersNotificationTargetConfig;
import org.thingsboard.server.common.data.notification.targets.platform.TenantAdministratorsFilter;
import org.thingsboard.server.common.data.notification.targets.platform.UsersFilter;
import org.thingsboard.server.common.data.notification.template.NotificationTemplate;
import org.thingsboard.server.common.data.notification.template.NotificationTemplateConfig;
import org.thingsboard.server.common.data.notification.template.WebDeliveryMethodNotificationTemplate;
import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent;
import org.thingsboard.server.dao.settings.AdminSettingsService;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import static org.thingsboard.common.util.JacksonUtil.newObjectNode;
import static org.thingsboard.server.dao.DaoUtil.toUUIDs;
@Service
@RequiredArgsConstructor
@ -66,39 +101,189 @@ public class DefaultNotificationSettingsService implements NotificationSettingsS
});
}
// TODO: validate that wasn't already created (catch exception unique name)
// FIXME: user that does not have access to some entity, gets notifications about this entity - check permissions?
@Transactional(propagation = Propagation.NOT_SUPPORTED) // so that parent transaction is not aborted on method failure
@Override
public void createDefaultNotificationConfigs(TenantId tenantId) {
if (tenantId.equals(TenantId.SYS_TENANT_ID)) {
// TODO
NotificationTarget allUsers = createTarget(tenantId, "All users", new AllUsersFilter(),
tenantId.isSysTenantId() ? "All platform users" : "All users in scope of the tenant");
NotificationTarget tenantAdmins = createTarget(tenantId, "Tenant administrators", new TenantAdministratorsFilter(),
tenantId.isSysTenantId() ? "All tenant administrators" : "Tenant administrators");
if (tenantId.isSysTenantId()) {
createTemplate(tenantId, "Maintenance work notification", NotificationType.GENERAL,
"Infrastructure maintenance",
"Maintenance work is scheduled for tomorrow (7:00 a.m. - 9:00 a.m. UTC). You may face major service interruptions, sorry for the inconvenience");
return;
}
NotificationTarget allUsersTarget = new NotificationTarget();
allUsersTarget.setTenantId(tenantId);
allUsersTarget.setName("All users");
NotificationTarget originatorEntityOwnerUsers = createTarget(tenantId, "Users of rule trigger entity's owner", new OriginatorEntityOwnerUsersFilter(),
"Customer users in case trigger entity (e.g. alarm) has customer, tenant admins otherwise");
NotificationTarget actionTargetUser = createTarget(tenantId, "Action target", new ActionTargetUserFilter(),
"If rule trigger is an action that targets some user (e.g. alarm assigned to user) - this user");
NotificationTemplate alarmNotificationTemplate = createTemplate(tenantId, "Alarm notification", NotificationType.ALARM,
"Alarm '${alarmType}' - ${action}",
"Severity: ${alarmSeverity}, originator: ${alarmOriginatorEntityType} '${alarmOriginatorName}'",
"notifications", null, null);
AlarmNotificationRuleTriggerConfig alarmRuleTriggerConfig = new AlarmNotificationRuleTriggerConfig();
alarmRuleTriggerConfig.setAlarmTypes(null);
alarmRuleTriggerConfig.setAlarmSeverities(Set.of(AlarmSeverity.MAJOR, AlarmSeverity.CRITICAL));
alarmRuleTriggerConfig.setNotifyOn(Set.of(AlarmAction.CREATED, AlarmAction.SEVERITY_CHANGED, AlarmAction.ACKNOWLEDGED, AlarmAction.CLEARED));
createRule(tenantId, "Major or critical alarm", alarmNotificationTemplate.getId(), alarmRuleTriggerConfig,
List.of(originatorEntityOwnerUsers.getId()), "Send notification to tenant admins or customer users " +
"when any major or critical alarm is created, updated or cleared");
NotificationTemplate deviceActionNotificationTemplate = createTemplate(tenantId, "Device action notification", NotificationType.ENTITY_ACTION,
"${entityType} was ${actionType}",
"${entityType} '${entityName}' was ${actionType} by user ${originatorUserName}",
"info","Go to Device", "/devices/${entityId}");
EntityActionNotificationRuleTriggerConfig deviceActionRuleTriggerConfig = new EntityActionNotificationRuleTriggerConfig();
deviceActionRuleTriggerConfig.setEntityType(EntityType.DEVICE);
deviceActionRuleTriggerConfig.setCreated(true);
deviceActionRuleTriggerConfig.setUpdated(false);
deviceActionRuleTriggerConfig.setDeleted(true);
createRule(tenantId, "Device created or deleted", deviceActionNotificationTemplate.getId(), deviceActionRuleTriggerConfig,
List.of(originatorEntityOwnerUsers.getId()), "Send notification to tenant admins or customer users " +
"when device is created or deleted");
NotificationTemplate deviceInactivityNotificationTemplate = createTemplate(tenantId, "Device inactivity notification", NotificationType.DEVICE_INACTIVITY,
"Device '${deviceName}' inactive",
"Device '${deviceName}' with type '${deviceType}' became inactive",
"info", "Go to Device", "/devices/${deviceId}");
DeviceInactivityNotificationRuleTriggerConfig deviceInactivityRuleTriggerConfig = new DeviceInactivityNotificationRuleTriggerConfig();
deviceInactivityRuleTriggerConfig.setDevices(null);
deviceInactivityRuleTriggerConfig.setDeviceProfiles(null);
createRule(tenantId, "Device inactivity", deviceInactivityNotificationTemplate.getId(), deviceInactivityRuleTriggerConfig,
List.of(originatorEntityOwnerUsers.getId()), "Send notification to tenant admins or customer users " +
"when any device became inactive");
NotificationTemplate alarmCommentNotificationTemplate = createTemplate(tenantId, "Alarm comment notification", NotificationType.ALARM_COMMENT,
"Comment on '${alarmType}' alarm",
"${userName} ${action} comment: ${comment}",
"people", null, null);
AlarmCommentNotificationRuleTriggerConfig alarmCommentRuleTriggerConfig = new AlarmCommentNotificationRuleTriggerConfig();
alarmCommentRuleTriggerConfig.setAlarmTypes(null);
alarmCommentRuleTriggerConfig.setAlarmSeverities(null);
alarmCommentRuleTriggerConfig.setAlarmStatuses(Set.of(AlarmSearchStatus.ACTIVE));
alarmCommentRuleTriggerConfig.setOnlyUserComments(true);
alarmCommentRuleTriggerConfig.setNotifyOnCommentUpdate(false);
createRule(tenantId, "Comment on active alarm", alarmCommentNotificationTemplate.getId(), alarmCommentRuleTriggerConfig,
List.of(originatorEntityOwnerUsers.getId()), "Send notification to tenant admins or customer users " +
"when comment is added by user on active alarm");
NotificationTemplate alarmAssignedNotificationTemplate = createTemplate(tenantId, "Alarm assigned notification", NotificationType.ALARM_ASSIGNMENT,
"Alarm '${alarmType}' (${alarmSeverity}) was assigned to user",
"${userName} assigned alarm on ${alarmOriginatorEntityType} '${alarmOriginatorName}' to ${assigneeEmail}",
"person", null, null);
AlarmAssignmentNotificationRuleTriggerConfig alarmAssignmentRuleTriggerConfig = new AlarmAssignmentNotificationRuleTriggerConfig();
alarmAssignmentRuleTriggerConfig.setAlarmTypes(null);
alarmAssignmentRuleTriggerConfig.setAlarmSeverities(null);
alarmAssignmentRuleTriggerConfig.setAlarmStatuses(null);
alarmAssignmentRuleTriggerConfig.setNotifyOn(Set.of(AlarmAssignmentNotificationRuleTriggerConfig.Action.ASSIGNED));
createRule(tenantId, "Alarm assigned", alarmAssignedNotificationTemplate.getId(), alarmAssignmentRuleTriggerConfig,
List.of(actionTargetUser.getId()), "Send notification to user when any alarm was assigned to him");
NotificationTemplate ruleEngineComponentLifecycleFailureNotificationTemplate = createTemplate(tenantId, "Rule chain/node lifecycle failure notification", NotificationType.RULE_ENGINE_COMPONENT_LIFECYCLE_EVENT,
"${componentType} '${componentName}' failed to ${action}",
"Rule chain '${ruleChainName}' - ${action} failure:<br/>${error}",
"warning", "Go to Rule chain", "/ruleChains/${ruleChainId}");
RuleEngineComponentLifecycleEventNotificationRuleTriggerConfig ruleEngineComponentLifecycleEventRuleTriggerConfig = new RuleEngineComponentLifecycleEventNotificationRuleTriggerConfig();
ruleEngineComponentLifecycleEventRuleTriggerConfig.setRuleChains(null);
ruleEngineComponentLifecycleEventRuleTriggerConfig.setRuleChainEvents(Set.of(ComponentLifecycleEvent.STARTED, ComponentLifecycleEvent.UPDATED, ComponentLifecycleEvent.STOPPED));
ruleEngineComponentLifecycleEventRuleTriggerConfig.setOnlyRuleChainLifecycleFailures(true);
ruleEngineComponentLifecycleEventRuleTriggerConfig.setTrackRuleNodeEvents(true);
ruleEngineComponentLifecycleEventRuleTriggerConfig.setRuleNodeEvents(Set.of(ComponentLifecycleEvent.STARTED, ComponentLifecycleEvent.UPDATED, ComponentLifecycleEvent.STOPPED));
ruleEngineComponentLifecycleEventRuleTriggerConfig.setOnlyRuleNodeLifecycleFailures(true);
createRule(tenantId, "Rule chain/node lifecycle failure", ruleEngineComponentLifecycleFailureNotificationTemplate.getId(),
ruleEngineComponentLifecycleEventRuleTriggerConfig, List.of(tenantAdmins.getId()),
"Send notification to tenant admins when any Rule chain or Rule node failed to start, update or stop");
}
private NotificationTarget createTarget(TenantId tenantId, String name, UsersFilter filter, String description) {
NotificationTarget target = new NotificationTarget();
target.setTenantId(tenantId);
target.setName(name);
PlatformUsersNotificationTargetConfig targetConfig = new PlatformUsersNotificationTargetConfig();
targetConfig.setUsersFilter(new AllUsersFilter());
targetConfig.setDescription("All users in scope of tenant");
allUsersTarget.setConfiguration(targetConfig);
allUsersTarget = notificationTargetService.saveNotificationTarget(tenantId, allUsersTarget);
NotificationTarget originatorEntityOwnerUsers = new NotificationTarget();
originatorEntityOwnerUsers.setTenantId(tenantId);
originatorEntityOwnerUsers.setName("Users of rule trigger entity's owner");
targetConfig.setUsersFilter(new OriginatorEntityOwnerUsersFilter());
targetConfig.setDescription("For usage with notification rules. For example, if alarm trigger type is chosen, " +
"notifications will be sent to alarm owner's users, e.g. it's customer's users");
originatorEntityOwnerUsers.setConfiguration(targetConfig);
originatorEntityOwnerUsers = notificationTargetService.saveNotificationTarget(tenantId, originatorEntityOwnerUsers);
NotificationTemplate alarmNotificationTemplate = new NotificationTemplate();
targetConfig.setUsersFilter(filter);
targetConfig.setDescription(description);
target.setConfiguration(targetConfig);
return notificationTargetService.saveNotificationTarget(tenantId, target);
}
private NotificationTemplate createTemplate(TenantId tenantId, String name, NotificationType notificationType,
String subjectTemplate, String textTemplate) {
return createTemplate(tenantId, name, notificationType, subjectTemplate, textTemplate, null, null, null);
}
private NotificationTemplate createTemplate(TenantId tenantId, String name, NotificationType notificationType,
String subjectTemplate, String textTemplate,
String icon, String button, String link) {
NotificationTemplate template = new NotificationTemplate();
template.setTenantId(tenantId);
template.setName(name);
template.setNotificationType(notificationType);
NotificationTemplateConfig templateConfig = new NotificationTemplateConfig();
templateConfig.setNotificationSubject(subjectTemplate);
templateConfig.setDefaultTextTemplate(textTemplate);
WebDeliveryMethodNotificationTemplate webTemplate = new WebDeliveryMethodNotificationTemplate();
ObjectNode additionalConfig = newObjectNode();
ObjectNode iconConfig = additionalConfig.set("icon", newObjectNode());
ObjectNode buttonConfig = additionalConfig.set("actionButtonConfig", newObjectNode());
if (icon != null) {
iconConfig.put("enabled", true)
.put("icon", icon)
.put("color", "#757575");
} else {
iconConfig.put("enabled", false);
}
if (button != null) {
buttonConfig.put("enabled", true)
.put("text", button)
.put("linkType", "LINK")
.put("link", link);
} else {
buttonConfig.put("enabled", false);
}
webTemplate.setAdditionalConfig(additionalConfig);
templateConfig.setDeliveryMethodsTemplates(Map.of(
NotificationDeliveryMethod.WEB, webTemplate
));
/*
* TODO:
* rule chain start failure
* alarm
* {"icon":{"enabled":true,"icon":"info","color":"#757575"},"actionButtonConfig":{"enabled":true,"text":"Go to device","linkType":"LINK","link":"/devices/aa4a3660-c3e9-11ed-934f-bdfa9bfa7568"}}
* */
template.setConfiguration(templateConfig);
return notificationTemplateService.saveNotificationTemplate(tenantId, template);
}
private NotificationRule createRule(TenantId tenantId, String name, NotificationTemplateId templateId,
NotificationRuleTriggerConfig triggerConfig, List<NotificationTargetId> targets,
String description) {
NotificationRule rule = new NotificationRule();
rule.setTenantId(tenantId);
rule.setName(name);
rule.setTemplateId(templateId);
rule.setTriggerType(triggerConfig.getTriggerType());
rule.setTriggerConfig(triggerConfig);
if (rule.getTriggerType() == NotificationRuleTriggerType.ALARM) {
EscalatedNotificationRuleRecipientsConfig recipientsConfig = new EscalatedNotificationRuleRecipientsConfig();
recipientsConfig.setTriggerType(rule.getTriggerType());
recipientsConfig.setEscalationTable(Map.of(0, toUUIDs(targets)));
rule.setRecipientsConfig(recipientsConfig);
} else {
DefaultNotificationRuleRecipientsConfig recipientsConfig = new DefaultNotificationRuleRecipientsConfig();
recipientsConfig.setTriggerType(rule.getTriggerType());
recipientsConfig.setTargets(toUUIDs(targets));
rule.setRecipientsConfig(recipientsConfig);
}
NotificationRuleConfig additionalConfig = new NotificationRuleConfig();
additionalConfig.setDescription(description);
rule.setAdditionalConfig(additionalConfig);
return notificationRuleService.saveNotificationRule(tenantId, rule);
}
}

6
dao/src/main/java/org/thingsboard/server/dao/tenant/TenantServiceImpl.java

@ -195,7 +195,11 @@ public class TenantServiceImpl extends AbstractCachedEntityService<TenantId, Ten
deviceProfileService.createDefaultDeviceProfile(savedTenant.getId());
assetProfileService.createDefaultAssetProfile(savedTenant.getId());
apiUsageStateService.createDefaultApiUsageState(savedTenant.getId(), null);
notificationSettingsService.createDefaultNotificationConfigs(savedTenant.getId());
try {
notificationSettingsService.createDefaultNotificationConfigs(savedTenant.getId());
} catch (Throwable e) {
log.error("Failed to create default notification configs for tenant {}", savedTenant.getId(), e);
}
}
return savedTenant;
}

Loading…
Cancel
Save