diff --git a/application/src/main/data/upgrade/3.4.2/schema_update.sql b/application/src/main/data/upgrade/3.4.2/schema_update.sql new file mode 100644 index 0000000000..9b259cca3e --- /dev/null +++ b/application/src/main/data/upgrade/3.4.2/schema_update.sql @@ -0,0 +1,54 @@ +-- +-- Copyright © 2016-2022 The Thingsboard Authors +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- + + +CREATE TABLE IF NOT EXISTS notification_target ( + id UUID NOT NULL CONSTRAINT notification_target_pkey PRIMARY KEY, + created_time BIGINT NOT NULL, + tenant_id UUID NOT NULL, + name VARCHAR(255) NOT NULL, + configuration varchar(1000) NOT NULL +); +CREATE INDEX IF NOT EXISTS idx_notification_target_tenant_id_and_created_time ON notification_target(tenant_id, created_time DESC); + +CREATE TABLE IF NOT EXISTS notification_request ( + id UUID NOT NULL CONSTRAINT notification_request_pkey PRIMARY KEY, + created_time BIGINT NOT NULL, + tenant_id UUID NOT NULL, + target_id UUID NOT NULL CONSTRAINT fk_notification_request_target_id REFERENCES notification_target(id), + notification_reason VARCHAR NOT NULL, + text_template VARCHAR NOT NULL, + notification_info VARCHAR(1000), + notification_severity VARCHAR(32), + additional_config VARCHAR(1000), + sender_id UUID +); +CREATE INDEX IF NOT EXISTS idx_notification_request_tenant_id_and_created_time ON notification_request(tenant_id, created_time DESC); + +CREATE TABLE IF NOT EXISTS notification ( + id UUID NOT NULL, + created_time BIGINT NOT NULL, + request_id UUID NOT NULL CONSTRAINT fk_notification_request_id + REFERENCES notification_request(id) ON DELETE CASCADE, + recipient_id UUID NOT NULL, + reason VARCHAR NOT NULL, + text VARCHAR NOT NULL, + info VARCHAR(1000), + severity VARCHAR(32), + status VARCHAR(32) +) PARTITION BY RANGE (created_time); +CREATE INDEX IF NOT EXISTS idx_notification_recipient_id_and_created_time ON notification(recipient_id, created_time DESC); +CREATE INDEX IF NOT EXISTS idx_notification_recipient_id_and_status_and_created_time ON notification(recipient_id, status, created_time DESC); diff --git a/application/src/main/java/org/thingsboard/server/config/SwaggerConfiguration.java b/application/src/main/java/org/thingsboard/server/config/SwaggerConfiguration.java index c53cf1b504..49e041f1af 100644 --- a/application/src/main/java/org/thingsboard/server/config/SwaggerConfiguration.java +++ b/application/src/main/java/org/thingsboard/server/config/SwaggerConfiguration.java @@ -25,6 +25,7 @@ import org.springframework.core.annotation.Order; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; +import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; import org.thingsboard.server.common.data.security.Authority; @@ -138,6 +139,7 @@ public class SwaggerConfiguration { ) .securitySchemes(newArrayList(httpLogin())) .securityContexts(newArrayList(securityContext())) + .ignoredParameterTypes(AuthenticationPrincipal.class) .enableUrlTemplating(true); } diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/notification/NotificationService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/notification/NotificationService.java index a582758639..c8e1a7ea08 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/notification/NotificationService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/notification/NotificationService.java @@ -16,6 +16,7 @@ package org.thingsboard.server.dao.notification; import org.thingsboard.server.common.data.id.NotificationId; +import org.thingsboard.server.common.data.id.NotificationRequestId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.notification.Notification; @@ -28,12 +29,16 @@ public interface NotificationService { NotificationRequest createNotificationRequest(TenantId tenantId, NotificationRequest notificationRequest); + NotificationRequest findNotificationRequestById(TenantId tenantId, NotificationRequestId id); + PageData findNotificationRequestsByTenantIdAndPageLink(TenantId tenantId, PageLink pageLink); + void deleteNotificationRequest(TenantId tenantId, NotificationRequestId id); + Notification createNotification(TenantId tenantId, Notification notification); - void updateNotificationStatus(TenantId tenantId, NotificationId notificationId, NotificationStatus status); + Notification updateNotificationStatus(TenantId tenantId, NotificationId notificationId, NotificationStatus status); PageData findNotificationsByUserIdAndReadStatusAndPageLink(TenantId tenantId, UserId userId, boolean unreadOnly, PageLink pageLink); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/EntityType.java b/common/data/src/main/java/org/thingsboard/server/common/data/EntityType.java index 0798647903..bdcff739f7 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/EntityType.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/EntityType.java @@ -19,5 +19,7 @@ package org.thingsboard.server.common.data; * @author Andrew Shvayka */ public enum EntityType { - TENANT, CUSTOMER, USER, DASHBOARD, ASSET, DEVICE, ALARM, RULE_CHAIN, RULE_NODE, ENTITY_VIEW, WIDGETS_BUNDLE, WIDGET_TYPE, TENANT_PROFILE, DEVICE_PROFILE, ASSET_PROFILE, API_USAGE_STATE, TB_RESOURCE, OTA_PACKAGE, EDGE, RPC, QUEUE; + TENANT, CUSTOMER, USER, DASHBOARD, ASSET, DEVICE, ALARM, RULE_CHAIN, RULE_NODE, ENTITY_VIEW, WIDGETS_BUNDLE, WIDGET_TYPE, + TENANT_PROFILE, DEVICE_PROFILE, ASSET_PROFILE, API_USAGE_STATE, TB_RESOURCE, OTA_PACKAGE, EDGE, RPC, QUEUE, + NOTIFICATION_TARGET, NOTIFICATION_REQUEST; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/id/EntityIdFactory.java b/common/data/src/main/java/org/thingsboard/server/common/data/id/EntityIdFactory.java index da9a5c49eb..93080269b2 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/id/EntityIdFactory.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/id/EntityIdFactory.java @@ -81,6 +81,10 @@ public class EntityIdFactory { return new RpcId(uuid); case QUEUE: return new QueueId(uuid); + case NOTIFICATION_TARGET: + return new NotificationTargetId(uuid); + case NOTIFICATION_REQUEST: + return new NotificationRequestId(uuid); } throw new IllegalArgumentException("EntityType " + type + " is not supported!"); } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/id/NotificationId.java b/common/data/src/main/java/org/thingsboard/server/common/data/id/NotificationId.java index a52bfdd9d1..2a467d3a07 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/id/NotificationId.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/id/NotificationId.java @@ -16,12 +16,13 @@ package org.thingsboard.server.common.data.id; import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; import java.util.UUID; public class NotificationId extends UUIDBased { @JsonCreator - public NotificationId(UUID id) { + public NotificationId(@JsonProperty("id") UUID id) { super(id); } } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/id/NotificationRequestId.java b/common/data/src/main/java/org/thingsboard/server/common/data/id/NotificationRequestId.java index cffea0f6f5..3272d93d6f 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/id/NotificationRequestId.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/id/NotificationRequestId.java @@ -16,12 +16,21 @@ package org.thingsboard.server.common.data.id; import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import org.thingsboard.server.common.data.EntityType; import java.util.UUID; -public class NotificationRequestId extends UUIDBased { +public class NotificationRequestId extends UUIDBased implements EntityId { + @JsonCreator - public NotificationRequestId(UUID id) { + public NotificationRequestId(@JsonProperty("id") UUID id) { super(id); } + + @Override + public EntityType getEntityType() { + return EntityType.NOTIFICATION_REQUEST; + } + } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/id/NotificationTargetId.java b/common/data/src/main/java/org/thingsboard/server/common/data/id/NotificationTargetId.java index 3d8dddfe0e..44211d85fd 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/id/NotificationTargetId.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/id/NotificationTargetId.java @@ -16,12 +16,21 @@ package org.thingsboard.server.common.data.id; import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import org.thingsboard.server.common.data.EntityType; import java.util.UUID; -public class NotificationTargetId extends UUIDBased { +public class NotificationTargetId extends UUIDBased implements EntityId { + @JsonCreator - public NotificationTargetId(UUID id) { + public NotificationTargetId(@JsonProperty("id") UUID id) { super(id); } + + @Override + public EntityType getEntityType() { + return EntityType.NOTIFICATION_TARGET; + } + } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/Notification.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/Notification.java index 02f0fb2aa4..a633ad6433 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/Notification.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/Notification.java @@ -34,7 +34,9 @@ public class Notification extends SearchTextBased { private NotificationRequestId requestId; private UserId recipientId; + private String reason; private String text; + private NotificationInfo info; private NotificationSeverity severity; private NotificationStatus status; // private UserId senderId; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationStatus.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationStatus.java index 7e504cbe15..3484768860 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationStatus.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/NotificationStatus.java @@ -17,6 +17,5 @@ package org.thingsboard.server.common.data.notification; public enum NotificationStatus { SENT, - DELIVERED, READ } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/NotificationTarget.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/NotificationTarget.java index 957a6d359f..8b873b5ca9 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/NotificationTarget.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/NotificationTarget.java @@ -23,12 +23,20 @@ import org.thingsboard.server.common.data.HasTenantId; import org.thingsboard.server.common.data.id.NotificationTargetId; import org.thingsboard.server.common.data.id.TenantId; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + @Data @EqualsAndHashCode(callSuper = true) public class NotificationTarget extends BaseData implements HasTenantId, HasName { + @NotNull private TenantId tenantId; + @NotBlank private String name; + @NotNull + @Valid private NotificationTargetConfig configuration; } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/SingleUserNotificationTargetConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/SingleUserNotificationTargetConfig.java index cf0b4316d0..9fbb6ca600 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/SingleUserNotificationTargetConfig.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/notification/targets/SingleUserNotificationTargetConfig.java @@ -18,9 +18,12 @@ package org.thingsboard.server.common.data.notification.targets; import lombok.Data; import org.thingsboard.server.common.data.id.UserId; +import javax.validation.constraints.NotNull; + @Data public class SingleUserNotificationTargetConfig implements NotificationTargetConfig { + @NotNull private UserId userId; @Override diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/BaseSqlEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/BaseSqlEntity.java index 6e8a4a7076..5256eee7db 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/BaseSqlEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/BaseSqlEntity.java @@ -15,7 +15,10 @@ */ package org.thingsboard.server.dao.model; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JsonNode; import lombok.Data; +import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.id.UUIDBased; import javax.persistence.Column; @@ -75,4 +78,16 @@ public abstract class BaseSqlEntity implements BaseEntity { } } + protected JsonNode toJson(Object value) { + if (value != null) { + return JacksonUtil.valueToTree(value); + } else { + return null; + } + } + + protected T fromJson(JsonNode json) { + return JacksonUtil.convertValue(json, new TypeReference() {}); + } + } diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java b/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java index 5c938de98c..13d149bcf5 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java @@ -655,7 +655,9 @@ public class ModelConstants { public static final String NOTIFICATION_TABLE_NAME = "notification"; public static final String NOTIFICATION_REQUEST_ID_PROPERTY = "request_id"; public static final String NOTIFICATION_RECIPIENT_ID_PROPERTY = "recipient_id"; + public static final String NOTIFICATION_REASON_PROPERTY = "reason"; public static final String NOTIFICATION_TEXT_PROPERTY = "text"; + public static final String NOTIFICATION_INFO_PROPERTY = "info"; public static final String NOTIFICATION_SEVERITY_PROPERTY = "severity"; public static final String NOTIFICATION_STATUS_PROPERTY = "status"; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/NotificationEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/NotificationEntity.java index ad7c506d4b..be3532e300 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/NotificationEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/NotificationEntity.java @@ -15,16 +15,22 @@ */ package org.thingsboard.server.dao.model.sql; +import com.fasterxml.jackson.databind.JsonNode; import lombok.Data; import lombok.EqualsAndHashCode; +import org.hibernate.annotations.Type; +import org.hibernate.annotations.TypeDef; +import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.server.common.data.id.NotificationId; import org.thingsboard.server.common.data.id.NotificationRequestId; import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.notification.Notification; +import org.thingsboard.server.common.data.notification.NotificationInfo; import org.thingsboard.server.common.data.notification.NotificationSeverity; import org.thingsboard.server.common.data.notification.NotificationStatus; import org.thingsboard.server.dao.model.BaseSqlEntity; import org.thingsboard.server.dao.model.ModelConstants; +import org.thingsboard.server.dao.util.mapping.JsonStringType; import javax.persistence.Column; import javax.persistence.Entity; @@ -36,18 +42,26 @@ import java.util.UUID; @Data @EqualsAndHashCode(callSuper = true) @Entity +@TypeDef(name = "json", typeClass = JsonStringType.class) @Table(name = ModelConstants.NOTIFICATION_TABLE_NAME) public class NotificationEntity extends BaseSqlEntity { - @Column(name = ModelConstants.NOTIFICATION_REQUEST_ID_PROPERTY) + @Column(name = ModelConstants.NOTIFICATION_REQUEST_ID_PROPERTY, nullable = false) private UUID requestId; - @Column(name = ModelConstants.NOTIFICATION_RECIPIENT_ID_PROPERTY) + @Column(name = ModelConstants.NOTIFICATION_RECIPIENT_ID_PROPERTY, nullable = false) private UUID recipientId; - @Column(name = ModelConstants.NOTIFICATION_TEXT_PROPERTY) + @Column(name = ModelConstants.NOTIFICATION_REASON_PROPERTY, nullable = false) + private String reason; + + @Column(name = ModelConstants.NOTIFICATION_TEXT_PROPERTY, nullable = false) private String text; + @Type(type = "json") + @Column(name = ModelConstants.NOTIFICATION_INFO_PROPERTY) + private JsonNode info; + @Column(name = ModelConstants.NOTIFICATION_SEVERITY_PROPERTY) private NotificationSeverity severity; @@ -62,7 +76,12 @@ public class NotificationEntity extends BaseSqlEntity { setCreatedTime(notification.getCreatedTime()); setRequestId(getUuid(notification.getRequestId())); setRecipientId(getUuid(notification.getRecipientId())); + setReason(notification.getReason()); setText(notification.getText()); + if (notification.getInfo() != null) { + setInfo(JacksonUtil.valueToTree(notification.getInfo())); + } + setSeverity(notification.getSeverity()); setStatus(notification.getStatus()); } @@ -73,7 +92,12 @@ public class NotificationEntity extends BaseSqlEntity { notification.setCreatedTime(createdTime); notification.setRequestId(createId(requestId, NotificationRequestId::new)); notification.setRecipientId(createId(recipientId, UserId::new)); + notification.setReason(reason); notification.setText(text); + if (info != null) { + notification.setInfo(JacksonUtil.treeToValue(info, NotificationInfo.class)); + } + notification.setSeverity(severity); notification.setStatus(status); return notification; } diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/NotificationRequestEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/NotificationRequestEntity.java index 23a8ae1059..f469f4aed7 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/NotificationRequestEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/NotificationRequestEntity.java @@ -47,16 +47,16 @@ import java.util.UUID; @Table(name = ModelConstants.NOTIFICATION_REQUEST_TABLE_NAME) public class NotificationRequestEntity extends BaseSqlEntity { - @Column(name = ModelConstants.TENANT_ID_PROPERTY) + @Column(name = ModelConstants.TENANT_ID_PROPERTY, nullable = false) private UUID tenantId; - @Column(name = ModelConstants.NOTIFICATION_REQUEST_TARGET_ID_PROPERTY) + @Column(name = ModelConstants.NOTIFICATION_REQUEST_TARGET_ID_PROPERTY, nullable = false) private UUID targetId; - @Column(name = ModelConstants.NOTIFICATION_REQUEST_NOTIFICATION_REASON_PROPERTY) + @Column(name = ModelConstants.NOTIFICATION_REQUEST_NOTIFICATION_REASON_PROPERTY, nullable = false) private String notificationReason; - @Column(name = ModelConstants.NOTIFICATION_REQUEST_TEXT_TEMPLATE_PROPERTY) + @Column(name = ModelConstants.NOTIFICATION_REQUEST_TEXT_TEMPLATE_PROPERTY, nullable = false) private String textTemplate; @Type(type = "json") @@ -83,9 +83,9 @@ public class NotificationRequestEntity extends BaseSqlEntity { - @Column(name = ModelConstants.TENANT_ID_PROPERTY) + @Column(name = ModelConstants.TENANT_ID_PROPERTY, nullable = false) private UUID tenantId; - @Column(name = ModelConstants.NAME_PROPERTY) + @Column(name = ModelConstants.NAME_PROPERTY, nullable = false) private String name; @Type(type = "json") - @Column(name = ModelConstants.NOTIFICATION_TARGET_CONFIGURATION_PROPERTY) + @Column(name = ModelConstants.NOTIFICATION_TARGET_CONFIGURATION_PROPERTY, nullable = false) private JsonNode configuration; public NotificationTargetEntity() {} diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/notification/NotificationRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/notification/NotificationRepository.java index 9ee5b07121..07fc48e13f 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/notification/NotificationRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/notification/NotificationRepository.java @@ -40,4 +40,6 @@ public interface NotificationRepository extends JpaRepository