Improvements for Microsoft Teams notifications
This commit is contained in:
parent
70666b6f93
commit
1a93db75e0
@ -17,28 +17,37 @@ package org.thingsboard.server.service.notification.channels;
|
|||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
import com.google.common.base.Strings;
|
import com.google.common.base.Strings;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
import org.apache.commons.codec.binary.Base64;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.boot.web.client.RestTemplateBuilder;
|
import org.springframework.boot.web.client.RestTemplateBuilder;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.web.client.RestTemplate;
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
import org.thingsboard.common.util.JacksonUtil;
|
||||||
import org.thingsboard.server.common.data.id.TenantId;
|
import org.thingsboard.server.common.data.id.TenantId;
|
||||||
import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod;
|
import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod;
|
||||||
|
import org.thingsboard.server.common.data.notification.info.NotificationInfo;
|
||||||
import org.thingsboard.server.common.data.notification.targets.MicrosoftTeamsNotificationTargetConfig;
|
import org.thingsboard.server.common.data.notification.targets.MicrosoftTeamsNotificationTargetConfig;
|
||||||
import org.thingsboard.server.common.data.notification.template.MicrosoftTeamsDeliveryMethodNotificationTemplate;
|
import org.thingsboard.server.common.data.notification.template.MicrosoftTeamsDeliveryMethodNotificationTemplate;
|
||||||
|
import org.thingsboard.server.common.data.notification.template.MicrosoftTeamsDeliveryMethodNotificationTemplate.Button.LinkType;
|
||||||
import org.thingsboard.server.service.notification.NotificationProcessingContext;
|
import org.thingsboard.server.service.notification.NotificationProcessingContext;
|
||||||
|
import org.thingsboard.server.service.security.system.SystemSecurityService;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class MicrosoftTeamsNotificationChannel implements NotificationChannel<MicrosoftTeamsNotificationTargetConfig, MicrosoftTeamsDeliveryMethodNotificationTemplate> {
|
public class MicrosoftTeamsNotificationChannel implements NotificationChannel<MicrosoftTeamsNotificationTargetConfig, MicrosoftTeamsDeliveryMethodNotificationTemplate> {
|
||||||
|
|
||||||
|
private final SystemSecurityService systemSecurityService;
|
||||||
|
|
||||||
@Setter
|
@Setter
|
||||||
private RestTemplate restTemplate = new RestTemplateBuilder()
|
private RestTemplate restTemplate = new RestTemplateBuilder()
|
||||||
.setConnectTimeout(Duration.of(15, ChronoUnit.SECONDS))
|
.setConnectTimeout(Duration.of(15, ChronoUnit.SECONDS))
|
||||||
@ -47,11 +56,6 @@ public class MicrosoftTeamsNotificationChannel implements NotificationChannel<Mi
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendNotification(MicrosoftTeamsNotificationTargetConfig targetConfig, MicrosoftTeamsDeliveryMethodNotificationTemplate processedTemplate, NotificationProcessingContext ctx) throws Exception {
|
public void sendNotification(MicrosoftTeamsNotificationTargetConfig targetConfig, MicrosoftTeamsDeliveryMethodNotificationTemplate processedTemplate, NotificationProcessingContext ctx) throws Exception {
|
||||||
if (StringUtils.isNotEmpty(processedTemplate.getCustomMessageCardJson())) {
|
|
||||||
restTemplate.postForEntity(targetConfig.getWebhookUrl(), processedTemplate.getCustomMessageCardJson(), String.class);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Message message = new Message();
|
Message message = new Message();
|
||||||
message.setThemeColor(Strings.emptyToNull(processedTemplate.getThemeColor()));
|
message.setThemeColor(Strings.emptyToNull(processedTemplate.getThemeColor()));
|
||||||
if (StringUtils.isEmpty(processedTemplate.getSubject())) {
|
if (StringUtils.isEmpty(processedTemplate.getSubject())) {
|
||||||
@ -63,14 +67,42 @@ public class MicrosoftTeamsNotificationChannel implements NotificationChannel<Mi
|
|||||||
section.setActivitySubtitle(processedTemplate.getBody());
|
section.setActivitySubtitle(processedTemplate.getBody());
|
||||||
message.setSections(List.of(section));
|
message.setSections(List.of(section));
|
||||||
}
|
}
|
||||||
if (processedTemplate.getButton() != null) {
|
var button = processedTemplate.getButton();
|
||||||
var button = processedTemplate.getButton();
|
if (button != null && button.isEnabled()) {
|
||||||
Message.ActionCard actionCard = new Message.ActionCard();
|
String uri;
|
||||||
actionCard.setType("OpenUri");
|
if (button.getLinkType() == LinkType.DASHBOARD) {
|
||||||
actionCard.setName(button.getName());
|
String state = null;
|
||||||
var target = new Message.ActionCard.Target("default", button.getUri());
|
if (button.isSetEntityIdInState() || StringUtils.isNotEmpty(button.getDashboardState())) {
|
||||||
actionCard.setTargets(List.of(target));
|
ObjectNode stateObject = JacksonUtil.newObjectNode();
|
||||||
message.setPotentialAction(List.of(actionCard));
|
if (button.isSetEntityIdInState()) {
|
||||||
|
stateObject.putObject("params")
|
||||||
|
.set("entityId", Optional.ofNullable(ctx.getRequest().getInfo())
|
||||||
|
.map(NotificationInfo::getStateEntityId)
|
||||||
|
.map(JacksonUtil::valueToTree)
|
||||||
|
.orElse(null));
|
||||||
|
} else {
|
||||||
|
stateObject.putObject("params");
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotEmpty(button.getDashboardState())) {
|
||||||
|
stateObject.put("id", button.getDashboardState());
|
||||||
|
}
|
||||||
|
state = Base64.encodeBase64String(JacksonUtil.OBJECT_MAPPER.writeValueAsBytes(List.of(stateObject)));
|
||||||
|
}
|
||||||
|
uri = systemSecurityService.getBaseUrl(ctx.getTenantId(), null, null) + "/dashboards/" + button.getDashboardId();
|
||||||
|
if (state != null) {
|
||||||
|
uri += "?state=" + state;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
uri = button.getLink();
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotBlank(uri) && button.getText() != null) {
|
||||||
|
Message.ActionCard actionCard = new Message.ActionCard();
|
||||||
|
actionCard.setType("OpenUri");
|
||||||
|
actionCard.setName(button.getText());
|
||||||
|
var target = new Message.ActionCard.Target("default", uri);
|
||||||
|
actionCard.setTargets(List.of(target));
|
||||||
|
message.setPotentialAction(List.of(actionCard));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
restTemplate.postForEntity(targetConfig.getWebhookUrl(), message, String.class);
|
restTemplate.postForEntity(targetConfig.getWebhookUrl(), message, String.class);
|
||||||
|
|||||||
@ -249,7 +249,7 @@ public class DefaultSystemSecurityService implements SystemSecurityService {
|
|||||||
|
|
||||||
JsonNode prohibitDifferentUrl = generalSettings.getJsonValue().get("prohibitDifferentUrl");
|
JsonNode prohibitDifferentUrl = generalSettings.getJsonValue().get("prohibitDifferentUrl");
|
||||||
|
|
||||||
if (prohibitDifferentUrl != null && prohibitDifferentUrl.asBoolean()) {
|
if ((prohibitDifferentUrl != null && prohibitDifferentUrl.asBoolean()) || httpServletRequest == null) {
|
||||||
baseUrl = generalSettings.getJsonValue().get("baseUrl").asText();
|
baseUrl = generalSettings.getJsonValue().get("baseUrl").asText();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -558,8 +558,9 @@ public class NotificationApiTest extends AbstractNotificationApiTest {
|
|||||||
template.setBody("Body: " + templateParams);
|
template.setBody("Body: " + templateParams);
|
||||||
template.setThemeColor("ff0000");
|
template.setThemeColor("ff0000");
|
||||||
var button = new MicrosoftTeamsDeliveryMethodNotificationTemplate.Button();
|
var button = new MicrosoftTeamsDeliveryMethodNotificationTemplate.Button();
|
||||||
button.setName("Button: " + templateParams);
|
button.setEnabled(true);
|
||||||
button.setUri("https://" + templateParams);
|
button.setText("Button: " + templateParams);
|
||||||
|
button.setLink("https://" + templateParams);
|
||||||
template.setButton(button);
|
template.setButton(button);
|
||||||
NotificationTemplate notificationTemplate = new NotificationTemplate();
|
NotificationTemplate notificationTemplate = new NotificationTemplate();
|
||||||
notificationTemplate.setName("Notification to Teams");
|
notificationTemplate.setName("Notification to Teams");
|
||||||
|
|||||||
@ -22,6 +22,7 @@ import lombok.ToString;
|
|||||||
import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod;
|
import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@ -33,16 +34,13 @@ public class MicrosoftTeamsDeliveryMethodNotificationTemplate extends DeliveryMe
|
|||||||
private String themeColor;
|
private String themeColor;
|
||||||
private Button button;
|
private Button button;
|
||||||
|
|
||||||
private String customMessageCardJson;
|
|
||||||
|
|
||||||
private final List<TemplatableValue> templatableValues = List.of(
|
private final List<TemplatableValue> templatableValues = List.of(
|
||||||
TemplatableValue.of(this::getBody, this::setBody),
|
TemplatableValue.of(this::getBody, this::setBody),
|
||||||
TemplatableValue.of(this::getSubject, this::setSubject),
|
TemplatableValue.of(this::getSubject, this::setSubject),
|
||||||
TemplatableValue.of(() -> button != null ? button.getName() : null,
|
TemplatableValue.of(() -> button != null ? button.getText() : null,
|
||||||
processed -> {if (button != null) button.setName(processed);}),
|
processed -> { if (button != null) button.setText(processed); }),
|
||||||
TemplatableValue.of(() -> button != null ? button.getUri() : null,
|
TemplatableValue.of(() -> button != null ? button.getLink() : null,
|
||||||
processed -> {if (button != null) button.setUri(processed);}),
|
processed -> { if (button != null) button.setLink(processed); })
|
||||||
TemplatableValue.of(this::getCustomMessageCardJson, this::setCustomMessageCardJson)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
public MicrosoftTeamsDeliveryMethodNotificationTemplate(MicrosoftTeamsDeliveryMethodNotificationTemplate other) {
|
public MicrosoftTeamsDeliveryMethodNotificationTemplate(MicrosoftTeamsDeliveryMethodNotificationTemplate other) {
|
||||||
@ -50,7 +48,6 @@ public class MicrosoftTeamsDeliveryMethodNotificationTemplate extends DeliveryMe
|
|||||||
this.subject = other.subject;
|
this.subject = other.subject;
|
||||||
this.themeColor = other.themeColor;
|
this.themeColor = other.themeColor;
|
||||||
this.button = other.button != null ? new Button(other.button) : null;
|
this.button = other.button != null ? new Button(other.button) : null;
|
||||||
this.customMessageCardJson = other.customMessageCardJson;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -66,12 +63,27 @@ public class MicrosoftTeamsDeliveryMethodNotificationTemplate extends DeliveryMe
|
|||||||
@Data
|
@Data
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
public static class Button {
|
public static class Button {
|
||||||
private String name;
|
private boolean enabled;
|
||||||
private String uri;
|
private String text;
|
||||||
|
private LinkType linkType;
|
||||||
|
private String link;
|
||||||
|
|
||||||
|
private UUID dashboardId;
|
||||||
|
private String dashboardState;
|
||||||
|
private boolean setEntityIdInState;
|
||||||
|
|
||||||
public Button(Button other) {
|
public Button(Button other) {
|
||||||
this.name = other.name;
|
this.enabled = other.enabled;
|
||||||
this.uri = other.uri;
|
this.text = other.text;
|
||||||
|
this.linkType = other.linkType;
|
||||||
|
this.link = other.link;
|
||||||
|
this.dashboardId = other.dashboardId;
|
||||||
|
this.dashboardState = other.dashboardState;
|
||||||
|
this.setEntityIdInState = other.setEntityIdInState;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum LinkType {
|
||||||
|
LINK, DASHBOARD
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user