Merge branch 'feature/entities-version-control' of github.com:thingsboard/thingsboard into feature/entities-version-control
This commit is contained in:
commit
a1b0817e06
@ -36,6 +36,7 @@ import org.thingsboard.server.service.sync.ie.exporting.EntityExportService;
|
||||
import org.thingsboard.server.service.sync.ie.exporting.impl.BaseEntityExportService;
|
||||
import org.thingsboard.server.service.sync.ie.exporting.impl.DefaultEntityExportService;
|
||||
import org.thingsboard.server.service.sync.ie.importing.EntityImportService;
|
||||
import org.thingsboard.server.service.sync.vc.data.EntitiesImportCtx;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
@ -74,9 +75,9 @@ public class DefaultEntitiesExportImportService implements EntitiesExportImportS
|
||||
}
|
||||
|
||||
@Override
|
||||
public <E extends ExportableEntity<I>, I extends EntityId> EntityImportResult<E> importEntity(SecurityUser user, EntityExportData<E> exportData, EntityImportSettings importSettings,
|
||||
public <E extends ExportableEntity<I>, I extends EntityId> EntityImportResult<E> importEntity(EntitiesImportCtx ctx, EntityExportData<E> exportData,
|
||||
boolean saveReferences, boolean sendEvents) throws ThingsboardException {
|
||||
if (!rateLimitService.checkEntityImportLimit(user.getTenantId())) {
|
||||
if (!rateLimitService.checkEntityImportLimit(ctx.getTenantId())) {
|
||||
throw new ThingsboardException("Rate limit for entities import is exceeded", ThingsboardErrorCode.TOO_MANY_REQUESTS);
|
||||
}
|
||||
if (exportData.getEntity() == null || exportData.getEntity().getId() == null) {
|
||||
@ -86,7 +87,7 @@ public class DefaultEntitiesExportImportService implements EntitiesExportImportS
|
||||
EntityType entityType = exportData.getEntityType();
|
||||
EntityImportService<I, E, EntityExportData<E>> importService = getImportService(entityType);
|
||||
|
||||
EntityImportResult<E> importResult = importService.importEntity(user, exportData, importSettings);
|
||||
EntityImportResult<E> importResult = importService.importEntity(ctx, exportData);
|
||||
|
||||
if (saveReferences) {
|
||||
importResult.getSaveReferencesCallback().run();
|
||||
|
||||
@ -24,6 +24,7 @@ import org.thingsboard.server.common.data.sync.ie.EntityExportSettings;
|
||||
import org.thingsboard.server.common.data.sync.ie.EntityImportResult;
|
||||
import org.thingsboard.server.common.data.sync.ie.EntityImportSettings;
|
||||
import org.thingsboard.server.service.security.model.SecurityUser;
|
||||
import org.thingsboard.server.service.sync.vc.data.EntitiesImportCtx;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
@ -31,7 +32,7 @@ public interface EntitiesExportImportService {
|
||||
|
||||
<E extends ExportableEntity<I>, I extends EntityId> EntityExportData<E> exportEntity(SecurityUser user, I entityId, EntityExportSettings exportSettings) throws ThingsboardException;
|
||||
|
||||
<E extends ExportableEntity<I>, I extends EntityId> EntityImportResult<E> importEntity(SecurityUser user, EntityExportData<E> exportData, EntityImportSettings importSettings,
|
||||
<E extends ExportableEntity<I>, I extends EntityId> EntityImportResult<E> importEntity(EntitiesImportCtx ctx, EntityExportData<E> exportData,
|
||||
boolean saveReferences, boolean sendEvents) throws ThingsboardException;
|
||||
|
||||
|
||||
|
||||
@ -151,23 +151,6 @@ public class DefaultExportableEntitiesService implements ExportableEntitiesServi
|
||||
entityRemover.accept(tenantId, id);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void checkPermission(SecurityUser user, HasId<? extends EntityId> entity, EntityType entityType, Operation operation) throws ThingsboardException {
|
||||
if (entity instanceof HasTenantId) {
|
||||
accessControlService.checkPermission(user, Resource.of(entityType), operation, entity.getId(), (HasTenantId) entity);
|
||||
} else {
|
||||
accessControlService.checkPermission(user, Resource.of(entityType), operation);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkPermission(SecurityUser user, EntityId entityId, Operation operation) throws ThingsboardException {
|
||||
HasId<EntityId> entity = findEntityByTenantIdAndId(user.getTenantId(), entityId);
|
||||
checkPermission(user, entity, entityId.getEntityType(), operation);
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <E> Dao<E> getDao(EntityType entityType) {
|
||||
return (Dao<E>) daos.get(entityType);
|
||||
|
||||
@ -40,9 +40,4 @@ public interface ExportableEntitiesService {
|
||||
|
||||
<I extends EntityId> void removeById(TenantId tenantId, I id);
|
||||
|
||||
|
||||
void checkPermission(SecurityUser user, HasId<? extends EntityId> entity, EntityType entityType, Operation operation) throws ThingsboardException;
|
||||
|
||||
void checkPermission(SecurityUser user, EntityId entityId, Operation operation) throws ThingsboardException;
|
||||
|
||||
}
|
||||
|
||||
@ -66,7 +66,6 @@ public class DefaultEntityExportService<I extends EntityId, E extends Exportable
|
||||
if (entity == null) {
|
||||
throw new IllegalArgumentException(entityId.getEntityType() + " [" + entityId.getId() + "] not found");
|
||||
}
|
||||
exportableEntitiesService.checkPermission(user, entity, entity.getId().getEntityType(), Operation.READ);
|
||||
|
||||
exportData.setEntity(entity);
|
||||
exportData.setEntityType(entityId.getEntityType());
|
||||
@ -90,22 +89,14 @@ public class DefaultEntityExportService<I extends EntityId, E extends Exportable
|
||||
List<EntityRelation> relations = new ArrayList<>();
|
||||
|
||||
List<EntityRelation> inboundRelations = relationService.findByTo(user.getTenantId(), entity.getId(), RelationTypeGroup.COMMON);
|
||||
for (EntityRelation relation : inboundRelations) {
|
||||
exportableEntitiesService.checkPermission(user, relation.getFrom(), Operation.READ);
|
||||
}
|
||||
relations.addAll(inboundRelations);
|
||||
|
||||
List<EntityRelation> outboundRelations = relationService.findByFrom(user.getTenantId(), entity.getId(), RelationTypeGroup.COMMON);
|
||||
for (EntityRelation relation : outboundRelations) {
|
||||
exportableEntitiesService.checkPermission(user, relation.getTo(), Operation.READ);
|
||||
}
|
||||
relations.addAll(outboundRelations);
|
||||
return relations;
|
||||
}
|
||||
|
||||
private Map<String, List<AttributeExportData>> exportAttributes(SecurityUser user, E entity) throws ThingsboardException {
|
||||
exportableEntitiesService.checkPermission(user, entity, entity.getId().getEntityType(), Operation.READ_ATTRIBUTES);
|
||||
|
||||
List<String> scopes;
|
||||
if (entity.getId().getEntityType() == EntityType.DEVICE) {
|
||||
scopes = List.of(DataConstants.SERVER_SCOPE, DataConstants.SHARED_SCOPE);
|
||||
|
||||
@ -23,10 +23,11 @@ import org.thingsboard.server.service.security.model.SecurityUser;
|
||||
import org.thingsboard.server.common.data.sync.ie.EntityImportResult;
|
||||
import org.thingsboard.server.common.data.sync.ie.EntityImportSettings;
|
||||
import org.thingsboard.server.common.data.sync.ie.EntityExportData;
|
||||
import org.thingsboard.server.service.sync.vc.data.EntitiesImportCtx;
|
||||
|
||||
public interface EntityImportService<I extends EntityId, E extends ExportableEntity<I>, D extends EntityExportData<E>> {
|
||||
|
||||
EntityImportResult<E> importEntity(SecurityUser user, D exportData, EntityImportSettings importSettings) throws ThingsboardException;
|
||||
EntityImportResult<E> importEntity(EntitiesImportCtx ctx, D exportData) throws ThingsboardException;
|
||||
|
||||
EntityType getEntityType();
|
||||
|
||||
|
||||
@ -28,6 +28,7 @@ import org.thingsboard.server.dao.asset.AssetService;
|
||||
import org.thingsboard.server.queue.util.TbCoreComponent;
|
||||
import org.thingsboard.server.service.security.model.SecurityUser;
|
||||
import org.thingsboard.server.common.data.sync.ie.EntityExportData;
|
||||
import org.thingsboard.server.service.sync.vc.data.EntitiesImportCtx;
|
||||
|
||||
@Service
|
||||
@TbCoreComponent
|
||||
@ -43,7 +44,7 @@ public class AssetImportService extends BaseEntityImportService<AssetId, Asset,
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Asset prepareAndSave(TenantId tenantId, Asset asset, EntityExportData<Asset> exportData, IdProvider idProvider, EntityImportSettings importSettings) {
|
||||
protected Asset prepareAndSave(EntitiesImportCtx ctx, Asset asset, EntityExportData<Asset> exportData, IdProvider idProvider) {
|
||||
return assetService.saveAsset(asset);
|
||||
}
|
||||
|
||||
|
||||
@ -53,6 +53,7 @@ import org.thingsboard.server.service.security.model.SecurityUser;
|
||||
import org.thingsboard.server.service.security.permission.Operation;
|
||||
import org.thingsboard.server.service.sync.ie.exporting.ExportableEntitiesService;
|
||||
import org.thingsboard.server.service.sync.ie.importing.EntityImportService;
|
||||
import org.thingsboard.server.service.sync.vc.data.EntitiesImportCtx;
|
||||
import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@ -81,54 +82,53 @@ public abstract class BaseEntityImportService<I extends EntityId, E extends Expo
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public EntityImportResult<E> importEntity(SecurityUser user, D exportData, EntityImportSettings importSettings) throws ThingsboardException {
|
||||
public EntityImportResult<E> importEntity(EntitiesImportCtx ctx, D exportData) throws ThingsboardException {
|
||||
E entity = exportData.getEntity();
|
||||
E existingEntity = findExistingEntity(user.getTenantId(), entity, importSettings);
|
||||
E existingEntity = findExistingEntity(ctx, entity);
|
||||
|
||||
entity.setExternalId(entity.getId());
|
||||
|
||||
EntityImportResult<E> importResult = new EntityImportResult<>();
|
||||
IdProvider idProvider = new IdProvider(user, importSettings, importResult);
|
||||
setOwner(user.getTenantId(), entity, idProvider);
|
||||
IdProvider idProvider = new IdProvider(ctx, importResult);
|
||||
setOwner(ctx.getTenantId(), entity, idProvider);
|
||||
if (existingEntity == null) {
|
||||
entity.setId(null);
|
||||
exportableEntitiesService.checkPermission(user, entity, getEntityType(), Operation.CREATE);
|
||||
} else {
|
||||
entity.setId(existingEntity.getId());
|
||||
entity.setCreatedTime(existingEntity.getCreatedTime());
|
||||
exportableEntitiesService.checkPermission(user, existingEntity, getEntityType(), Operation.WRITE);
|
||||
}
|
||||
|
||||
E savedEntity = prepareAndSave(user.getTenantId(), entity, exportData, idProvider, importSettings);
|
||||
E savedEntity = prepareAndSave(ctx, entity, exportData, idProvider);
|
||||
|
||||
importResult.setSavedEntity(savedEntity);
|
||||
importResult.setOldEntity(existingEntity);
|
||||
importResult.setEntityType(getEntityType());
|
||||
|
||||
processAfterSaved(user, importResult, exportData, idProvider, importSettings);
|
||||
processAfterSaved(ctx, importResult, exportData, idProvider);
|
||||
|
||||
ctx.putInternalId(exportData.getExternalId(), savedEntity.getId());
|
||||
|
||||
return importResult;
|
||||
}
|
||||
|
||||
protected abstract void setOwner(TenantId tenantId, E entity, IdProvider idProvider);
|
||||
|
||||
protected abstract E prepareAndSave(TenantId tenantId, E entity, D exportData, IdProvider idProvider, EntityImportSettings importSettings);
|
||||
protected abstract E prepareAndSave(EntitiesImportCtx ctx, E entity, D exportData, IdProvider idProvider);
|
||||
|
||||
|
||||
protected void processAfterSaved(SecurityUser user, EntityImportResult<E> importResult, D exportData,
|
||||
IdProvider idProvider, EntityImportSettings importSettings) throws ThingsboardException {
|
||||
protected void processAfterSaved(EntitiesImportCtx ctx, EntityImportResult<E> importResult, D exportData, IdProvider idProvider) throws ThingsboardException {
|
||||
E savedEntity = importResult.getSavedEntity();
|
||||
E oldEntity = importResult.getOldEntity();
|
||||
|
||||
importResult.addSendEventsCallback(() -> {
|
||||
onEntitySaved(user, savedEntity, oldEntity);
|
||||
onEntitySaved(ctx.getUser(), savedEntity, oldEntity);
|
||||
});
|
||||
|
||||
if (importSettings.isUpdateRelations() && exportData.getRelations() != null) {
|
||||
importRelations(user, exportData.getRelations(), importResult);
|
||||
if (ctx.isUpdateRelations() && exportData.getRelations() != null) {
|
||||
importRelations(ctx.getUser(), exportData.getRelations(), importResult);
|
||||
}
|
||||
if (importSettings.isSaveAttributes() && exportData.getAttributes() != null) {
|
||||
importAttributes(user, exportData.getAttributes(), importResult);
|
||||
if (ctx.isSaveAttributes() && exportData.getAttributes() != null) {
|
||||
importAttributes(ctx.getUser(), exportData.getAttributes(), importResult);
|
||||
}
|
||||
}
|
||||
|
||||
@ -138,12 +138,10 @@ public abstract class BaseEntityImportService<I extends EntityId, E extends Expo
|
||||
for (EntityRelation relation : relations) {
|
||||
if (!relation.getTo().equals(entity.getId())) {
|
||||
HasId<EntityId> to = findInternalEntity(user.getTenantId(), relation.getTo());
|
||||
exportableEntitiesService.checkPermission(user, to, to.getId().getEntityType(), Operation.WRITE);
|
||||
relation.setTo(to.getId());
|
||||
}
|
||||
if (!relation.getFrom().equals(entity.getId())) {
|
||||
HasId<EntityId> from = findInternalEntity(user.getTenantId(), relation.getFrom());
|
||||
exportableEntitiesService.checkPermission(user, from, from.getId().getEntityType(), Operation.WRITE);
|
||||
relation.setFrom(from.getId());
|
||||
}
|
||||
}
|
||||
@ -155,15 +153,6 @@ public abstract class BaseEntityImportService<I extends EntityId, E extends Expo
|
||||
|
||||
for (EntityRelation existingRelation : existingRelations) {
|
||||
if (!relations.contains(existingRelation)) {
|
||||
EntityId otherEntity = null;
|
||||
if (!existingRelation.getTo().equals(entity.getId())) {
|
||||
otherEntity = existingRelation.getTo();
|
||||
} else if (!existingRelation.getFrom().equals(entity.getId())) {
|
||||
otherEntity = existingRelation.getFrom();
|
||||
}
|
||||
if (otherEntity != null) {
|
||||
exportableEntitiesService.checkPermission(user, otherEntity, Operation.WRITE);
|
||||
}
|
||||
relationService.deleteRelation(user.getTenantId(), existingRelation);
|
||||
importResult.addSendEventsCallback(() -> {
|
||||
entityActionService.logEntityAction(user, existingRelation.getFrom(), null, null,
|
||||
@ -234,12 +223,12 @@ public abstract class BaseEntityImportService<I extends EntityId, E extends Expo
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected E findExistingEntity(TenantId tenantId, E entity, EntityImportSettings importSettings) {
|
||||
return (E) Optional.ofNullable(exportableEntitiesService.findEntityByTenantIdAndExternalId(tenantId, entity.getId()))
|
||||
.or(() -> Optional.ofNullable(exportableEntitiesService.findEntityByTenantIdAndId(tenantId, entity.getId())))
|
||||
protected E findExistingEntity(EntitiesImportCtx ctx, E entity) {
|
||||
return (E) Optional.ofNullable(exportableEntitiesService.findEntityByTenantIdAndExternalId(ctx.getTenantId(), entity.getId()))
|
||||
.or(() -> Optional.ofNullable(exportableEntitiesService.findEntityByTenantIdAndId(ctx.getTenantId(), entity.getId())))
|
||||
.or(() -> {
|
||||
if (importSettings.isFindExistingByName()) {
|
||||
return Optional.ofNullable(exportableEntitiesService.findEntityByTenantIdAndName(tenantId, getEntityType(), entity.getName()));
|
||||
if (ctx.isFindExistingByName()) {
|
||||
return Optional.ofNullable(exportableEntitiesService.findEntityByTenantIdAndName(ctx.getTenantId(), getEntityType(), entity.getName()));
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
@ -255,22 +244,27 @@ public abstract class BaseEntityImportService<I extends EntityId, E extends Expo
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@RequiredArgsConstructor
|
||||
protected class IdProvider {
|
||||
private final SecurityUser user;
|
||||
private final EntityImportSettings importSettings;
|
||||
private final EntitiesImportCtx ctx;
|
||||
private final EntityImportResult<E> importResult;
|
||||
|
||||
public <ID extends EntityId> ID getInternalId(ID externalId) {
|
||||
return getInternalId(externalId, true);
|
||||
}
|
||||
}
|
||||
|
||||
public <ID extends EntityId> ID getInternalId(ID externalId, boolean throwExceptionIfNotFound) {
|
||||
if (externalId == null || externalId.isNullUid()) return null;
|
||||
|
||||
EntityId localId = ctx.getInternalId(externalId);
|
||||
if (localId != null) {
|
||||
return (ID) localId;
|
||||
}
|
||||
|
||||
HasId<ID> entity;
|
||||
try {
|
||||
entity = findInternalEntity(user.getTenantId(), externalId);
|
||||
entity = findInternalEntity(ctx.getTenantId(), externalId);
|
||||
} catch (Exception e) {
|
||||
if (throwExceptionIfNotFound) {
|
||||
throw e;
|
||||
@ -279,17 +273,26 @@ public abstract class BaseEntityImportService<I extends EntityId, E extends Expo
|
||||
return null;
|
||||
}
|
||||
}
|
||||
try {
|
||||
exportableEntitiesService.checkPermission(user, entity, entity.getId().getEntityType(), Operation.READ);
|
||||
} catch (ThingsboardException e) {
|
||||
throw new IllegalArgumentException(e.getMessage(), e);
|
||||
}
|
||||
ctx.putInternalId(externalId, entity.getId());
|
||||
return entity.getId();
|
||||
}
|
||||
|
||||
public Optional<EntityId> getInternalIdByUuid(UUID externalUuid) {
|
||||
if (externalUuid.equals(EntityId.NULL_UUID)) return Optional.empty();
|
||||
|
||||
for (EntityType entityType : EntityType.values()) {
|
||||
EntityId externalId;
|
||||
try {
|
||||
externalId = EntityIdFactory.getByTypeAndUuid(entityType, externalUuid);
|
||||
} catch (Exception e) {
|
||||
continue;
|
||||
}
|
||||
EntityId internalId = ctx.getInternalId(externalId);
|
||||
if (internalId != null) {
|
||||
return Optional.of(internalId);
|
||||
}
|
||||
}
|
||||
|
||||
for (EntityType entityType : EntityType.values()) {
|
||||
EntityId externalId;
|
||||
try {
|
||||
@ -301,12 +304,13 @@ public abstract class BaseEntityImportService<I extends EntityId, E extends Expo
|
||||
EntityId internalId = getInternalId(externalId, false);
|
||||
if (internalId != null) {
|
||||
return Optional.of(internalId);
|
||||
} else if (importSettings.isResetExternalIdsOfAnotherTenant()) {
|
||||
} else if (ctx.isResetExternalIdsOfAnotherTenant()) {
|
||||
try {
|
||||
if (exportableEntitiesService.findEntityById(externalId) != null) {
|
||||
return Optional.of(EntityIdFactory.getByTypeAndUuid(entityType, EntityId.NULL_UUID));
|
||||
}
|
||||
} catch (Exception ignored) {}
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -29,6 +29,7 @@ import org.thingsboard.server.dao.customer.CustomerService;
|
||||
import org.thingsboard.server.queue.util.TbCoreComponent;
|
||||
import org.thingsboard.server.service.security.model.SecurityUser;
|
||||
import org.thingsboard.server.common.data.sync.ie.EntityExportData;
|
||||
import org.thingsboard.server.service.sync.vc.data.EntitiesImportCtx;
|
||||
|
||||
@Service
|
||||
@TbCoreComponent
|
||||
@ -44,13 +45,13 @@ public class CustomerImportService extends BaseEntityImportService<CustomerId, C
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Customer prepareAndSave(TenantId tenantId, Customer customer, EntityExportData<Customer> exportData, IdProvider idProvider, EntityImportSettings importSettings) {
|
||||
protected Customer prepareAndSave(EntitiesImportCtx ctx, Customer customer, EntityExportData<Customer> exportData, IdProvider idProvider) {
|
||||
if (!customer.isPublic()) {
|
||||
return customerService.saveCustomer(customer);
|
||||
} else {
|
||||
Customer publicCustomer = customerService.findOrCreatePublicCustomer(tenantId);
|
||||
Customer publicCustomer = customerService.findOrCreatePublicCustomer(ctx.getTenantId());
|
||||
publicCustomer.setExternalId(customer.getExternalId());
|
||||
return customerDao.save(tenantId, publicCustomer);
|
||||
return customerDao.save(ctx.getTenantId(), publicCustomer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -34,6 +34,7 @@ import org.thingsboard.server.common.data.sync.ie.EntityImportSettings;
|
||||
import org.thingsboard.server.dao.dashboard.DashboardService;
|
||||
import org.thingsboard.server.queue.util.TbCoreComponent;
|
||||
import org.thingsboard.server.service.security.model.SecurityUser;
|
||||
import org.thingsboard.server.service.sync.vc.data.EntitiesImportCtx;
|
||||
import org.thingsboard.server.utils.RegexUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@ -58,16 +59,17 @@ public class DashboardImportService extends BaseEntityImportService<DashboardId,
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Dashboard findExistingEntity(TenantId tenantId, Dashboard dashboard, EntityImportSettings importSettings) {
|
||||
Dashboard existingDashboard = super.findExistingEntity(tenantId, dashboard, importSettings);
|
||||
if (existingDashboard == null && importSettings.isFindExistingByName()) {
|
||||
existingDashboard = dashboardService.findTenantDashboardsByTitle(tenantId, dashboard.getName()).stream().findFirst().orElse(null);
|
||||
protected Dashboard findExistingEntity(EntitiesImportCtx ctx, Dashboard dashboard) {
|
||||
Dashboard existingDashboard = super.findExistingEntity(ctx, dashboard);
|
||||
if (existingDashboard == null && ctx.isFindExistingByName()) {
|
||||
existingDashboard = dashboardService.findTenantDashboardsByTitle(ctx.getTenantId(), dashboard.getName()).stream().findFirst().orElse(null);
|
||||
}
|
||||
return existingDashboard;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Dashboard prepareAndSave(TenantId tenantId, Dashboard dashboard, EntityExportData<Dashboard> exportData, IdProvider idProvider, EntityImportSettings importSettings) {
|
||||
protected Dashboard prepareAndSave(EntitiesImportCtx ctx, Dashboard dashboard, EntityExportData<Dashboard> exportData, IdProvider idProvider) {
|
||||
var tenantId = ctx.getTenantId();
|
||||
JsonNode configuration = dashboard.getConfiguration();
|
||||
JsonNode entityAliases = configuration.get("entityAliases");
|
||||
if (entityAliases != null && entityAliases.isObject()) {
|
||||
|
||||
@ -27,6 +27,7 @@ import org.thingsboard.server.dao.device.DeviceService;
|
||||
import org.thingsboard.server.queue.util.TbCoreComponent;
|
||||
import org.thingsboard.server.service.security.model.SecurityUser;
|
||||
import org.thingsboard.server.common.data.sync.ie.DeviceExportData;
|
||||
import org.thingsboard.server.service.sync.vc.data.EntitiesImportCtx;
|
||||
|
||||
@Service
|
||||
@TbCoreComponent
|
||||
@ -42,11 +43,11 @@ public class DeviceImportService extends BaseEntityImportService<DeviceId, Devic
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Device prepareAndSave(TenantId tenantId, Device device, DeviceExportData exportData, IdProvider idProvider, EntityImportSettings importSettings) {
|
||||
protected Device prepareAndSave(EntitiesImportCtx ctx, Device device, DeviceExportData exportData, IdProvider idProvider) {
|
||||
device.setDeviceProfileId(idProvider.getInternalId(device.getDeviceProfileId()));
|
||||
device.setFirmwareId(idProvider.getInternalId(device.getFirmwareId()));
|
||||
device.setSoftwareId(idProvider.getInternalId(device.getSoftwareId()));
|
||||
if (exportData.getCredentials() != null && importSettings.isSaveCredentials()) {
|
||||
if (exportData.getCredentials() != null && ctx.isSaveCredentials()) {
|
||||
exportData.getCredentials().setId(null);
|
||||
exportData.getCredentials().setDeviceId(null);
|
||||
return deviceService.saveDeviceWithCredentials(device, exportData.getCredentials());
|
||||
|
||||
@ -30,6 +30,7 @@ import org.thingsboard.server.queue.util.TbCoreComponent;
|
||||
import org.thingsboard.server.service.ota.OtaPackageStateService;
|
||||
import org.thingsboard.server.service.security.model.SecurityUser;
|
||||
import org.thingsboard.server.common.data.sync.ie.EntityExportData;
|
||||
import org.thingsboard.server.service.sync.vc.data.EntitiesImportCtx;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@ -47,7 +48,7 @@ public class DeviceProfileImportService extends BaseEntityImportService<DevicePr
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DeviceProfile prepareAndSave(TenantId tenantId, DeviceProfile deviceProfile, EntityExportData<DeviceProfile> exportData, IdProvider idProvider, EntityImportSettings importSettings) {
|
||||
protected DeviceProfile prepareAndSave(EntitiesImportCtx ctx, DeviceProfile deviceProfile, EntityExportData<DeviceProfile> exportData, IdProvider idProvider) {
|
||||
deviceProfile.setDefaultRuleChainId(idProvider.getInternalId(deviceProfile.getDefaultRuleChainId()));
|
||||
deviceProfile.setDefaultDashboardId(idProvider.getInternalId(deviceProfile.getDefaultDashboardId()));
|
||||
deviceProfile.setFirmwareId(idProvider.getInternalId(deviceProfile.getFirmwareId()));
|
||||
|
||||
@ -33,6 +33,7 @@ import org.thingsboard.server.common.data.sync.ie.RuleChainExportData;
|
||||
import org.thingsboard.server.dao.rule.RuleChainService;
|
||||
import org.thingsboard.server.queue.util.TbCoreComponent;
|
||||
import org.thingsboard.server.service.security.model.SecurityUser;
|
||||
import org.thingsboard.server.service.sync.vc.data.EntitiesImportCtx;
|
||||
import org.thingsboard.server.utils.RegexUtils;
|
||||
|
||||
import java.util.Collections;
|
||||
@ -52,16 +53,16 @@ public class RuleChainImportService extends BaseEntityImportService<RuleChainId,
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RuleChain findExistingEntity(TenantId tenantId, RuleChain ruleChain, EntityImportSettings importSettings) {
|
||||
RuleChain existingRuleChain = super.findExistingEntity(tenantId, ruleChain, importSettings);
|
||||
if (existingRuleChain == null && importSettings.isFindExistingByName()) {
|
||||
existingRuleChain = ruleChainService.findTenantRuleChainsByTypeAndName(tenantId, ruleChain.getType(), ruleChain.getName()).stream().findFirst().orElse(null);
|
||||
protected RuleChain findExistingEntity(EntitiesImportCtx ctx, RuleChain ruleChain) {
|
||||
RuleChain existingRuleChain = super.findExistingEntity(ctx, ruleChain);
|
||||
if (existingRuleChain == null && ctx.isFindExistingByName()) {
|
||||
existingRuleChain = ruleChainService.findTenantRuleChainsByTypeAndName(ctx.getTenantId(), ruleChain.getType(), ruleChain.getName()).stream().findFirst().orElse(null);
|
||||
}
|
||||
return existingRuleChain;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RuleChain prepareAndSave(TenantId tenantId, RuleChain ruleChain, RuleChainExportData exportData, IdProvider idProvider, EntityImportSettings importSettings) {
|
||||
protected RuleChain prepareAndSave(EntitiesImportCtx ctx, RuleChain ruleChain, RuleChainExportData exportData, IdProvider idProvider) {
|
||||
RuleChainMetaData metaData = exportData.getMetaData();
|
||||
Optional.ofNullable(metaData.getNodes()).orElse(Collections.emptyList())
|
||||
.forEach(ruleNode -> {
|
||||
@ -85,8 +86,8 @@ public class RuleChainImportService extends BaseEntityImportService<RuleChainId,
|
||||
|
||||
ruleChain = ruleChainService.saveRuleChain(ruleChain);
|
||||
exportData.getMetaData().setRuleChainId(ruleChain.getId());
|
||||
ruleChainService.saveRuleChainMetaData(tenantId, exportData.getMetaData());
|
||||
return ruleChainService.findRuleChainById(tenantId, ruleChain.getId());
|
||||
ruleChainService.saveRuleChainMetaData(ctx.getTenantId(), exportData.getMetaData());
|
||||
return ruleChainService.findRuleChainById(ctx.getTenantId(), ruleChain.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -32,6 +32,7 @@ import org.thingsboard.server.dao.widget.WidgetTypeService;
|
||||
import org.thingsboard.server.dao.widget.WidgetsBundleService;
|
||||
import org.thingsboard.server.queue.util.TbCoreComponent;
|
||||
import org.thingsboard.server.service.security.model.SecurityUser;
|
||||
import org.thingsboard.server.service.sync.vc.data.EntitiesImportCtx;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
@ -50,17 +51,17 @@ public class WidgetsBundleImportService extends BaseEntityImportService<WidgetsB
|
||||
}
|
||||
|
||||
@Override
|
||||
protected WidgetsBundle prepareAndSave(TenantId tenantId, WidgetsBundle widgetsBundle, WidgetsBundleExportData exportData, IdProvider idProvider, EntityImportSettings importSettings) {
|
||||
protected WidgetsBundle prepareAndSave(EntitiesImportCtx ctx, WidgetsBundle widgetsBundle, WidgetsBundleExportData exportData, IdProvider idProvider) {
|
||||
WidgetsBundle savedWidgetsBundle = widgetsBundleService.saveWidgetsBundle(widgetsBundle);
|
||||
if (widgetsBundle.getId() == null) {
|
||||
for (WidgetTypeDetails widget : exportData.getWidgets()) {
|
||||
widget.setId(null);
|
||||
widget.setTenantId(tenantId);
|
||||
widget.setTenantId(ctx.getTenantId());
|
||||
widget.setBundleAlias(savedWidgetsBundle.getAlias());
|
||||
widgetTypeService.saveWidgetType(widget);
|
||||
}
|
||||
} else {
|
||||
Map<String, WidgetTypeInfo> existingWidgets = widgetTypeService.findWidgetTypesInfosByTenantIdAndBundleAlias(tenantId, savedWidgetsBundle.getAlias()).stream()
|
||||
Map<String, WidgetTypeInfo> existingWidgets = widgetTypeService.findWidgetTypesInfosByTenantIdAndBundleAlias(ctx.getTenantId(), savedWidgetsBundle.getAlias()).stream()
|
||||
.collect(Collectors.toMap(BaseWidgetType::getAlias, w -> w));
|
||||
for (WidgetTypeDetails widget : exportData.getWidgets()) {
|
||||
WidgetTypeInfo existingWidget;
|
||||
@ -70,13 +71,13 @@ public class WidgetsBundleImportService extends BaseEntityImportService<WidgetsB
|
||||
} else {
|
||||
widget.setId(null);
|
||||
}
|
||||
widget.setTenantId(tenantId);
|
||||
widget.setTenantId(ctx.getTenantId());
|
||||
widget.setBundleAlias(savedWidgetsBundle.getAlias());
|
||||
widgetTypeService.saveWidgetType(widget);
|
||||
}
|
||||
existingWidgets.values().stream()
|
||||
.map(BaseWidgetType::getId)
|
||||
.forEach(widgetTypeId -> widgetTypeService.deleteWidgetType(tenantId, widgetTypeId));
|
||||
.forEach(widgetTypeId -> widgetTypeService.deleteWidgetType(ctx.getTenantId(), widgetTypeId));
|
||||
}
|
||||
return savedWidgetsBundle;
|
||||
}
|
||||
|
||||
@ -77,6 +77,7 @@ import org.thingsboard.server.service.sync.ie.exporting.ExportableEntitiesServic
|
||||
import org.thingsboard.server.service.sync.ie.importing.impl.MissingEntityException;
|
||||
import org.thingsboard.server.service.sync.vc.autocommit.TbAutoCommitSettingsService;
|
||||
import org.thingsboard.server.service.sync.vc.data.CommitGitRequest;
|
||||
import org.thingsboard.server.service.sync.vc.data.EntitiesImportCtx;
|
||||
import org.thingsboard.server.service.sync.vc.repository.TbRepositorySettingsService;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
@ -244,13 +245,13 @@ public class DefaultEntitiesVersionControlService implements EntitiesVersionCont
|
||||
|
||||
private VersionLoadResult loadSingleEntity(SecurityUser user, VersionLoadConfig config, EntityExportData entityData) {
|
||||
try {
|
||||
EntityImportResult<?> importResult = exportImportService.importEntity(user, entityData,
|
||||
EntityImportSettings.builder()
|
||||
var ctx = new EntitiesImportCtx(user, EntityImportSettings.builder()
|
||||
.updateRelations(config.isLoadRelations())
|
||||
.saveAttributes(config.isLoadAttributes())
|
||||
.saveCredentials(config.isLoadCredentials())
|
||||
.findExistingByName(false)
|
||||
.build(), true, true);
|
||||
.build());
|
||||
EntityImportResult<?> importResult = exportImportService.importEntity(ctx, entityData, true, true);
|
||||
return VersionLoadResult.success(EntityTypeLoadResult.builder()
|
||||
.entityType(importResult.getEntityType())
|
||||
.created(importResult.getOldEntity() == null ? 1 : 0)
|
||||
@ -269,6 +270,8 @@ public class DefaultEntitiesVersionControlService implements EntitiesVersionCont
|
||||
List<ThrowingRunnable> saveReferencesCallbacks = new ArrayList<>();
|
||||
List<ThrowingRunnable> sendEventsCallbacks = new ArrayList<>();
|
||||
|
||||
EntitiesImportCtx ctx = new EntitiesImportCtx(user);
|
||||
|
||||
List<EntityType> entityTypes = request.getEntityTypes().keySet().stream()
|
||||
.sorted(exportImportService.getEntityTypeComparatorForImport()).collect(Collectors.toList());
|
||||
for (EntityType entityType : entityTypes) {
|
||||
@ -285,21 +288,20 @@ public class DefaultEntitiesVersionControlService implements EntitiesVersionCont
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
EntityImportSettings importSettings = EntityImportSettings.builder()
|
||||
ctx.setSettings(EntityImportSettings.builder()
|
||||
.updateRelations(config.isLoadRelations())
|
||||
.saveAttributes(config.isLoadAttributes())
|
||||
.findExistingByName(config.isFindExistingEntityByName())
|
||||
.build();
|
||||
.build());
|
||||
for (EntityExportData entityData : entityDataList) {
|
||||
EntityImportResult<?> importResult;
|
||||
try {
|
||||
importResult = exportImportService.importEntity(user, entityData,
|
||||
importSettings, false, false);
|
||||
importResult = exportImportService.importEntity(ctx, entityData, false, false);
|
||||
} catch (Exception e) {
|
||||
throw new LoadEntityException(entityData, e);
|
||||
}
|
||||
if (importResult.getUpdatedAllExternalIds() != null && !importResult.getUpdatedAllExternalIds()) {
|
||||
toReimport.put(entityData.getEntity().getExternalId(), importSettings);
|
||||
toReimport.put(entityData.getEntity().getExternalId(), ctx.getSettings());
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -324,8 +326,8 @@ public class DefaultEntitiesVersionControlService implements EntitiesVersionCont
|
||||
try {
|
||||
EntityExportData entityData = gitServiceQueue.getEntity(user.getTenantId(), request.getVersionId(), externalId).get();
|
||||
importSettings.setResetExternalIdsOfAnotherTenant(true);
|
||||
EntityImportResult<?> importResult = exportImportService.importEntity(user, entityData,
|
||||
importSettings, false, false);
|
||||
ctx.setSettings(importSettings);
|
||||
EntityImportResult<?> importResult = exportImportService.importEntity(ctx, entityData, false, false);
|
||||
|
||||
EntityTypeLoadResult stats = results.get(externalId.getEntityType());
|
||||
if (importResult.getOldEntity() == null) stats.setCreated(stats.getCreated() + 1);
|
||||
@ -347,11 +349,6 @@ public class DefaultEntitiesVersionControlService implements EntitiesVersionCont
|
||||
return exportableEntitiesService.findEntitiesByTenantId(user.getTenantId(), entityType, pageLink);
|
||||
}, 100, entity -> {
|
||||
if (importedEntities.get(entityType) == null || !importedEntities.get(entityType).contains(entity.getId())) {
|
||||
try {
|
||||
exportableEntitiesService.checkPermission(user, entity, entityType, Operation.DELETE);
|
||||
} catch (ThingsboardException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
exportableEntitiesService.removeById(user.getTenantId(), entity.getId());
|
||||
|
||||
sendEventsCallbacks.add(() -> {
|
||||
|
||||
@ -0,0 +1,75 @@
|
||||
/**
|
||||
* Copyright © 2016-2022 The Thingsboard Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.thingsboard.server.service.sync.vc.data;
|
||||
|
||||
import lombok.Data;
|
||||
import org.thingsboard.server.common.data.id.EntityId;
|
||||
import org.thingsboard.server.common.data.id.TenantId;
|
||||
import org.thingsboard.server.common.data.sync.ie.EntityImportSettings;
|
||||
import org.thingsboard.server.service.security.model.SecurityUser;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
public class EntitiesImportCtx {
|
||||
|
||||
private final SecurityUser user;
|
||||
private EntityImportSettings settings;
|
||||
|
||||
private final Map<EntityId, EntityId> externalToInternalIdMap = new HashMap<>();
|
||||
|
||||
public EntitiesImportCtx(SecurityUser user) {
|
||||
this(user, null);
|
||||
}
|
||||
|
||||
public EntitiesImportCtx(SecurityUser user, EntityImportSettings settings) {
|
||||
this.user = user;
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
public TenantId getTenantId() {
|
||||
return user.getTenantId();
|
||||
}
|
||||
|
||||
public boolean isFindExistingByName() {
|
||||
return getSettings().isFindExistingByName();
|
||||
}
|
||||
|
||||
public boolean isUpdateRelations() {
|
||||
return getSettings().isUpdateRelations();
|
||||
}
|
||||
|
||||
public boolean isSaveAttributes() {
|
||||
return getSettings().isSaveAttributes();
|
||||
}
|
||||
|
||||
public boolean isSaveCredentials() {
|
||||
return getSettings().isSaveCredentials();
|
||||
}
|
||||
|
||||
public boolean isResetExternalIdsOfAnotherTenant() {
|
||||
return getSettings().isResetExternalIdsOfAnotherTenant();
|
||||
}
|
||||
|
||||
public EntityId getInternalId(EntityId externalId) {
|
||||
return externalToInternalIdMap.get(externalId);
|
||||
}
|
||||
|
||||
public void putInternalId(EntityId externalId, EntityId internalId) {
|
||||
externalToInternalIdMap.put(externalId, internalId);
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user