Commit c698b92397b66db24e7aafd040203d34140113a5
Merge branch 'master' of github.com:thingsboard/thingsboard
Showing
5 changed files
with
99 additions
and
45 deletions
... | ... | @@ -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 | ... | ... |