Merge branch 'rc'

This commit is contained in:
Igor Kulikov 2024-12-05 15:10:22 +02:00
commit a8de539ea0
12 changed files with 134 additions and 74 deletions

View File

@ -477,7 +477,7 @@ public class NotificationController extends BaseController {
SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH) SYSTEM_OR_TENANT_AUTHORITY_PARAGRAPH)
@GetMapping("/notification/deliveryMethods") @GetMapping("/notification/deliveryMethods")
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
public Set<NotificationDeliveryMethod> getAvailableDeliveryMethods(@AuthenticationPrincipal SecurityUser user) throws ThingsboardException { public List<NotificationDeliveryMethod> getAvailableDeliveryMethods(@AuthenticationPrincipal SecurityUser user) throws ThingsboardException {
return notificationCenter.getAvailableDeliveryMethods(user.getTenantId()); return notificationCenter.getAvailableDeliveryMethods(user.getTenantId());
} }

View File

@ -101,7 +101,7 @@ public class ResourcesUpdater {
for (DashboardId dashboardId : dashboards) { for (DashboardId dashboardId : dashboards) {
executor.submit(() -> { executor.submit(() -> {
Dashboard dashboard = dashboardService.findDashboardById(TenantId.SYS_TENANT_ID, dashboardId); Dashboard dashboard = dashboardService.findDashboardById(TenantId.SYS_TENANT_ID, dashboardId);
boolean updated = resourceService.updateResourcesUsage(dashboard); // will convert resources ids to new structure boolean updated = resourceService.updateResourcesUsage(dashboard.getTenantId(), dashboard); // will convert resources ids to new structure
if (updated) { if (updated) {
dashboardService.saveDashboard(dashboard); dashboardService.saveDashboard(dashboard);
updatedCount.incrementAndGet(); updatedCount.incrementAndGet();
@ -130,7 +130,7 @@ public class ResourcesUpdater {
for (WidgetTypeId widgetTypeId : widgets) { for (WidgetTypeId widgetTypeId : widgets) {
executor.submit(() -> { executor.submit(() -> {
WidgetTypeDetails widgetTypeDetails = widgetTypeService.findWidgetTypeDetailsById(TenantId.SYS_TENANT_ID, widgetTypeId); WidgetTypeDetails widgetTypeDetails = widgetTypeService.findWidgetTypeDetailsById(TenantId.SYS_TENANT_ID, widgetTypeId);
boolean updated = resourceService.updateResourcesUsage(widgetTypeDetails); boolean updated = resourceService.updateResourcesUsage(widgetTypeDetails.getTenantId(), widgetTypeDetails);
if (updated) { if (updated) {
widgetTypeService.saveWidgetType(widgetTypeDetails); widgetTypeService.saveWidgetType(widgetTypeDetails);
updatedCount.incrementAndGet(); updatedCount.incrementAndGet();

View File

@ -417,7 +417,7 @@ public class DefaultNotificationCenter extends AbstractSubscriptionService imple
} }
@Override @Override
public Set<NotificationDeliveryMethod> getAvailableDeliveryMethods(TenantId tenantId) { public List<NotificationDeliveryMethod> getAvailableDeliveryMethods(TenantId tenantId) {
return channels.values().stream() return channels.values().stream()
.filter(channel -> { .filter(channel -> {
try { try {
@ -428,7 +428,7 @@ public class DefaultNotificationCenter extends AbstractSubscriptionService imple
} }
}) })
.map(NotificationChannel::getDeliveryMethod) .map(NotificationChannel::getDeliveryMethod)
.collect(Collectors.toSet()); .sorted().toList();
} }
@Override @Override

View File

@ -46,7 +46,7 @@ import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Comparator; import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.function.Function; import java.util.function.Supplier;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
@ -132,12 +132,12 @@ public class DefaultTbResourceService extends AbstractTbEntityService implements
@Override @Override
public List<ResourceExportData> exportResources(Dashboard dashboard, SecurityUser user) throws ThingsboardException { public List<ResourceExportData> exportResources(Dashboard dashboard, SecurityUser user) throws ThingsboardException {
return exportResources(dashboard, imageService::getUsedImages, resourceService::getUsedResources, user); return exportResources(() -> imageService.getUsedImages(dashboard), () -> resourceService.getUsedResources(user.getTenantId(), dashboard), user);
} }
@Override @Override
public List<ResourceExportData> exportResources(WidgetTypeDetails widgetTypeDetails, SecurityUser user) throws ThingsboardException { public List<ResourceExportData> exportResources(WidgetTypeDetails widgetTypeDetails, SecurityUser user) throws ThingsboardException {
return exportResources(widgetTypeDetails, imageService::getUsedImages, resourceService::getUsedResources, user); return exportResources(() -> imageService.getUsedImages(widgetTypeDetails), () -> resourceService.getUsedResources(user.getTenantId(), widgetTypeDetails), user);
} }
@Override @Override
@ -153,13 +153,12 @@ public class DefaultTbResourceService extends AbstractTbEntityService implements
} }
} }
private <T> List<ResourceExportData> exportResources(T entity, private <T> List<ResourceExportData> exportResources(Supplier<Collection<TbResourceInfo>> imagesProcessor,
Function<T, Collection<TbResourceInfo>> imagesProcessor, Supplier<Collection<TbResourceInfo>> resourcesProcessor,
Function<T, Collection<TbResourceInfo>> resourcesProcessor,
SecurityUser user) throws ThingsboardException { SecurityUser user) throws ThingsboardException {
List<TbResourceInfo> resources = new ArrayList<>(); List<TbResourceInfo> resources = new ArrayList<>();
resources.addAll(imagesProcessor.apply(entity)); resources.addAll(imagesProcessor.get());
resources.addAll(resourcesProcessor.apply(entity)); resources.addAll(resourcesProcessor.get());
for (TbResourceInfo resourceInfo : resources) { for (TbResourceInfo resourceInfo : resources) {
accessControlService.checkPermission(user, Resource.TB_RESOURCE, Operation.READ, resourceInfo.getId(), resourceInfo); accessControlService.checkPermission(user, Resource.TB_RESOURCE, Operation.READ, resourceInfo.getId(), resourceInfo);
} }

View File

@ -17,6 +17,7 @@ package org.thingsboard.server.controller;
import com.datastax.oss.driver.api.core.uuid.Uuids; import com.datastax.oss.driver.api.core.uuid.Uuids;
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.junit.After; import org.junit.After;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
@ -602,13 +603,14 @@ public class DashboardControllerTest extends AbstractControllerTest {
dashboard.setTitle("My dashboard"); dashboard.setTitle("My dashboard");
dashboard.setConfiguration(JacksonUtil.newObjectNode() dashboard.setConfiguration(JacksonUtil.newObjectNode()
.put("someImage", "tb-image;/api/images/tenant/" + imageInfo.getResourceKey()) .put("someImage", "tb-image;/api/images/tenant/" + imageInfo.getResourceKey())
.set("widgets", JacksonUtil.toJsonNode(""" .<ObjectNode>set("widgets", JacksonUtil.toJsonNode("""
{"xxx": {"xxx":
{"config":{"actions":{"elementClick":[ {"config":{"actions":{"elementClick":[
{"customResources":[{"url":{"entityType":"TB_RESOURCE","id": {"customResources":[{"url":{"entityType":"TB_RESOURCE","id":
"tb-resource;/api/resource/js_module/tenant/gateway-management-extension.js"},"isModule":true}, "tb-resource;/api/resource/js_module/tenant/gateway-management-extension.js"},"isModule":true},
{"url":"tb-resource;/api/resource/js_module/tenant/gateway-management-extension.js","isModule":true}]}]}}}} {"url":"tb-resource;/api/resource/js_module/tenant/gateway-management-extension.js","isModule":true}]}]}}}}
"""))); """))
.put("someResource", "tb-resource;/api/resource/js_module/tenant/gateway-management-extension.js"));
dashboard = doPost("/api/dashboard", dashboard, Dashboard.class); dashboard = doPost("/api/dashboard", dashboard, Dashboard.class);
Dashboard exportedDashboard = doGet("/api/dashboard/" + dashboard.getUuidId() + "?includeResources=true", Dashboard.class); Dashboard exportedDashboard = doGet("/api/dashboard/" + dashboard.getUuidId() + "?includeResources=true", Dashboard.class);
@ -637,12 +639,18 @@ public class DashboardControllerTest extends AbstractControllerTest {
doPost("/api/resource", resource, TbResourceInfo.class); doPost("/api/resource", resource, TbResourceInfo.class);
Dashboard importedDashboard = doPost("/api/dashboard", exportedDashboard, Dashboard.class); Dashboard importedDashboard = doPost("/api/dashboard", exportedDashboard, Dashboard.class);
String newResourceKey = "gateway-management-extension_(1).js";
imageRef = importedDashboard.getConfiguration().get("someImage").asText(); imageRef = importedDashboard.getConfiguration().get("someImage").asText();
assertThat(imageRef).isEqualTo("tb-image;/api/images/tenant/" + imageInfo.getResourceKey()); assertThat(imageRef).isEqualTo("tb-image;/api/images/tenant/" + imageInfo.getResourceKey());
resourceRef = importedDashboard.getConfiguration().get("widgets").get("xxx").get("config")
.get("actions").get("elementClick").get(0).get("customResources").get(0).get("url").asText(); List<String> resourcesRefs = new ArrayList<>();
String newResourceKey = "gateway-management-extension_(1).js"; resourcesRefs.add(importedDashboard.getConfiguration().get("widgets").get("xxx").get("config")
assertThat(resourceRef).isEqualTo("tb-resource;/api/resource/js_module/tenant/" + newResourceKey); .get("actions").get("elementClick").get(0).get("customResources").get(0).get("url").asText());
resourcesRefs.add(importedDashboard.getConfiguration().get("someResource").asText());
assertThat(resourcesRefs).allSatisfy(ref -> {
assertThat(ref).isEqualTo("tb-resource;/api/resource/js_module/tenant/" + newResourceKey);
});
TbResourceInfo importedImageInfo = doGet("/api/images/tenant/" + imageInfo.getResourceKey() + "/info", TbResourceInfo.class); TbResourceInfo importedImageInfo = doGet("/api/images/tenant/" + imageInfo.getResourceKey() + "/info", TbResourceInfo.class);
assertThat(importedImageInfo.getEtag()).isEqualTo(imageInfo.getEtag()); assertThat(importedImageInfo.getEtag()).isEqualTo(imageInfo.getEtag());

View File

@ -80,13 +80,13 @@ public interface ResourceService extends EntityDaoService {
TbResourceInfo findSystemOrTenantResourceByEtag(TenantId tenantId, ResourceType resourceType, String etag); TbResourceInfo findSystemOrTenantResourceByEtag(TenantId tenantId, ResourceType resourceType, String etag);
boolean updateResourcesUsage(Dashboard dashboard); boolean updateResourcesUsage(TenantId tenantId, Dashboard dashboard);
boolean updateResourcesUsage(WidgetTypeDetails widgetTypeDetails); boolean updateResourcesUsage(TenantId tenantId, WidgetTypeDetails widgetTypeDetails);
Collection<TbResourceInfo> getUsedResources(Dashboard dashboard); Collection<TbResourceInfo> getUsedResources(TenantId tenantId, Dashboard dashboard);
Collection<TbResourceInfo> getUsedResources(WidgetTypeDetails widgetTypeDetails); Collection<TbResourceInfo> getUsedResources(TenantId tenantId, WidgetTypeDetails widgetTypeDetails);
TbResource createOrUpdateSystemResource(ResourceType resourceType, String resourceKey, byte[] data); TbResource createOrUpdateSystemResource(ResourceType resourceType, String resourceKey, byte[] data);

View File

@ -50,7 +50,8 @@ public class WidgetType extends BaseWidgetType {
@JsonIgnore @JsonIgnore
public JsonNode getDefaultConfig() { public JsonNode getDefaultConfig() {
return Optional.ofNullable(descriptor.get("defaultConfig")) return Optional.ofNullable(descriptor)
.map(descriptor -> descriptor.get("defaultConfig"))
.filter(JsonNode::isTextual).map(JsonNode::asText) .filter(JsonNode::isTextual).map(JsonNode::asText)
.map(json -> { .map(json -> {
try { try {

View File

@ -162,18 +162,19 @@ public class DashboardServiceImpl extends AbstractEntityService implements Dashb
dashboardValidator.validate(dashboard, DashboardInfo::getTenantId); dashboardValidator.validate(dashboard, DashboardInfo::getTenantId);
} }
try { try {
TenantId tenantId = dashboard.getTenantId();
if (CollectionUtils.isNotEmpty(dashboard.getResources())) { if (CollectionUtils.isNotEmpty(dashboard.getResources())) {
resourceService.importResources(dashboard.getTenantId(), dashboard.getResources()); resourceService.importResources(tenantId, dashboard.getResources());
} }
imageService.updateImagesUsage(dashboard); imageService.updateImagesUsage(dashboard);
resourceService.updateResourcesUsage(dashboard); resourceService.updateResourcesUsage(tenantId, dashboard);
var saved = dashboardDao.save(dashboard.getTenantId(), dashboard); var saved = dashboardDao.save(tenantId, dashboard);
publishEvictEvent(new DashboardTitleEvictEvent(saved.getId())); publishEvictEvent(new DashboardTitleEvictEvent(saved.getId()));
eventPublisher.publishEvent(SaveEntityEvent.builder().tenantId(saved.getTenantId()) eventPublisher.publishEvent(SaveEntityEvent.builder().tenantId(tenantId)
.entityId(saved.getId()).created(dashboard.getId() == null).build()); .entityId(saved.getId()).created(dashboard.getId() == null).build());
if (dashboard.getId() == null) { if (dashboard.getId() == null) {
countService.publishCountEntityEvictEvent(saved.getTenantId(), EntityType.DASHBOARD); countService.publishCountEntityEvictEvent(tenantId, EntityType.DASHBOARD);
} }
return saved; return saved;
} catch (Exception e) { } catch (Exception e) {

View File

@ -57,6 +57,7 @@ import org.thingsboard.server.dao.service.Validator;
import org.thingsboard.server.dao.service.validator.ResourceDataValidator; import org.thingsboard.server.dao.service.validator.ResourceDataValidator;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Base64; import java.util.Base64;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
@ -401,18 +402,33 @@ public class BaseResourceService extends AbstractCachedEntityService<ResourceInf
} }
@Override @Override
public boolean updateResourcesUsage(Dashboard dashboard) { public boolean updateResourcesUsage(TenantId tenantId, Dashboard dashboard) {
if (dashboard.getConfiguration() == null) {
return false;
}
Map<String, String> links = getResourcesLinks(dashboard.getResources()); Map<String, String> links = getResourcesLinks(dashboard.getResources());
return updateResourcesUsage(dashboard.getTenantId(), dashboard.getConfiguration(), DASHBOARD_RESOURCES_MAPPING, links); return updateResourcesUsage(tenantId, List.of(dashboard.getConfiguration()), List.of(DASHBOARD_RESOURCES_MAPPING), links);
} }
@Override @Override
public boolean updateResourcesUsage(WidgetTypeDetails widgetTypeDetails) { public boolean updateResourcesUsage(TenantId tenantId, WidgetTypeDetails widgetTypeDetails) {
Map<String, String> links = getResourcesLinks(widgetTypeDetails.getResources()); Map<String, String> links = getResourcesLinks(widgetTypeDetails.getResources());
boolean updated = updateResourcesUsage(widgetTypeDetails.getTenantId(), widgetTypeDetails.getDescriptor(), WIDGET_RESOURCES_MAPPING, links); List<JsonNode> jsonNodes = new ArrayList<>(2);
List<Map<String, String>> mappings = new ArrayList<>(2);
if (widgetTypeDetails.getDescriptor() != null) {
jsonNodes.add(widgetTypeDetails.getDescriptor());
mappings.add(WIDGET_RESOURCES_MAPPING);
}
JsonNode defaultConfig = widgetTypeDetails.getDefaultConfig(); JsonNode defaultConfig = widgetTypeDetails.getDefaultConfig();
if (defaultConfig != null) { if (defaultConfig != null) {
updated |= updateResourcesUsage(widgetTypeDetails.getTenantId(), defaultConfig, WIDGET_DEFAULT_CONFIG_RESOURCES_MAPPING, links); jsonNodes.add(defaultConfig);
mappings.add(WIDGET_DEFAULT_CONFIG_RESOURCES_MAPPING);
}
boolean updated = updateResourcesUsage(tenantId, jsonNodes, mappings, links);
if (defaultConfig != null) {
widgetTypeDetails.setDefaultConfig(defaultConfig); widgetTypeDetails.setDefaultConfig(defaultConfig);
} }
return updated; return updated;
@ -433,8 +449,9 @@ public class BaseResourceService extends AbstractCachedEntityService<ResourceInf
return links; return links;
} }
private boolean updateResourcesUsage(TenantId tenantId, JsonNode jsonNode, Map<String, String> mapping, Map<String, String> links) { private boolean updateResourcesUsage(TenantId tenantId, List<JsonNode> jsonNodes, List<Map<String, String>> mappings, Map<String, String> links) {
return processResources(jsonNode, mapping, value -> { log.trace("[{}] updateResourcesUsage (new links: {}) for {}", tenantId, links, jsonNodes);
return processResources(jsonNodes, mappings, value -> {
String link = getResourceLink(value); String link = getResourceLink(value);
if (link != null) { if (link != null) {
String newLink = links.get(link); String newLink = links.get(link);
@ -462,23 +479,31 @@ public class BaseResourceService extends AbstractCachedEntityService<ResourceInf
} }
@Override @Override
public Collection<TbResourceInfo> getUsedResources(Dashboard dashboard) { public Collection<TbResourceInfo> getUsedResources(TenantId tenantId, Dashboard dashboard) {
return getUsedResources(dashboard.getTenantId(), dashboard.getConfiguration(), DASHBOARD_RESOURCES_MAPPING).values(); return getUsedResources(tenantId, List.of(dashboard.getConfiguration()), List.of(DASHBOARD_RESOURCES_MAPPING)).values();
} }
@Override @Override
public Collection<TbResourceInfo> getUsedResources(WidgetTypeDetails widgetTypeDetails) { public Collection<TbResourceInfo> getUsedResources(TenantId tenantId, WidgetTypeDetails widgetTypeDetails) {
Map<TbResourceId, TbResourceInfo> resources = getUsedResources(widgetTypeDetails.getTenantId(), widgetTypeDetails.getDescriptor(), WIDGET_RESOURCES_MAPPING); List<JsonNode> jsonNodes = new ArrayList<>(2);
List<Map<String, String>> mappings = new ArrayList<>(2);
jsonNodes.add(widgetTypeDetails.getDescriptor());
mappings.add(WIDGET_RESOURCES_MAPPING);
JsonNode defaultConfig = widgetTypeDetails.getDefaultConfig(); JsonNode defaultConfig = widgetTypeDetails.getDefaultConfig();
if (defaultConfig != null) { if (defaultConfig != null) {
resources.putAll(getUsedResources(widgetTypeDetails.getTenantId(), defaultConfig, WIDGET_DEFAULT_CONFIG_RESOURCES_MAPPING)); jsonNodes.add(defaultConfig);
} mappings.add(WIDGET_DEFAULT_CONFIG_RESOURCES_MAPPING);
return resources.values();
} }
private Map<TbResourceId, TbResourceInfo> getUsedResources(TenantId tenantId, JsonNode jsonNode, Map<String, String> mapping) { return getUsedResources(tenantId, jsonNodes, mappings).values();
}
private Map<TbResourceId, TbResourceInfo> getUsedResources(TenantId tenantId, List<JsonNode> jsonNodes, List<Map<String, String>> mappings) {
Map<TbResourceId, TbResourceInfo> resources = new HashMap<>(); Map<TbResourceId, TbResourceInfo> resources = new HashMap<>();
processResources(jsonNode, mapping, value -> { log.trace("[{}] getUsedResources for {}", tenantId, jsonNodes);
processResources(jsonNodes, mappings, value -> {
String link = getResourceLink(value); String link = getResourceLink(value);
if (link == null) { if (link == null) {
return value; return value;
@ -517,9 +542,14 @@ public class BaseResourceService extends AbstractCachedEntityService<ResourceInf
} }
} }
private boolean processResources(JsonNode jsonNode, Map<String, String> mapping, UnaryOperator<String> processor) { private boolean processResources(List<JsonNode> jsonNodes, List<Map<String, String>> mappings, UnaryOperator<String> processor) {
AtomicBoolean updated = new AtomicBoolean(false); AtomicBoolean updated = new AtomicBoolean(false);
JacksonUtil.replaceByMapping(jsonNode, mapping, Collections.emptyMap(), (name, urlNode) -> {
for (int i = 0; i < jsonNodes.size(); i++) {
JsonNode jsonNode = jsonNodes.get(i);
// processing by mappings first
if (i <= mappings.size() - 1) {
JacksonUtil.replaceByMapping(jsonNode, mappings.get(i), Collections.emptyMap(), (name, urlNode) -> {
String value = null; String value = null;
if (urlNode.isTextual()) { // link is in the right place if (urlNode.isTextual()) { // link is in the right place
value = urlNode.asText(); value = urlNode.asText();
@ -539,10 +569,30 @@ public class BaseResourceService extends AbstractCachedEntityService<ResourceInf
JsonNode newValue = new TextNode(value); JsonNode newValue = new TextNode(value);
if (!newValue.toString().equals(urlNode.toString())) { if (!newValue.toString().equals(urlNode.toString())) {
updated.set(true); updated.set(true);
log.trace("Replaced '{}' with '{}'", urlNode, newValue); log.trace("Replaced by mapping '{}' ({}) with '{}'", value, name, newValue);
} }
return newValue; return newValue;
}); });
}
// processing all
JacksonUtil.replaceAll(jsonNode, "", (name, value) -> {
if (!StringUtils.startsWith(value, DataConstants.TB_RESOURCE_PREFIX + "/api/resource/")) {
return value;
}
String newValue = processor.apply(value);
if (StringUtils.equals(value, newValue)) {
return value;
} else {
updated.set(true);
log.trace("Replaced '{}' ({}) with '{}'", value, name, newValue);
return newValue;
}
});
}
return updated.get(); return updated.get();
} }
@ -555,7 +605,7 @@ public class BaseResourceService extends AbstractCachedEntityService<ResourceInf
importResources(dashboard.getTenantId(), dashboard.getResources()); importResources(dashboard.getTenantId(), dashboard.getResources());
} }
imageService.updateImagesUsage(dashboard); imageService.updateImagesUsage(dashboard);
updateResourcesUsage(dashboard); updateResourcesUsage(dashboard.getTenantId(), dashboard);
data = JacksonUtil.writeValueAsBytes(dashboard); data = JacksonUtil.writeValueAsBytes(dashboard);
} }

View File

@ -99,14 +99,15 @@ public class WidgetTypeServiceImpl implements WidgetTypeService {
log.trace("Executing saveWidgetType [{}]", widgetTypeDetails); log.trace("Executing saveWidgetType [{}]", widgetTypeDetails);
widgetTypeValidator.validate(widgetTypeDetails, WidgetType::getTenantId); widgetTypeValidator.validate(widgetTypeDetails, WidgetType::getTenantId);
try { try {
TenantId tenantId = widgetTypeDetails.getTenantId();
if (CollectionUtils.isNotEmpty(widgetTypeDetails.getResources())) { if (CollectionUtils.isNotEmpty(widgetTypeDetails.getResources())) {
resourceService.importResources(widgetTypeDetails.getTenantId(), widgetTypeDetails.getResources()); resourceService.importResources(tenantId, widgetTypeDetails.getResources());
} }
imageService.updateImagesUsage(widgetTypeDetails); imageService.updateImagesUsage(widgetTypeDetails);
resourceService.updateResourcesUsage(widgetTypeDetails); resourceService.updateResourcesUsage(tenantId, widgetTypeDetails);
WidgetTypeDetails result = widgetTypeDao.save(widgetTypeDetails.getTenantId(), widgetTypeDetails); WidgetTypeDetails result = widgetTypeDao.save(tenantId, widgetTypeDetails);
eventPublisher.publishEvent(SaveEntityEvent.builder().tenantId(result.getTenantId()) eventPublisher.publishEvent(SaveEntityEvent.builder().tenantId(tenantId)
.entityId(result.getId()).created(widgetTypeDetails.getId() == null).build()); .entityId(result.getId()).created(widgetTypeDetails.getId() == null).build());
return result; return result;
} catch (Exception t) { } catch (Exception t) {

View File

@ -83,7 +83,7 @@
<zookeeper.version>3.9.2</zookeeper.version> <zookeeper.version>3.9.2</zookeeper.version>
<protobuf.version>3.25.5</protobuf.version> <!-- A Major v4 does not support by the pubsub yet--> <protobuf.version>3.25.5</protobuf.version> <!-- A Major v4 does not support by the pubsub yet-->
<grpc.version>1.63.0</grpc.version> <grpc.version>1.63.0</grpc.version>
<tbel.version>1.2.4</tbel.version> <tbel.version>1.2.5</tbel.version>
<lombok.version>1.18.32</lombok.version> <lombok.version>1.18.32</lombok.version>
<paho.client.version>1.2.5</paho.client.version> <paho.client.version>1.2.5</paho.client.version>
<paho.mqttv5.client.version>1.2.5</paho.mqttv5.client.version> <paho.mqttv5.client.version>1.2.5</paho.mqttv5.client.version>

View File

@ -30,7 +30,7 @@ import org.thingsboard.server.common.data.notification.info.NotificationInfo;
import org.thingsboard.server.common.data.notification.targets.platform.UsersFilter; 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.NotificationTemplate;
import java.util.Set; import java.util.List;
public interface NotificationCenter { public interface NotificationCenter {
@ -48,6 +48,6 @@ public interface NotificationCenter {
void deleteNotification(TenantId tenantId, UserId recipientId, NotificationId notificationId); void deleteNotification(TenantId tenantId, UserId recipientId, NotificationId notificationId);
Set<NotificationDeliveryMethod> getAvailableDeliveryMethods(TenantId tenantId); List<NotificationDeliveryMethod> getAvailableDeliveryMethods(TenantId tenantId);
} }