Commit 676a60e8042ce105427d7475f1c09fa3f55aede8

Authored by Andrew Shvayka
Committed by GitHub
1 parent 8e0eab37

Revert "[3.3.3] Entities search within all tenants"

... ... @@ -17,10 +17,9 @@ package org.thingsboard.server.controller;
17 17
18 18 import io.swagger.annotations.ApiOperation;
19 19 import io.swagger.annotations.ApiParam;
20   -import lombok.RequiredArgsConstructor;
  20 +import org.springframework.beans.factory.annotation.Autowired;
21 21 import org.springframework.http.ResponseEntity;
22 22 import org.springframework.security.access.prepost.PreAuthorize;
23   -import org.springframework.web.bind.annotation.PostMapping;
24 23 import org.springframework.web.bind.annotation.RequestBody;
25 24 import org.springframework.web.bind.annotation.RequestMapping;
26 25 import org.springframework.web.bind.annotation.RequestMethod;
... ... @@ -37,30 +36,20 @@ import org.thingsboard.server.common.data.query.EntityCountQuery;
37 36 import org.thingsboard.server.common.data.query.EntityData;
38 37 import org.thingsboard.server.common.data.query.EntityDataPageLink;
39 38 import org.thingsboard.server.common.data.query.EntityDataQuery;
40   -import org.thingsboard.server.data.search.EntitiesSearchRequest;
41   -import org.thingsboard.server.data.search.EntitySearchResult;
42 39 import org.thingsboard.server.queue.util.TbCoreComponent;
43   -import org.thingsboard.server.service.query.EntitiesSearchService;
44 40 import org.thingsboard.server.service.query.EntityQueryService;
45 41
46 42 import static org.thingsboard.server.controller.ControllerConstants.ALARM_DATA_QUERY_DESCRIPTION;
47 43 import static org.thingsboard.server.controller.ControllerConstants.ENTITY_COUNT_QUERY_DESCRIPTION;
48 44 import static org.thingsboard.server.controller.ControllerConstants.ENTITY_DATA_QUERY_DESCRIPTION;
49   -import static org.thingsboard.server.controller.ControllerConstants.NEW_LINE;
50   -import static org.thingsboard.server.controller.ControllerConstants.PAGE_NUMBER_DESCRIPTION;
51   -import static org.thingsboard.server.controller.ControllerConstants.PAGE_SIZE_DESCRIPTION;
52   -import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_ALLOWABLE_VALUES;
53   -import static org.thingsboard.server.controller.ControllerConstants.SORT_ORDER_DESCRIPTION;
54   -import static org.thingsboard.server.controller.ControllerConstants.SORT_PROPERTY_DESCRIPTION;
55 45
56 46 @RestController
57 47 @TbCoreComponent
58 48 @RequestMapping("/api")
59   -@RequiredArgsConstructor
60 49 public class EntityQueryController extends BaseController {
61 50
62   - private final EntityQueryService entityQueryService;
63   - private final EntitiesSearchService entitiesSearchService;
  51 + @Autowired
  52 + private EntityQueryService entityQueryService;
64 53
65 54 private static final int MAX_PAGE_SIZE = 100;
66 55
... ... @@ -134,70 +123,4 @@ public class EntityQueryController extends BaseController {
134 123 }
135 124 }
136 125
137   - @ApiOperation(value = "Search entities (searchEntities)", notes = "Search entities with specified entity type by id or name within the whole platform. " +
138   - "Searchable entity types are: CUSTOMER, USER, DEVICE, DEVICE_PROFILE, ASSET, ENTITY_VIEW, DASHBOARD, " +
139   - "RULE_CHAIN, EDGE, OTA_PACKAGE, TB_RESOURCE, WIDGETS_BUNDLE, TENANT, TENANT_PROFILE." + NEW_LINE +
140   - "The platform will search for entities, where a name contains the search text (case-insensitively), " +
141   - "or if the search query is a valid UUID (e.g. 128e4d40-26b3-11ec-aaeb-c7661c54701e) then " +
142   - "it will also search for an entity where id fully matches the query. If search query is empty " +
143   - "then all entities will be returned (according to page number, page size and sorting)." + NEW_LINE +
144   - "The returned result is a page of EntitySearchResult, which contains: " +
145   - "entity id, entity fields represented as strings, tenant info and owner info. " +
146   - "Returned entity fields are: name, type (will be present for USER, DEVICE, ASSET, ENTITY_VIEW, RULE_CHAIN, " +
147   - "EDGE, OTA_PACKAGE, TB_RESOURCE entity types; in case of USER - the type is its authority), " +
148   - "createdTime and lastActivityTime (will only be present for DEVICE and USER; for USER it is its last login time). " +
149   - "Tenant info contains tenant's id and title; owner info contains the same info for an entity's owner " +
150   - "(its customer, or if it is not a customer's entity - tenant)." + NEW_LINE +
151   - "Example response value:\n" +
152   - "{\n" +
153   - " \"data\": [\n" +
154   - " {\n" +
155   - " \"entityId\": {\n" +
156   - " \"entityType\": \"DEVICE\",\n" +
157   - " \"id\": \"48be0670-25c9-11ec-a618-8165eb6b112a\"\n" +
158   - " },\n" +
159   - " \"fields\": {\n" +
160   - " \"name\": \"Thermostat T1\",\n" +
161   - " \"createdTime\": \"1633430698071\",\n" +
162   - " \"lastActivityTime\": \"1635761085285\",\n" +
163   - " \"type\": \"thermostat\"\n" +
164   - " },\n" +
165   - " \"tenantInfo\": {\n" +
166   - " \"id\": {\n" +
167   - " \"entityType\": \"TENANT\",\n" +
168   - " \"id\": \"2ddd6120-25c9-11ec-a618-8165eb6b112a\"\n" +
169   - " },\n" +
170   - " \"name\": \"Tenant\"\n" +
171   - " },\n" +
172   - " \"ownerInfo\": {\n" +
173   - " \"id\": {\n" +
174   - " \"entityType\": \"CUSTOMER\",\n" +
175   - " \"id\": \"26cba800-eee3-11eb-9e2c-fb031bd4619c\"\n" +
176   - " },\n" +
177   - " \"name\": \"Customer A\"\n" +
178   - " }\n" +
179   - " }\n" +
180   - " ],\n" +
181   - " \"totalPages\": 1,\n" +
182   - " \"totalElements\": 1,\n" +
183   - " \"hasNext\": false\n" +
184   - "}")
185   - @PostMapping("/entities/search")
186   - @PreAuthorize("hasAnyAuthority('SYS_ADMIN')")
187   - public PageData<EntitySearchResult> searchEntities(@RequestBody EntitiesSearchRequest request,
188   - @ApiParam(value = PAGE_NUMBER_DESCRIPTION, required = true)
189   - @RequestParam int page,
190   - @ApiParam(value = PAGE_SIZE_DESCRIPTION, required = true)
191   - @RequestParam int pageSize,
192   - @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = "name, type, createdTime, lastActivityTime, createdTime, tenantId, customerId", required = false)
193   - @RequestParam(required = false) String sortProperty,
194   - @ApiParam(value = SORT_ORDER_DESCRIPTION, allowableValues = SORT_ORDER_ALLOWABLE_VALUES, required = false)
195   - @RequestParam(required = false) String sortOrder) throws ThingsboardException {
196   - try {
197   - return entitiesSearchService.searchEntities(getCurrentUser(), request, createPageLink(pageSize, page, null, sortProperty, sortOrder));
198   - } catch (Exception e) {
199   - throw handleException(e);
200   - }
201   - }
202   -
203 126 }
... ...
1   -/**
2   - * Copyright © 2016-2021 The Thingsboard Authors
3   - *
4   - * Licensed under the Apache License, Version 2.0 (the "License");
5   - * you may not use this file except in compliance with the License.
6   - * You may obtain a copy of the License at
7   - *
8   - * http://www.apache.org/licenses/LICENSE-2.0
9   - *
10   - * Unless required by applicable law or agreed to in writing, software
11   - * distributed under the License is distributed on an "AS IS" BASIS,
12   - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   - * See the License for the specific language governing permissions and
14   - * limitations under the License.
15   - */
16   -package org.thingsboard.server.data.search;
17   -
18   -import lombok.Data;
19   -import org.thingsboard.server.common.data.EntityType;
20   -
21   -@Data
22   -public class EntitiesSearchRequest {
23   - private EntityType entityType;
24   - private String searchQuery;
25   -}
1   -/**
2   - * Copyright © 2016-2021 The Thingsboard Authors
3   - *
4   - * Licensed under the Apache License, Version 2.0 (the "License");
5   - * you may not use this file except in compliance with the License.
6   - * You may obtain a copy of the License at
7   - *
8   - * http://www.apache.org/licenses/LICENSE-2.0
9   - *
10   - * Unless required by applicable law or agreed to in writing, software
11   - * distributed under the License is distributed on an "AS IS" BASIS,
12   - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   - * See the License for the specific language governing permissions and
14   - * limitations under the License.
15   - */
16   -package org.thingsboard.server.data.search;
17   -
18   -import lombok.AllArgsConstructor;
19   -import lombok.Data;
20   -import lombok.NoArgsConstructor;
21   -import org.thingsboard.server.common.data.id.EntityId;
22   -import org.thingsboard.server.common.data.id.TenantId;
23   -
24   -import java.util.Map;
25   -
26   -@Data
27   -public class EntitySearchResult {
28   - private EntityId entityId;
29   - private Map<String, String> fields;
30   -
31   - private EntityTenantInfo tenantInfo;
32   - private EntityOwnerInfo ownerInfo;
33   -
34   - @Data
35   - @AllArgsConstructor
36   - @NoArgsConstructor
37   - public static final class EntityTenantInfo {
38   - private TenantId id;
39   - private String name;
40   - }
41   -
42   - @Data
43   - @AllArgsConstructor
44   - @NoArgsConstructor
45   - public static final class EntityOwnerInfo {
46   - private EntityId id;
47   - private String name;
48   - }
49   -
50   -}
1   -/**
2   - * Copyright © 2016-2021 The Thingsboard Authors
3   - *
4   - * Licensed under the Apache License, Version 2.0 (the "License");
5   - * you may not use this file except in compliance with the License.
6   - * You may obtain a copy of the License at
7   - *
8   - * http://www.apache.org/licenses/LICENSE-2.0
9   - *
10   - * Unless required by applicable law or agreed to in writing, software
11   - * distributed under the License is distributed on an "AS IS" BASIS,
12   - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   - * See the License for the specific language governing permissions and
14   - * limitations under the License.
15   - */
16   -package org.thingsboard.server.service.query;
17   -
18   -import org.thingsboard.server.common.data.page.PageData;
19   -import org.thingsboard.server.common.data.page.PageLink;
20   -import org.thingsboard.server.data.search.EntitiesSearchRequest;
21   -import org.thingsboard.server.data.search.EntitySearchResult;
22   -import org.thingsboard.server.service.security.model.SecurityUser;
23   -
24   -public interface EntitiesSearchService {
25   - PageData<EntitySearchResult> searchEntities(SecurityUser user, EntitiesSearchRequest request, PageLink pageLink);
26   -}
1   -/**
2   - * Copyright © 2016-2021 The Thingsboard Authors
3   - *
4   - * Licensed under the Apache License, Version 2.0 (the "License");
5   - * you may not use this file except in compliance with the License.
6   - * You may obtain a copy of the License at
7   - *
8   - * http://www.apache.org/licenses/LICENSE-2.0
9   - *
10   - * Unless required by applicable law or agreed to in writing, software
11   - * distributed under the License is distributed on an "AS IS" BASIS,
12   - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   - * See the License for the specific language governing permissions and
14   - * limitations under the License.
15   - */
16   -package org.thingsboard.server.service.query;
17   -
18   -import com.google.common.base.Strings;
19   -import lombok.RequiredArgsConstructor;
20   -import lombok.extern.slf4j.Slf4j;
21   -import org.apache.commons.lang3.StringUtils;
22   -import org.springframework.stereotype.Service;
23   -import org.thingsboard.server.common.data.ContactBased;
24   -import org.thingsboard.server.common.data.Customer;
25   -import org.thingsboard.server.common.data.EntityType;
26   -import org.thingsboard.server.common.data.Tenant;
27   -import org.thingsboard.server.common.data.id.CustomerId;
28   -import org.thingsboard.server.common.data.id.EntityId;
29   -import org.thingsboard.server.common.data.id.TenantId;
30   -import org.thingsboard.server.common.data.page.PageData;
31   -import org.thingsboard.server.common.data.page.PageLink;
32   -import org.thingsboard.server.common.data.page.SortOrder;
33   -import org.thingsboard.server.common.data.query.EntityData;
34   -import org.thingsboard.server.common.data.query.EntityDataPageLink;
35   -import org.thingsboard.server.common.data.query.EntityDataQuery;
36   -import org.thingsboard.server.common.data.query.EntityDataSortOrder;
37   -import org.thingsboard.server.common.data.query.EntityKey;
38   -import org.thingsboard.server.common.data.query.EntityKeyType;
39   -import org.thingsboard.server.common.data.query.EntityNameOrIdFilter;
40   -import org.thingsboard.server.dao.customer.CustomerService;
41   -import org.thingsboard.server.dao.tenant.TenantService;
42   -import org.thingsboard.server.data.search.EntitiesSearchRequest;
43   -import org.thingsboard.server.data.search.EntitySearchResult;
44   -import org.thingsboard.server.queue.util.TbCoreComponent;
45   -import org.thingsboard.server.service.security.model.SecurityUser;
46   -import org.thingsboard.server.service.state.DefaultDeviceStateService;
47   -
48   -import java.util.ArrayList;
49   -import java.util.Collections;
50   -import java.util.EnumSet;
51   -import java.util.HashMap;
52   -import java.util.List;
53   -import java.util.Map;
54   -import java.util.Optional;
55   -import java.util.Set;
56   -import java.util.UUID;
57   -import java.util.stream.Collectors;
58   -import java.util.stream.Stream;
59   -
60   -import static org.thingsboard.server.common.data.EntityType.ASSET;
61   -import static org.thingsboard.server.common.data.EntityType.CUSTOMER;
62   -import static org.thingsboard.server.common.data.EntityType.DASHBOARD;
63   -import static org.thingsboard.server.common.data.EntityType.DEVICE;
64   -import static org.thingsboard.server.common.data.EntityType.DEVICE_PROFILE;
65   -import static org.thingsboard.server.common.data.EntityType.EDGE;
66   -import static org.thingsboard.server.common.data.EntityType.ENTITY_VIEW;
67   -import static org.thingsboard.server.common.data.EntityType.OTA_PACKAGE;
68   -import static org.thingsboard.server.common.data.EntityType.RULE_CHAIN;
69   -import static org.thingsboard.server.common.data.EntityType.TB_RESOURCE;
70   -import static org.thingsboard.server.common.data.EntityType.TENANT;
71   -import static org.thingsboard.server.common.data.EntityType.TENANT_PROFILE;
72   -import static org.thingsboard.server.common.data.EntityType.USER;
73   -import static org.thingsboard.server.common.data.EntityType.WIDGETS_BUNDLE;
74   -import static org.thingsboard.server.dao.sql.query.EntityKeyMapping.CREATED_TIME;
75   -import static org.thingsboard.server.dao.sql.query.EntityKeyMapping.CUSTOMER_ID;
76   -import static org.thingsboard.server.dao.sql.query.EntityKeyMapping.LAST_ACTIVITY_TIME;
77   -import static org.thingsboard.server.dao.sql.query.EntityKeyMapping.NAME;
78   -import static org.thingsboard.server.dao.sql.query.EntityKeyMapping.TENANT_ID;
79   -import static org.thingsboard.server.dao.sql.query.EntityKeyMapping.TYPE;
80   -
81   -@Service
82   -@TbCoreComponent
83   -@RequiredArgsConstructor
84   -@Slf4j
85   -public class EntitiesSearchServiceImpl implements EntitiesSearchService {
86   - private final EntityQueryService entityQueryService;
87   -
88   - private final TenantService tenantService;
89   - private final CustomerService customerService;
90   - private final DefaultDeviceStateService deviceStateService;
91   -
92   - private static final List<EntityKey> entityResponseFields = Stream.of(CREATED_TIME, NAME, TYPE, TENANT_ID, CUSTOMER_ID)
93   - .map(field -> new EntityKey(EntityKeyType.ENTITY_FIELD, field))
94   - .collect(Collectors.toList());
95   -
96   - private static final Set<EntityType> searchableEntityTypes = EnumSet.of(
97   - TENANT, CUSTOMER, USER, DASHBOARD, ASSET, DEVICE, RULE_CHAIN, ENTITY_VIEW,
98   - WIDGETS_BUNDLE, TENANT_PROFILE, DEVICE_PROFILE, TB_RESOURCE, OTA_PACKAGE, EDGE
99   - );
100   -
101   - @Override
102   - public PageData<EntitySearchResult> searchEntities(SecurityUser user, EntitiesSearchRequest request, PageLink pageLink) {
103   - EntityType entityType = request.getEntityType();
104   - if (!searchableEntityTypes.contains(entityType)) {
105   - return new PageData<>();
106   - }
107   -
108   - EntityDataQuery query = createSearchQuery(request.getSearchQuery(), entityType, pageLink);
109   - PageData<EntityData> resultPage = entityQueryService.findEntityDataByQuery(user, query);
110   -
111   - Map<EntityId, ContactBased<? extends EntityId>> localOwnersCache = new HashMap<>();
112   - return resultPage.mapData(entityData -> {
113   - Map<String, String> fields = new HashMap<>();
114   - entityData.getLatest().values().stream()
115   - .flatMap(values -> values.entrySet().stream())
116   - .forEach(entry -> fields.put(entry.getKey(), Strings.emptyToNull(entry.getValue().getValue())));
117   -
118   - EntitySearchResult entitySearchResult = new EntitySearchResult();
119   -
120   - entitySearchResult.setEntityId(entityData.getEntityId());
121   - entitySearchResult.setFields(fields);
122   - setOwnerInfo(entitySearchResult, localOwnersCache);
123   -
124   - return entitySearchResult;
125   - });
126   - }
127   -
128   - private EntityDataQuery createSearchQuery(String searchQuery, EntityType entityType, PageLink pageLink) {
129   - EntityDataPageLink entityDataPageLink = new EntityDataPageLink();
130   - entityDataPageLink.setPageSize(pageLink.getPageSize());
131   - entityDataPageLink.setPage(pageLink.getPage());
132   - if (pageLink.getSortOrder() != null && StringUtils.isNotEmpty(pageLink.getSortOrder().getProperty())) {
133   - entityDataPageLink.setSortOrder(new EntityDataSortOrder(new EntityKey(EntityKeyType.ENTITY_FIELD, pageLink.getSortOrder().getProperty()),
134   - EntityDataSortOrder.Direction.valueOf(Optional.ofNullable(pageLink.getSortOrder().getDirection()).orElse(SortOrder.Direction.ASC).name())));
135   - }
136   -
137   - EntityNameOrIdFilter filter = new EntityNameOrIdFilter();
138   - filter.setEntityType(entityType);
139   - filter.setNameOrId(searchQuery);
140   -
141   - List<EntityKey> entityFields = entityResponseFields;
142   - List<EntityKey> latestValues = Collections.emptyList();
143   -
144   - if (entityType == USER) {
145   - entityFields = new ArrayList<>(entityFields);
146   - entityFields.add(new EntityKey(EntityKeyType.ENTITY_FIELD, LAST_ACTIVITY_TIME));
147   - } else if (entityType == DEVICE) {
148   - EntityKey lastActivityTimeKey;
149   - if (deviceStateService.isPersistToTelemetry()) {
150   - lastActivityTimeKey = new EntityKey(EntityKeyType.TIME_SERIES, LAST_ACTIVITY_TIME);
151   - } else {
152   - lastActivityTimeKey = new EntityKey(EntityKeyType.SERVER_ATTRIBUTE, LAST_ACTIVITY_TIME);
153   - }
154   - latestValues = List.of(lastActivityTimeKey);
155   - if (entityDataPageLink.getSortOrder() != null && entityDataPageLink.getSortOrder().getKey().getKey().equals(LAST_ACTIVITY_TIME)) {
156   - entityDataPageLink.getSortOrder().setKey(lastActivityTimeKey);
157   - }
158   - }
159   -
160   - return new EntityDataQuery(filter, entityDataPageLink, entityFields, latestValues, Collections.emptyList());
161   - }
162   -
163   - private void setOwnerInfo(EntitySearchResult entitySearchResult, Map<EntityId, ContactBased<? extends EntityId>> localOwnersCache) {
164   - Map<String, String> fields = entitySearchResult.getFields();
165   -
166   - UUID tenantUuid = toUuid(fields.remove(TENANT_ID));
167   - UUID customerUuid = toUuid(fields.remove(CUSTOMER_ID));
168   -
169   - Tenant tenant = null;
170   - if (tenantUuid != null) {
171   - tenant = getTenant(new TenantId(tenantUuid), localOwnersCache);
172   - }
173   -
174   - ContactBased<? extends EntityId> owner;
175   - if (customerUuid != null) {
176   - owner = getCustomer(new CustomerId(customerUuid), localOwnersCache);
177   - } else {
178   - owner = tenant;
179   - }
180   -
181   - if (tenant != null) {
182   - entitySearchResult.setTenantInfo(new EntitySearchResult.EntityTenantInfo(tenant.getId(), tenant.getName()));
183   - }
184   - if (owner != null) {
185   - entitySearchResult.setOwnerInfo(new EntitySearchResult.EntityOwnerInfo(owner.getId(), owner.getName()));
186   - }
187   - }
188   -
189   - private Tenant getTenant(TenantId tenantId, Map<EntityId, ContactBased<? extends EntityId>> localOwnersCache) {
190   - return (Tenant) localOwnersCache.computeIfAbsent(tenantId, id -> tenantService.findTenantById(tenantId));
191   - }
192   -
193   - private Customer getCustomer(CustomerId customerId, Map<EntityId, ContactBased<? extends EntityId>> localOwnersCache) {
194   - return (Customer) localOwnersCache.computeIfAbsent(customerId, id -> customerService.findCustomerById(TenantId.SYS_TENANT_ID, customerId));
195   - }
196   -
197   - private UUID toUuid(String uuid) {
198   - try {
199   - UUID id = UUID.fromString(uuid);
200   - if (!id.equals(EntityId.NULL_UUID)) {
201   - return id;
202   - }
203   - } catch (Exception ignored) {}
204   -
205   - return null;
206   - }
207   -
208   -}
... ... @@ -69,6 +69,5 @@ public interface PermissionChecker<I extends EntityId, T extends HasTenantId> {
69 69 }
70 70 };
71 71
72   - PermissionChecker allowReadPermissionChecker = new GenericPermissionChecker(Operation.READ, Operation.READ_TELEMETRY, Operation.READ_ATTRIBUTES);
73 72
74 73 }
... ...
... ... @@ -17,7 +17,10 @@ package org.thingsboard.server.service.security.permission;
17 17
18 18 import org.springframework.stereotype.Component;
19 19 import org.thingsboard.server.common.data.HasTenantId;
  20 +import org.thingsboard.server.common.data.User;
