Add validation for EntityDataPageLink

This commit is contained in:
ViacheslavKlimov 2022-12-09 16:25:09 +02:00
parent bb42362f1d
commit 2494cec616
6 changed files with 43 additions and 19 deletions

View File

@ -23,7 +23,6 @@ import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.support.DefaultMessageSourceResolvable;
@ -47,6 +46,7 @@ import org.thingsboard.server.common.data.EntityViewInfo;
import org.thingsboard.server.common.data.HasTenantId;
import org.thingsboard.server.common.data.OtaPackage;
import org.thingsboard.server.common.data.OtaPackageInfo;
import org.thingsboard.server.common.data.StringUtils;
import org.thingsboard.server.common.data.TbResource;
import org.thingsboard.server.common.data.TbResourceInfo;
import org.thingsboard.server.common.data.Tenant;
@ -120,6 +120,7 @@ import org.thingsboard.server.dao.queue.QueueService;
import org.thingsboard.server.dao.relation.RelationService;
import org.thingsboard.server.dao.rpc.RpcService;
import org.thingsboard.server.dao.rule.RuleChainService;
import org.thingsboard.server.dao.service.Validator;
import org.thingsboard.server.dao.tenant.TbTenantProfileCache;
import org.thingsboard.server.dao.tenant.TenantProfileService;
import org.thingsboard.server.dao.tenant.TenantService;
@ -131,7 +132,6 @@ import org.thingsboard.server.queue.discovery.PartitionService;
import org.thingsboard.server.queue.provider.TbQueueProducerProvider;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.component.ComponentDiscoveryService;
import org.thingsboard.server.service.edge.EdgeNotificationService;
import org.thingsboard.server.service.edge.rpc.EdgeRpcService;
import org.thingsboard.server.service.entitiy.TbNotificationEntityService;
import org.thingsboard.server.service.ota.OtaPackageStateService;
@ -418,7 +418,7 @@ public abstract class BaseController {
PageLink createPageLink(int pageSize, int page, String textSearch, String sortProperty, String sortOrder) throws ThingsboardException {
if (StringUtils.isNotEmpty(sortProperty)) {
if (!StringUtils.isAlphanumeric(sortProperty)) {
if (!Validator.isValidProperty(sortProperty)) {
throw new IllegalArgumentException("Invalid sort property");
}
SortOrder.Direction direction = SortOrder.Direction.ASC;

View File

@ -400,7 +400,7 @@ public abstract class BaseEntityQueryControllerTest extends AbstractControllerTe
EntityDataQuery query = new EntityDataQuery(filter, pageLink, entityFields, latestValues, null);
ResultActions result = doPost("/api/entitiesQuery/find", query).andExpect(status().isBadRequest());
assertThat(getErrorMessage(result)).contains("Invalid").contains("sort key");
assertThat(getErrorMessage(result)).contains("Invalid").contains("sort property");
}
}

View File

@ -33,4 +33,8 @@ public class RegexUtils {
});
}
public static boolean matches(String input, Pattern pattern) {
return pattern.matcher(input).matches();
}
}

View File

@ -65,6 +65,7 @@ import java.util.concurrent.Executors;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.thingsboard.server.dao.service.Validator.validateEntityDataPageLink;
import static org.thingsboard.server.dao.service.Validator.validateId;
@Service
@ -139,6 +140,7 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ
public PageData<AlarmData> findAlarmDataByQueryForEntities(TenantId tenantId,
AlarmDataQuery query, Collection<EntityId> orderedEntityIds) {
validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
validateEntityDataPageLink(query.getPageLink());
return alarmDao.findAlarmDataByQueryForEntities(tenantId, query, orderedEntityIds);
}

View File

