Commit c698b92397b66db24e7aafd040203d34140113a5

Authored by Igor Kulikov
2 parents ea3c6f34 436aedef

Merge branch 'master' of github.com:thingsboard/thingsboard

... ... @@ -124,7 +124,7 @@ public class DefaultAlarmQueryRepository implements AlarmQueryRepository {
124 124 AlarmDataQuery query, Collection<EntityId> orderedEntityIds) {
125 125 return transactionTemplate.execute(status -> {
126 126 AlarmDataPageLink pageLink = query.getPageLink();
127   - QueryContext ctx = new QueryContext();
  127 + QueryContext ctx = new QueryContext(new QuerySecurityContext(tenantId, customerId, EntityType.ALARM));
128 128 ctx.addUuidListParameter("entity_ids", orderedEntityIds.stream().map(EntityId::getId).collect(Collectors.toList()));
129 129
130 130 StringBuilder selectPart = new StringBuilder(FIELDS_SELECTION);
... ...
... ... @@ -227,11 +227,11 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository {
227 227 @Override
228 228 public long countEntitiesByQuery(TenantId tenantId, CustomerId customerId, EntityCountQuery query) {
229 229 EntityType entityType = resolveEntityType(query.getEntityFilter());
230   - QueryContext ctx = new QueryContext();
  230 + QueryContext ctx = new QueryContext(new QuerySecurityContext(tenantId, customerId, entityType));
231 231 ctx.append("select count(e.id) from ");
232   - ctx.append(addEntityTableQuery(ctx, query.getEntityFilter(), entityType));
  232 + ctx.append(addEntityTableQuery(ctx, query.getEntityFilter()));
233 233 ctx.append(" e where ");
234   - ctx.append(buildEntityWhere(ctx, tenantId, customerId, query.getEntityFilter(), Collections.emptyList(), entityType));
  234 + ctx.append(buildEntityWhere(ctx, query.getEntityFilter(), Collections.emptyList()));
235 235 // log.error("QUERY: {}", ctx.getQuery());
236 236 // Arrays.asList(ctx.getParameterNames()).forEach(param -> log.error("QUERY PARAM: {}->{}", param, ctx.getValue(param)));
237 237 return transactionTemplate.execute(status -> jdbcTemplate.queryForObject(ctx.getQuery(), ctx, Long.class));
... ... @@ -240,8 +240,8 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository {
240 240 @Override
241 241 public PageData<EntityData> findEntityDataByQuery(TenantId tenantId, CustomerId customerId, EntityDataQuery query) {
242 242 return transactionTemplate.execute(status -> {
243   - QueryContext ctx = new QueryContext();
244 243 EntityType entityType = resolveEntityType(query.getEntityFilter());
  244 + QueryContext ctx = new QueryContext(new QuerySecurityContext(tenantId, customerId, entityType));
245 245 EntityDataPageLink pageLink = query.getPageLink();
246 246
247 247 List<EntityKeyMapping> mappings = EntityKeyMapping.prepareKeyMapping(query);
... ... @@ -264,9 +264,9 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository {
264 264 .collect(Collectors.toList());
265 265
266 266
267   - String entityWhereClause = DefaultEntityQueryRepository.this.buildEntityWhere(ctx, tenantId, customerId, query.getEntityFilter(), entityFieldsFiltersMapping, entityType);
  267 + String entityWhereClause = DefaultEntityQueryRepository.this.buildEntityWhere(ctx, query.getEntityFilter(), entityFieldsFiltersMapping);
268 268 String latestJoins = EntityKeyMapping.buildLatestJoins(ctx, query.getEntityFilter(), entityType, allLatestMappings);
269   - String whereClause = DefaultEntityQueryRepository.this.buildWhere(ctx, latestFiltersMapping, query.getEntityFilter().getType(), entityType);
  269 + String whereClause = DefaultEntityQueryRepository.this.buildWhere(ctx, latestFiltersMapping, query.getEntityFilter().getType());
270 270 String textSearchQuery = DefaultEntityQueryRepository.this.buildTextSearchQuery(ctx, selectionMapping, pageLink.getTextSearch());
271 271 String entityFieldsSelection = EntityKeyMapping.buildSelections(entityFieldsSelectionMapping, query.getEntityFilter().getType(), entityType);
272 272 String entityTypeStr;
... ... @@ -289,7 +289,7 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository {
289 289 String fromClause = String.format("from (select %s from (select %s from %s e where %s) entities %s %s) result %s",
290 290 topSelection,
291 291 entityFieldsSelection,
292   - addEntityTableQuery(ctx, query.getEntityFilter(), entityType),
  292 + addEntityTableQuery(ctx, query.getEntityFilter()),
293 293 entityWhereClause,
294 294 latestJoins,
295 295 whereClause,
... ... @@ -323,15 +323,10 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository {
323 323 });
324 324 }
325 325
326   - private String buildEntityWhere(QueryContext ctx,
327   - TenantId tenantId,
328   - CustomerId customerId,
329   - EntityFilter entityFilter,
330   - List<EntityKeyMapping> entityFieldsFilters,
331   - EntityType entityType) {
332   - String permissionQuery = this.buildPermissionQuery(ctx, entityFilter, tenantId, customerId, entityType);
  326 + private String buildEntityWhere(QueryContext ctx, EntityFilter entityFilter, List<EntityKeyMapping> entityFieldsFilters) {
  327 + String permissionQuery = this.buildPermissionQuery(ctx, entityFilter);
333 328 String entityFilterQuery = this.buildEntityFilterQuery(ctx, entityFilter);
334   - String entityFieldsQuery = EntityKeyMapping.buildQuery(ctx, entityFieldsFilters, entityFilter.getType(), entityType);
  329 + String entityFieldsQuery = EntityKeyMapping.buildQuery(ctx, entityFieldsFilters, entityFilter.getType());
335 330 String result = permissionQuery;
336 331 if (!entityFilterQuery.isEmpty()) {
337 332 result += " and " + entityFilterQuery;
... ... @@ -342,28 +337,28 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository {
342 337 return result;
343 338 }
344 339
345   - private String buildPermissionQuery(QueryContext ctx, EntityFilter entityFilter, TenantId tenantId, CustomerId customerId, EntityType entityType) {
  340 + private String buildPermissionQuery(QueryContext ctx, EntityFilter entityFilter) {
346 341 switch (entityFilter.getType()) {
347 342 case RELATIONS_QUERY:
348 343 case DEVICE_SEARCH_QUERY:
349 344 case ASSET_SEARCH_QUERY:
350 345 case ENTITY_VIEW_SEARCH_QUERY:
351   - return this.defaultPermissionQuery(ctx, tenantId, customerId, entityType);
  346 + return this.defaultPermissionQuery(ctx);
352 347 default:
353   - if (entityType == EntityType.TENANT) {
354   - ctx.addUuidParameter("permissions_tenant_id", tenantId.getId());
  348 + if (ctx.getEntityType() == EntityType.TENANT) {
  349 + ctx.addUuidParameter("permissions_tenant_id", ctx.getTenantId().getId());
355 350 return "e.id=:permissions_tenant_id";
356 351 } else {
357   - return this.defaultPermissionQuery(ctx, tenantId, customerId, entityType);
  352 + return this.defaultPermissionQuery(ctx);
358 353 }
359 354 }
360 355 }
361 356
362   - private String defaultPermissionQuery(QueryContext ctx, TenantId tenantId, CustomerId customerId, EntityType entityType) {
363   - ctx.addUuidParameter("permissions_tenant_id", tenantId.getId());
364   - if (customerId != null && !customerId.isNullUid()) {
365   - ctx.addUuidParameter("permissions_customer_id", customerId.getId());
366   - if (entityType == EntityType.CUSTOMER) {
  357 + private String defaultPermissionQuery(QueryContext ctx) {
  358 + ctx.addUuidParameter("permissions_tenant_id", ctx.getTenantId().getId());
  359 + if (ctx.getCustomerId() != null && !ctx.getCustomerId().isNullUid()) {
  360 + ctx.addUuidParameter("permissions_customer_id", ctx.getCustomerId().getId());
  361 + if (ctx.getEntityType() == EntityType.CUSTOMER) {
367 362 return "e.tenant_id=:permissions_tenant_id and e.id=:permissions_customer_id";
368 363 } else {
369 364 return "e.tenant_id=:permissions_tenant_id and e.customer_id=:permissions_customer_id";
... ... @@ -395,7 +390,7 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository {
395 390 }
396 391 }
397 392
398   - private String addEntityTableQuery(QueryContext ctx, EntityFilter entityFilter, EntityType entityType) {
  393 + private String addEntityTableQuery(QueryContext ctx, EntityFilter entityFilter) {
399 394 switch (entityFilter.getType()) {
400 395 case RELATIONS_QUERY:
401 396 return relationQuery(ctx, (RelationsQueryFilter) entityFilter);
... ... @@ -409,7 +404,7 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository {
409 404 EntityViewSearchQueryFilter entityViewQuery = (EntityViewSearchQueryFilter) entityFilter;
410 405 return entitySearchQuery(ctx, entityViewQuery, EntityType.ENTITY_VIEW, entityViewQuery.getEntityViewTypes());
411 406 default:
412   - return entityTableMap.get(entityType);
  407 + return entityTableMap.get(ctx.getEntityType());
413 408 }
414 409 }
415 410
... ... @@ -505,8 +500,8 @@ public class DefaultEntityQueryRepository implements EntityQueryRepository {
505 500 return from;
506 501 }
507 502
508   - private String buildWhere(QueryContext ctx, List<EntityKeyMapping> latestFiltersMapping, EntityFilterType filterType, EntityType entityType) {
509   - String latestFilters = EntityKeyMapping.buildQuery(ctx, latestFiltersMapping, filterType, entityType);
  503 + private String buildWhere(QueryContext ctx, List<EntityKeyMapping> latestFiltersMapping, EntityFilterType filterType) {
  504 + String latestFilters = EntityKeyMapping.buildQuery(ctx, latestFiltersMapping, filterType);
510 505 if (!StringUtils.isEmpty(latestFilters)) {
511 506 return String.format("where %s", latestFilters);
512 507 } else {
... ...
... ... @@ -214,11 +214,11 @@ public class EntityKeyMapping {
214 214 return alias;
215 215 }
216 216
217   - public Stream<String> toQueries(QueryContext ctx, EntityFilterType filterType, EntityType entityType) {
  217 + public Stream<String> toQueries(QueryContext ctx, EntityFilterType filterType) {
218 218 if (hasFilter()) {
219 219 String keyAlias = entityKey.getType().equals(EntityKeyType.ENTITY_FIELD) ? "e" : alias;
220 220 return keyFilters.stream().map(keyFilter ->
221   - this.buildKeyQuery(ctx, keyAlias, keyFilter, filterType, entityType));
  221 + this.buildKeyQuery(ctx, keyAlias, keyFilter, filterType));
222 222 } else {
223 223 return null;
224 224 }
... ... @@ -271,8 +271,8 @@ public class EntityKeyMapping {
271 271 Collectors.joining(" "));
272 272 }
273 273
274   - public static String buildQuery(QueryContext ctx, List<EntityKeyMapping> mappings, EntityFilterType filterType, EntityType entityType) {
275   - return mappings.stream().flatMap(mapping -> mapping.toQueries(ctx, filterType, entityType)).filter(Objects::nonNull).collect(
  274 + public static String buildQuery(QueryContext ctx, List<EntityKeyMapping> mappings, EntityFilterType filterType) {
  275 + return mappings.stream().flatMap(mapping -> mapping.toQueries(ctx, filterType)).filter(Objects::nonNull).collect(
276 276 Collectors.joining(" AND "));
277 277 }
278 278
... ... @@ -385,33 +385,33 @@ public class EntityKeyMapping {
385 385 }
386 386
387 387 private String buildKeyQuery(QueryContext ctx, String alias, KeyFilter keyFilter,
388   - EntityFilterType filterType, EntityType entityType) {
389   - return this.buildPredicateQuery(ctx, alias, keyFilter.getKey(), keyFilter.getPredicate(), filterType, entityType);
  388 + EntityFilterType filterType) {
  389 + return this.buildPredicateQuery(ctx, alias, keyFilter.getKey(), keyFilter.getPredicate(), filterType);
390 390 }
391 391
392 392 private String buildPredicateQuery(QueryContext ctx, String alias, EntityKey key,
393   - KeyFilterPredicate predicate, EntityFilterType filterType, EntityType entityType) {
  393 + KeyFilterPredicate predicate, EntityFilterType filterType) {
394 394 if (predicate.getType().equals(FilterPredicateType.COMPLEX)) {
395   - return this.buildComplexPredicateQuery(ctx, alias, key, (ComplexFilterPredicate) predicate, filterType, entityType);
  395 + return this.buildComplexPredicateQuery(ctx, alias, key, (ComplexFilterPredicate) predicate, filterType);
396 396 } else {
397   - return this.buildSimplePredicateQuery(ctx, alias, key, predicate, filterType, entityType);
  397 + return this.buildSimplePredicateQuery(ctx, alias, key, predicate, filterType);
398 398 }
399 399 }
400 400
401 401 private String buildComplexPredicateQuery(QueryContext ctx, String alias, EntityKey key,
402   - ComplexFilterPredicate predicate, EntityFilterType filterType, EntityType entityType) {
  402 + ComplexFilterPredicate predicate, EntityFilterType filterType) {
403 403 return predicate.getPredicates().stream()
404   - .map(keyFilterPredicate -> this.buildPredicateQuery(ctx, alias, key, keyFilterPredicate, filterType, entityType))
  404 + .map(keyFilterPredicate -> this.buildPredicateQuery(ctx, alias, key, keyFilterPredicate, filterType))
405 405 .filter(Objects::nonNull).collect(Collectors.joining(
406 406 " " + predicate.getOperation().name() + " "
407 407 ));
408 408 }
409 409
410 410 private String buildSimplePredicateQuery(QueryContext ctx, String alias, EntityKey key,
411   - KeyFilterPredicate predicate, EntityFilterType filterType, EntityType entityType) {
  411 + KeyFilterPredicate predicate, EntityFilterType filterType) {
412 412 if (key.getType().equals(EntityKeyType.ENTITY_FIELD)) {
413   - Set<String> existingEntityFields = getExistingEntityFields(filterType, entityType);
414   - String entityFieldAlias = getEntityFieldAlias(filterType, entityType);
  413 + Set<String> existingEntityFields = getExistingEntityFields(filterType, ctx.getEntityType());
  414 + String entityFieldAlias = getEntityFieldAlias(filterType, ctx.getEntityType());
415 415 String column = null;
416 416 if (existingEntityFields.contains(entityFieldAlias)) {
417 417 column = entityFieldColumnMap.get(entityFieldAlias);
... ...
... ... @@ -17,6 +17,9 @@ package org.thingsboard.server.dao.sql.query;
17 17
18 18 import org.hibernate.type.PostgresUUIDType;
19 19 import org.springframework.jdbc.core.namedparam.SqlParameterSource;
  20 +import org.thingsboard.server.common.data.EntityType;
  21 +import org.thingsboard.server.common.data.id.CustomerId;
  22 +import org.thingsboard.server.common.data.id.TenantId;
20 23
21 24 import java.sql.Types;
22 25 import java.util.HashMap;
... ... @@ -27,10 +30,12 @@ import java.util.UUID;
27 30 public class QueryContext implements SqlParameterSource {
28 31 private static final PostgresUUIDType UUID_TYPE = new PostgresUUIDType();
29 32
  33 + private final QuerySecurityContext securityCtx;
30 34 private final StringBuilder query;
31 35 private final Map<String, Parameter> params;
32 36
33   - public QueryContext() {
  37 + public QueryContext(QuerySecurityContext securityCtx) {
  38 + this.securityCtx = securityCtx;
34 39 query = new StringBuilder();
35 40 params = new HashMap<>();
36 41 }
... ... @@ -123,4 +128,16 @@ public class QueryContext implements SqlParameterSource {
123 128 this.name = name;
124 129 }
125 130 }
  131 +
  132 + public TenantId getTenantId() {
  133 + return securityCtx.getTenantId();
  134 + }
  135 +
  136 + public CustomerId getCustomerId() {
  137 + return securityCtx.getCustomerId();
  138 + }
  139 +
  140 + public EntityType getEntityType() {
  141 + return securityCtx.getEntityType();
  142 + }
126 143 }
... ...
  1 +/**
  2 + * Copyright © 2016-2020 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.dao.sql.query;
  17 +
  18 +import lombok.AllArgsConstructor;
  19 +import lombok.Getter;
  20 +import org.hibernate.type.PostgresUUIDType;
  21 +import org.springframework.jdbc.core.namedparam.SqlParameterSource;
  22 +import org.thingsboard.server.common.data.EntityType;
  23 +import org.thingsboard.server.common.data.id.CustomerId;
  24 +import org.thingsboard.server.common.data.id.TenantId;
  25 +
  26 +import java.sql.Types;
  27 +import java.util.HashMap;
  28 +import java.util.List;
  29 +import java.util.Map;
  30 +import java.util.UUID;
  31 +
  32 +@AllArgsConstructor
  33 +public class QuerySecurityContext {
  34 +
  35 + @Getter
  36 + private final TenantId tenantId;
  37 + @Getter
  38 + private final CustomerId customerId;
  39 + @Getter
  40 + private final EntityType entityType;
  41 +
  42 +}
\ No newline at end of file
... ...