Revert "[3.3.3] Entities search within all tenants"
This commit is contained in:
		
							parent
							
								
									8e0eab37a8
								
							
						
					
					
						commit
						676a60e804
					
				@ -17,10 +17,9 @@ package org.thingsboard.server.controller;
 | 
			
		||||
 | 
			
		||||
import io.swagger.annotations.ApiOperation;
 | 
			
		||||
import io.swagger.annotations.ApiParam;
 | 
			
		||||
import lombok.RequiredArgsConstructor;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.http.ResponseEntity;
 | 
			
		||||
import org.springframework.security.access.prepost.PreAuthorize;
 | 
			
		||||
import org.springframework.web.bind.annotation.PostMapping;
 | 
			
		||||
import org.springframework.web.bind.annotation.RequestBody;
 | 
			
		||||
import org.springframework.web.bind.annotation.RequestMapping;
 | 
			
		||||
import org.springframework.web.bind.annotation.RequestMethod;
 | 
			
		||||
@ -37,30 +36,20 @@ import org.thingsboard.server.common.data.query.EntityCountQuery;
 | 
			
		||||
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.data.search.EntitiesSearchRequest;
 | 
			
		||||
import org.thingsboard.server.data.search.EntitySearchResult;
 | 
			
		||||
import org.thingsboard.server.queue.util.TbCoreComponent;
 | 
			
		||||
import org.thingsboard.server.service.query.EntitiesSearchService;
 | 
			
		||||
import org.thingsboard.server.service.query.EntityQueryService;
 | 
			
		||||
 | 
			
		||||
import static org.thingsboard.server.controller.ControllerConstants.ALARM_DATA_QUERY_DESCRIPTION;
 | 
			
		||||
import static org.thingsboard.server.controller.ControllerConstants.ENTITY_COUNT_QUERY_DESCRIPTION;
 | 
			
		||||
import static org.thingsboard.server.controller.ControllerConstants.ENTITY_DATA_QUERY_DESCRIPTION;
 | 
			
		||||
import static org.thingsboard.server.controller.ControllerConstants.NEW_LINE;
 | 
			
		||||
import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION;
 | 
			
		||||
import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION;
 | 
			
		||||
import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_ALLOWABLE_VALUES;
 | 
			
		||||
import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION;
 | 
			
		||||
import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION;
 | 
			
		||||
 | 
			
		||||
@RestController
 | 
			
		||||
@TbCoreComponent
 | 
			
		||||
@RequestMapping("/api")
 | 
			
		||||
@RequiredArgsConstructor
 | 
			
		||||
public class EntityQueryController extends BaseController {
 | 
			
		||||
 | 
			
		||||
    private final EntityQueryService entityQueryService;
 | 
			
		||||
    private final EntitiesSearchService entitiesSearchService;
 | 
			
		||||
    @Autowired
 | 
			
		||||
    private EntityQueryService entityQueryService;
 | 
			
		||||
 | 
			
		||||
    private static final int MAX_PAGE_SIZE = 100;
 | 
			
		||||
 | 
			
		||||
@ -134,70 +123,4 @@ public class EntityQueryController extends BaseController {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiOperation(value = "Search entities (searchEntities)", notes = "Search entities with specified entity type by id or name within the whole platform. " +
 | 
			
		||||
            "Searchable entity types are: CUSTOMER, USER, DEVICE, DEVICE_PROFILE, ASSET, ENTITY_VIEW, DASHBOARD, " +
 | 
			
		||||
            "RULE_CHAIN, EDGE, OTA_PACKAGE, TB_RESOURCE, WIDGETS_BUNDLE, TENANT, TENANT_PROFILE." + NEW_LINE +
 | 
			
		||||
            "The platform will search for entities, where a name contains the search text (case-insensitively), " +
 | 
			
		||||
            "or if the search query is a valid UUID (e.g. 128e4d40-26b3-11ec-aaeb-c7661c54701e) then " +
 | 
			
		||||
            "it will also search for an entity where id fully matches the query. If search query is empty " +
 | 
			
		||||
            "then all entities will be returned (according to page number, page size and sorting)." + NEW_LINE +
 | 
			
		||||
            "The returned result is a page of EntitySearchResult, which contains: " +
 | 
			
		||||
            "entity id, entity fields represented as strings, tenant info and owner info. " +
 | 
			
		||||
            "Returned entity fields are: name, type (will be present for USER, DEVICE, ASSET, ENTITY_VIEW, RULE_CHAIN, " +
 | 
			
		||||
            "EDGE, OTA_PACKAGE, TB_RESOURCE entity types; in case of USER - the type is its authority), " +
 | 
			
		||||
            "createdTime and lastActivityTime (will only be present for DEVICE and USER; for USER it is its last login time). " +
 | 
			
		||||
            "Tenant info contains tenant's id and title; owner info contains the same info for an entity's owner " +
 | 
			
		||||
            "(its customer, or if it is not a customer's entity - tenant)." + NEW_LINE +
 | 
			
		||||
            "Example response value:\n" +
 | 
			
		||||
            "{\n" +
 | 
			
		||||
            "    \"data\": [\n" +
 | 
			
		||||
            "        {\n" +
 | 
			
		||||
            "            \"entityId\": {\n" +
 | 
			
		||||
            "                \"entityType\": \"DEVICE\",\n" +
 | 
			
		||||
            "                \"id\": \"48be0670-25c9-11ec-a618-8165eb6b112a\"\n" +
 | 
			
		||||
            "            },\n" +
 | 
			
		||||
            "            \"fields\": {\n" +
 | 
			
		||||
            "                \"name\": \"Thermostat T1\",\n" +
 | 
			
		||||
            "                \"createdTime\": \"1633430698071\",\n" +
 | 
			
		||||
            "                \"lastActivityTime\": \"1635761085285\",\n" +
 | 
			
		||||
            "                \"type\": \"thermostat\"\n" +
 | 
			
		||||
            "            },\n" +
 | 
			
		||||
            "            \"tenantInfo\": {\n" +
 | 
			
		||||
            "                \"id\": {\n" +
 | 
			
		||||
            "                    \"entityType\": \"TENANT\",\n" +
 | 
			
		||||
            "                    \"id\": \"2ddd6120-25c9-11ec-a618-8165eb6b112a\"\n" +
 | 
			
		||||
            "                },\n" +
 | 
			
		||||
            "                \"name\": \"Tenant\"\n" +
 | 
			
		||||
            "            },\n" +
 | 
			
		||||
            "            \"ownerInfo\": {\n" +
 | 
			
		||||
            "                \"id\": {\n" +
 | 
			
		||||
            "                    \"entityType\": \"CUSTOMER\",\n" +
 | 
			
		||||
            "                    \"id\": \"26cba800-eee3-11eb-9e2c-fb031bd4619c\"\n" +
 | 
			
		||||
            "                },\n" +
 | 
			
		||||
            "                \"name\": \"Customer A\"\n" +
 | 
			
		||||
            "            }\n" +
 | 
			
		||||
            "        }\n" +
 | 
			
		||||
            "    ],\n" +
 | 
			
		||||
            "    \"totalPages\": 1,\n" +
 | 
			
		||||
            "    \"totalElements\": 1,\n" +
 | 
			
		||||
            "    \"hasNext\": false\n" +
 | 
			
		||||
            "}")
 | 
			
		||||
    @PostMapping("/entities/search")
 | 
			
		||||
    @PreAuthorize("hasAnyAuthority('SYS_ADMIN')")
 | 
			
		||||
    public PageData<EntitySearchResult> searchEntities(@RequestBody EntitiesSearchRequest request,
 | 
			
		||||
                                                       @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true)
 | 
			
		||||
                                                       @RequestParam int page,
 | 
			
		||||
                                                       @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true)
 | 
			