@ -60,6 +60,7 @@ import org.thingsboard.server.dao.tenant.TenantService;
import org.thingsboard.server.dao.user.UserService;
import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID;
import static org.thingsboard.server.dao.service.Validator.validateEntityDataPageLink;
import static org.thingsboard.server.dao.service.Validator.validateId;
/**
@ -239,21 +240,6 @@ public class BaseEntityService extends AbstractEntityService implements EntitySe
validateEntityDataPageLink(query.getPageLink());
}
private static void validateEntityDataPageLink(EntityDataPageLink pageLink) {
if (pageLink == null) {
throw new IncorrectParameterException("Entity Data Page link must be specified.");
} else if (pageLink.getPageSize() < 1) {
throw new IncorrectParameterException("Incorrect entity data page link page size '" + pageLink.getPageSize() + "'. Page size must be greater than zero.");
} else if (pageLink.getPage() < 0) {
throw new IncorrectParameterException("Incorrect entity data page link page '" + pageLink.getPage() + "'. Page must be positive integer.");
} else if (pageLink.getSortOrder() != null && pageLink.getSortOrder().getKey() != null) {
String sortKey = pageLink.getSortOrder().getKey().getKey();
if (StringUtils.isNotEmpty(sortKey) && !StringUtils.isAlphanumeric(sortKey)) {
throw new IncorrectParameterException("Invalid entity data page link sort key");
}
}
}
private static void validateRelationQuery(RelationsQueryFilter queryFilter) {
if (queryFilter.isMultiRoot() && queryFilter.getMultiRootEntitiesType() ==null){
throw new IncorrectParameterException("Multi-root relation query filter should contain 'multiRootEntitiesType'");

View File

@ -15,16 +15,24 @@
*/
package org.thingsboard.server.dao.service;
import org.apache.commons.lang3.StringUtils;
import org.thingsboard.common.util.RegexUtils;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.UUIDBased;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.query.EntityDataPageLink;
import org.thingsboard.server.common.data.query.EntityKey;
import org.thingsboard.server.common.data.query.EntityKeyType;
import org.thingsboard.server.dao.exception.IncorrectParameterException;
import java.util.List;
import java.util.UUID;
import java.util.regex.Pattern;
public class Validator {
public static final Pattern PROPERTY_PATTERN = Pattern.compile("^[\\p{L}0-9_-]+$"); // Unicode letters, numbers, '_' and '-' allowed
/**
* This method validate <code>EntityId</code> entity id. If entity id is invalid than throw
* <code>IncorrectParameterException</code> exception
@ -122,7 +130,31 @@ public class Validator {
throw new IncorrectParameterException("Incorrect page link page size '"+pageLink.getPageSize()+"'. Page size must be greater than zero.");
} else if (pageLink.getPage() < 0) {
throw new IncorrectParameterException("Incorrect page link page '"+pageLink.getPage()+"'. Page must be positive integer.");
} else if (pageLink.getSortOrder() != null) {
if (!isValidProperty(pageLink.getSortOrder().getProperty())) {
throw new IncorrectParameterException("Invalid page link sort property");
}
}
}
public static void validateEntityDataPageLink(EntityDataPageLink pageLink) {
if (pageLink == null) {
throw new IncorrectParameterException("Entity Data Page link must be specified.");
} else if (pageLink.getPageSize() < 1) {
throw new IncorrectParameterException("Incorrect entity data page link page size '" + pageLink.getPageSize() + "'. Page size must be greater than zero.");
} else if (pageLink.getPage() < 0) {
throw new IncorrectParameterException("Incorrect entity data page link page '" + pageLink.getPage() + "'. Page must be positive integer.");
} else if (pageLink.getSortOrder() != null && pageLink.getSortOrder().getKey() != null) {
EntityKey sortKey = pageLink.getSortOrder().getKey();
if ((sortKey.getType() == EntityKeyType.ENTITY_FIELD || sortKey.getType() == EntityKeyType.ALARM_FIELD)
&& !isValidProperty(sortKey.getKey())) {
throw new IncorrectParameterException("Invalid entity data page link sort property");
}
}
}
public static boolean isValidProperty(String key) {
return StringUtils.isEmpty(key) || RegexUtils.matches(key, PROPERTY_PATTERN);
}
}