Improvements for Microsoft Teams notifications

This commit is contained in:
ViacheslavKlimov 2023-08-04 17:33:11 +03:00
parent 70666b6f93
commit 1a93db75e0
4 changed files with 73 additions and 28 deletions

View File

@ -17,28 +17,37 @@ package org.thingsboard.server.service.notification.channels;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.base.Strings;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.stereotype.Component;
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.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.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.security.system.SystemSecurityService;
import java.time.Duration;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Optional;
@Component
@RequiredArgsConstructor
public class MicrosoftTeamsNotificationChannel implements NotificationChannel<MicrosoftTeamsNotificationTargetConfig, MicrosoftTeamsDeliveryMethodNotificationTemplate> {
private final SystemSecurityService systemSecurityService;
@Setter
private RestTemplate restTemplate = new RestTemplateBuilder()
.setConnectTimeout(Duration.of(15, ChronoUnit.SECONDS))
@ -47,11 +56,6 @@ public class MicrosoftTeamsNotificationChannel implements NotificationChannel<Mi
@Override
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.setThemeColor(Strings.emptyToNull(processedTemplate.getThemeColor()));
if (StringUtils.isEmpty(processedTemplate.getSubject())) {
@ -63,14 +67,42 @@ public class MicrosoftTeamsNotificationChannel implements NotificationChannel<Mi
section.setActivitySubtitle(processedTemplate.getBody());
message.setSections(List.of(section));
}
if (processedTemplate.getButton() != null) {
var button = processedTemplate.getButton();
Message.ActionCard actionCard = new Message.ActionCard();
actionCard.setType("OpenUri");
actionCard.setName(button.getName());
var target = new Message.ActionCard.Target("default", button.getUri());
actionCard.setTargets(List.of(target));
message.setPotentialAction(List.of(actionCard));
var button = processedTemplate.getButton();
if (button != null && button.isEnabled()) {
String uri;
if (button.getLinkType() == LinkType.DASHBOARD) {
String state = null;
if (button.isSetEntityIdInState() || StringUtils.isNotEmpty(button.getDashboardState())) {
ObjectNode stateObject = JacksonUtil.newObjectNode();
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);

View File

@ -249,7 +249,7 @@ public class DefaultSystemSecurityService implements SystemSecurityService {
JsonNode prohibitDifferentUrl = generalSettings.getJsonValue().get("prohibitDifferentUrl");
if (prohibitDifferentUrl != null && prohibitDifferentUrl.asBoolean()) {
if ((prohibitDifferentUrl != null && prohibitDifferentUrl.asBoolean()) || httpServletRequest == null) {
baseUrl = generalSettings.getJsonValue().get("baseUrl").asText();
}

View File

@ -558,8 +558,9 @@ public class NotificationApiTest extends AbstractNotificationApiTest {
template.setBody("Body: " + templateParams);
template.setThemeColor("ff0000");
var button = new MicrosoftTeamsDeliveryMethodNotificationTemplate.Button();
button.setName("Button: " + templateParams);
button.setUri("https://" + templateParams);
button.setEnabled(true);
button.setText("Button: " + templateParams);
button.setLink("https://" + templateParams);
template.setButton(button);
NotificationTemplate notificationTemplate = new NotificationTemplate();
notificationTemplate.setName("Notification to Teams");

View File

@ -22,6 +22,7 @@ import lombok.ToString;
import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod;
import java.util.List;
import java.util.UUID;
@Data
@EqualsAndHashCode(callSuper = true)
@ -33,16 +34,13 @@ public class MicrosoftTeamsDeliveryMethodNotificationTemplate extends DeliveryMe
private String themeColor;
private Button button;
private String customMessageCardJson;
private final List<TemplatableValue> templatableValues = List.of(
TemplatableValue.of(this::getBody, this::setBody),
TemplatableValue.of(this::getSubject, this::setSubject),
TemplatableValue.of(() -> button != null ? button.getName() : null,
processed -> {if (button != null) button.setName(processed);}),
TemplatableValue.of(() -> button != null ? button.getUri() : null,
processed -> {if (button != null) button.setUri(processed);}),
TemplatableValue.of(this::getCustomMessageCardJson, this::setCustomMessageCardJson)
TemplatableValue.of(() -> button != null ? button.getText() : null,
processed -> { if (button != null) button.setText(processed); }),
TemplatableValue.of(() -> button != null ? button.getLink() : null,
processed -> { if (button != null) button.setLink(processed); })
);
public MicrosoftTeamsDeliveryMethodNotificationTemplate(MicrosoftTeamsDeliveryMethodNotificationTemplate other) {
@ -50,7 +48,6 @@ public class MicrosoftTeamsDeliveryMethodNotificationTemplate extends DeliveryMe
this.subject = other.subject;
this.themeColor = other.themeColor;
this.button = other.button != null ? new Button(other.button) : null;
this.customMessageCardJson = other.customMessageCardJson;
}
@Override
@ -66,12 +63,27 @@ public class MicrosoftTeamsDeliveryMethodNotificationTemplate extends DeliveryMe
@Data
@NoArgsConstructor
public static class Button {
private String name;
private String uri;
private boolean enabled;
private String text;
private LinkType linkType;
private String link;
private UUID dashboardId;
private String dashboardState;
private boolean setEntityIdInState;
public Button(Button other) {
this.name = other.name;
this.uri = other.uri;
this.enabled = other.enabled;
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
}
}