Images upgrade; minor refactoring
This commit is contained in:
parent
5337943747
commit
ddfa55ba6e
@ -112,6 +112,8 @@ public class ThingsboardInstallService {
|
||||
} else if ("3.0.1-cassandra".equals(upgradeFromVersion)) {
|
||||
log.info("Migrating ThingsBoard latest timeseries data from cassandra to SQL database ...");
|
||||
latestMigrateService.migrate();
|
||||
} else if (upgradeFromVersion.equals("3.6.2-images")) {
|
||||
installScripts.updateImages();
|
||||
} else {
|
||||
switch (upgradeFromVersion) {
|
||||
case "1.2.3": //NOSONAR, Need to execute gradual upgrade starting from upgradeFromVersion
|
||||
@ -279,7 +281,6 @@ public class ThingsboardInstallService {
|
||||
log.info("Updating system data...");
|
||||
dataUpdateService.upgradeRuleNodes();
|
||||
systemDataLoaderService.loadSystemWidgets();
|
||||
// installScripts.migrateTenantImages();
|
||||
installScripts.loadSystemLwm2mResources();
|
||||
}
|
||||
log.info("Upgrade finished successfully!");
|
||||
|
||||
@ -27,12 +27,9 @@ import org.thingsboard.server.common.data.ResourceType;
|
||||
import org.thingsboard.server.common.data.TbResource;
|
||||
import org.thingsboard.server.common.data.exception.ThingsboardException;
|
||||
import org.thingsboard.server.common.data.id.CustomerId;
|
||||
import org.thingsboard.server.common.data.id.DashboardId;
|
||||
import org.thingsboard.server.common.data.id.TenantId;
|
||||
import org.thingsboard.server.common.data.id.WidgetTypeId;
|
||||
import org.thingsboard.server.common.data.oauth2.OAuth2ClientRegistrationTemplate;
|
||||
import org.thingsboard.server.common.data.page.PageData;
|
||||
import org.thingsboard.server.common.data.page.PageDataIterable;
|
||||
import org.thingsboard.server.common.data.page.PageLink;
|
||||
import org.thingsboard.server.common.data.rule.RuleChain;
|
||||
import org.thingsboard.server.common.data.rule.RuleChainMetaData;
|
||||
@ -302,47 +299,12 @@ public class InstallScripts {
|
||||
}
|
||||
}
|
||||
|
||||
public void migrateTenantImages() {
|
||||
var widgetsBundles = new PageDataIterable<>(widgetsBundleService::findAllWidgetsBundles, 100);
|
||||
for (WidgetsBundle widgetsBundle : widgetsBundles) {
|
||||
try {
|
||||
boolean updated = imagesUpdater.updateWidgetsBundle(widgetsBundle);
|
||||
if (updated) {
|
||||
widgetsBundleService.saveWidgetsBundle(widgetsBundle);
|
||||
log.info("[{}][{}][{}] Migrated widgets bundle images", widgetsBundle.getTenantId(), widgetsBundle.getId(), widgetsBundle.getTitle());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("[{}][{}][{}] Failed to migrate widgets bundle images", widgetsBundle.getTenantId(), widgetsBundle.getId(), widgetsBundle.getTitle(), e);
|
||||
}
|
||||
}
|
||||
|
||||
var widgetTypes = new PageDataIterable<>(widgetTypeService::findAllWidgetTypesIds, 1024);
|
||||
for (WidgetTypeId widgetTypeId : widgetTypes) {
|
||||
WidgetTypeDetails widgetTypeDetails = widgetTypeService.findWidgetTypeDetailsById(TenantId.SYS_TENANT_ID, widgetTypeId);
|
||||
try {
|
||||
boolean updated = imagesUpdater.updateWidget(widgetTypeDetails);
|
||||
if (updated) {
|
||||
widgetTypeService.saveWidgetType(widgetTypeDetails);
|
||||
log.info("[{}][{}][{}] Migrated widget type images", widgetTypeDetails.getTenantId(), widgetTypeDetails.getId(), widgetTypeDetails.getName());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("[{}][{}][{}] Failed to migrate widget type images", widgetTypeDetails.getTenantId(), widgetTypeDetails.getId(), widgetTypeDetails.getName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
var dashboards = new PageDataIterable<>(dashboardService::findAllDashboardsIds, 1024);
|
||||
for (DashboardId dashboardId : dashboards) {
|
||||
Dashboard dashboard = dashboardService.findDashboardById(TenantId.SYS_TENANT_ID, dashboardId);
|
||||
try {
|
||||
boolean updated = imagesUpdater.updateDashboard(dashboard);
|
||||
if (updated) {
|
||||
dashboardService.saveDashboard(dashboard);
|
||||
log.info("[{}][{}][{}] Migrated dashboard images", dashboard.getTenantId(), dashboardId, dashboard.getTitle());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("[{}][{}][{}] Failed to migrate dashboard images", dashboard.getTenantId(), dashboardId, dashboard.getTitle(), e);
|
||||
}
|
||||
}
|
||||
public void updateImages() {
|
||||
imagesUpdater.updateWidgetsBundlesImages();
|
||||
imagesUpdater.updateWidgetTypesImages();
|
||||
imagesUpdater.updateDashboardsImages();
|
||||
imagesUpdater.updateDeviceProfilesImages();
|
||||
imagesUpdater.updateAssetProfilesImages();
|
||||
}
|
||||
|
||||
public void loadDashboards(TenantId tenantId, CustomerId customerId) throws Exception {
|
||||
|
||||
@ -15,226 +15,141 @@
|
||||
*/
|
||||
package org.thingsboard.server.service.install.update;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import lombok.Data;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.thingsboard.common.util.JacksonUtil;
|
||||
import org.thingsboard.server.common.data.Dashboard;
|
||||
import org.thingsboard.server.common.data.ResourceType;
|
||||
import org.thingsboard.server.common.data.TbResource;
|
||||
import org.thingsboard.server.common.data.TbResourceInfo;
|
||||
import org.thingsboard.server.common.data.DeviceProfile;
|
||||
import org.thingsboard.server.common.data.asset.AssetProfile;
|
||||
import org.thingsboard.server.common.data.id.DashboardId;
|
||||
import org.thingsboard.server.common.data.id.TenantId;
|
||||
import org.thingsboard.server.common.data.id.WidgetTypeId;
|
||||
import org.thingsboard.server.common.data.page.PageDataIterable;
|
||||
import org.thingsboard.server.common.data.widget.WidgetTypeDetails;
|
||||
import org.thingsboard.server.common.data.widget.WidgetsBundle;
|
||||
import org.thingsboard.server.dao.asset.AssetProfileDao;
|
||||
import org.thingsboard.server.dao.dashboard.DashboardDao;
|
||||
import org.thingsboard.server.dao.device.DeviceProfileDao;
|
||||
import org.thingsboard.server.dao.resource.ImageService;
|
||||
import org.thingsboard.server.dao.util.ImageUtils;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Base64;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import org.thingsboard.server.dao.widget.WidgetTypeDao;
|
||||
import org.thingsboard.server.dao.widget.WidgetsBundleDao;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class ImagesUpdater {
|
||||
|
||||
private final ImageService imageService;
|
||||
private final WidgetsBundleDao widgetsBundleDao;
|
||||
private final WidgetTypeDao widgetTypeDao;
|
||||
private final DashboardDao dashboardDao;
|
||||
private final DeviceProfileDao deviceProfileDao;
|
||||
private final AssetProfileDao assetProfileDao;
|
||||
|
||||
private static final String IMAGE_NAME_SUFFIX = " - image";
|
||||
private static final String BACKGROUND_IMAGE_NAME_SUFFIX = " - background image";
|
||||
private static final String BACKGROUND_IMAGE_KEY_SUFFIX = "#background_image";
|
||||
private static final String MAP_IMAGE_NAME_SUFFIX = " - map image";
|
||||
private static final String MAP_IMAGE_KEY_SUFFIX = "#map_image";
|
||||
private static final String MARKER_IMAGE_NAME_SUFFIX = " - marker image ";
|
||||
private static final String MARKER_IMAGE_KEY_SUFFIX = "#marker_image_";
|
||||
|
||||
public boolean updateDashboard(Dashboard dashboard) {
|
||||
String imageKeyPrefix = "dashboard_" + dashboard.getUuidId();
|
||||
String image = dashboard.getImage();
|
||||
ImageSaveResult result = saveImage(dashboard.getTenantId(), dashboard.getTitle() + IMAGE_NAME_SUFFIX,
|
||||
imageKeyPrefix + ".image", image, null);
|
||||
dashboard.setImage(result.getLink());
|
||||
boolean updated = result.isUpdated();
|
||||
|
||||
for (ObjectNode widgetConfig : dashboard.getWidgetsConfig()) {
|
||||
String fqn;
|
||||
if (widgetConfig.has("typeFullFqn")) {
|
||||
fqn = StringUtils.substringAfter(widgetConfig.get("typeFullFqn").asText(), "."); // removing prefix ('system' or 'tenant')
|
||||
} else {
|
||||
fqn = widgetConfig.get("bundleAlias").asText() + "." + widgetConfig.get("typeAlias").asText();
|
||||
}
|
||||
String widgetName = widgetConfig.get("config").get("title").asText();
|
||||
updated |= updateWidgetConfig(dashboard.getTenantId(), widgetConfig.get("config"),
|
||||
dashboard.getTitle() + " - " + widgetName + " widget",
|
||||
imageKeyPrefix + "." + fqn, fqn);
|
||||
}
|
||||
return updated;
|
||||
}
|
||||
|
||||
public boolean updateWidgetsBundle(WidgetsBundle widgetsBundle) {
|
||||
String bundleName = widgetsBundle.getTitle();
|
||||
String bundleAlias = widgetsBundle.getAlias();
|
||||
|
||||
String image = widgetsBundle.getImage();
|
||||
ImageSaveResult result = saveImage(widgetsBundle.getTenantId(), bundleName + IMAGE_NAME_SUFFIX, bundleAlias, image, bundleAlias);
|
||||
String imageLink = result.getLink();
|
||||
widgetsBundle.setImage(imageLink);
|
||||
|
||||
return result.isUpdated();
|
||||
}
|
||||
|
||||
public boolean updateWidget(WidgetTypeDetails widgetType) {
|
||||
String widgetName = widgetType.getName();
|
||||
String widgetFqn = widgetType.getFqn();
|
||||
boolean updated;
|
||||
|
||||
String previewImage = widgetType.getImage();
|
||||
ImageSaveResult result = saveImage(widgetType.getTenantId(), widgetName + IMAGE_NAME_SUFFIX, widgetFqn, previewImage, widgetFqn);
|
||||
updated = result.isUpdated();
|
||||
widgetType.setImage(result.getLink());
|
||||
|
||||
JsonNode descriptor = widgetType.getDescriptor();
|
||||
if (!descriptor.isObject()) {
|
||||
return updated;
|
||||
}
|
||||
JsonNode defaultConfig = JacksonUtil.toJsonNode(descriptor.get("defaultConfig").asText());
|
||||
updated |= updateWidgetConfig(widgetType.getTenantId(), defaultConfig, widgetName, widgetFqn, widgetFqn);
|
||||
((ObjectNode) descriptor).put("defaultConfig", defaultConfig.toString());
|
||||
return updated;
|
||||
}
|
||||
|
||||
private boolean updateWidgetConfig(TenantId tenantId, JsonNode widgetConfigJson, String imageNamePrefix, String imageKeyPrefix, String widgetFqn) {
|
||||
boolean updated = false;
|
||||
ObjectNode widgetSettings = (ObjectNode) widgetConfigJson.get("settings");
|
||||
ArrayNode markerImages = (ArrayNode) widgetSettings.get("markerImages");
|
||||
if (markerImages != null && !markerImages.isEmpty()) {
|
||||
for (int i = 0; i < markerImages.size(); i++) {
|
||||
String imageName = imageNamePrefix + MARKER_IMAGE_NAME_SUFFIX + (i + 1);
|
||||
String imageKey = imageKeyPrefix + MARKER_IMAGE_KEY_SUFFIX + (i + 1);
|
||||
ImageSaveResult result = saveImage(tenantId, imageName, imageKey, markerImages.get(i).asText(), widgetFqn);
|
||||
markerImages.set(i, result.getLink());
|
||||
updated |= result.isUpdated();
|
||||
}
|
||||
}
|
||||
|
||||
String mapImage = getText(widgetSettings, "mapImageUrl");
|
||||
if (mapImage != null) {
|
||||
String imageName = imageNamePrefix + MAP_IMAGE_NAME_SUFFIX;
|
||||
String imageKey = imageKeyPrefix + MAP_IMAGE_KEY_SUFFIX;
|
||||
ImageSaveResult result = saveImage(tenantId, imageName, imageKey, mapImage, widgetFqn);
|
||||
widgetSettings.put("mapImageUrl", result.getLink());
|
||||
updated |= result.isUpdated();
|
||||
}
|
||||
|
||||
String backgroundImage = getText(widgetSettings, "backgroundImageUrl");
|
||||
if (backgroundImage != null) {
|
||||
String imageName = imageNamePrefix + BACKGROUND_IMAGE_NAME_SUFFIX;
|
||||
String imageKey = imageKeyPrefix + BACKGROUND_IMAGE_KEY_SUFFIX;
|
||||
ImageSaveResult result = saveImage(tenantId, imageName, imageKey, backgroundImage, widgetFqn);
|
||||
widgetSettings.put("backgroundImageUrl", result.getLink());
|
||||
updated |= result.isUpdated();
|
||||
}
|
||||
|
||||
JsonNode backgroundConfigNode = widgetSettings.get("background");
|
||||
if (backgroundConfigNode != null && backgroundConfigNode.isObject()) {
|
||||
ObjectNode backgroundConfig = (ObjectNode) backgroundConfigNode;
|
||||
if ("image".equals(getText(backgroundConfig, "type"))) {
|
||||
String imageBase64 = getText(backgroundConfig, "imageBase64");
|
||||
if (imageBase64 != null) {
|
||||
String imageName = imageNamePrefix + BACKGROUND_IMAGE_NAME_SUFFIX;
|
||||
String imageKey = imageKeyPrefix + BACKGROUND_IMAGE_KEY_SUFFIX;
|
||||
ImageSaveResult result = saveImage(tenantId, imageName, imageKey, imageBase64, widgetFqn);
|
||||
backgroundConfig.set("imageBase64", null);
|
||||
backgroundConfig.put("imageUrl", result.getLink());
|
||||
backgroundConfig.put("type", "imageUrl");
|
||||
updated |= result.isUpdated();
|
||||
public void updateWidgetsBundlesImages() {
|
||||
log.info("Updating widgets bundles images...");
|
||||
var widgetsBundles = new PageDataIterable<>(widgetsBundleDao::findAllWidgetsBundles, 128);
|
||||
int updatedCount = 0;
|
||||
int totalCount = 0;
|
||||
for (WidgetsBundle widgetsBundle : widgetsBundles) {
|
||||
totalCount++;
|
||||
try {
|
||||
boolean updated = imageService.replaceBase64WithImageUrl(widgetsBundle, "bundle");
|
||||
if (updated) {
|
||||
widgetsBundleDao.save(widgetsBundle.getTenantId(), widgetsBundle);
|
||||
log.debug("[{}][{}][{}] Updated widgets bundle images", widgetsBundle.getTenantId(), widgetsBundle.getId(), widgetsBundle.getTitle());
|
||||
updatedCount++;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("[{}][{}][{}] Failed to update widgets bundle images", widgetsBundle.getTenantId(), widgetsBundle.getId(), widgetsBundle.getTitle(), e);
|
||||
}
|
||||
}
|
||||
return updated;
|
||||
log.info("Updated {} widgets bundles out of {}", updatedCount, totalCount);
|
||||
}
|
||||
|
||||
|
||||
private ImageSaveResult saveImage(TenantId tenantId, String name, String key, String data,
|
||||
String existingImageQuery) {
|
||||
if (data == null) {
|
||||
return new ImageSaveResult(null, false);
|
||||
}
|
||||
String base64Data = StringUtils.substringAfter(data, "base64,");
|
||||
if (base64Data.isEmpty()) {
|
||||
return new ImageSaveResult(data, false);
|
||||
}
|
||||
|
||||
String imageMediaType = StringUtils.substringBetween(data, "data:", ";base64");
|
||||
String extension = ImageUtils.mediaTypeToFileExtension(imageMediaType);
|
||||
key += "." + extension;
|
||||
|
||||
byte[] imageData = Base64.getDecoder().decode(base64Data);
|
||||
String imageLink = saveImage(tenantId, name, key, imageData, imageMediaType, existingImageQuery);
|
||||
return new ImageSaveResult(imageLink, !imageLink.equals(data));
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
private String saveImage(TenantId tenantId, String name, String key, byte[] imageData, String mediaType,
|
||||
String existingImageQuery) {
|
||||
TbResourceInfo imageInfo = imageService.getImageInfoByTenantIdAndKey(tenantId, key);
|
||||
if (imageInfo == null && !tenantId.isSysTenantId() && existingImageQuery != null) {
|
||||
List<TbResourceInfo> similarImages = imageService.findSimilarImagesByTenantIdAndKeyStartingWith(TenantId.SYS_TENANT_ID, imageData, existingImageQuery);
|
||||
if (similarImages.isEmpty()) {
|
||||
similarImages = imageService.findSimilarImagesByTenantIdAndKeyStartingWith(tenantId, imageData, existingImageQuery);
|
||||
}
|
||||
if (!similarImages.isEmpty()) {
|
||||
imageInfo = similarImages.get(0);
|
||||
if (similarImages.size() > 1) {
|
||||
log.debug("Found more than one image resources for key {}: {}", existingImageQuery, similarImages);
|
||||
public void updateWidgetTypesImages() {
|
||||
log.info("Updating widget types images...");
|
||||
var widgetTypes = new PageDataIterable<>(widgetTypeDao::findAllWidgetTypesIds, 1024);
|
||||
int updatedCount = 0;
|
||||
int totalCount = 0;
|
||||
for (WidgetTypeId widgetTypeId : widgetTypes) {
|
||||
totalCount++;
|
||||
WidgetTypeDetails widgetTypeDetails = widgetTypeDao.findById(TenantId.SYS_TENANT_ID, widgetTypeId.getId());
|
||||
try {
|
||||
boolean updated = imageService.replaceBase64WithImageUrl(widgetTypeDetails);
|
||||
if (updated) {
|
||||
widgetTypeDao.save(widgetTypeDetails.getTenantId(), widgetTypeDetails);
|
||||
log.debug("[{}][{}][{}] Updated widget type images", widgetTypeDetails.getTenantId(), widgetTypeDetails.getId(), widgetTypeDetails.getName());
|
||||
updatedCount++;
|
||||
}
|
||||
String link = imageInfo.getLink();
|
||||
log.info("[{}] Using image {} for {}", tenantId, link, key);
|
||||
return link;
|
||||
} catch (Exception e) {
|
||||
log.error("[{}][{}][{}] Failed to update widget type images", widgetTypeDetails.getTenantId(), widgetTypeDetails.getId(), widgetTypeDetails.getName(), e);
|
||||
}
|
||||
}
|
||||
TbResource image;
|
||||
if (imageInfo == null) {
|
||||
image = new TbResource();
|
||||
image.setTenantId(tenantId);
|
||||
image.setResourceType(ResourceType.IMAGE);
|
||||
image.setResourceKey(key);
|
||||
} else if (tenantId.isSysTenantId()) {
|
||||
image = new TbResource(imageInfo);
|
||||
} else {
|
||||
return imageInfo.getLink();
|
||||
log.info("Updated {} widget types out of {}", updatedCount, totalCount);
|
||||
}
|
||||
|
||||
public void updateDashboardsImages() {
|
||||
log.info("Updating dashboards images...");
|
||||
var dashboards = new PageDataIterable<>(dashboardDao::findAllIds, 1024);
|
||||
int updatedCount = 0;
|
||||
int totalCount = 0;
|
||||
for (DashboardId dashboardId : dashboards) {
|
||||
totalCount++;
|
||||
Dashboard dashboard = dashboardDao.findById(TenantId.SYS_TENANT_ID, dashboardId.getId());
|
||||
try {
|
||||
boolean updated = imageService.replaceBase64WithImageUrl(dashboard);
|
||||
if (updated) {
|
||||
dashboardDao.save(dashboard.getTenantId(), dashboard);
|
||||
log.info("[{}][{}][{}] Updated dashboard images", dashboard.getTenantId(), dashboardId, dashboard.getTitle());
|
||||
updatedCount++;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("[{}][{}][{}] Failed to update dashboard images", dashboard.getTenantId(), dashboardId, dashboard.getTitle(), e);
|
||||
}
|
||||
}
|
||||
image.setTitle(name);
|
||||
image.setFileName(key);
|
||||
image.setDescriptor(JacksonUtil.newObjectNode()
|
||||
.put("mediaType", mediaType));
|
||||
image.setData(imageData);
|
||||
|
||||
TbResourceInfo savedImage = imageService.saveImage(image);
|
||||
log.info("[{}] {} image '{}' ({})", tenantId, imageInfo == null ? "Created" : "Updated",
|
||||
image.getTitle(), image.getResourceKey());
|
||||
return savedImage.getLink();
|
||||
log.info("Updated {} dashboards out of {}", updatedCount, totalCount);
|
||||
}
|
||||
|
||||
private String getText(JsonNode jsonNode, String field) {
|
||||
return Optional.ofNullable(jsonNode.get(field))
|
||||
.filter(JsonNode::isTextual)
|
||||
.map(JsonNode::asText).orElse(null);
|
||||
public void updateDeviceProfilesImages() {
|
||||
log.info("Updating device profiles images...");
|
||||
var deviceProfiles = new PageDataIterable<>(deviceProfileDao::findAll, 256);
|
||||
int updatedCount = 0;
|
||||
int totalCount = 0;
|
||||
for (DeviceProfile deviceProfile : deviceProfiles) {
|
||||
totalCount++;
|
||||
try {
|
||||
boolean updated = imageService.replaceBase64WithImageUrl(deviceProfile, "device profile");
|
||||
if (updated) {
|
||||
deviceProfileDao.save(deviceProfile.getTenantId(), deviceProfile);
|
||||
log.debug("[{}][{}][{}] Updated device profile images", deviceProfile.getTenantId(), deviceProfile.getId(), deviceProfile.getName());
|
||||
updatedCount++;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("[{}][{}][{}] Failed to update device profile images", deviceProfile.getTenantId(), deviceProfile.getId(), deviceProfile.getName(), e);
|
||||
}
|
||||
}
|
||||
log.info("Updated {} device profiles out of {}", updatedCount, totalCount);
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class ImageSaveResult {
|
||||
private final String link;
|
||||
private final boolean updated;
|
||||
public void updateAssetProfilesImages() {
|
||||
log.info("Updating asset profiles images...");
|
||||
var assetProfiles = new PageDataIterable<>(assetProfileDao::findAll, 256);
|
||||
int updatedCount = 0;
|
||||
int totalCount = 0;
|
||||
for (AssetProfile assetProfile : assetProfiles) {
|
||||
totalCount++;
|
||||
try {
|
||||
boolean updated = imageService.replaceBase64WithImageUrl(assetProfile, "asset profile");
|
||||
if (updated) {
|
||||
assetProfileDao.save(assetProfile.getTenantId(), assetProfile);
|
||||
log.debug("[{}][{}][{}] Updated asset profile images", assetProfile.getTenantId(), assetProfile.getId(), assetProfile.getName());
|
||||
updatedCount++;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("[{}][{}][{}] Failed to update asset profile images", assetProfile.getTenantId(), assetProfile.getId(), assetProfile.getName(), e);
|
||||
}
|
||||
}
|
||||
log.info("Updated {} asset profiles out of {}", updatedCount, totalCount);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,145 +0,0 @@
|
||||
/**
|
||||
* Copyright © 2016-2023 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.
|
||||
*/
|
||||
package org.thingsboard.server.service.install.update;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.util.Base64Utils;
|
||||
import org.thingsboard.common.util.JacksonUtil;
|
||||
import org.thingsboard.server.dao.util.ImageUtils;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Optional;
|
||||
|
||||
@Slf4j
|
||||
public class SystemImagesMigrator {
|
||||
|
||||
private static final Path dataDir = Path.of(
|
||||
"/home/*/thingsboard-ce/application/src/main/data"
|
||||
);
|
||||
private static final Path imagesDir = dataDir.resolve("images");
|
||||
private static final Path widgetBundlesDir = dataDir.resolve("json").resolve("system").resolve("widget_bundles");
|
||||
private static final Path widgetTypesDir = dataDir.resolve("json").resolve("system").resolve("widget_types");
|
||||
private static final Path demoDashboardsDir = dataDir.resolve("json").resolve("demo").resolve("dashboards");
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
Files.list(widgetTypesDir).forEach(file -> {
|
||||
ObjectNode widgetTypeJson = (ObjectNode) JacksonUtil.toJsonNode(file.toFile());
|
||||
updateWidget(widgetTypeJson);
|
||||
saveJson(file, widgetTypeJson);
|
||||
});
|
||||
|
||||
Files.list(widgetBundlesDir).forEach(file -> {
|
||||
JsonNode widgetsBundleDescriptorJson = JacksonUtil.toJsonNode(file.toFile());
|
||||
ObjectNode widgetsBundleJson = (ObjectNode) widgetsBundleDescriptorJson.get("widgetsBundle");
|
||||
updateWidgetsBundle(widgetsBundleJson);
|
||||
saveJson(file, widgetsBundleDescriptorJson);
|
||||
});
|
||||
|
||||
Files.list(demoDashboardsDir).forEach(file -> {
|
||||
ObjectNode dashboardJson = (ObjectNode) JacksonUtil.toJsonNode(file.toFile());
|
||||
updateDashboard(dashboardJson);
|
||||
saveJson(file, dashboardJson);
|
||||
});
|
||||
}
|
||||
|
||||
public static void updateWidgetsBundle(ObjectNode widgetsBundleJson) {
|
||||
String imageLink = getText(widgetsBundleJson, "image");
|
||||
widgetsBundleJson.put("image", inlineImage(imageLink, "widget_bundles"));
|
||||
}
|
||||
|
||||
public static void updateWidget(ObjectNode widgetJson) {
|
||||
String previewImageLink = widgetJson.get("image").asText();
|
||||
widgetJson.put("image", inlineImage(previewImageLink, "widgets"));
|
||||
|
||||
ObjectNode descriptor = (ObjectNode) widgetJson.get("descriptor");
|
||||
JsonNode defaultConfig = JacksonUtil.toJsonNode(descriptor.get("defaultConfig").asText());
|
||||
updateWidgetConfig(defaultConfig, "widgets");
|
||||
descriptor.put("defaultConfig", defaultConfig.toString());
|
||||
}
|
||||
|
||||
public static void updateDashboard(ObjectNode dashboardJson) {
|
||||
String image = getText(dashboardJson, "image");
|
||||
dashboardJson.put("image", inlineImage(image, "dashboards"));
|
||||
|
||||
dashboardJson.get("configuration").get("widgets").elements().forEachRemaining(widgetConfig -> {
|
||||
updateWidgetConfig(widgetConfig.get("config"), "dashboards");
|
||||
});
|
||||
}
|
||||
|
||||
private static void updateWidgetConfig(JsonNode widgetConfigJson, String directory) {
|
||||
ObjectNode widgetSettings = (ObjectNode) widgetConfigJson.get("settings");
|
||||
ArrayNode markerImages = (ArrayNode) widgetSettings.get("markerImages");
|
||||
if (markerImages != null && !markerImages.isEmpty()) {
|
||||
for (int i = 0; i < markerImages.size(); i++) {
|
||||
markerImages.set(i, inlineImage(markerImages.get(i).asText(), directory));
|
||||
}
|
||||
}
|
||||
|
||||
String mapImage = getText(widgetSettings, "mapImageUrl");
|
||||
if (mapImage != null) {
|
||||
widgetSettings.put("mapImageUrl", inlineImage(mapImage, directory));
|
||||
}
|
||||
|
||||
String backgroundImage = getText(widgetSettings, "backgroundImageUrl");
|
||||
if (backgroundImage != null) {
|
||||
widgetSettings.put("backgroundImageUrl", inlineImage(backgroundImage, directory));
|
||||
}
|
||||
|
||||
JsonNode backgroundConfigNode = widgetSettings.get("background");
|
||||
if (backgroundConfigNode != null && backgroundConfigNode.isObject()) {
|
||||
ObjectNode backgroundConfig = (ObjectNode) backgroundConfigNode;
|
||||
if ("imageUrl".equals(getText(backgroundConfig, "type"))) {
|
||||
String imageLink = getText(backgroundConfig, "imageUrl");
|
||||
if (imageLink != null && imageLink.startsWith("/api/images")) {
|
||||
backgroundConfig.put("imageBase64", inlineImage(imageLink, directory));
|
||||
backgroundConfig.set("imageUrl", null);
|
||||
backgroundConfig.put("type", "image");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
private static String inlineImage(String url, String subDir) {
|
||||
if (url != null && url.startsWith("/api/images")) {
|
||||
String imageKey = StringUtils.substringAfterLast(url, "/");
|
||||
Path file = imagesDir.resolve(subDir).resolve(imageKey);
|
||||
String mediaType = ImageUtils.fileExtensionToMediaType(StringUtils.substringAfterLast(imageKey, "."));
|
||||
return "data:" + mediaType + ";base64," + Base64Utils.encodeToString(Files.readAllBytes(file));
|
||||
} else {
|
||||
return url;
|
||||
}
|
||||
}
|
||||
|
||||
private static String getText(JsonNode jsonNode, String field) {
|
||||
return Optional.ofNullable(jsonNode.get(field))
|
||||
.filter(JsonNode::isTextual)
|
||||
.map(JsonNode::asText).orElse(null);
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
private static void saveJson(Path file, JsonNode json) {
|
||||
Files.write(file, JacksonUtil.toPrettyString(json).getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
}
|
||||
@ -29,7 +29,7 @@ import org.thingsboard.server.dao.entity.EntityDaoService;
|
||||
import java.util.List;
|
||||
|
||||
public interface DashboardService extends EntityDaoService {
|
||||
|
||||
|
||||
Dashboard findDashboardById(TenantId tenantId, DashboardId dashboardId);
|
||||
|
||||
ListenableFuture<Dashboard> findDashboardByIdAsync(TenantId tenantId, DashboardId dashboardId);
|
||||
@ -74,6 +74,4 @@ public interface DashboardService extends EntityDaoService {
|
||||
|
||||
List<Dashboard> findTenantDashboardsByTitle(TenantId tenantId, String title);
|
||||
|
||||
PageData<DashboardId> findAllDashboardsIds(PageLink pageLink);
|
||||
|
||||
}
|
||||
|
||||
@ -16,7 +16,6 @@
|
||||
package org.thingsboard.server.dao.resource;
|
||||
|
||||
import org.thingsboard.server.common.data.Dashboard;
|
||||
import org.thingsboard.server.common.data.EntityType;
|
||||
import org.thingsboard.server.common.data.HasImage;
|
||||
import org.thingsboard.server.common.data.TbImageDeleteResult;
|
||||
import org.thingsboard.server.common.data.TbResource;
|
||||
@ -25,11 +24,8 @@ import org.thingsboard.server.common.data.id.TbResourceId;
|
||||
import org.thingsboard.server.common.data.id.TenantId;
|
||||
import org.thingsboard.server.common.data.page.PageData;
|
||||
import org.thingsboard.server.common.data.page.PageLink;
|
||||
import org.thingsboard.server.common.data.widget.WidgetType;
|
||||
import org.thingsboard.server.common.data.widget.WidgetTypeDetails;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ImageService {
|
||||
|
||||
TbResourceInfo saveImage(TbResource image);
|
||||
@ -48,11 +44,9 @@ public interface ImageService {
|
||||
|
||||
TbImageDeleteResult deleteImage(TbResourceInfo imageInfo, boolean force);
|
||||
|
||||
List<TbResourceInfo> findSimilarImagesByTenantIdAndKeyStartingWith(TenantId tenantId, byte[] data, String imageKeyStartingWith);
|
||||
|
||||
TbResourceInfo findImageByTenantIdAndEtag(TenantId tenantId, String etag);
|
||||
|
||||
boolean replaceBase64WithImageUrl(HasImage hasImage, String title, String type);
|
||||
boolean replaceBase64WithImageUrl(HasImage entity, String type);
|
||||
boolean replaceBase64WithImageUrl(Dashboard dashboard);
|
||||
boolean replaceBase64WithImageUrl(WidgetTypeDetails widgetType);
|
||||
|
||||
|
||||
@ -27,7 +27,6 @@ import org.thingsboard.server.common.data.page.PageLink;
|
||||
import org.thingsboard.server.dao.entity.EntityDaoService;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public interface ResourceService extends EntityDaoService {
|
||||
|
||||
@ -55,8 +54,6 @@ public interface ResourceService extends EntityDaoService {
|
||||
|
||||
PageData<TbResource> findTenantResourcesByResourceTypeAndPageLink(TenantId tenantId, ResourceType lwm2mModel, PageLink pageLink);
|
||||
|
||||
Set<String> findResourceKeysByTenantIdResourceTypeAndKeyPrefix(TenantId tenantId, ResourceType resourceType, String key);
|
||||
|
||||
void deleteResource(TenantId tenantId, TbResourceId resourceId);
|
||||
|
||||
void deleteResource(TenantId tenantId, TbResourceId resourceId, boolean force);
|
||||
|
||||
@ -62,6 +62,4 @@ public interface WidgetTypeService extends EntityDaoService {
|
||||
|
||||
void deleteWidgetTypesByTenantId(TenantId tenantId);
|
||||
|
||||
PageData<WidgetTypeId> findAllWidgetTypesIds(PageLink pageLink);
|
||||
|
||||
}
|
||||
|
||||
@ -46,8 +46,6 @@ public interface WidgetsBundleService extends EntityDaoService {
|
||||
|
||||
List<WidgetsBundle> findAllTenantWidgetsBundlesByTenantId(TenantId tenantId);
|
||||
|
||||
PageData<WidgetsBundle> findAllWidgetsBundles(PageLink pageLink);
|
||||
|
||||
void deleteWidgetsBundlesByTenantId(TenantId tenantId);
|
||||
|
||||
}
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
*/
|
||||
package org.thingsboard.server.common.data;
|
||||
|
||||
public interface HasImage extends HasTenantId {
|
||||
public interface HasImage extends HasTenantId, HasName {
|
||||
|
||||
String getImage();
|
||||
|
||||
|
||||
@ -21,7 +21,6 @@ import org.thingsboard.server.common.data.id.AssetProfileId;
|
||||
import org.thingsboard.server.common.data.id.TenantId;
|
||||
import org.thingsboard.server.common.data.page.PageData;
|
||||
import org.thingsboard.server.common.data.page.PageLink;
|
||||
import org.thingsboard.server.common.data.widget.WidgetsBundle;
|
||||
import org.thingsboard.server.dao.Dao;
|
||||
import org.thingsboard.server.dao.ExportableEntityDao;
|
||||
import org.thingsboard.server.dao.ImageContainerDao;
|
||||
@ -45,4 +44,7 @@ public interface AssetProfileDao extends Dao<AssetProfile>, ExportableEntityDao<
|
||||
AssetProfileInfo findDefaultAssetProfileInfo(TenantId tenantId);
|
||||
|
||||
AssetProfile findByName(TenantId tenantId, String profileName);
|
||||
|
||||
PageData<AssetProfile> findAll(PageLink pageLink);
|
||||
|
||||
}
|
||||
|
||||
@ -145,7 +145,7 @@ public class AssetProfileServiceImpl extends AbstractCachedEntityService<AssetPr
|
||||
}
|
||||
AssetProfile savedAssetProfile;
|
||||
try {
|
||||
imageService.replaceBase64WithImageUrl(assetProfile, assetProfile.getName(), "asset profile");
|
||||
imageService.replaceBase64WithImageUrl(assetProfile, "asset profile");
|
||||
savedAssetProfile = assetProfileDao.saveAndFlush(assetProfile.getTenantId(), assetProfile);
|
||||
publishEvictEvent(new AssetProfileEvictEvent(savedAssetProfile.getTenantId(), savedAssetProfile.getName(),
|
||||
oldAssetProfile != null ? oldAssetProfile.getName() : null, savedAssetProfile.getId(), savedAssetProfile.isDefault()));
|
||||
|
||||
@ -371,11 +371,6 @@ public class DashboardServiceImpl extends AbstractEntityService implements Dashb
|
||||
return dashboardDao.findByTenantIdAndTitle(tenantId.getId(), title);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageData<DashboardId> findAllDashboardsIds(PageLink pageLink) {
|
||||
return dashboardDao.findAllIds(pageLink);
|
||||
}
|
||||
|
||||
private final PaginatedRemover<TenantId, DashboardId> tenantDashboardsRemover = new PaginatedRemover<>() {
|
||||
|
||||
@Override
|
||||
|
||||
@ -17,7 +17,6 @@ package org.thingsboard.server.dao.device;
|
||||
|
||||
import org.thingsboard.server.common.data.DeviceProfile;
|
||||
import org.thingsboard.server.common.data.DeviceProfileInfo;
|
||||
import org.thingsboard.server.common.data.asset.AssetProfileInfo;
|
||||
import org.thingsboard.server.common.data.id.DeviceProfileId;
|
||||
import org.thingsboard.server.common.data.id.TenantId;
|
||||
import org.thingsboard.server.common.data.page.PageData;
|
||||
@ -47,4 +46,7 @@ public interface DeviceProfileDao extends Dao<DeviceProfile>, ExportableEntityDa
|
||||
DeviceProfile findByProvisionDeviceKey(String provisionDeviceKey);
|
||||
|
||||
DeviceProfile findByName(TenantId tenantId, String profileName);
|
||||
|
||||
PageData<DeviceProfile> findAll(PageLink pageLink);
|
||||
|
||||
}
|
||||
|
||||
@ -182,7 +182,7 @@ public class DeviceProfileServiceImpl extends AbstractCachedEntityService<Device
|
||||
}
|
||||
DeviceProfile savedDeviceProfile;
|
||||
try {
|
||||
imageService.replaceBase64WithImageUrl(deviceProfile, deviceProfile.getName(), "device profile");
|
||||
imageService.replaceBase64WithImageUrl(deviceProfile, "device profile");
|
||||
savedDeviceProfile = deviceProfileDao.saveAndFlush(deviceProfile.getTenantId(), deviceProfile);
|
||||
publishEvictEvent(new DeviceProfileEvictEvent(savedDeviceProfile.getTenantId(), savedDeviceProfile.getName(),
|
||||
oldDeviceProfile != null ? oldDeviceProfile.getName() : null, savedDeviceProfile.getId(), savedDeviceProfile.isDefault(),
|
||||
|
||||
@ -19,21 +19,20 @@ import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import com.google.common.hash.Hashing;
|
||||
import lombok.Data;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.Base64Utils;
|
||||
import org.thingsboard.common.util.JacksonUtil;
|
||||
import org.thingsboard.common.util.RegexUtils;
|
||||
import org.thingsboard.server.common.data.Dashboard;
|
||||
import org.thingsboard.server.common.data.DataConstants;
|
||||
import org.thingsboard.server.common.data.EntityType;
|
||||
import org.thingsboard.server.common.data.HasImage;
|
||||
import org.thingsboard.server.common.data.ImageDescriptor;
|
||||
import org.thingsboard.server.common.data.ResourceType;
|
||||
import org.thingsboard.server.common.data.StringUtils;
|
||||
import org.thingsboard.server.common.data.TbImageDeleteResult;
|
||||
import org.thingsboard.server.common.data.TbResource;
|
||||
import org.thingsboard.server.common.data.TbResourceInfo;
|
||||
@ -66,7 +65,6 @@ import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Queue;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
@ -177,19 +175,16 @@ public class BaseImageService extends BaseResourceService implements ImageServic
|
||||
String basename = StringUtils.substringBeforeLast(filename, ".");
|
||||
String extension = StringUtils.substringAfterLast(filename, ".");
|
||||
|
||||
Pattern similarImagesPattern = Pattern.compile(
|
||||
Pattern.quote(basename) + "_(\\d+)\\.?" + Pattern.quote(extension)
|
||||
Set<String> existing = resourceInfoDao.findKeysByTenantIdAndResourceTypeAndResourceKeyPrefix(
|
||||
tenantId, ResourceType.IMAGE, basename
|
||||
);
|
||||
int maxImageIdx = resourceInfoDao.findKeysByTenantIdAndResourceTypeAndResourceKeyStartingWith(
|
||||
tenantId, ResourceType.IMAGE, basename + "_").stream()
|
||||
.map(key -> RegexUtils.getMatch(key, similarImagesPattern, 1))
|
||||
.filter(Objects::nonNull).mapToInt(Integer::parseInt)
|
||||
.max().orElse(0);
|
||||
String uniqueKey = basename + "_" + (maxImageIdx + 1);
|
||||
if (!extension.isEmpty()) {
|
||||
uniqueKey += "." + extension;
|
||||
String resourceKey = filename;
|
||||
int idx = 1;
|
||||
while (existing.contains(resourceKey)) {
|
||||
resourceKey = basename + "_(" + idx + ")." + extension;
|
||||
idx++;
|
||||
}
|
||||
return uniqueKey;
|
||||
return resourceKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -259,47 +254,57 @@ public class BaseImageService extends BaseResourceService implements ImageServic
|
||||
return result.success(success).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TbResourceInfo> findSimilarImagesByTenantIdAndKeyStartingWith(TenantId tenantId, byte[] data, String imageKeyStartingWith) {
|
||||
String etag = calculateEtag(data);
|
||||
return resourceInfoDao.findByTenantIdAndEtagAndKeyStartingWith(tenantId, etag, imageKeyStartingWith);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TbResourceInfo findImageByTenantIdAndEtag(TenantId tenantId, String etag) {
|
||||
return resourceInfoDao.findByTenantIdAndEtag(tenantId, ResourceType.IMAGE, etag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceBase64WithImageUrl(HasImage entity, String title, String type) {
|
||||
entity.setImage(base64ToImageUrl(entity.getTenantId(), "\"" + title + "\" " + type + " image", entity.getImage()));
|
||||
return true; //TODO: should return true only if something is changed.
|
||||
public boolean replaceBase64WithImageUrl(HasImage entity, String type) {
|
||||
String imageName = "\"" + entity.getName() + "\" ";
|
||||
if (entity.getTenantId() == null || entity.getTenantId().isSysTenantId()) {
|
||||
imageName += "system ";
|
||||
}
|
||||
imageName = imageName + type + " image";
|
||||
|
||||
UpdateResult result = base64ToImageUrl(entity.getTenantId(), imageName, entity.getImage());
|
||||
entity.setImage(result.getValue());
|
||||
return result.isUpdated();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceBase64WithImageUrl(WidgetTypeDetails entity) {
|
||||
String prefix = "\"" + entity.getName() + "\" widget"; // TODO: "system widget" if SYS TENANT ID;
|
||||
entity.setImage(base64ToImageUrl(entity.getTenantId(), prefix + " image", entity.getImage()));
|
||||
String prefix = "\"" + entity.getName() + "\" ";
|
||||
if (entity.getTenantId() == null || entity.getTenantId().isSysTenantId()) {
|
||||
prefix += "system ";
|
||||
}
|
||||
prefix += "widget";
|
||||
UpdateResult result = base64ToImageUrl(entity.getTenantId(), prefix + " image", entity.getImage());
|
||||
entity.setImage(result.getValue());
|
||||
boolean updated = result.isUpdated();
|
||||
if (entity.getDescriptor().isObject()) {
|
||||
ObjectNode descriptor = (ObjectNode) entity.getDescriptor();
|
||||
JsonNode defaultConfig = JacksonUtil.toJsonNode(descriptor.get("defaultConfig").asText());
|
||||
base64ToImageUrlUsingMapping(entity.getTenantId(), WIDGET_TYPE_BASE64_MAPPING, Collections.singletonMap("prefix", prefix), defaultConfig);
|
||||
updated |= base64ToImageUrlUsingMapping(entity.getTenantId(), WIDGET_TYPE_BASE64_MAPPING, Collections.singletonMap("prefix", prefix), defaultConfig);
|
||||
descriptor.put("defaultConfig", defaultConfig.toString());
|
||||
}
|
||||
base64ToImageUrlRecursively(entity.getTenantId(), prefix, entity.getDescriptor());
|
||||
return true; //TODO: should return true only if something is changed.
|
||||
updated |= base64ToImageUrlRecursively(entity.getTenantId(), prefix, entity.getDescriptor());
|
||||
return updated;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceBase64WithImageUrl(Dashboard entity) {
|
||||
String prefix = "\"" + entity.getTitle() + "\" dashboard";
|
||||
entity.setImage(base64ToImageUrl(entity.getTenantId(), prefix + " image", entity.getImage()));
|
||||
base64ToImageUrlUsingMapping(entity.getTenantId(), DASHBOARD_BASE64_MAPPING, Collections.singletonMap("prefix", prefix), entity.getConfiguration());
|
||||
base64ToImageUrlRecursively(entity.getTenantId(), prefix, entity.getConfiguration());
|
||||
return true; //TODO: should return true only if something is changed.
|
||||
var result = base64ToImageUrl(entity.getTenantId(), prefix + " image", entity.getImage());
|
||||
boolean updated = result.isUpdated();
|
||||
entity.setImage(result.getValue());
|
||||
updated |= base64ToImageUrlUsingMapping(entity.getTenantId(), DASHBOARD_BASE64_MAPPING, Collections.singletonMap("prefix", prefix), entity.getConfiguration());
|
||||
updated |= base64ToImageUrlRecursively(entity.getTenantId(), prefix, entity.getConfiguration());
|
||||
return updated;
|
||||
}
|
||||
|
||||
private void base64ToImageUrlUsingMapping(TenantId tenantId, Map<String, String> mapping, Map<String, String> templateParams, JsonNode configuration) {
|
||||
private boolean base64ToImageUrlUsingMapping(TenantId tenantId, Map<String, String> mapping, Map<String, String> templateParams, JsonNode configuration) {
|
||||
boolean updated = false;
|
||||
for (var entry : mapping.entrySet()) {
|
||||
String expression = entry.getValue();
|
||||
Queue<JsonPathProcessingTask> tasks = new LinkedList<>();
|
||||
@ -330,8 +335,8 @@ public class BaseImageService extends BaseResourceService implements ImageServic
|
||||
String variableName = null;
|
||||
String variableValue = null;
|
||||
if (token.contains("[$")) {
|
||||
variableName = org.apache.commons.lang3.StringUtils.substringBetween(token, "[$", "]");
|
||||
token = org.apache.commons.lang3.StringUtils.substringBefore(token, "[$");
|
||||
variableName = StringUtils.substringBetween(token, "[$", "]");
|
||||
token = StringUtils.substringBefore(token, "[$");
|
||||
}
|
||||
if (node.has(token)) {
|
||||
JsonNode value = node.get(token);
|
||||
@ -344,16 +349,20 @@ public class BaseImageService extends BaseResourceService implements ImageServic
|
||||
name = name.replace("$" + replacements.getKey(), replacements.getValue());
|
||||
}
|
||||
if (node.isObject() && value.isTextual()) {
|
||||
((ObjectNode) node).put(token, base64ToImageUrl(tenantId, name, value.asText()));
|
||||
var result = base64ToImageUrl(tenantId, name, value.asText());
|
||||
((ObjectNode) node).put(token, result.getValue());
|
||||
updated |= result.isUpdated();
|
||||
} else if (value.isArray()) {
|
||||
ArrayNode array = (ArrayNode) value;
|
||||
for (int i = 0; i < array.size(); i++) {
|
||||
String arrayElementName = name.replace("$index", Integer.toString(i));
|
||||
array.set(i, base64ToImageUrl(tenantId, arrayElementName, array.get(i).asText()));
|
||||
UpdateResult result = base64ToImageUrl(tenantId, arrayElementName, array.get(i).asText());
|
||||
array.set(i, result.getValue());
|
||||
updated |= result.isUpdated();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (org.thingsboard.server.common.data.StringUtils.isNotEmpty(variableName) && org.thingsboard.server.common.data.StringUtils.isNotEmpty(variableValue)) {
|
||||
if (StringUtils.isNotEmpty(variableName) && StringUtils.isNotEmpty(variableValue)) {
|
||||
tasks.add(task.next(value, variableName, variableValue));
|
||||
} else {
|
||||
tasks.add(task.next(value));
|
||||
@ -363,17 +372,18 @@ public class BaseImageService extends BaseResourceService implements ImageServic
|
||||
}
|
||||
}
|
||||
}
|
||||
return updated;
|
||||
}
|
||||
|
||||
private String base64ToImageUrl(TenantId tenantId, String name, String data) {
|
||||
private UpdateResult base64ToImageUrl(TenantId tenantId, String name, String data) {
|
||||
return base64ToImageUrl(tenantId, name, data, false);
|
||||
}
|
||||
|
||||
private static final Pattern TB_IMAGE_METADATA_PATTERN = Pattern.compile("^tb-image:(.*):(.*);data:(.*);.*");
|
||||
|
||||
private String base64ToImageUrl(TenantId tenantId, String name, String data, boolean strict) {
|
||||
private UpdateResult base64ToImageUrl(TenantId tenantId, String name, String data, boolean strict) {
|
||||
if (StringUtils.isBlank(data)) {
|
||||
return data;
|
||||
return UpdateResult.of(false, data);
|
||||
}
|
||||
var matcher = TB_IMAGE_METADATA_PATTERN.matcher(data);
|
||||
boolean matches = matcher.matches();
|
||||
@ -385,67 +395,58 @@ public class BaseImageService extends BaseResourceService implements ImageServic
|
||||
mdResourceName = new String(Base64Utils.decodeFromString(matcher.group(2)), StandardCharsets.UTF_8);
|
||||
mdMediaType = matcher.group(3);
|
||||
} else if (data.startsWith(DataConstants.TB_IMAGE_PREFIX + "data:image/") || (!strict && data.startsWith("data:image/"))) {
|
||||
mdMediaType = org.apache.commons.lang3.StringUtils.substringBetween(data, "data:", ";base64");
|
||||
mdMediaType = StringUtils.substringBetween(data, "data:", ";base64");
|
||||
} else {
|
||||
return data;
|
||||
return UpdateResult.of(false, data);
|
||||
}
|
||||
String base64Data = org.apache.commons.lang3.StringUtils.substringAfter(data, "base64,");
|
||||
String base64Data = StringUtils.substringAfter(data, "base64,");
|
||||
String extension = ImageUtils.mediaTypeToFileExtension(mdMediaType);
|
||||
byte[] imageData = Base64.getDecoder().decode(base64Data);
|
||||
String etag = Hashing.sha256().hashBytes(imageData).toString();
|
||||
String etag = calculateEtag(imageData);
|
||||
var imageInfo = findImageByTenantIdAndEtag(tenantId, etag);
|
||||
if (imageInfo == null) {
|
||||
TbResource image = new TbResource();
|
||||
image.setTenantId(tenantId);
|
||||
image.setResourceType(ResourceType.IMAGE);
|
||||
|
||||
if (StringUtils.isBlank(mdResourceName)) {
|
||||
mdResourceName = name;
|
||||
}
|
||||
image.setTitle(mdResourceName);
|
||||
|
||||
String fileName;
|
||||
if (StringUtils.isBlank(mdResourceKey)) {
|
||||
fileName = mdResourceName.toLowerCase()
|
||||
//TODO: improve to list all the special characters via regexp or similar
|
||||
.replace("'", "")
|
||||
.replace("\"", "")
|
||||
.replace(" ", "_")
|
||||
.replace("/", "_");
|
||||
mdResourceKey = fileName + "." + extension;
|
||||
.replace("'", "").replace("\"", "")
|
||||
.replace(" ", "_").replace("/", "_")
|
||||
+ "." + extension;
|
||||
} else {
|
||||
fileName = mdResourceKey.split("\\.")[0];
|
||||
fileName = mdResourceKey;
|
||||
}
|
||||
|
||||
Set<String> existingKeys = findResourceKeysByTenantIdResourceTypeAndKeyPrefix(tenantId, ResourceType.IMAGE, mdResourceKey);
|
||||
int idx = 1;
|
||||
while (existingKeys.contains(mdResourceKey)) {
|
||||
mdResourceKey = fileName + "_(" + idx + ")." + extension;
|
||||
idx++;
|
||||
}
|
||||
image.setResourceKey(mdResourceKey);
|
||||
image.setTitle(mdResourceName);
|
||||
image.setFileName(mdResourceKey);
|
||||
image.setFileName(fileName);
|
||||
image.setDescriptor(JacksonUtil.newObjectNode().put("mediaType", mdMediaType));
|
||||
image.setData(imageData);
|
||||
imageInfo = saveImage(image);
|
||||
}
|
||||
return DataConstants.TB_IMAGE_PREFIX + imageInfo.getLink();
|
||||
return UpdateResult.of(true, DataConstants.TB_IMAGE_PREFIX + imageInfo.getLink());
|
||||
}
|
||||
|
||||
private void base64ToImageUrlRecursively(TenantId tenantId, String title, JsonNode root) {
|
||||
private boolean base64ToImageUrlRecursively(TenantId tenantId, String title, JsonNode root) {
|
||||
boolean updated = false;
|
||||
Queue<JsonNodeProcessingTask> tasks = new LinkedList<>();
|
||||
tasks.add(new JsonNodeProcessingTask(title, root));
|
||||
while (!tasks.isEmpty()) {
|
||||
JsonNodeProcessingTask task = tasks.poll();
|
||||
JsonNode node = task.getNode();
|
||||
String currentPath = org.thingsboard.server.common.data.StringUtils.isBlank(task.getPath()) ? "" : (task.getPath() + " ");
|
||||
String currentPath = StringUtils.isBlank(task.getPath()) ? "" : (task.getPath() + " ");
|
||||
if (node.isObject()) {
|
||||
ObjectNode on = (ObjectNode) node;
|
||||
for (Iterator<String> it = on.fieldNames(); it.hasNext(); ) {
|
||||
String childName = it.next();
|
||||
JsonNode childValue = on.get(childName);
|
||||
if (childValue.isTextual()) {
|
||||
on.put(childName, base64ToImageUrl(tenantId, currentPath + childName, childValue.asText(), true));
|
||||
UpdateResult result = base64ToImageUrl(tenantId, currentPath + childName, childValue.asText(), true);
|
||||
on.put(childName, result.getValue());
|
||||
updated |= result.isUpdated();
|
||||
} else if (childValue.isObject() || childValue.isArray()) {
|
||||
tasks.add(new JsonNodeProcessingTask(currentPath + childName, childValue));
|
||||
}
|
||||
@ -461,6 +462,7 @@ public class BaseImageService extends BaseResourceService implements ImageServic
|
||||
}
|
||||
}
|
||||
}
|
||||
return updated;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -486,7 +488,7 @@ public class BaseImageService extends BaseResourceService implements ImageServic
|
||||
while (!tasks.isEmpty()) {
|
||||
JsonNodeProcessingTask task = tasks.poll();
|
||||
JsonNode node = task.getNode();
|
||||
String currentPath = org.thingsboard.server.common.data.StringUtils.isBlank(task.getPath()) ? "" : (task.getPath() + ".");
|
||||
String currentPath = StringUtils.isBlank(task.getPath()) ? "" : (task.getPath() + ".");
|
||||
if (node.isObject()) {
|
||||
ObjectNode on = (ObjectNode) node;
|
||||
for (Iterator<String> it = on.fieldNames(); it.hasNext(); ) {
|
||||
@ -536,7 +538,7 @@ public class BaseImageService extends BaseResourceService implements ImageServic
|
||||
}
|
||||
|
||||
private ImageCacheKey getKeyFromUrl(TenantId tenantId, String url) {
|
||||
if (org.thingsboard.server.common.data.StringUtils.isBlank(url)) {
|
||||
if (StringUtils.isBlank(url)) {
|
||||
return null;
|
||||
}
|
||||
TenantId imageTenantId = null;
|
||||
@ -555,4 +557,10 @@ public class BaseImageService extends BaseResourceService implements ImageServic
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Data(staticConstructor = "of")
|
||||
private static class UpdateResult {
|
||||
private final boolean updated;
|
||||
private final String value;
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,10 +44,8 @@ import org.thingsboard.server.dao.service.PaginatedRemover;
|
||||
import org.thingsboard.server.dao.service.Validator;
|
||||
import org.thingsboard.server.dao.service.validator.ResourceDataValidator;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.thingsboard.server.dao.device.DeviceServiceImpl.INCORRECT_TENANT_ID;
|
||||
import static org.thingsboard.server.dao.service.Validator.validateId;
|
||||
@ -199,13 +197,6 @@ public class BaseResourceService extends AbstractCachedEntityService<ResourceInf
|
||||
return resourceDao.findResourcesByTenantIdAndResourceType(tenantId, resourceType, pageLink);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> findResourceKeysByTenantIdResourceTypeAndKeyPrefix(TenantId tenantId, ResourceType resourceType, String key) {
|
||||
log.trace("Executing findResourceKeysByTenantIdAndPrefix [{}][{}]", tenantId, key);
|
||||
validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
|
||||
return resourceDao.findResourceKeysByTenantIdResourceTypeAndKeyPrefix(tenantId, resourceType, key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteResourcesByTenantId(TenantId tenantId) {
|
||||
log.trace("Executing deleteResourcesByTenantId, tenantId [{}]", tenantId);
|
||||
|
||||
@ -26,7 +26,6 @@ import org.thingsboard.server.dao.ExportableEntityDao;
|
||||
import org.thingsboard.server.dao.TenantEntityWithDataDao;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public interface TbResourceDao extends Dao<TbResource>, TenantEntityWithDataDao, ExportableEntityDao<TbResourceId, TbResource> {
|
||||
|
||||
@ -47,5 +46,4 @@ public interface TbResourceDao extends Dao<TbResource>, TenantEntityWithDataDao,
|
||||
|
||||
byte[] getResourcePreview(TenantId tenantId, TbResourceId resourceId);
|
||||
|
||||
Set<String> findResourceKeysByTenantIdResourceTypeAndKeyPrefix(TenantId tenantId, ResourceType resourceType, String keyPrefix);
|
||||
}
|
||||
|
||||
@ -24,6 +24,7 @@ import org.thingsboard.server.common.data.page.PageLink;
|
||||
import org.thingsboard.server.dao.Dao;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public interface TbResourceInfoDao extends Dao<TbResourceInfo> {
|
||||
|
||||
@ -35,7 +36,7 @@ public interface TbResourceInfoDao extends Dao<TbResourceInfo> {
|
||||
|
||||
boolean existsByTenantIdAndResourceTypeAndResourceKey(TenantId tenantId, ResourceType resourceType, String resourceKey);
|
||||
|
||||
List<String> findKeysByTenantIdAndResourceTypeAndResourceKeyStartingWith(TenantId tenantId, ResourceType resourceType, String resourceKeyQuery);
|
||||
Set<String> findKeysByTenantIdAndResourceTypeAndResourceKeyPrefix(TenantId tenantId, ResourceType resourceType, String prefix);
|
||||
|
||||
List<TbResourceInfo> findByTenantIdAndEtagAndKeyStartingWith(TenantId tenantId, String etag, String query);
|
||||
|
||||
|
||||
@ -33,7 +33,6 @@ import org.thingsboard.server.dao.model.sql.AssetProfileEntity;
|
||||
import org.thingsboard.server.dao.sql.JpaAbstractDao;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
@ -99,6 +98,11 @@ public class JpaAssetProfileDao extends JpaAbstractDao<AssetProfileEntity, Asset
|
||||
return DaoUtil.getData(assetProfileRepository.findByTenantIdAndName(tenantId.getId(), profileName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageData<AssetProfile> findAll(PageLink pageLink) {
|
||||
return DaoUtil.toPageData(assetProfileRepository.findAll(DaoUtil.toPageable(pageLink)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public AssetProfile findByTenantIdAndExternalId(UUID tenantId, UUID externalId) {
|
||||
return DaoUtil.getData(assetProfileRepository.findByTenantIdAndExternalId(tenantId, externalId));
|
||||
|
||||
@ -25,7 +25,6 @@ import org.thingsboard.server.common.data.DeviceProfileInfo;
|
||||
import org.thingsboard.server.common.data.DeviceTransportType;
|
||||
import org.thingsboard.server.common.data.EntityType;
|
||||
import org.thingsboard.server.common.data.StringUtils;
|
||||
import org.thingsboard.server.common.data.asset.AssetProfileInfo;
|
||||
import org.thingsboard.server.common.data.id.DeviceProfileId;
|
||||
import org.thingsboard.server.common.data.id.TenantId;
|
||||
import org.thingsboard.server.common.data.page.PageData;
|
||||
@ -37,7 +36,6 @@ import org.thingsboard.server.dao.sql.JpaAbstractDao;
|
||||
import org.thingsboard.server.dao.util.SqlDao;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
@ -118,6 +116,11 @@ public class JpaDeviceProfileDao extends JpaAbstractDao<DeviceProfileEntity, Dev
|
||||
return DaoUtil.getData(deviceProfileRepository.findByTenantIdAndName(tenantId.getId(), profileName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageData<DeviceProfile> findAll(PageLink pageLink) {
|
||||
return DaoUtil.toPageData(deviceProfileRepository.findAll(DaoUtil.toPageable(pageLink)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeviceProfile findByTenantIdAndExternalId(UUID tenantId, UUID externalId) {
|
||||
return DaoUtil.getData(deviceProfileRepository.findByTenantIdAndExternalId(tenantId, externalId));
|
||||
|
||||
@ -31,9 +31,7 @@ import org.thingsboard.server.dao.resource.TbResourceDao;
|
||||
import org.thingsboard.server.dao.sql.JpaAbstractDao;
|
||||
import org.thingsboard.server.dao.util.SqlDao;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
@Slf4j
|
||||
@ -127,11 +125,6 @@ public class JpaTbResourceDao extends JpaAbstractDao<TbResourceEntity, TbResourc
|
||||
.map(TbResourceId::new));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> findResourceKeysByTenantIdResourceTypeAndKeyPrefix(TenantId tenantId, ResourceType resourceType, String keyPrefix) {
|
||||
return new HashSet<>(resourceRepository.findResourceKeys(tenantId.getId(), resourceType.name(), keyPrefix + "%"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public TbResourceId getExternalIdByInternal(TbResourceId internalId) {
|
||||
return DaoUtil.toEntityId(resourceRepository.getExternalIdByInternal(internalId.getId()), TbResourceId::new);
|
||||
|
||||
@ -17,7 +17,6 @@ package org.thingsboard.server.dao.sql.resource;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.thingsboard.server.common.data.ResourceType;
|
||||
@ -97,8 +96,8 @@ public class JpaTbResourceInfoDao extends JpaAbstractDao<TbResourceInfoEntity, T
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> findKeysByTenantIdAndResourceTypeAndResourceKeyStartingWith(TenantId tenantId, ResourceType resourceType, String resourceKeyQuery) {
|
||||
return resourceInfoRepository.findKeysByTenantIdAndResourceTypeAndResourceKeyStartingWith(tenantId.getId(), resourceType.name(), resourceKeyQuery);
|
||||
public Set<String> findKeysByTenantIdAndResourceTypeAndResourceKeyPrefix(TenantId tenantId, ResourceType resourceType, String prefix) {
|
||||
return resourceInfoRepository.findKeysByTenantIdAndResourceTypeAndResourceKeyStartingWith(tenantId.getId(), resourceType.name(), prefix);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -23,6 +23,7 @@ import org.springframework.data.repository.query.Param;
|
||||
import org.thingsboard.server.dao.model.sql.TbResourceInfoEntity;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface TbResourceInfoRepository extends JpaRepository<TbResourceInfoEntity, UUID> {
|
||||
@ -57,10 +58,10 @@ public interface TbResourceInfoRepository extends JpaRepository<TbResourceInfoEn
|
||||
boolean existsByTenantIdAndResourceTypeAndResourceKey(UUID tenantId, String resourceType, String resourceKey);
|
||||
|
||||
@Query(value = "SELECT r.resource_key FROM resource r WHERE r.tenant_id = :tenantId AND r.resource_type = :resourceType " +
|
||||
"AND starts_with(r.resource_key, :resourceKeyStartsWith)", nativeQuery = true)
|
||||
List<String> findKeysByTenantIdAndResourceTypeAndResourceKeyStartingWith(@Param("tenantId") UUID tenantId,
|
||||
@Param("resourceType") String resourceType,
|
||||
@Param("resourceKeyStartsWith") String resourceKeyStartsWith);
|
||||
"AND starts_with(r.resource_key, :prefix)", nativeQuery = true)
|
||||
Set<String> findKeysByTenantIdAndResourceTypeAndResourceKeyStartingWith(@Param("tenantId") UUID tenantId,
|
||||
@Param("resourceType") String resourceType,
|
||||
@Param("prefix") String prefix);
|
||||
|
||||
List<TbResourceInfoEntity> findByTenantIdAndEtagAndResourceKeyStartingWith(UUID tenantId, String etag, String query);
|
||||
|
||||
|
||||
@ -26,7 +26,7 @@ import org.thingsboard.server.dao.model.sql.TbResourceEntity;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface TbResourceRepository extends JpaRepository<TbResourceEntity, UUID> , ExportableEntityRepository<TbResourceEntity> {
|
||||
public interface TbResourceRepository extends JpaRepository<TbResourceEntity, UUID>, ExportableEntityRepository<TbResourceEntity> {
|
||||
|
||||
TbResourceEntity findByTenantIdAndResourceTypeAndResourceKey(UUID tenantId, String resourceType, String resourceKey);
|
||||
|
||||
@ -94,8 +94,4 @@ public interface TbResourceRepository extends JpaRepository<TbResourceEntity, UU
|
||||
@Query("SELECT id FROM TbResourceInfoEntity WHERE tenantId = :tenantId")
|
||||
Page<UUID> findIdsByTenantId(@Param("tenantId") UUID tenantId, Pageable pageable);
|
||||
|
||||
@Query("SELECT resourceKey FROM TbResourceInfoEntity WHERE tenantId = :tenantId AND resourceType = :resourceType AND resourceKey LIKE :resourceKeyPrefix ")
|
||||
List<String> findResourceKeys(@Param("tenantId")UUID tenantId,
|
||||
@Param("resourceType") String resourceType,
|
||||
@Param("resourceKeyPrefix") String resourceKeyPrefix);
|
||||
}
|
||||
|
||||
@ -226,11 +226,6 @@ public class WidgetTypeServiceImpl implements WidgetTypeService {
|
||||
tenantWidgetTypeRemover.removeEntities(tenantId, tenantId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageData<WidgetTypeId> findAllWidgetTypesIds(PageLink pageLink) {
|
||||
return widgetTypeDao.findAllWidgetTypesIds(pageLink);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<HasId<?>> findEntity(TenantId tenantId, EntityId entityId) {
|
||||
return Optional.ofNullable(findWidgetTypeById(tenantId, new WidgetTypeId(entityId.getId())));
|
||||
|
||||
@ -75,7 +75,7 @@ public class WidgetsBundleServiceImpl implements WidgetsBundleService {
|
||||
log.trace("Executing saveWidgetsBundle [{}]", widgetsBundle);
|
||||
widgetsBundleValidator.validate(widgetsBundle, WidgetsBundle::getTenantId);
|
||||
try {
|
||||
imageService.replaceBase64WithImageUrl(widgetsBundle, widgetsBundle.getName(), "bundle");
|
||||
imageService.replaceBase64WithImageUrl(widgetsBundle, "bundle");
|
||||
WidgetsBundle result = widgetsBundleDao.save(widgetsBundle.getTenantId(), widgetsBundle);
|
||||
eventPublisher.publishEvent(SaveEntityEvent.builder().tenantId(result.getTenantId())
|
||||
.entityId(result.getId()).added(widgetsBundle.getId() == null).build());
|
||||
@ -172,11 +172,6 @@ public class WidgetsBundleServiceImpl implements WidgetsBundleService {
|
||||
return widgetsBundles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageData<WidgetsBundle> findAllWidgetsBundles(PageLink pageLink) {
|
||||
return widgetsBundleDao.findAllWidgetsBundles(pageLink);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteWidgetsBundlesByTenantId(TenantId tenantId) {
|
||||
log.trace("Executing deleteWidgetsBundlesByTenantId, tenantId [{}]", tenantId);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user