		||||
                                                       @RequestParam int pageSize,
 | 
			
		||||
                                                       @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = "name, type, createdTime, lastActivityTime, createdTime, tenantId, customerId", required = false)
 | 
			
		||||
                                                       @RequestParam(required = false) String sortProperty,
 | 
			
		||||
                                                       @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES, required = false)
 | 
			
		||||
                                                       @RequestParam(required = false) String sortOrder) throws ThingsboardException {
 | 
			
		||||
        try {
 | 
			
		||||
            return entitiesSearchService.searchEntities(getCurrentUser(), request, createPageLink(pageSize, page, null, sortProperty, sortOrder));
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            throw handleException(e);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,25 +0,0 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright © 2016-2021 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.data.search;
 | 
			
		||||
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import org.thingsboard.server.common.data.EntityType;
 | 
			
		||||
 | 
			
		||||
@Data
 | 
			
		||||
public class EntitiesSearchRequest {
 | 
			
		||||
    private EntityType entityType;
 | 
			
		||||
    private String searchQuery;
 | 
			
		||||
}
 | 
			
		||||
@ -1,50 +0,0 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright © 2016-2021 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.data.search;
 | 
			
		||||
 | 
			
		||||
import lombok.AllArgsConstructor;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import lombok.NoArgsConstructor;
 | 
			
		||||
import org.thingsboard.server.common.data.id.EntityId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.TenantId;
 | 
			
		||||
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
@Data
 | 
			
		||||
public class EntitySearchResult {
 | 
			
		||||
    private EntityId entityId;
 | 
			
		||||
    private Map<String, String> fields;
 | 
			
		||||
 | 
			
		||||
    private EntityTenantInfo tenantInfo;
 | 
			
		||||
    private EntityOwnerInfo ownerInfo;
 | 
			
		||||
 | 
			
		||||
    @Data
 | 
			
		||||
    @AllArgsConstructor
 | 
			
		||||
    @NoArgsConstructor
 | 
			
		||||
    public static final class EntityTenantInfo {
 | 
			
		||||
        private TenantId id;
 | 
			
		||||
        private String name;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Data
 | 
			
		||||
    @AllArgsConstructor
 | 
			
		||||
    @NoArgsConstructor
 | 
			
		||||
    public static final class EntityOwnerInfo {
 | 
			
		||||
        private EntityId id;
 | 
			
		||||
        private String name;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -1,26 +0,0 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright © 2016-2021 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.query;
 | 
			
		||||
 | 
			
		||||
import org.thingsboard.server.common.data.page.PageData;
 | 
			
		||||
import org.thingsboard.server.common.data.page.PageLink;
 | 
			
		||||
import org.thingsboard.server.data.search.EntitiesSearchRequest;
 | 
			
		||||
import org.thingsboard.server.data.search.EntitySearchResult;
 | 
			
		||||
import org.thingsboard.server.service.security.model.SecurityUser;
 | 
			
		||||
 | 
			
		||||
public interface EntitiesSearchService {
 | 
			
		||||
    PageData<EntitySearchResult> searchEntities(SecurityUser user, EntitiesSearchRequest request, PageLink pageLink);
 | 
			
		||||
}
 | 
			
		||||
@ -1,208 +0,0 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright © 2016-2021 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.query;
 | 
			
		||||
 | 
			
		||||
import com.google.common.base.Strings;
 | 
			
		||||
import lombok.RequiredArgsConstructor;
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import org.apache.commons.lang3.StringUtils;
 | 
			
		||||
import org.springframework.stereotype.Service;
 | 
			
		||||
import org.thingsboard.server.common.data.ContactBased;
 | 
			
		||||
import org.thingsboard.server.common.data.Customer;
 | 
			
		||||
import org.thingsboard.server.common.data.EntityType;
 | 
			
		||||
import org.thingsboard.server.common.data.Tenant;
 | 
			
		||||
import org.thingsboard.server.common.data.id.CustomerId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.EntityId;
 | 
			
		||||
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.page.SortOrder;
 | 
			
		||||
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.EntityKey;
 | 
			
		||||
import org.thingsboard.server.common.data.query.EntityKeyType;
 | 
			
		||||
import org.thingsboard.server.common.data.query.EntityNameOrIdFilter;
 | 
			
		||||
import org.thingsboard.server.dao.customer.CustomerService;
 | 
			
		||||
import org.thingsboard.server.dao.tenant.TenantService;
 | 
			
		||||
import org.thingsboard.server.data.search.EntitiesSearchRequest;
 | 
			
		||||
import org.thingsboard.server.data.search.EntitySearchResult;
 | 
			
		||||
import org.thingsboard.server.queue.util.TbCoreComponent;
 | 
			
		||||
import org.thingsboard.server.service.security.model.SecurityUser;
 | 
			
		||||
import org.thingsboard.server.service.state.DefaultDeviceStateService;
 | 
			
		||||
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
import java.util.EnumSet;
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.Optional;
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
import java.util.UUID;
 | 
			
		||||
import java.util.stream.Collectors;
 | 
			
		||||
import java.util.stream.Stream;
 | 
			
		||||
 | 
			
		||||
import static org.thingsboard.server.common.data.EntityType.ASSET;
 | 
			
		||||
import static org.thingsboard.server.common.data.EntityType.CUSTOMER;
 | 
			
		||||
import static org.thingsboard.server.common.data.EntityType.DASHBOARD;
 | 
			
		||||
import static org.thingsboard.server.common.data.EntityType.DEVICE;
 | 
			
		||||
import static org.thingsboard.server.common.data.EntityType.DEVICE_PROFILE;
 | 
			
		||||
import static org.thingsboard.server.common.data.EntityType.EDGE;
 | 
			
		||||
import static org.thingsboard.server.common.data.EntityType.ENTITY_VIEW;
 | 
			
		||||
import static org.thingsboard.server.common.data.EntityType.OTA_PACKAGE;
 | 
			
		||||
import static org.thingsboard.server.common.data.EntityType.RULE_CHAIN;
 | 
			
		||||
import static org.thingsboard.server.common.data.EntityType.TB_RESOURCE;
 | 
			
		||||
import static org.thingsboard.server.common.data.EntityType.TENANT;
 | 
			
		||||
import static org.thingsboard.server.common.data.EntityType.TENANT_PROFILE;
 | 
			
		||||
import static org.thingsboard.server.common.data.EntityType.USER;
 | 
			
		||||
import static org.thingsboard.server.common.data.EntityType.WIDGETS_BUNDLE;
 | 
			
		||||
import static org.thingsboard.server.dao.sql.query.EntityKeyMapping.CREATED_TIME;
 | 
			
		||||
import static org.thingsboard.server.dao.sql.query.EntityKeyMapping.CUSTOMER_ID;
 | 
			
		||||
import static org.thingsboard.server.dao.sql.query.EntityKeyMapping.LAST_ACTIVITY_TIME;
 | 
			
		||||
import static org.thingsboard.server.dao.sql.query.EntityKeyMapping.NAME;
 | 
			
		||||
import static org.thingsboard.server.dao.sql.query.EntityKeyMapping.TENANT_ID;
 | 
			
		||||
import static org.thingsboard.server.dao.sql.query.EntityKeyMapping.TYPE;
 | 
			
		||||
 | 
			
		||||
@Service
 | 
			
		||||
@TbCoreComponent
 | 
			
		||||
@RequiredArgsConstructor
 | 
			
		||||
@Slf4j
 | 
			
		||||
public class EntitiesSearchServiceImpl implements EntitiesSearchService {
 | 
			
		||||
    private final EntityQueryService entityQueryService;
 | 
			
		||||
 | 
			
		||||
    private final TenantService tenantService;
 | 
			
		||||
    private final CustomerService customerService;
 | 
			
		||||
    private final DefaultDeviceStateService deviceStateService;
 | 
			
		||||
 | 
			
		||||
    private static final List<EntityKey> entityResponseFields = Stream.of(CREATED_TIME, NAME, TYPE, TENANT_ID, CUSTOMER_ID)
 | 
			
		||||
            .map(field -> new EntityKey(EntityKeyType.ENTITY_FIELD, field))
 | 
			
		||||
            .collect(Collectors.toList());
 | 
			
		||||
 | 
			
		||||
    private static final Set<EntityType> searchableEntityTypes = EnumSet.of(
 | 
			
		||||
            TENANT, CUSTOMER, USER, DASHBOARD, ASSET, DEVICE, RULE_CHAIN, ENTITY_VIEW,
 | 
			
		||||
            WIDGETS_BUNDLE, TENANT_PROFILE, DEVICE_PROFILE, TB_RESOURCE, OTA_PACKAGE, EDGE
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public PageData<EntitySearchResult> searchEntities(SecurityUser user, EntitiesSearchRequest request, PageLink pageLink) {
 | 
			
		||||
        EntityType entityType = request.getEntityType();
 | 
			
		||||
        if (!searchableEntityTypes.contains(entityType)) {
 | 
			
		||||
            return new PageData<>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        EntityDataQuery query = createSearchQuery(request.getSearchQuery(), entityType, pageLink);
 | 
			
		||||
        PageData<EntityData> resultPage = entityQueryService.findEntityDataByQuery(user, query);
 | 
			
		||||
 | 
			
		||||
        Map<EntityId, ContactBased<? extends EntityId>> localOwnersCache = new HashMap<>();
 | 
			
		||||
        return resultPage.mapData(entityData -> {
 | 
			
		||||
            Map<String, String> fields = new HashMap<>();
 | 
			
		||||
            entityData.getLatest().values().stream()
 | 
			
		||||
                    .flatMap(values -> values.entrySet().stream())
 | 
			
		||||
                    .forEach(entry -> fields.put(entry.getKey(), Strings.emptyToNull(entry.getValue().getValue())));
 | 
			
		||||
 | 
			
		||||
            EntitySearchResult entitySearchResult = new EntitySearchResult();
 | 
			
		||||
 | 
			
		||||
            entitySearchResult.setEntityId(entityData.getEntityId());
 | 
			
		||||
            entitySearchResult.setFields(fields);
 | 
			
		||||
            setOwnerInfo(entitySearchResult, localOwnersCache);
 | 
			
		||||
 | 
			
		||||
            return entitySearchResult;
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private EntityDataQuery createSearchQuery(String searchQuery, EntityType entityType, PageLink pageLink) {
 | 
			
		||||
        EntityDataPageLink entityDataPageLink = new EntityDataPageLink();
 | 
			
		||||
        entityDataPageLink.setPageSize(pageLink.getPageSize());
 | 
			
		||||
        entityDataPageLink.setPage(pageLink.getPage());
 | 
			
		||||
        if (pageLink.getSortOrder() != null && StringUtils.isNotEmpty(pageLink.getSortOrder().getProperty())) {
 | 
			
		||||
            entityDataPageLink.setSortOrder(new EntityDataSortOrder(new EntityKey(EntityKeyType.ENTITY_FIELD, pageLink.getSortOrder().getProperty()),
 | 
			
		||||
                    EntityDataSortOrder.Direction.valueOf(Optional.ofNullable(pageLink.getSortOrder().getDirection()).orElse(SortOrder.Direction.ASC).name())));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        EntityNameOrIdFilter filter = new EntityNameOrIdFilter();
 | 
			
		||||
        filter.setEntityType(entityType);
 | 
			
		||||
        filter.setNameOrId(searchQuery);
 | 
			
		||||
 | 
			
		||||
        List<EntityKey> entityFields = entityResponseFields;
 | 
			
		||||
        List<EntityKey> latestValues = Collections.emptyList();
 | 
			
		||||
 | 
			
		||||
        if (entityType == USER) {
 | 
			
		||||
            entityFields = new ArrayList<>(entityFields);
 | 
			
		||||
            entityFields.add(new EntityKey(EntityKeyType.ENTITY_FIELD, LAST_ACTIVITY_TIME));
 | 
			
		||||
        } else if (entityType == DEVICE) {
 | 
			
		||||
            EntityKey lastActivityTimeKey;
 | 
			
		||||
            if (deviceStateService.isPersistToTelemetry()) {
 | 
			
		||||
                lastActivityTimeKey = new EntityKey(EntityKeyType.TIME_SERIES, LAST_ACTIVITY_TIME);
 | 
			
		||||
            } else {
 | 
			
		||||
                lastActivityTimeKey = new EntityKey(EntityKeyType.SERVER_ATTRIBUTE, LAST_ACTIVITY_TIME);
 | 
			
		||||
            }
 | 
			
		||||
            latestValues = List.of(lastActivityTimeKey);
 | 
			
		||||
            if (entityDataPageLink.getSortOrder() != null && entityDataPageLink.getSortOrder().getKey().getKey().equals(LAST_ACTIVITY_TIME)) {
 | 
			
		||||
                entityDataPageLink.getSortOrder().setKey(lastActivityTimeKey);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return new EntityDataQuery(filter, entityDataPageLink, entityFields, latestValues, Collections.emptyList());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void setOwnerInfo(EntitySearchResult entitySearchResult, Map<EntityId, ContactBased<? extends EntityId>> localOwnersCache) {
 | 
			
		||||
        Map<String, String> fields = entitySearchResult.getFields();
 | 
			
		||||
 | 
			
		||||
        UUID tenantUuid = toUuid(fields.remove(TENANT_ID));
 | 
			
		||||
        UUID customerUuid = toUuid(fields.remove(CUSTOMER_ID));
 | 
			
		||||
 | 
			
		||||
        Tenant tenant = null;
 | 
			
		||||
        if (tenantUuid != null) {
 | 
			
		||||
            tenant = getTenant(new TenantId(tenantUuid), localOwnersCache);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ContactBased<? extends EntityId> owner;
 | 
			
		||||
        if (customerUuid != null) {
 | 
			
		||||
            owner = getCustomer(new CustomerId(customerUuid), localOwnersCache);
 | 
			
		||||
        } else {
 | 
			
		||||
            owner = tenant;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (tenant != null) {
 | 
			
		||||
            entitySearchResult.setTenantInfo(new EntitySearchResult.EntityTenantInfo(tenant.getId(), tenant.getName()));
 | 
			
		||||
        }
 | 
			
		||||
        if (owner != null) {
 | 
			
		||||
            entitySearchResult.setOwnerInfo(new EntitySearchResult.EntityOwnerInfo(owner.getId(), owner.getName()));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private Tenant getTenant(TenantId tenantId, Map<EntityId, ContactBased<? extends EntityId>> localOwnersCache) {
 | 
			
		||||
        return (Tenant) localOwnersCache.computeIfAbsent(tenantId, id -> tenantService.findTenantById(tenantId));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private Customer getCustomer(CustomerId customerId, Map<EntityId, ContactBased<? extends EntityId>> localOwnersCache) {
 | 
			
		||||
        return (Customer) localOwnersCache.computeIfAbsent(customerId, id -> customerService.findCustomerById(TenantId.SYS_TENANT_ID, customerId));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private UUID toUuid(String uuid) {
 | 
			
		||||
        try {
 | 
			
		||||
            UUID id = UUID.fromString(uuid);
 | 
			
		||||
            if (!id.equals(EntityId.NULL_UUID)) {
 | 
			
		||||
                return id;
 | 
			
		||||
            }
 | 
			
		||||
        } catch (Exception ignored) {}
 | 
			
		||||
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -69,6 +69,5 @@ public interface PermissionChecker<I extends EntityId, T extends HasTenantId> {
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    PermissionChecker allowReadPermissionChecker = new GenericPermissionChecker(Operation.READ, Operation.READ_TELEMETRY, Operation.READ_ATTRIBUTES);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -17,7 +17,10 @@ package org.thingsboard.server.service.security.permission;
 | 
			
		||||
 | 
			
		||||
import org.springframework.stereotype.Component;
 | 
			
		||||
import org.thingsboard.server.common.data.HasTenantId;
 | 
			
		||||
import org.thingsboard.server.common.data.User;
 | 
			
		||||
import org.thingsboard.server.common.data.id.EntityId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.UserId;
 | 
			
		||||
import org.thingsboard.server.common.data.security.Authority;
 | 
			
		||||
import org.thingsboard.server.service.security.model.SecurityUser;
 | 
			
		||||
 | 
			
		||||
@Component(value="sysAdminPermissions")
 | 
			
		||||
@ -26,29 +29,23 @@ public class SysAdminPermissions extends AbstractPermissions {
 | 
			
		||||
    public SysAdminPermissions() {
 | 
			
		||||
        super();
 | 
			
		||||
        put(Resource.ADMIN_SETTINGS, PermissionChecker.allowAllPermissionChecker);
 | 
			
		||||
        put(Resource.DASHBOARD, PermissionChecker.allowReadPermissionChecker);
 | 
			
		||||
        put(Resource.DASHBOARD, new PermissionChecker.GenericPermissionChecker(Operation.READ));
 | 
			
		||||
        put(Resource.TENANT, PermissionChecker.allowAllPermissionChecker);
 | 
			
		||||
        put(Resource.RULE_CHAIN, PermissionChecker.allowReadPermissionChecker);
 | 
			
		||||
        put(Resource.USER, PermissionChecker.allowAllPermissionChecker);
 | 
			
		||||
        put(Resource.RULE_CHAIN, systemEntityPermissionChecker);
 | 
			
		||||
        put(Resource.USER, userPermissionChecker);
 | 
			
		||||
        put(Resource.WIDGETS_BUNDLE, systemEntityPermissionChecker);
 | 
			
		||||
        put(Resource.WIDGET_TYPE, systemEntityPermissionChecker);
 | 
			
		||||
        put(Resource.OAUTH2_CONFIGURATION_INFO, PermissionChecker.allowAllPermissionChecker);
 | 
			
		||||
        put(Resource.OAUTH2_CONFIGURATION_TEMPLATE, PermissionChecker.allowAllPermissionChecker);
 | 
			
		||||
        put(Resource.TENANT_PROFILE, PermissionChecker.allowAllPermissionChecker);
 | 
			
		||||
        put(Resource.TB_RESOURCE, PermissionChecker.allowAllPermissionChecker);
 | 
			
		||||
        put(Resource.CUSTOMER, PermissionChecker.allowReadPermissionChecker);
 | 
			
		||||
        put(Resource.ASSET, PermissionChecker.allowReadPermissionChecker);
 | 
			
		||||
        put(Resource.DEVICE, PermissionChecker.allowReadPermissionChecker);
 | 
			
		||||
        put(Resource.ENTITY_VIEW, PermissionChecker.allowReadPermissionChecker);
 | 
			
		||||
        put(Resource.DEVICE_PROFILE, PermissionChecker.allowReadPermissionChecker);
 | 
			
		||||
        put(Resource.OTA_PACKAGE, PermissionChecker.allowReadPermissionChecker);
 | 
			
		||||
        put(Resource.EDGE, PermissionChecker.allowReadPermissionChecker);
 | 
			
		||||
        put(Resource.TB_RESOURCE, systemEntityPermissionChecker);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static final PermissionChecker systemEntityPermissionChecker = new PermissionChecker() {
 | 
			
		||||
 | 
			
		||||
        @Override
 | 
			
		||||
        public boolean hasPermission(SecurityUser user, Operation operation, EntityId entityId, HasTenantId entity) {
 | 
			
		||||
 | 
			
		||||
            if (entity.getTenantId() != null && !entity.getTenantId().isNullUid()) {
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
@ -56,4 +53,16 @@ public class SysAdminPermissions extends AbstractPermissions {
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    private static final PermissionChecker userPermissionChecker = new PermissionChecker<UserId, User>() {
 | 
			
		||||
 | 
			
		||||
        @Override
 | 
			
		||||
        public boolean hasPermission(SecurityUser user, Operation operation, UserId userId, User userEntity) {
 | 
			
		||||
            if (Authority.CUSTOMER_USER.equals(userEntity.getAuthority())) {
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -29,8 +29,7 @@ public enum EntityFilterType {
 | 
			
		||||
    DEVICE_SEARCH_QUERY("deviceSearchQuery"),
 | 
			
		||||
    ENTITY_VIEW_SEARCH_QUERY("entityViewSearchQuery"),
 | 
			
		||||
    EDGE_SEARCH_QUERY("edgeSearchQuery"),
 | 
			
		||||
    API_USAGE_STATE("apiUsageState"),
 | 
			
		||||
    ENTITY_NAME_OR_ID("entityNameOrId");
 | 
			
		||||
    API_USAGE_STATE("apiUsageState");
 | 
			
		||||
 | 
			
		||||
    private final String label;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,32 +0,0 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright © 2016-2021 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.common.data.query;
 | 
			
		||||
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import lombok.EqualsAndHashCode;
 | 
			
		||||
import org.thingsboard.server.common.data.EntityType;
 | 
			
		||||
 | 
			
		||||
@EqualsAndHashCode(callSuper = true)
 | 
			
		||||
@Data
 | 
			
		||||
public class EntityNameOrIdFilter extends EntitySearchQueryFilter {
 | 
			
		||||
    private String nameOrId;
 | 
			
		||||
    private EntityType entityType;
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public EntityFilterType getType() {
 | 
			
		||||
        return EntityFilterType.ENTITY_NAME_OR_ID;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -44,7 +44,6 @@ import org.thingsboard.server.common.data.query.EntityFilterType;
 | 
			
		||||
import org.thingsboard.server.common.data.query.EntityKeyType;
 | 
			
		||||
import org.thingsboard.server.common.data.query.EntityListFilter;
 | 
			
		||||
import org.thingsboard.server.common.data.query.EntityNameFilter;
 | 
			
		||||
import org.thingsboard.server.common.data.query.EntityNameOrIdFilter;
 | 
			
		||||
import org.thingsboard.server.common.data.query.EntitySearchQueryFilter;
 | 
			
		||||
import org.thingsboard.server.common.data.query.EntityTypeFilter;
 | 
			
		||||
import org.thingsboard.server.common.data.query.EntityViewSearchQueryFilter;
 | 
			
		||||
@ -237,12 +236,6 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository {
 | 
			
		||||
        entityTableMap.put(EntityType.TENANT, "tenant");
 | 
			
		||||
        entityTableMap.put(EntityType.API_USAGE_STATE, SELECT_API_USAGE_STATE);
 | 
			
		||||
        entityTableMap.put(EntityType.EDGE, "edge");
 | 
			
		||||
        entityTableMap.put(EntityType.RULE_CHAIN, "rule_chain");
 | 
			
		||||
        entityTableMap.put(EntityType.WIDGETS_BUNDLE, "widgets_bundle");
 | 
			
		||||
        entityTableMap.put(EntityType.TENANT_PROFILE, "tenant_profile");
 | 
			
		||||
        entityTableMap.put(EntityType.DEVICE_PROFILE, "device_profile");
 | 
			
		||||
        entityTableMap.put(EntityType.TB_RESOURCE, "resource");
 | 
			
		||||
        entityTableMap.put(EntityType.OTA_PACKAGE, "ota_package");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static EntityType[] RELATION_QUERY_ENTITY_TYPES = new EntityType[]{
 | 
			
		||||
@ -448,7 +441,7 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository {
 | 
			
		||||
                Optional<EntityKeyMapping> sortOrderMappingOpt = mappings.stream().filter(EntityKeyMapping::isSortOrder).findFirst();
 | 
			
		||||
                if (sortOrderMappingOpt.isPresent()) {
 | 
			
		||||
                    EntityKeyMapping sortOrderMapping = sortOrderMappingOpt.get();
 | 
			
		||||
                    String direction = sortOrder.getDirection() == EntityDataSortOrder.Direction.ASC ? "asc" : "desc nulls last";
 | 
			
		||||
                    String direction = sortOrder.getDirection() == EntityDataSortOrder.Direction.ASC ? "asc" : "desc";
 | 
			
		||||
                    if (sortOrderMapping.getEntityKey().getType() == EntityKeyType.ENTITY_FIELD) {
 | 
			
		||||
                        dataQuery = String.format("%s order by %s %s, result.id %s", dataQuery, sortOrderMapping.getValueAlias(), direction, direction);
 | 
			
		||||
                    } else {
 | 
			
		||||
@ -478,26 +471,15 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository {
 | 
			
		||||
        String entityFieldsQuery = EntityKeyMapping.buildQuery(ctx, entityFieldsFilters, entityFilter.getType());
 | 
			
		||||
        String result = permissionQuery;
 | 
			
		||||
        if (!entityFilterQuery.isEmpty()) {
 | 
			
		||||
            if (!result.isEmpty()) {
 | 
			
		||||
            result += " and (" + entityFilterQuery + ")";
 | 
			
		||||
            } else {
 | 
			
		||||
                result = "(" + entityFilterQuery + ")";
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if (!entityFieldsQuery.isEmpty()) {
 | 
			
		||||
            if (!result.isEmpty()) {
 | 
			
		||||
            result += " and (" + entityFieldsQuery + ")";
 | 
			
		||||
            } else {
 | 
			
		||||
                result = "(" + entityFieldsQuery + ")";
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private String buildPermissionQuery(QueryContext ctx, EntityFilter entityFilter) {
 | 
			
		||||
        if (ctx.getTenantId().equals(TenantId.SYS_TENANT_ID)) {
 | 
			
		||||
            return "";
 | 
			
		||||
        }
 | 
			
		||||
        switch (entityFilter.getType()) {
 | 
			
		||||
            case RELATIONS_QUERY:
 | 
			
		||||
            case DEVICE_SEARCH_QUERY:
 | 
			
		||||
@ -566,8 +548,6 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository {
 | 
			
		||||
            case API_USAGE_STATE:
 | 
			
		||||
            case ENTITY_TYPE:
 | 
			
		||||
                return "";
 | 
			
		||||
            case ENTITY_NAME_OR_ID:
 | 
			
		||||
                return entityNameOrIdQuery(ctx, (EntityNameOrIdFilter) entityFilter);
 | 
			
		||||
            default:
 | 
			
		||||
                throw new RuntimeException("Not implemented!");
 | 
			
		||||
        }
 | 
			
		||||
@ -779,27 +759,7 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository {
 | 
			
		||||
 | 
			
		||||
    private String entityNameQuery(QueryContext ctx, EntityNameFilter filter) {
 | 
			
		||||
        ctx.addStringParameter("entity_filter_name_filter", filter.getEntityNameFilter());
 | 
			
		||||
        return "lower(e.search_text) like lower(concat('%', :entity_filter_name_filter, '%'))";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private String entityNameOrIdQuery(QueryContext ctx, EntityNameOrIdFilter filter) {
 | 
			
		||||
        String nameOrId = filter.getNameOrId();
 | 
			
		||||
        if (StringUtils.isNotEmpty(nameOrId)) {
 | 
			
		||||
            nameOrId = nameOrId.replaceAll("%", "\\\\%").replaceAll("_", "\\\\_");
 | 
			
		||||
            ctx.addStringParameter("entity_id_or_search_text_filter", nameOrId);
 | 
			
		||||
            String query = "";
 | 
			
		||||
 | 
			
		||||
            String searchTextField = EntityKeyMapping.searchTextFields.get(filter.getEntityType());
 | 
			
		||||
            query += "lower(e." + searchTextField + ") like lower(concat('%', :entity_id_or_search_text_filter, '%'))";
 | 
			
		||||
 | 
			
		||||
            try {
 | 
			
		||||
                UUID.fromString(nameOrId);
 | 
			
		||||
                query += " or e.id = :entity_id_or_search_text_filter::uuid";
 | 
			
		||||
            } catch (Exception ignored) {}
 | 
			
		||||
 | 
			
		||||
            return query;
 | 
			
		||||
        }
 | 
			
		||||
        return "true";
 | 
			
		||||
        return "lower(e.search_text) like lower(concat(:entity_filter_name_filter, '%%'))";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private String typeQuery(QueryContext ctx, EntityFilter filter) {
 | 
			
		||||
@ -827,7 +787,7 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository {
 | 
			
		||||
        }
 | 
			
		||||
        ctx.addStringParameter("entity_filter_type_query_type", type);
 | 
			
		||||
        ctx.addStringParameter("entity_filter_type_query_name", name);
 | 
			
		||||
        return "e.type = :entity_filter_type_query_type and lower(e.search_text) like lower(concat('%', :entity_filter_type_query_name, '%'))";
 | 
			
		||||
        return "e.type = :entity_filter_type_query_type and lower(e.search_text) like lower(concat(:entity_filter_type_query_name, '%%'))";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private EntityType resolveEntityType(EntityFilter entityFilter) {
 | 
			
		||||
@ -856,8 +816,6 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository {
 | 
			
		||||
                return ((RelationsQueryFilter) entityFilter).getRootEntity().getEntityType();
 | 
			
		||||
            case API_USAGE_STATE:
 | 
			
		||||
                return EntityType.API_USAGE_STATE;
 | 
			
		||||
            case ENTITY_NAME_OR_ID:
 | 
			
		||||
                return ((EntityNameOrIdFilter) entityFilter).getEntityType();
 | 
			
		||||
            default:
 | 
			
		||||
                throw new RuntimeException("Not implemented!");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -38,7 +38,6 @@ import org.thingsboard.server.dao.model.ModelConstants;
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.Arrays;
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
import java.util.EnumMap;
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.HashSet;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
@ -54,8 +53,6 @@ public class EntityKeyMapping {
 | 
			
		||||
    private static final Map<EntityType, Set<String>> allowedEntityFieldMap = new HashMap<>();
 | 
			
		||||
    private static final Map<String, String> entityFieldColumnMap = new HashMap<>();
 | 
			
		||||
    private static final Map<EntityType, Map<String, String>> aliases = new HashMap<>();
 | 
			
		||||
    private static final Map<EntityType, Map<String, String>> propertiesFunctions = new EnumMap<>(EntityType.class);
 | 
			
		||||
    public static final Map<EntityType, String> searchTextFields = new EnumMap<>(EntityType.class);
 | 
			
		||||
 | 
			
		||||
    public static final String CREATED_TIME = "createdTime";
 | 
			
		||||
    public static final String ENTITY_TYPE = "entityType";
 | 
			
		||||
@ -75,17 +72,12 @@ public class EntityKeyMapping {
 | 
			
		||||
    public static final String ZIP = "zip";
 | 
			
		||||
    public static final String PHONE = "phone";
 | 
			
		||||
    public static final String ADDITIONAL_INFO = "additionalInfo";
 | 
			
		||||
    public static final String TENANT_ID = "tenantId";
 | 
			
		||||
    public static final String CUSTOMER_ID = "customerId";
 | 
			
		||||
    public static final String AUTHORITY = "authority";
 | 
			
		||||
    public static final String RESOURCE_TYPE = "resourceType";
 | 
			
		||||
    public static final String LAST_ACTIVITY_TIME = "lastActivityTime";
 | 
			
		||||
 | 
			
		||||
    public static final List<String> typedEntityFields = Arrays.asList(CREATED_TIME, ENTITY_TYPE, NAME, TYPE, ADDITIONAL_INFO, TENANT_ID);
 | 
			
		||||
    public static final List<String> typedEntityFields = Arrays.asList(CREATED_TIME, ENTITY_TYPE, NAME, TYPE, ADDITIONAL_INFO);
 | 
			
		||||
    public static final List<String> widgetEntityFields = Arrays.asList(CREATED_TIME, ENTITY_TYPE, NAME);
 | 
			
		||||
    public static final List<String> commonEntityFields = Arrays.asList(CREATED_TIME, ENTITY_TYPE, NAME, ADDITIONAL_INFO);
 | 
			
		||||
 | 
			
		||||
    public static final List<String> dashboardEntityFields = Arrays.asList(CREATED_TIME, ENTITY_TYPE, TITLE, TENANT_ID);
 | 
			
		||||
    public static final List<String> labeledEntityFields = Arrays.asList(CREATED_TIME, ENTITY_TYPE, NAME, TYPE, LABEL, ADDITIONAL_INFO, TENANT_ID, CUSTOMER_ID);
 | 
			
		||||
    public static final List<String> dashboardEntityFields = Arrays.asList(CREATED_TIME, ENTITY_TYPE, TITLE);
 | 
			
		||||
    public static final List<String> labeledEntityFields = Arrays.asList(CREATED_TIME, ENTITY_TYPE, NAME, TYPE, LABEL, ADDITIONAL_INFO);
 | 
			
		||||
    public static final List<String> contactBasedEntityFields = Arrays.asList(CREATED_TIME, ENTITY_TYPE, EMAIL, TITLE, COUNTRY, STATE, CITY, ADDRESS, ADDRESS_2, ZIP, PHONE, ADDITIONAL_INFO);
 | 
			
		||||
 | 
			
		||||
    public static final Set<String> apiUsageStateEntityFields =  new HashSet<>(Arrays.asList(CREATED_TIME, ENTITY_TYPE, NAME));
 | 
			
		||||
@ -95,31 +87,20 @@ public class EntityKeyMapping {
 | 
			
		||||
    static {
 | 
			
		||||
        allowedEntityFieldMap.put(EntityType.DEVICE, new HashSet<>(labeledEntityFields));
 | 
			
		||||
        allowedEntityFieldMap.put(EntityType.ASSET, new HashSet<>(labeledEntityFields));
 | 
			
		||||
        allowedEntityFieldMap.put(EntityType.EDGE, new HashSet<>(labeledEntityFields));
 | 
			
		||||
        allowedEntityFieldMap.put(EntityType.ENTITY_VIEW, new HashSet<>(typedEntityFields));
 | 
			
		||||
        allowedEntityFieldMap.get(EntityType.ENTITY_VIEW).add(CUSTOMER_ID);
 | 
			
		||||
 | 
			
		||||
        allowedEntityFieldMap.put(EntityType.TENANT, new HashSet<>(contactBasedEntityFields));
 | 
			
		||||
        allowedEntityFieldMap.get(EntityType.TENANT).add(REGION);
 | 
			
		||||
        allowedEntityFieldMap.put(EntityType.CUSTOMER, new HashSet<>(contactBasedEntityFields));
 | 
			
		||||
        allowedEntityFieldMap.get(EntityType.CUSTOMER).add(TENANT_ID);
 | 
			
		||||
 | 
			
		||||
        allowedEntityFieldMap.put(EntityType.USER, new HashSet<>(Arrays.asList(CREATED_TIME, FIRST_NAME, LAST_NAME, EMAIL,
 | 
			
		||||
                ADDITIONAL_INFO, AUTHORITY, TENANT_ID, CUSTOMER_ID)));
 | 
			
		||||
 | 
			
		||||
        allowedEntityFieldMap.put(EntityType.DEVICE_PROFILE, new HashSet<>(commonEntityFields));
 | 
			
		||||
        allowedEntityFieldMap.get(EntityType.DEVICE_PROFILE).add(TENANT_ID);
 | 
			
		||||
        allowedEntityFieldMap.put(EntityType.USER, new HashSet<>(Arrays.asList(CREATED_TIME, FIRST_NAME, LAST_NAME, EMAIL, ADDITIONAL_INFO)));
 | 
			
		||||
 | 
			
		||||
        allowedEntityFieldMap.put(EntityType.DASHBOARD, new HashSet<>(dashboardEntityFields));
 | 
			
		||||
        allowedEntityFieldMap.put(EntityType.RULE_CHAIN, new HashSet<>(commonEntityFields));
 | 
			
		||||
        allowedEntityFieldMap.get(EntityType.RULE_CHAIN).add(TENANT_ID);
 | 
			
		||||
        allowedEntityFieldMap.get(EntityType.RULE_CHAIN).add(TYPE);
 | 
			
		||||
        allowedEntityFieldMap.put(EntityType.RULE_NODE, new HashSet<>(commonEntityFields));
 | 
			
		||||
        allowedEntityFieldMap.put(EntityType.WIDGET_TYPE, new HashSet<>(Arrays.asList(CREATED_TIME, ENTITY_TYPE, NAME, TENANT_ID)));
 | 
			
		||||
        allowedEntityFieldMap.put(EntityType.WIDGETS_BUNDLE, new HashSet<>(Arrays.asList(CREATED_TIME, ENTITY_TYPE, TITLE, TENANT_ID)));
 | 
			
		||||
        allowedEntityFieldMap.put(EntityType.WIDGET_TYPE, new HashSet<>(widgetEntityFields));
 | 
			
		||||
        allowedEntityFieldMap.put(EntityType.WIDGETS_BUNDLE, new HashSet<>(widgetEntityFields));
 | 
			
		||||
        allowedEntityFieldMap.put(EntityType.API_USAGE_STATE, apiUsageStateEntityFields);
 | 
			
		||||
        allowedEntityFieldMap.put(EntityType.TB_RESOURCE, Set.of(CREATED_TIME, ENTITY_TYPE, RESOURCE_TYPE, TITLE, TENANT_ID));
 | 
			
		||||
        allowedEntityFieldMap.put(EntityType.OTA_PACKAGE, Set.of(CREATED_TIME, ENTITY_TYPE, TYPE, TITLE, TENANT_ID));
 | 
			
		||||
 | 
			
		||||
        entityFieldColumnMap.put(CREATED_TIME, ModelConstants.CREATED_TIME_PROPERTY);
 | 
			
		||||
        entityFieldColumnMap.put(ENTITY_TYPE, ModelConstants.ENTITY_TYPE_PROPERTY);
 | 
			
		||||
@ -139,42 +120,25 @@ public class EntityKeyMapping {
 | 
			
		||||
        entityFieldColumnMap.put(ZIP, ModelConstants.ZIP_PROPERTY);
 | 
			
		||||
        entityFieldColumnMap.put(PHONE, ModelConstants.PHONE_PROPERTY);
 | 
			
		||||
        entityFieldColumnMap.put(ADDITIONAL_INFO, ModelConstants.ADDITIONAL_INFO_PROPERTY);
 | 
			
		||||
        entityFieldColumnMap.put(TENANT_ID, ModelConstants.TENANT_ID_PROPERTY);
 | 
			
		||||
        entityFieldColumnMap.put(CUSTOMER_ID, ModelConstants.CUSTOMER_ID_PROPERTY);
 | 
			
		||||
        entityFieldColumnMap.put(AUTHORITY, ModelConstants.USER_AUTHORITY_PROPERTY);
 | 
			
		||||
        entityFieldColumnMap.put(RESOURCE_TYPE, ModelConstants.RESOURCE_TYPE_COLUMN);
 | 
			
		||||
 | 
			
		||||
        Map<String, String> contactBasedAliases = new HashMap<>();
 | 
			
		||||
        contactBasedAliases.put(NAME, TITLE);
 | 
			
		||||
        contactBasedAliases.put(LABEL, TITLE);
 | 
			
		||||
        aliases.put(EntityType.TENANT, contactBasedAliases);
 | 
			
		||||
        aliases.put(EntityType.CUSTOMER, new HashMap<>(contactBasedAliases));
 | 
			
		||||
        aliases.put(EntityType.CUSTOMER, contactBasedAliases);
 | 
			
		||||
        aliases.put(EntityType.DASHBOARD, contactBasedAliases);
 | 
			
		||||
        Map<String, String> commonEntityAliases = new HashMap<>();
 | 
			
		||||
        commonEntityAliases.put(TITLE, NAME);
 | 
			
		||||
        aliases.put(EntityType.DEVICE, commonEntityAliases);
 | 
			
		||||
        aliases.put(EntityType.ASSET, commonEntityAliases);
 | 
			
		||||
        aliases.put(EntityType.ENTITY_VIEW, commonEntityAliases);
 | 
			
		||||
        aliases.put(EntityType.EDGE, commonEntityAliases);
 | 
			
		||||
        aliases.put(EntityType.WIDGETS_BUNDLE, new HashMap<>(commonEntityAliases));
 | 
			
		||||
        aliases.get(EntityType.WIDGETS_BUNDLE).put(NAME, TITLE);
 | 
			
		||||
        aliases.put(EntityType.WIDGETS_BUNDLE, commonEntityAliases);
 | 
			
		||||
 | 
			
		||||
        Map<String, String> userEntityAliases = new HashMap<>();
 | 
			
		||||
        userEntityAliases.put(TITLE, EMAIL);
 | 
			
		||||
        userEntityAliases.put(LABEL, EMAIL);
 | 
			
		||||
        userEntityAliases.put(NAME, EMAIL);
 | 
			
		||||
        userEntityAliases.put(TYPE, AUTHORITY);
 | 
			
		||||
        aliases.put(EntityType.USER, userEntityAliases);
 | 
			
		||||
        aliases.put(EntityType.TB_RESOURCE, Map.of(NAME, TITLE, TYPE, RESOURCE_TYPE));
 | 
			
		||||
        aliases.put(EntityType.OTA_PACKAGE, Map.of(NAME, TITLE));
 | 
			
		||||
 | 
			
		||||
        propertiesFunctions.put(EntityType.USER, Map.of(
 | 
			
		||||
                LAST_ACTIVITY_TIME, "cast(e.additional_info::json ->> 'lastLoginTs' as bigint)"
 | 
			
		||||
        ));
 | 
			
		||||
 | 
			
		||||
        Arrays.stream(EntityType.values()).forEach(entityType -> {
 | 
			
		||||
            searchTextFields.put(entityType, ModelConstants.SEARCH_TEXT_PROPERTY);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private int index;
 | 
			
		||||
@ -215,10 +179,6 @@ public class EntityKeyMapping {
 | 
			
		||||
                    String column = entityFieldColumnMap.get(alias);
 | 
			
		||||
                    return String.format("cast(e.%s as varchar) as %s", column, getValueAlias());
 | 
			
		||||
                } else {
 | 
			
		||||
                    Map<String, String> entityPropertiesFunctions = propertiesFunctions.get(entityType);
 | 
			
		||||
                    if (entityPropertiesFunctions != null && entityPropertiesFunctions.containsKey(alias)) {
 | 
			
		||||
                        return String.format("%s as %s", entityPropertiesFunctions.get(alias), getValueAlias());
 | 
			
		||||
                    }
 | 
			
		||||
                    return String.format("'' as %s", getValueAlias());
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user