6 changed files with 239 additions and 168 deletions
@ -0,0 +1,206 @@ |
|||||
|
/** |
||||
|
* 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.exporting; |
||||
|
|
||||
|
import lombok.RequiredArgsConstructor; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||
|
import org.springframework.dao.DataAccessException; |
||||
|
import org.springframework.stereotype.Service; |
||||
|
import org.thingsboard.server.common.data.EntityType; |
||||
|
import org.thingsboard.server.common.data.ExportableEntity; |
||||
|
import org.thingsboard.server.common.data.HasTenantId; |
||||
|
import org.thingsboard.server.common.data.exception.ThingsboardException; |
||||
|
import org.thingsboard.server.common.data.id.CustomerId; |
||||
|
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.common.data.query.EntityData; |
||||
|
import org.thingsboard.server.common.data.query.EntityDataPageLink; |
||||
|
import org.thingsboard.server.common.data.query.EntityDataQuery; |
||||
|
import org.thingsboard.server.common.data.query.EntityDataSortOrder; |
||||
|
import org.thingsboard.server.common.data.query.EntityFilter; |
||||
|
import org.thingsboard.server.common.data.query.EntityKey; |
||||
|
import org.thingsboard.server.common.data.query.EntityKeyType; |
||||
|
import org.thingsboard.server.common.data.query.EntityTypeFilter; |
||||
|
import org.thingsboard.server.dao.Dao; |
||||
|
import org.thingsboard.server.dao.ExportableEntityDao; |
||||
|
import org.thingsboard.server.dao.entity.EntityService; |
||||
|
import org.thingsboard.server.queue.util.TbCoreComponent; |
||||
|
import org.thingsboard.server.service.security.model.SecurityUser; |
||||
|
import org.thingsboard.server.service.security.permission.AccessControlService; |
||||
|
import org.thingsboard.server.service.security.permission.Operation; |
||||
|
import org.thingsboard.server.service.security.permission.Resource; |
||||
|
import org.thingsboard.server.service.sync.exporting.data.request.CustomEntityFilterExportRequest; |
||||
|
import org.thingsboard.server.service.sync.exporting.data.request.CustomEntityQueryExportRequest; |
||||
|
import org.thingsboard.server.service.sync.exporting.data.request.EntityListExportRequest; |
||||
|
import org.thingsboard.server.service.sync.exporting.data.request.EntityTypeExportRequest; |
||||
|
import org.thingsboard.server.service.sync.exporting.data.request.ExportRequest; |
||||
|
import org.thingsboard.server.service.sync.exporting.data.request.SingleEntityExportRequest; |
||||
|
|
||||
|
import java.util.Collection; |
||||
|
import java.util.Collections; |
||||
|
import java.util.HashMap; |
||||
|
import java.util.List; |
||||
|
import java.util.Map; |
||||
|
import java.util.Optional; |
||||
|
import java.util.stream.Collectors; |
||||
|
|
||||
|
import static org.thingsboard.server.dao.sql.query.EntityKeyMapping.CREATED_TIME; |
||||
|
|
||||
|
@Service |
||||
|
@TbCoreComponent |
||||
|
@RequiredArgsConstructor |
||||
|
@Slf4j |
||||
|
public class DefaultExportableEntitiesService implements ExportableEntitiesService { |
||||
|
|
||||
|
private final Map<EntityType, Dao<?>> daos = new HashMap<>(); |
||||
|
|
||||
|
private final EntityService entityService; |
||||
|
private final AccessControlService accessControlService; |
||||
|
|
||||
|
|
||||
|
@Override |
||||
|
public <E extends ExportableEntity<I>, I extends EntityId> E findEntityByTenantIdAndExternalId(TenantId tenantId, I externalId) { |
||||
|
EntityType entityType = externalId.getEntityType(); |
||||
|
Dao<E> dao = getDao(entityType); |
||||
|
|
||||
|
if (dao instanceof ExportableEntityDao) { |
||||
|
ExportableEntityDao<E> exportableEntityDao = (ExportableEntityDao<E>) dao; |
||||
|
return exportableEntityDao.findByTenantIdAndExternalId(tenantId.getId(), externalId.getId()); |
||||
|
} else { |
||||
|
return null; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public <E extends HasId<I>, I extends EntityId> E findEntityByTenantIdAndId(TenantId tenantId, I id) { |
||||
|
EntityType entityType = id.getEntityType(); |
||||
|
Dao<E> dao = getDao(entityType); |
||||
|
|
||||
|
E entity = dao.findById(tenantId, id.getId()); |
||||
|
if (((HasTenantId) entity).getTenantId().equals(tenantId)) { |
||||
|
return entity; |
||||
|
} |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public <E extends ExportableEntity<I>, I extends EntityId> E findEntityByTenantIdAndName(TenantId tenantId, EntityType entityType, String name) { |
||||
|
Dao<E> dao = getDao(entityType); |
||||
|
|
||||
|
if (dao instanceof ExportableEntityDao) { |
||||
|
ExportableEntityDao<E> exportableEntityDao = (ExportableEntityDao<E>) dao; |
||||
|
try { |
||||
|
return exportableEntityDao.findByTenantIdAndName(tenantId.getId(), name); |
||||
|
} catch (UnsupportedOperationException ignored) { |
||||
|
} |
||||
|
} |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
@Override |
||||
|
public List<EntityId> findEntitiesForRequest(TenantId tenantId, ExportRequest request) { |
||||
|
switch (request.getType()) { |
||||
|
case SINGLE_ENTITY: { |
||||
|
return List.of(((SingleEntityExportRequest) request).getEntityId()); |
||||
|
} |
||||
|
case ENTITY_LIST: { |
||||
|
return ((EntityListExportRequest) request).getEntitiesIds(); |
||||
|
} |
||||
|
case ENTITY_TYPE: { |
||||
|
EntityTypeExportRequest exportRequest = (EntityTypeExportRequest) request; |
||||
|
EntityTypeFilter entityTypeFilter = new EntityTypeFilter(); |
||||
|
entityTypeFilter.setEntityType(exportRequest.getEntityType()); |
||||
|
|
||||
|
CustomerId customerId = Optional.ofNullable(exportRequest.getCustomerId()).orElse(new CustomerId(EntityId.NULL_UUID)); |
||||
|
return findEntitiesByFilter(tenantId, customerId, entityTypeFilter, exportRequest.getPage(), exportRequest.getPageSize()); |
||||
|
} |
||||
|
case CUSTOM_ENTITY_FILTER: { |
||||
|
CustomEntityFilterExportRequest exportRequest = (CustomEntityFilterExportRequest) request; |
||||
|
EntityFilter filter = exportRequest.getFilter(); |
||||
|
|
||||
|
CustomerId customerId = Optional.ofNullable(exportRequest.getCustomerId()).orElse(new CustomerId(EntityId.NULL_UUID)); |
||||
|
return findEntitiesByFilter(tenantId, customerId, filter, exportRequest.getPage(), exportRequest.getPageSize()); |
||||
|
} |
||||
|
case CUSTOM_ENTITY_QUERY: { |
||||
|
CustomEntityQueryExportRequest exportRequest = (CustomEntityQueryExportRequest) request; |
||||
|
EntityDataQuery query = exportRequest.getQuery(); |
||||
|
|
||||
|
CustomerId customerId = Optional.ofNullable(exportRequest.getCustomerId()).orElse(new CustomerId(EntityId.NULL_UUID)); |
||||
|
return findEntitiesByQuery(tenantId, customerId, query); |
||||
|
} |
||||
|
default: { |
||||
|
throw new IllegalArgumentException("Export request is not supported"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private List<EntityId> findEntitiesByFilter(TenantId tenantId, CustomerId customerId, EntityFilter filter, int page, int pageSize) { |
||||
|
EntityDataPageLink pageLink = new EntityDataPageLink(); |
||||
|
pageLink.setPage(page); |
||||
|
pageLink.setPageSize(pageSize); |
||||
|
EntityKey sortProperty = new EntityKey(EntityKeyType.ENTITY_FIELD, CREATED_TIME); |
||||
|
pageLink.setSortOrder(new EntityDataSortOrder(sortProperty, EntityDataSortOrder.Direction.DESC)); |
||||
|
|
||||
|
EntityDataQuery query = new EntityDataQuery(filter, pageLink, List.of(sortProperty), Collections.emptyList(), Collections.emptyList()); |
||||
|
return findEntitiesByQuery(tenantId, customerId, query); |
||||
|
} |
||||
|
|
||||
|
private List<EntityId> findEntitiesByQuery(TenantId tenantId, CustomerId customerId, EntityDataQuery query) { |
||||
|
try { |
||||
|
return entityService.findEntityDataByQuery(tenantId, customerId, query).getData().stream() |
||||
|
.map(EntityData::getEntityId) |
||||
|
.collect(Collectors.toList()); |
||||
|
} catch (DataAccessException e) { |
||||
|
log.error("Failed to find entity data by query: {}", e.getMessage()); |
||||
|
throw new IllegalArgumentException("Entity filter cannot be processed"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
@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); |
||||
|
} |
||||
|
|
||||
|
@Autowired |
||||
|
private void setDaos(Collection<Dao<?>> daos) { |
||||
|
daos.forEach(dao -> { |
||||
|
if (dao.getEntityType() != null) { |
||||
|
this.daos.put(dao.getEntityType(), dao); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
} |
||||
Loading…
Reference in new issue