20 21 import org.thingsboard.server.common.data.id.EntityId;
  22 +import org.thingsboard.server.common.data.id.UserId;
  23 +import org.thingsboard.server.common.data.security.Authority;
21 24 import org.thingsboard.server.service.security.model.SecurityUser;
22 25
23 26 @Component(value="sysAdminPermissions")
... ... @@ -26,29 +29,23 @@ public class SysAdminPermissions extends AbstractPermissions {
26 29 public SysAdminPermissions() {
27 30 super();
28 31 put(Resource.ADMIN_SETTINGS, PermissionChecker.allowAllPermissionChecker);
29   - put(Resource.DASHBOARD, PermissionChecker.allowReadPermissionChecker);
  32 + put(Resource.DASHBOARD, new PermissionChecker.GenericPermissionChecker(Operation.READ));
30 33 put(Resource.TENANT, PermissionChecker.allowAllPermissionChecker);
31   - put(Resource.RULE_CHAIN, PermissionChecker.allowReadPermissionChecker);
32   - put(Resource.USER, PermissionChecker.allowAllPermissionChecker);
  34 + put(Resource.RULE_CHAIN, systemEntityPermissionChecker);
  35 + put(Resource.USER, userPermissionChecker);
33 36 put(Resource.WIDGETS_BUNDLE, systemEntityPermissionChecker);
34 37 put(Resource.WIDGET_TYPE, systemEntityPermissionChecker);
35 38 put(Resource.OAUTH2_CONFIGURATION_INFO, PermissionChecker.allowAllPermissionChecker);
36 39 put(Resource.OAUTH2_CONFIGURATION_TEMPLATE, PermissionChecker.allowAllPermissionChecker);
37 40 put(Resource.TENANT_PROFILE, PermissionChecker.allowAllPermissionChecker);
38   - put(Resource.TB_RESOURCE, PermissionChecker.allowAllPermissionChecker);
39   - put(Resource.CUSTOMER, PermissionChecker.allowReadPermissionChecker);
40   - put(Resource.ASSET, PermissionChecker.allowReadPermissionChecker);
41   - put(Resource.DEVICE, PermissionChecker.allowReadPermissionChecker);
42   - put(Resource.ENTITY_VIEW, PermissionChecker.allowReadPermissionChecker);
43   - put(Resource.DEVICE_PROFILE, PermissionChecker.allowReadPermissionChecker);
44   - put(Resource.OTA_PACKAGE, PermissionChecker.allowReadPermissionChecker);
45   - put(Resource.EDGE, PermissionChecker.allowReadPermissionChecker);
  41 + put(Resource.TB_RESOURCE, systemEntityPermissionChecker);
46 42 }
47 43
48 44 private static final PermissionChecker systemEntityPermissionChecker = new PermissionChecker() {
49 45
50 46 @Override
51 47 public boolean hasPermission(SecurityUser user, Operation operation, EntityId entityId, HasTenantId entity) {
  48 +
52 49 if (entity.getTenantId() != null && !entity.getTenantId().isNullUid()) {
53 50 return false;
54 51 }
... ... @@ -56,4 +53,16 @@ public class SysAdminPermissions extends AbstractPermissions {
56 53 }
57 54 };
58 55
  56 + private static final PermissionChecker userPermissionChecker = new PermissionChecker<UserId, User>() {
  57 +
  58 + @Override
  59 + public boolean hasPermission(SecurityUser user, Operation operation, UserId userId, User userEntity) {
  60 + if (Authority.CUSTOMER_USER.equals(userEntity.getAuthority())) {
  61 + return false;
  62 + }
  63 + return true;
  64 + }
  65 +
  66 + };
  67 +
59 68 }
... ...
... ... @@ -29,8 +29,7 @@ public enum EntityFilterType {
29 29 DEVICE_SEARCH_QUERY("deviceSearchQuery"),
30 30 ENTITY_VIEW_SEARCH_QUERY("entityViewSearchQuery"),
31 31 EDGE_SEARCH_QUERY("edgeSearchQuery"),
32   - API_USAGE_STATE("apiUsageState"),
33   - ENTITY_NAME_OR_ID("entityNameOrId");
  32 + API_USAGE_STATE("apiUsageState");
34 33
35 34 private final String label;
36 35
... ...
1   -/**
2   - * Copyright © 2016-2021 The Thingsboard Authors
3   - *
4   - * Licensed under the Apache License, Version 2.0 (the "License");
5   - * you may not use this file except in compliance with the License.
6   - * You may obtain a copy of the License at
7   - *
8   - * http://www.apache.org/licenses/LICENSE-2.0
9   - *
10   - * Unless required by applicable law or agreed to in writing, software
11   - * distributed under the License is distributed on an "AS IS" BASIS,
12   - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   - * See the License for the specific language governing permissions and
14   - * limitations under the License.
15   - */
16   -package org.thingsboard.server.common.data.query;
17   -
18   -import lombok.Data;
19   -import lombok.EqualsAndHashCode;
20   -import org.thingsboard.server.common.data.EntityType;
21   -
22   -@EqualsAndHashCode(callSuper = true)
23   -@Data
24   -public class EntityNameOrIdFilter extends EntitySearchQueryFilter {
25   - private String nameOrId;
26   - private EntityType entityType;
27   -
28   - @Override
29   - public EntityFilterType getType() {
30   - return EntityFilterType.ENTITY_NAME_OR_ID;
31   - }
32   -}
... ... @@ -44,7 +44,6 @@ import org.thingsboard.server.common.data.query.EntityFilterType;
44 44 import org.thingsboard.server.common.data.query.EntityKeyType;
45 45 import org.thingsboard.server.common.data.query.EntityListFilter;
46 46 import org.thingsboard.server.common.data.query.EntityNameFilter;
47   -import org.thingsboard.server.common.data.query.EntityNameOrIdFilter;
48 47 import org.thingsboard.server.common.data.query.EntitySearchQueryFilter;
49 48 import org.thingsboard.server.common.data.query.EntityTypeFilter;
50 49 import org.thingsboard.server.common.data.query.EntityViewSearchQueryFilter;
... ... @@ -237,12 +236,6 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository {
237 236 entityTableMap.put(EntityType.TENANT, "tenant");
238 237 entityTableMap.put(EntityType.API_USAGE_STATE, SELECT_API_USAGE_STATE);
239 238 entityTableMap.put(EntityType.EDGE, "edge");
240   - entityTableMap.put(EntityType.RULE_CHAIN, "rule_chain");
241   - entityTableMap.put(EntityType.WIDGETS_BUNDLE, "widgets_bundle");
242   - entityTableMap.put(EntityType.TENANT_PROFILE, "tenant_profile");
243   - entityTableMap.put(EntityType.DEVICE_PROFILE, "device_profile");
244   - entityTableMap.put(EntityType.TB_RESOURCE, "resource");
245   - entityTableMap.put(EntityType.OTA_PACKAGE, "ota_package");
246 239 }
247 240
248 241 public static EntityType[] RELATION_QUERY_ENTITY_TYPES = new EntityType[]{
... ... @@ -448,7 +441,7 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository {
448 441 Optional<EntityKeyMapping> sortOrderMappingOpt = mappings.stream().filter(EntityKeyMapping::isSortOrder).findFirst();
449 442 if (sortOrderMappingOpt.isPresent()) {
450 443 EntityKeyMapping sortOrderMapping = sortOrderMappingOpt.get();
451   - String direction = sortOrder.getDirection() == EntityDataSortOrder.Direction.ASC ? "asc" : "desc nulls last";
  444 + String direction = sortOrder.getDirection() == EntityDataSortOrder.Direction.ASC ? "asc" : "desc";
452 445 if (sortOrderMapping.getEntityKey().getType() == EntityKeyType.ENTITY_FIELD) {
453 446 dataQuery = String.format("%s order by %s %s, result.id %s", dataQuery, sortOrderMapping.getValueAlias(), direction, direction);
454 447 } else {
... ... @@ -478,26 +471,15 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository {
478 471 String entityFieldsQuery = EntityKeyMapping.buildQuery(ctx, entityFieldsFilters, entityFilter.getType());
479 472 String result = permissionQuery;
480 473 if (!entityFilterQuery.isEmpty()) {
481   - if (!result.isEmpty()) {
482   - result += " and (" + entityFilterQuery + ")";
483   - } else {
484   - result = "(" + entityFilterQuery + ")";
485   - }
  474 + result += " and (" + entityFilterQuery + ")";
486 475 }
487 476 if (!entityFieldsQuery.isEmpty()) {
488   - if (!result.isEmpty()) {
489   - result += " and (" + entityFieldsQuery + ")";
490   - } else {
491   - result = "(" + entityFieldsQuery + ")";
492   - }
  477 + result += " and (" + entityFieldsQuery + ")";
493 478 }
494 479 return result;
495 480 }
496 481
497 482 private String buildPermissionQuery(QueryContext ctx, EntityFilter entityFilter) {
498   - if (ctx.getTenantId().equals(TenantId.SYS_TENANT_ID)) {
499   - return "";
500   - }
501 483 switch (entityFilter.getType()) {
502 484 case RELATIONS_QUERY:
503 485 case DEVICE_SEARCH_QUERY:
... ... @@ -566,8 +548,6 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository {
566 548 case API_USAGE_STATE:
567 549 case ENTITY_TYPE:
568 550 return "";
569   - case ENTITY_NAME_OR_ID:
570   - return entityNameOrIdQuery(ctx, (EntityNameOrIdFilter) entityFilter);
571 551 default:
572 552 throw new RuntimeException("Not implemented!");
573 553 }
... ... @@ -779,27 +759,7 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository {
779 759
780 760 private String entityNameQuery(QueryContext ctx, EntityNameFilter filter) {
781 761 ctx.addStringParameter("entity_filter_name_filter", filter.getEntityNameFilter());
782   - return "lower(e.search_text) like lower(concat('%', :entity_filter_name_filter, '%'))";
783   - }
784   -
785   - private String entityNameOrIdQuery(QueryContext ctx, EntityNameOrIdFilter filter) {
786   - String nameOrId = filter.getNameOrId();
787   - if (StringUtils.isNotEmpty(nameOrId)) {
788   - nameOrId = nameOrId.replaceAll("%", "\\\\%").replaceAll("_", "\\\\_");
789   - ctx.addStringParameter("entity_id_or_search_text_filter", nameOrId);
790   - String query = "";
791   -
792   - String searchTextField = EntityKeyMapping.searchTextFields.get(filter.getEntityType());
793   - query += "lower(e." + searchTextField + ") like lower(concat('%', :entity_id_or_search_text_filter, '%'))";
794   -
795   - try {
796   - UUID.fromString(nameOrId);
797   - query += " or e.id = :entity_id_or_search_text_filter::uuid";
798   - } catch (Exception ignored) {}
799   -
800   - return query;
801   - }
802   - return "true";
  762 + return "lower(e.search_text) like lower(concat(:entity_filter_name_filter, '%%'))";
803 763 }
804 764
805 765 private String typeQuery(QueryContext ctx, EntityFilter filter) {
... ... @@ -827,7 +787,7 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository {
827 787 }
828 788 ctx.addStringParameter("entity_filter_type_query_type", type);
829 789 ctx.addStringParameter("entity_filter_type_query_name", name);
830   - return "e.type = :entity_filter_type_query_type and lower(e.search_text) like lower(concat('%', :entity_filter_type_query_name, '%'))";
  790 + return "e.type = :entity_filter_type_query_type and lower(e.search_text) like lower(concat(:entity_filter_type_query_name, '%%'))";
831 791 }
832 792
833 793 private EntityType resolveEntityType(EntityFilter entityFilter) {
... ... @@ -856,8 +816,6 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository {
856 816 return ((RelationsQueryFilter) entityFilter).getRootEntity().getEntityType();
857 817 case API_USAGE_STATE:
858 818 return EntityType.API_USAGE_STATE;
859   - case ENTITY_NAME_OR_ID:
860   - return ((EntityNameOrIdFilter) entityFilter).getEntityType();
861 819 default:
862 820 throw new RuntimeException("Not implemented!");
863 821 }
... ...
... ... @@ -38,7 +38,6 @@ import org.thingsboard.server.dao.model.ModelConstants;
38 38 import java.util.ArrayList;
39 39 import java.util.Arrays;
40 40 import java.util.Collections;
41   -import java.util.EnumMap;
42 41 import java.util.HashMap;
43 42 import java.util.HashSet;
44 43 import java.util.List;
... ... @@ -54,8 +53,6 @@ public class EntityKeyMapping {
54 53 private static final Map<EntityType, Set<String>> allowedEntityFieldMap = new HashMap<>();
55 54 private static final Map<String, String> entityFieldColumnMap = new HashMap<>();
56 55 private static final Map<EntityType, Map<String, String>> aliases = new HashMap<>();
57   - private static final Map<EntityType, Map<String, String>> propertiesFunctions = new EnumMap<>(EntityType.class);
58   - public static final Map<EntityType, String> searchTextFields = new EnumMap<>(EntityType.class);
59 56
60 57 public static final String CREATED_TIME = "createdTime";
61 58 public static final String ENTITY_TYPE = "entityType";
... ... @@ -75,51 +72,35 @@ public class EntityKeyMapping {
75 72 public static final String ZIP = "zip";
76 73 public static final String PHONE = "phone";
77 74 public static final String ADDITIONAL_INFO = "additionalInfo";
78   - public static final String TENANT_ID = "tenantId";
79   - public static final String CUSTOMER_ID = "customerId";
80   - public static final String AUTHORITY = "authority";
81   - public static final String RESOURCE_TYPE = "resourceType";
82   - public static final String LAST_ACTIVITY_TIME = "lastActivityTime";
83 75
84   - public static final List<String> typedEntityFields = Arrays.asList(CREATED_TIME, ENTITY_TYPE, NAME, TYPE, ADDITIONAL_INFO, TENANT_ID);
  76 + public static final List<String> typedEntityFields = Arrays.asList(CREATED_TIME, ENTITY_TYPE, NAME, TYPE, ADDITIONAL_INFO);
  77 + public static final List<String> widgetEntityFields = Arrays.asList(CREATED_TIME, ENTITY_TYPE, NAME);
85 78 public static final List<String> commonEntityFields = Arrays.asList(CREATED_TIME, ENTITY_TYPE, NAME, ADDITIONAL_INFO);
86   -
87   - public static final List<String> dashboardEntityFields = Arrays.asList(CREATED_TIME, ENTITY_TYPE, TITLE, TENANT_ID);
88   - public static final List<String> labeledEntityFields = Arrays.asList(CREATED_TIME, ENTITY_TYPE, NAME, TYPE, LABEL, ADDITIONAL_INFO, TENANT_ID, CUSTOMER_ID);
  79 + public static final List<String> dashboardEntityFields = Arrays.asList(CREATED_TIME, ENTITY_TYPE, TITLE);
  80 + public static final List<String> labeledEntityFields = Arrays.asList(CREATED_TIME, ENTITY_TYPE, NAME, TYPE, LABEL, ADDITIONAL_INFO);
89 81 public static final List<String> contactBasedEntityFields = Arrays.asList(CREATED_TIME, ENTITY_TYPE, EMAIL, TITLE, COUNTRY, STATE, CITY, ADDRESS, ADDRESS_2, ZIP, PHONE, ADDITIONAL_INFO);
90 82
91   - public static final Set<String> apiUsageStateEntityFields = new HashSet<>(Arrays.asList(CREATED_TIME, ENTITY_TYPE, NAME));
  83 + public static final Set<String> apiUsageStateEntityFields = new HashSet<>(Arrays.asList(CREATED_TIME, ENTITY_TYPE, NAME));
92 84 public static final Set<String> commonEntityFieldsSet = new HashSet<>(commonEntityFields);
93 85 public static final Set<String> relationQueryEntityFieldsSet = new HashSet<>(Arrays.asList(CREATED_TIME, ENTITY_TYPE, NAME, TYPE, LABEL, FIRST_NAME, LAST_NAME, EMAIL, REGION, TITLE, COUNTRY, STATE, CITY, ADDRESS, ADDRESS_2, ZIP, PHONE, ADDITIONAL_INFO));
94 86
95 87 static {
96 88 allowedEntityFieldMap.put(EntityType.DEVICE, new HashSet<>(labeledEntityFields));
97 89 allowedEntityFieldMap.put(EntityType.ASSET, new HashSet<>(labeledEntityFields));
98   - allowedEntityFieldMap.put(EntityType.EDGE, new HashSet<>(labeledEntityFields));
99 90 allowedEntityFieldMap.put(EntityType.ENTITY_VIEW, new HashSet<>(typedEntityFields));
100   - allowedEntityFieldMap.get(EntityType.ENTITY_VIEW).add(CUSTOMER_ID);
101 91
102 92 allowedEntityFieldMap.put(EntityType.TENANT, new HashSet<>(contactBasedEntityFields));
103 93 allowedEntityFieldMap.get(EntityType.TENANT).add(REGION);
104 94 allowedEntityFieldMap.put(EntityType.CUSTOMER, new HashSet<>(contactBasedEntityFields));
105   - allowedEntityFieldMap.get(EntityType.CUSTOMER).add(TENANT_ID);
106   -
107   - allowedEntityFieldMap.put(EntityType.USER, new HashSet<>(Arrays.asList(CREATED_TIME, FIRST_NAME, LAST_NAME, EMAIL,
108   - ADDITIONAL_INFO, AUTHORITY, TENANT_ID, CUSTOMER_ID)));
109 95
110   - allowedEntityFieldMap.put(EntityType.DEVICE_PROFILE, new HashSet<>(commonEntityFields));
111   - allowedEntityFieldMap.get(EntityType.DEVICE_PROFILE).add(TENANT_ID);
  96 + allowedEntityFieldMap.put(EntityType.USER, new HashSet<>(Arrays.asList(CREATED_TIME, FIRST_NAME, LAST_NAME, EMAIL, ADDITIONAL_INFO)));
112 97
113 98 allowedEntityFieldMap.put(EntityType.DASHBOARD, new HashSet<>(dashboardEntityFields));
114 99 allowedEntityFieldMap.put(EntityType.RULE_CHAIN, new HashSet<>(commonEntityFields));
115   - allowedEntityFieldMap.get(EntityType.RULE_CHAIN).add(TENANT_ID);
116   - allowedEntityFieldMap.get(EntityType.RULE_CHAIN).add(TYPE);
117 100 allowedEntityFieldMap.put(EntityType.RULE_NODE, new HashSet<>(commonEntityFields));
118   - allowedEntityFieldMap.put(EntityType.WIDGET_TYPE, new HashSet<>(Arrays.asList(CREATED_TIME, ENTITY_TYPE, NAME, TENANT_ID)));
119   - allowedEntityFieldMap.put(EntityType.WIDGETS_BUNDLE, new HashSet<>(Arrays.asList(CREATED_TIME, ENTITY_TYPE, TITLE, TENANT_ID)));
  101 + allowedEntityFieldMap.put(EntityType.WIDGET_TYPE, new HashSet<>(widgetEntityFields));
  102 + allowedEntityFieldMap.put(EntityType.WIDGETS_BUNDLE, new HashSet<>(widgetEntityFields));
120 103 allowedEntityFieldMap.put(EntityType.API_USAGE_STATE, apiUsageStateEntityFields);
121   - allowedEntityFieldMap.put(EntityType.TB_RESOURCE, Set.of(CREATED_TIME, ENTITY_TYPE, RESOURCE_TYPE, TITLE, TENANT_ID));
122   - allowedEntityFieldMap.put(EntityType.OTA_PACKAGE, Set.of(CREATED_TIME, ENTITY_TYPE, TYPE, TITLE, TENANT_ID));
123 104
124 105 entityFieldColumnMap.put(CREATED_TIME, ModelConstants.CREATED_TIME_PROPERTY);
125 106 entityFieldColumnMap.put(ENTITY_TYPE, ModelConstants.ENTITY_TYPE_PROPERTY);
... ... @@ -139,42 +120,25 @@ public class EntityKeyMapping {
139 120 entityFieldColumnMap.put(ZIP, ModelConstants.ZIP_PROPERTY);
140 121 entityFieldColumnMap.put(PHONE, ModelConstants.PHONE_PROPERTY);
141 122 entityFieldColumnMap.put(ADDITIONAL_INFO, ModelConstants.ADDITIONAL_INFO_PROPERTY);
142   - entityFieldColumnMap.put(TENANT_ID, ModelConstants.TENANT_ID_PROPERTY);
143   - entityFieldColumnMap.put(CUSTOMER_ID, ModelConstants.CUSTOMER_ID_PROPERTY);
144   - entityFieldColumnMap.put(AUTHORITY, ModelConstants.USER_AUTHORITY_PROPERTY);
145   - entityFieldColumnMap.put(RESOURCE_TYPE, ModelConstants.RESOURCE_TYPE_COLUMN);
146 123
147 124 Map<String, String> contactBasedAliases = new HashMap<>();
148 125 contactBasedAliases.put(NAME, TITLE);
149 126 contactBasedAliases.put(LABEL, TITLE);
150 127 aliases.put(EntityType.TENANT, contactBasedAliases);
151   - aliases.put(EntityType.CUSTOMER, new HashMap<>(contactBasedAliases));
  128 + aliases.put(EntityType.CUSTOMER, contactBasedAliases);
152 129 aliases.put(EntityType.DASHBOARD, contactBasedAliases);
153 130 Map<String, String> commonEntityAliases = new HashMap<>();
154 131 commonEntityAliases.put(TITLE, NAME);
155 132 aliases.put(EntityType.DEVICE, commonEntityAliases);
156 133 aliases.put(EntityType.ASSET, commonEntityAliases);
157 134 aliases.put(EntityType.ENTITY_VIEW, commonEntityAliases);
158   - aliases.put(EntityType.EDGE, commonEntityAliases);
159   - aliases.put(EntityType.WIDGETS_BUNDLE, new HashMap<>(commonEntityAliases));
160   - aliases.get(EntityType.WIDGETS_BUNDLE).put(NAME, TITLE);
  135 + aliases.put(EntityType.WIDGETS_BUNDLE, commonEntityAliases);
161 136
162 137 Map<String, String> userEntityAliases = new HashMap<>();
163 138 userEntityAliases.put(TITLE, EMAIL);
164 139 userEntityAliases.put(LABEL, EMAIL);
165 140 userEntityAliases.put(NAME, EMAIL);
166   - userEntityAliases.put(TYPE, AUTHORITY);
167 141 aliases.put(EntityType.USER, userEntityAliases);
168   - aliases.put(EntityType.TB_RESOURCE, Map.of(NAME, TITLE, TYPE, RESOURCE_TYPE));
169   - aliases.put(EntityType.OTA_PACKAGE, Map.of(NAME, TITLE));
170   -
171   - propertiesFunctions.put(EntityType.USER, Map.of(
172   - LAST_ACTIVITY_TIME, "cast(e.additional_info::json ->> 'lastLoginTs' as bigint)"
173   - ));
174   -
175   - Arrays.stream(EntityType.values()).forEach(entityType -> {
176   - searchTextFields.put(entityType, ModelConstants.SEARCH_TEXT_PROPERTY);
177   - });
178 142 }
179 143
180 144 private int index;
... ... @@ -215,10 +179,6 @@ public class EntityKeyMapping {
215 179 String column = entityFieldColumnMap.get(alias);
216 180 return String.format("cast(e.%s as varchar) as %s", column, getValueAlias());
217 181 } else {
218   - Map<String, String> entityPropertiesFunctions = propertiesFunctions.get(entityType);
219   - if (entityPropertiesFunctions != null && entityPropertiesFunctions.containsKey(alias)) {
220   - return String.format("%s as %s", entityPropertiesFunctions.get(alias), getValueAlias());
221   - }
222 182 return String.format("'' as %s", getValueAlias());
223 183 }
224 184 }
... ...