Tenant deletion with housekeeper

This commit is contained in:
ViacheslavKlimov 2024-02-15 14:26:33 +02:00
parent a1bede3cbb
commit faa93de102
37 changed files with 258 additions and 41 deletions

View File

@ -128,8 +128,13 @@ public class DefaultHousekeeperService implements HousekeeperService {
@Override
public void submitTask(HousekeeperTask task) {
submitTask(UUID.randomUUID(), task);
}
@Override
public void submitTask(UUID key, HousekeeperTask task) {
TopicPartitionInfo tpi = TopicPartitionInfo.builder().topic(producer.getDefaultTopic()).build();
producer.send(tpi, new TbProtoQueueMsg<>(UUID.randomUUID(), ToHousekeeperServiceMsg.newBuilder()
producer.send(tpi, new TbProtoQueueMsg<>(key, ToHousekeeperServiceMsg.newBuilder()
.setTask(HousekeeperTaskProto.newBuilder()
.setValue(ByteString.copyFrom(dataDecodingEncodingService.encode(task)))
.setTs(task.getTs())

View File

@ -49,7 +49,7 @@ public class HousekeeperReprocessingService {
@Value("${queue.core.housekeeper.poll-interval-ms:10000}")
private int pollInterval;
private final long startTs = System.currentTimeMillis();
private final long startTs = System.currentTimeMillis(); // fixme: some other tb-core might start earlier and submit for reprocessing
private boolean stopped;
// todo: stats
@ -114,12 +114,13 @@ public class HousekeeperReprocessingService {
msg = msg.toBuilder()
.setTask(task.toBuilder()
.setAttempt(attempt)
.setTs(System.currentTimeMillis())
.setTs(System.currentTimeMillis()) // maybe set ts + 1 hour so that no-one reprocesses it immediately
.build())
.build();
var producer = producerProvider.getHousekeeperDelayedMsgProducer();
TopicPartitionInfo tpi = TopicPartitionInfo.builder().topic(producer.getDefaultTopic()).build();
// fixme submit with the same msg key, so that the messages goes to this consumer and will not be processed by anyone else
producer.send(tpi, new TbProtoQueueMsg<>(UUID.randomUUID(), msg), null);
}

View File

@ -17,21 +17,29 @@ package org.thingsboard.server.service.housekeeper.processor;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.thingsboard.server.dao.housekeeper.data.HousekeeperTask;
import org.thingsboard.server.dao.entity.EntityDaoService;
import org.thingsboard.server.dao.entity.EntityServiceRegistry;
import org.thingsboard.server.dao.housekeeper.data.EntitiesDeletionHousekeeperTask;
import org.thingsboard.server.dao.housekeeper.data.HousekeeperTaskType;
@Component
@RequiredArgsConstructor
public class EntityDeletionTaskProcessor implements HousekeeperTaskProcessor<HousekeeperTask> {
public class EntitiesDeletionTaskProcessor implements HousekeeperTaskProcessor<EntitiesDeletionHousekeeperTask> {
private final EntityServiceRegistry entityServiceRegistry;
@Override
public void process(HousekeeperTask task) throws Exception {
public void process(EntitiesDeletionHousekeeperTask task) throws Exception {
EntityDaoService entityService = entityServiceRegistry.getServiceByEntityType(task.getEntityType());
if (entityService == null) {
throw new IllegalArgumentException("Unsupported entity type " + task.getEntityType());
}
entityService.deleteByTenantId(task.getTenantId());
}
@Override
public HousekeeperTaskType getTaskType() {
return HousekeeperTaskType.DELETE_ENTITY;
return HousekeeperTaskType.DELETE_ENTITIES;
}
}

View File

@ -34,6 +34,10 @@ public interface EntityDaoService {
throw new IllegalArgumentException(getEntityType().getNormalName() + " deletion not supported");
}
default void deleteByTenantId(TenantId tenantId) {
throw new IllegalArgumentException("Deletion by tenant id not supported for " + getEntityType().getNormalName());
}
EntityType getEntityType();
}

View File

@ -58,7 +58,8 @@ public enum EntityType {
NOTIFICATION_TEMPLATE (30),
NOTIFICATION_REQUEST (31),
NOTIFICATION (32),
NOTIFICATION_RULE (33);
NOTIFICATION_RULE (33),
ADMIN_SETTINGS(34);
@Getter
private final int protoNumber; // Corresponds to EntityTypeProto

View File

@ -304,6 +304,11 @@ public class AssetProfileServiceImpl extends AbstractCachedEntityService<AssetPr
tenantAssetProfilesRemover.removeEntities(tenantId, tenantId);
}
@Override
public void deleteByTenantId(TenantId tenantId) {
deleteAssetProfilesByTenantId(tenantId);
}
@Override
public Optional<HasId<?>> findEntity(TenantId tenantId, EntityId entityId) {
return Optional.ofNullable(findAssetProfileById(tenantId, new AssetProfileId(entityId.getId())));

View File

@ -279,6 +279,11 @@ public class BaseAssetService extends AbstractCachedEntityService<AssetCacheKey,
tenantAssetsRemover.removeEntities(tenantId, tenantId);
}
@Override
public void deleteByTenantId(TenantId tenantId) {
deleteAssetsByTenantId(tenantId);
}
@Override
public PageData<Asset> findAssetsByTenantIdAndCustomerId(TenantId tenantId, CustomerId customerId, PageLink pageLink) {
log.trace("Executing findAssetsByTenantIdAndCustomerId, tenantId [{}], customerId [{}], pageLink [{}]", tenantId, customerId, pageLink);

View File

@ -180,6 +180,11 @@ public class CustomerServiceImpl extends AbstractEntityService implements Custom
customersByTenantRemover.removeEntities(tenantId, tenantId);
}
@Override
public void deleteByTenantId(TenantId tenantId) {
deleteCustomersByTenantId(tenantId);
}
private PaginatedRemover<TenantId, Customer> customersByTenantRemover =
new PaginatedRemover<TenantId, Customer>() {

View File

@ -272,6 +272,11 @@ public class DashboardServiceImpl extends AbstractEntityService implements Dashb
tenantDashboardsRemover.removeEntities(tenantId, tenantId);
}
@Override
public void deleteByTenantId(TenantId tenantId) {
deleteDashboardsByTenantId(tenantId);
}
@Override
public PageData<DashboardInfo> findDashboardsByTenantIdAndCustomerId(TenantId tenantId, CustomerId customerId, PageLink pageLink) {
log.trace("Executing findDashboardsByTenantIdAndCustomerId, tenantId [{}], customerId [{}], pageLink [{}]", tenantId, customerId, pageLink);

View File

@ -359,6 +359,11 @@ public class DeviceProfileServiceImpl extends AbstractCachedEntityService<Device
tenantDeviceProfilesRemover.removeEntities(tenantId, tenantId);
}
@Override
public void deleteByTenantId(TenantId tenantId) {
deleteDeviceProfilesByTenantId(tenantId);
}
@Override
public Optional<HasId<?>> findEntity(TenantId tenantId, EntityId entityId) {
return Optional.ofNullable(findDeviceProfileById(tenantId, new DeviceProfileId(entityId.getId())));

View File

@ -422,6 +422,12 @@ public class DeviceServiceImpl extends AbstractCachedEntityService<DeviceCacheKe
tenantDevicesRemover.removeEntities(tenantId, tenantId);
}
@Transactional
@Override
public void deleteByTenantId(TenantId tenantId) {
deleteDevicesByTenantId(tenantId);
}
@Override
public PageData<Device> findDevicesByTenantIdAndCustomerId(TenantId tenantId, CustomerId customerId, PageLink pageLink) {
log.trace("Executing findDevicesByTenantIdAndCustomerId, tenantId [{}], customerId [{}], pageLink [{}]", tenantId, customerId, pageLink);

View File

@ -266,6 +266,11 @@ public class EdgeServiceImpl extends AbstractCachedEntityService<EdgeCacheKey, E
tenantEdgesRemover.removeEntities(tenantId, tenantId);
}
@Override
public void deleteByTenantId(TenantId tenantId) {
deleteEdgesByTenantId(tenantId);
}
@Override
public PageData<Edge> findEdgesByTenantIdAndCustomerId(TenantId tenantId, CustomerId customerId, PageLink pageLink) {
log.trace("Executing findEdgesByTenantIdAndCustomerId, tenantId [{}], customerId [{}], pageLink [{}]", tenantId, customerId, pageLink);

View File

@ -344,6 +344,11 @@ public class EntityViewServiceImpl extends AbstractCachedEntityService<EntityVie
tenantEntityViewRemover.removeEntities(tenantId, tenantId);
}
@Override
public void deleteByTenantId(TenantId tenantId) {
deleteEntityViewsByTenantId(tenantId);
}
@Override
public ListenableFuture<List<EntitySubtype>> findEntityViewTypesByTenantId(TenantId tenantId) {
log.trace("Executing findEntityViewTypesByTenantId, tenantId [{}]", tenantId);

View File

@ -27,6 +27,8 @@ import org.thingsboard.server.dao.eventsourcing.DeleteEntityEvent;
import org.thingsboard.server.dao.housekeeper.data.HousekeeperTask;
import org.thingsboard.server.dao.relation.RelationService;
import java.util.UUID;
@Component
@RequiredArgsConstructor
@Slf4j
@ -57,4 +59,11 @@ public class CleanUpService {
housekeeperService.submitTask(HousekeeperTask.deleteEntityAlarms(tenantId, entityId));
}
public void removeTenantEntities(TenantId tenantId, EntityType... entityTypes) {
UUID tasksKey = UUID.randomUUID(); // so that all tasks are processed synchronously from one partition
for (EntityType entityType : entityTypes) {
housekeeperService.submitTask(tasksKey, HousekeeperTask.deleteEntities(tenantId, entityType));
}
}
}

View File

@ -17,8 +17,13 @@ package org.thingsboard.server.dao.housekeeper;
import org.thingsboard.server.dao.housekeeper.data.HousekeeperTask;
import java.util.UUID;
public interface HousekeeperService {
void submitTask(HousekeeperTask task);
// tasks with the same key will be pushed to the same partition and thus processed synchronously
void submitTask(UUID key, HousekeeperTask task);
}

View File

@ -0,0 +1,32 @@
/**
* Copyright © 2016-2024 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.dao.housekeeper.data;
import lombok.Getter;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.id.TenantId;
@Getter
public class EntitiesDeletionHousekeeperTask extends HousekeeperTask {
private final EntityType entityType;
protected EntitiesDeletionHousekeeperTask(TenantId tenantId, EntityType entityType) {
super(tenantId, null, HousekeeperTaskType.DELETE_ENTITIES);
this.entityType = entityType;
}
}

View File

@ -16,6 +16,7 @@
package org.thingsboard.server.dao.housekeeper.data;
import lombok.Data;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.TenantId;
@ -57,4 +58,8 @@ public class HousekeeperTask implements Serializable {
return new HousekeeperTask(tenantId, entityId, HousekeeperTaskType.DELETE_ENTITY_ALARMS);
}
public static HousekeeperTask deleteEntities(TenantId tenantId, EntityType entityType) {
return new EntitiesDeletionHousekeeperTask(tenantId, entityType);
}
}

View File

@ -16,7 +16,7 @@
package org.thingsboard.server.dao.housekeeper.data;
public enum HousekeeperTaskType {
DELETE_ENTITY,
DELETE_ENTITIES,
DELETE_ATTRIBUTES,
DELETE_TELEMETRY, // maybe divide into latest and ts kv history?
DELETE_EVENTS,

View File

@ -104,6 +104,11 @@ public class DefaultNotificationRequestService implements NotificationRequestSer
notificationRequestDao.removeByTenantId(tenantId);
}
@Override
public void deleteByTenantId(TenantId tenantId) {
deleteNotificationRequestsByTenantId(tenantId);
}
@Override
public Optional<HasId<?>> findEntity(TenantId tenantId, EntityId entityId) {
return Optional.ofNullable(findNotificationRequestById(tenantId, new NotificationRequestId(entityId.getId())));

View File

@ -93,6 +93,11 @@ public class DefaultNotificationRuleService extends AbstractEntityService implem
notificationRuleDao.removeByTenantId(tenantId);
}
@Override
public void deleteByTenantId(TenantId tenantId) {
deleteNotificationRulesByTenantId(tenantId);
}
@Override
public Optional<HasId<?>> findEntity(TenantId tenantId, EntityId entityId) {
return Optional.ofNullable(findNotificationRuleById(tenantId, new NotificationRuleId(entityId.getId())));

View File

@ -201,6 +201,11 @@ public class DefaultNotificationTargetService extends AbstractEntityService impl
notificationTargetDao.removeByTenantId(tenantId);
}
@Override
public void deleteByTenantId(TenantId tenantId) {
deleteNotificationTargetsByTenantId(tenantId);
}
@Override
public long countNotificationTargetsByTenantId(TenantId tenantId) {
return notificationTargetDao.countByTenantId(tenantId);

View File

@ -89,6 +89,11 @@ public class DefaultNotificationTemplateService extends AbstractEntityService im
notificationTemplateDao.removeByTenantId(tenantId);
}
@Override
public void deleteByTenantId(TenantId tenantId) {
deleteNotificationTemplatesByTenantId(tenantId);
}
@Override
public Optional<HasId<?>> findEntity(TenantId tenantId, EntityId entityId) {
return Optional.ofNullable(findNotificationTemplateById(tenantId, new NotificationTemplateId(entityId.getId())));

View File

@ -230,6 +230,11 @@ public class BaseOtaPackageService extends AbstractCachedEntityService<OtaPackag
tenantOtaPackageRemover.removeEntities(tenantId, tenantId);
}
@Override
public void deleteByTenantId(TenantId tenantId) {
deleteOtaPackagesByTenantId(tenantId);
}
private PaginatedRemover<TenantId, OtaPackageInfo> tenantOtaPackageRemover =
new PaginatedRemover<>() {

View File

@ -129,6 +129,11 @@ public class BaseQueueService extends AbstractEntityService implements QueueServ
tenantQueuesRemover.removeEntities(tenantId, tenantId);
}
@Override
public void deleteByTenantId(TenantId tenantId) {
deleteQueuesByTenantId(tenantId);
}
@Override
public Optional<HasId<?>> findEntity(TenantId tenantId, EntityId entityId) {
return Optional.ofNullable(findQueueById(tenantId, new QueueId(entityId.getId())));

View File

@ -203,6 +203,11 @@ public class BaseResourceService extends AbstractCachedEntityService<ResourceInf
tenantResourcesRemover.removeEntities(tenantId, tenantId);
}
@Override
public void deleteByTenantId(TenantId tenantId) {
deleteResourcesByTenantId(tenantId);
}
@Override
public Optional<HasId<?>> findEntity(TenantId tenantId, EntityId entityId) {
return Optional.ofNullable(findResourceInfoById(tenantId, new TbResourceId(entityId.getId())));

View File

@ -66,6 +66,11 @@ public class BaseRpcService implements RpcService {
tenantRpcRemover.removeEntities(tenantId, tenantId);
}
@Override
public void deleteByTenantId(TenantId tenantId) {
deleteAllRpcByTenantId(tenantId);
}
@Override
public Rpc findById(TenantId tenantId, RpcId rpcId) {
log.trace("Executing findById, tenantId [{}], rpcId [{}]", tenantId, rpcId);

View File

@ -443,6 +443,11 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
tenantRuleChainsRemover.removeEntities(tenantId, tenantId);
}
@Override
public void deleteByTenantId(TenantId tenantId) {
deleteRuleChainsByTenantId(tenantId);
}
@Override
public RuleChainData exportTenantRuleChains(TenantId tenantId, PageLink pageLink) {
Validator.validateId(tenantId, "Incorrect tenant id for search rule chain request.");

View File

@ -21,14 +21,20 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.AdminSettings;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.id.AdminSettingsId;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.HasId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.dao.entity.EntityDaoService;
import org.thingsboard.server.dao.service.DataValidator;
import org.thingsboard.server.dao.service.Validator;
import java.util.Optional;
@Service
@Slf4j
public class AdminSettingsServiceImpl implements AdminSettingsService {
public class AdminSettingsServiceImpl implements AdminSettingsService, EntityDaoService {
@Autowired
private AdminSettingsDao adminSettingsDao;
@ -105,4 +111,19 @@ public class AdminSettingsServiceImpl implements AdminSettingsService {
}
}
@Override
public void deleteByTenantId(TenantId tenantId) {
deleteAdminSettingsByTenantId(tenantId);
}
@Override
public Optional<HasId<?>> findEntity(TenantId tenantId, EntityId entityId) {
return Optional.empty();
}
@Override
public EntityType getEntityType() {
return EntityType.ADMIN_SETTINGS;
}
}

View File

@ -196,8 +196,8 @@ public class JpaAttributeDao extends JpaAbstractDaoListeningExecutorService impl
public List<Pair<String, String>> removeAllByEntityId(TenantId tenantId, EntityId entityId) {
return jdbcTemplate.queryForList("DELETE FROM attribute_kv WHERE entity_type = ? and entity_id = ? " +
"RETURNING attribute_type, attribute_key", entityId.getEntityType().name(), entityId.getId()).stream()
.map(deleted -> Pair.of((String) deleted.get(ModelConstants.ATTRIBUTE_TYPE_COLUMN),
(String) deleted.get(ModelConstants.ATTRIBUTE_KEY_COLUMN)))
.map(row -> Pair.of((String) row.get(ModelConstants.ATTRIBUTE_TYPE_COLUMN),
(String) row.get(ModelConstants.ATTRIBUTE_KEY_COLUMN)))
.collect(Collectors.toList());
}

View File

@ -19,6 +19,7 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.UserId;
import org.thingsboard.server.common.data.settings.UserSettings;
import org.thingsboard.server.common.data.settings.UserSettingsCompositeKey;
import org.thingsboard.server.dao.DaoUtil;
@ -50,4 +51,9 @@ public class JpaUserSettingsDao extends JpaAbstractDaoListeningExecutorService i
userSettingsRepository.deleteById(id);
}
@Override
public void removeByUserId(TenantId tenantId, UserId userId) {
userSettingsRepository.deleteByUserId(userId.getId());
}
}

View File

@ -16,9 +16,20 @@
package org.thingsboard.server.dao.sql.user;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.transaction.annotation.Transactional;
import org.thingsboard.server.common.data.settings.UserSettingsCompositeKey;
import org.thingsboard.server.dao.model.sql.UserSettingsEntity;
import java.util.UUID;
public interface UserSettingsRepository extends JpaRepository<UserSettingsEntity, UserSettingsCompositeKey> {
@Transactional
@Modifying
@Query("DELETE FROM UserSettingsEntity s WHERE s.userId = :userId")
void deleteByUserId(@Param("userId") UUID userId);
}

View File

@ -211,41 +211,26 @@ public class TenantServiceImpl extends AbstractCachedEntityService<TenantId, Ten
return savedTenant;
}
/**
* We intentionally leave this method without "Transactional" annotation due to complexity of the method.
* Ideally we should delete related entites without "paginatedRemover" logic. But in such a case we can't clear cache and send events.
* We will create separate task to make "deleteTenant" transactional.
*/
@Transactional
@Override
public void deleteTenant(TenantId tenantId) {
log.trace("Executing deleteTenant [{}]", tenantId);
Validator.validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
entityViewService.deleteEntityViewsByTenantId(tenantId);
widgetsBundleService.deleteWidgetsBundlesByTenantId(tenantId);
widgetTypeService.deleteWidgetTypesByTenantId(tenantId);
assetService.deleteAssetsByTenantId(tenantId);
assetProfileService.deleteAssetProfilesByTenantId(tenantId);
deviceService.deleteDevicesByTenantId(tenantId);
deviceProfileService.deleteDeviceProfilesByTenantId(tenantId);
dashboardService.deleteDashboardsByTenantId(tenantId);
customerService.deleteCustomersByTenantId(tenantId);
edgeService.deleteEdgesByTenantId(tenantId);
userService.deleteTenantAdmins(tenantId);
ruleChainService.deleteRuleChainsByTenantId(tenantId);
apiUsageStateService.deleteApiUsageStateByTenantId(tenantId);
resourceService.deleteResourcesByTenantId(tenantId);
otaPackageService.deleteOtaPackagesByTenantId(tenantId);
rpcService.deleteAllRpcByTenantId(tenantId);
queueService.deleteQueuesByTenantId(tenantId);
notificationRequestService.deleteNotificationRequestsByTenantId(tenantId);
notificationRuleService.deleteNotificationRulesByTenantId(tenantId);
notificationTemplateService.deleteNotificationTemplatesByTenantId(tenantId);
notificationTargetService.deleteNotificationTargetsByTenantId(tenantId);
adminSettingsService.deleteAdminSettingsByTenantId(tenantId);
userService.deleteByTenantId(tenantId);
tenantDao.removeById(tenantId, tenantId.getId());
cleanUpService.removeTenantEntities(tenantId, // don't forget to implement deleteByTenantId from EntityDaoService when adding entity type to this list
EntityType.ENTITY_VIEW, EntityType.WIDGETS_BUNDLE, EntityType.WIDGET_TYPE,
EntityType.ASSET, EntityType.ASSET_PROFILE, EntityType.DEVICE, EntityType.DEVICE_PROFILE,
EntityType.DASHBOARD, EntityType.CUSTOMER, EntityType.EDGE, EntityType.RULE_CHAIN,
EntityType.API_USAGE_STATE, EntityType.TB_RESOURCE, EntityType.OTA_PACKAGE, EntityType.RPC,
EntityType.QUEUE, EntityType.NOTIFICATION_REQUEST, EntityType.NOTIFICATION_RULE,
EntityType.NOTIFICATION_TEMPLATE, EntityType.NOTIFICATION_TARGET, EntityType.ADMIN_SETTINGS
);
publishEvictEvent(new TenantEvictEvent(tenantId, true));
eventPublisher.publishEvent(DeleteEntityEvent.builder().tenantId(tenantId).entityId(tenantId).build());
alarmService.deleteEntityAlarmRecordsByTenantId(tenantId);
}
@Override

View File

@ -172,6 +172,11 @@ public class ApiUsageStateServiceImpl extends AbstractEntityService implements A
return Optional.ofNullable(findApiUsageStateById(tenantId, new ApiUsageStateId(entityId.getId())));
}
@Override
public void deleteByTenantId(TenantId tenantId) {
deleteApiUsageStateByTenantId(tenantId);
}
@Override
public EntityType getEntityType() {
return EntityType.API_USAGE_STATE;

View File

@ -85,6 +85,7 @@ public class UserServiceImpl extends AbstractEntityService implements UserServic
private final UserDao userDao;
private final UserCredentialsDao userCredentialsDao;
private final UserAuthSettingsDao userAuthSettingsDao;
private final UserSettingsDao userSettingsDao;
private final DataValidator<User> userValidator;
private final DataValidator<UserCredentials> userCredentialsValidator;
private final ApplicationEventPublisher eventPublisher;
@ -255,6 +256,7 @@ public class UserServiceImpl extends AbstractEntityService implements UserServic
validateId(userId, INCORRECT_USER_ID + userId);
userCredentialsDao.removeByUserId(tenantId, userId);
userAuthSettingsDao.removeByUserId(userId);
userSettingsDao.removeByUserId(tenantId, userId);
userDao.removeById(tenantId, userId.getId());
eventPublisher.publishEvent(new UserCredentialsInvalidationEvent(userId));
@ -313,6 +315,12 @@ public class UserServiceImpl extends AbstractEntityService implements UserServic
tenantAdminsRemover.removeEntities(tenantId, tenantId);
}
@Override
public void deleteByTenantId(TenantId tenantId) {
log.trace("Executing deleteByTenantId, tenantId [{}]", tenantId);
usersRemover.removeEntities(tenantId, tenantId);
}
@Override
public PageData<User> findCustomerUsers(TenantId tenantId, CustomerId customerId, PageLink pageLink) {
log.trace("Executing findCustomerUsers, tenantId [{}], customerId [{}], pageLink [{}]", tenantId, customerId, pageLink);
@ -464,6 +472,18 @@ public class UserServiceImpl extends AbstractEntityService implements UserServic
}
};
private final PaginatedRemover<TenantId, User> usersRemover = new PaginatedRemover<>() {
@Override
protected PageData<User> findEntities(TenantId tenantId, TenantId id, PageLink pageLink) {
return findUsersByTenantId(tenantId, pageLink);
}
@Override
protected void removeEntity(TenantId tenantId, User user) {
deleteUser(tenantId, user);
}
};
@Override
public Optional<HasId<?>> findEntity(TenantId tenantId, EntityId entityId) {
return Optional.ofNullable(findUserById(tenantId, new UserId(entityId.getId())));

View File

@ -16,6 +16,7 @@
package org.thingsboard.server.dao.user;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.UserId;
import org.thingsboard.server.common.data.settings.UserSettings;
import org.thingsboard.server.common.data.settings.UserSettingsCompositeKey;
@ -27,4 +28,6 @@ public interface UserSettingsDao {
void removeById(TenantId tenantId, UserSettingsCompositeKey key);
void removeByUserId(TenantId tenantId, UserId userId);
}

View File

@ -226,6 +226,11 @@ public class WidgetTypeServiceImpl implements WidgetTypeService {
tenantWidgetTypeRemover.removeEntities(tenantId, tenantId);
}
@Override
public void deleteByTenantId(TenantId tenantId) {
deleteWidgetTypesByTenantId(tenantId);
}
@Override
public Optional<HasId<?>> findEntity(TenantId tenantId, EntityId entityId) {
return Optional.ofNullable(findWidgetTypeById(tenantId, new WidgetTypeId(entityId.getId())));

View File

@ -179,6 +179,11 @@ public class WidgetsBundleServiceImpl implements WidgetsBundleService {
tenantWidgetsBundleRemover.removeEntities(tenantId, tenantId);
}
@Override
public void deleteByTenantId(TenantId tenantId) {
deleteWidgetsBundlesByTenantId(tenantId);
}
@Override
public Optional<HasId<?>> findEntity(TenantId tenantId, EntityId entityId) {
return Optional.ofNullable(findWidgetsBundleById(tenantId, new WidgetsBundleId(entityId.getId())));