Better error handling of invalid values in faceted search

This commit is contained in:
Francesco 2023-09-30 10:16:06 +02:00
parent fd2728083b
commit e72fcda5fe
6 changed files with 39 additions and 10 deletions

View File

@ -37,6 +37,7 @@ import tech.ailef.dbadmin.external.dto.FacetedSearchRequest;
import tech.ailef.dbadmin.external.dto.LogsSearchRequest; import tech.ailef.dbadmin.external.dto.LogsSearchRequest;
import tech.ailef.dbadmin.external.dto.PaginatedResult; import tech.ailef.dbadmin.external.dto.PaginatedResult;
import tech.ailef.dbadmin.external.dto.QueryFilter; import tech.ailef.dbadmin.external.dto.QueryFilter;
import tech.ailef.dbadmin.external.exceptions.DbAdminException;
import tech.ailef.dbadmin.external.exceptions.InvalidPageException; import tech.ailef.dbadmin.external.exceptions.InvalidPageException;
import tech.ailef.dbadmin.external.misc.Utils; import tech.ailef.dbadmin.external.misc.Utils;
import tech.ailef.dbadmin.internal.model.UserAction; import tech.ailef.dbadmin.internal.model.UserAction;
@ -184,6 +185,16 @@ public class DefaultDbAdminController {
} catch (InvalidPageException e) { } catch (InvalidPageException e) {
return "redirect:/" + properties.getBaseUrl() + "/model/" + className; return "redirect:/" + properties.getBaseUrl() + "/model/" + className;
} catch (DbAdminException e) {
model.addAttribute("error", e.getMessage());
model.addAttribute("errorTitle", "Invalid request");
model.addAttribute("schema", schema);
model.addAttribute("activePage", "entities");
model.addAttribute("sortKey", sortKey);
model.addAttribute("query", query);
model.addAttribute("sortOrder", sortOrder);
model.addAttribute("activeFilters", queryFilters);
return "model/list";
} }
} }

View File

@ -153,7 +153,12 @@ public class CustomJpaRepository extends SimpleJpaRepository {
String fieldName = dbField.getJavaName(); String fieldName = dbField.getJavaName();
String v = filter.getValue(); String v = filter.getValue();
Object value = dbField.getType().parseValue(v); Object value;
try {
value = dbField.getType().parseValue(v);
} catch (Exception e) {
throw new DbAdminException("Invalid value `" + v + "` specified for field `" + dbField.getName() + "`");
}
if (op == CompareOperator.STRING_EQ) { if (op == CompareOperator.STRING_EQ) {
if (value == null) if (value == null)

View File

@ -3,6 +3,7 @@ package tech.ailef.dbadmin.external.dto;
import java.util.Objects; import java.util.Objects;
import tech.ailef.dbadmin.external.dbmapping.DbField; import tech.ailef.dbadmin.external.dbmapping.DbField;
import tech.ailef.dbadmin.external.exceptions.DbAdminException;
/** /**
* A single filter in a FacetedSearchRequest. This describes a * A single filter in a FacetedSearchRequest. This describes a
@ -16,6 +17,8 @@ public class QueryFilter {
private String value; private String value;
public QueryFilter(DbField field, CompareOperator op, String value) { public QueryFilter(DbField field, CompareOperator op, String value) {
if (field == null)
throw new DbAdminException("Trying to build QueryFilter with null `field`");
this.field = field; this.field = field;
this.op = op; this.op = op;
this.value = value; this.value = value;
@ -53,7 +56,7 @@ public class QueryFilter {
public String toString() { public String toString() {
if (value != null && !value.toString().isBlank()) { if (value != null && !value.toString().isBlank()) {
String displayValue = value; String displayValue = value;
if (value.length() > 10) { if (value.length() > 18) {
displayValue = value.substring(0, 4) + "..." + value.substring(value.length() - 4); displayValue = value.substring(0, 4) + "..." + value.substring(value.length() - 4);
} }
return "'" + field.getName() + "' " + op.getDisplayName() + " '" + displayValue + "'"; return "'" + field.getName() + "' " + op.getDisplayName() + " '" + displayValue + "'";

View File

@ -7,6 +7,7 @@ import java.util.Set;
import org.springframework.util.MultiValueMap; import org.springframework.util.MultiValueMap;
import tech.ailef.dbadmin.external.dbmapping.DbField;
import tech.ailef.dbadmin.external.dbmapping.DbObjectSchema; import tech.ailef.dbadmin.external.dbmapping.DbObjectSchema;
import tech.ailef.dbadmin.external.dto.CompareOperator; import tech.ailef.dbadmin.external.dto.CompareOperator;
import tech.ailef.dbadmin.external.dto.QueryFilter; import tech.ailef.dbadmin.external.dto.QueryFilter;
@ -82,9 +83,16 @@ public interface Utils {
String field = fields.get(i); String field = fields.get(i);
String value = values.get(i); String value = values.get(i);
QueryFilter queryFilter = new QueryFilter(schema.getFieldByJavaName(field), CompareOperator.valueOf(op.toUpperCase()), value); // Check if the field can actually be found before creating the filter
// This shouldn't normally happen because this parameter is not provided
// by the user; but there's the chance of a stale bookmarked link referring
// to a non-existing schema or the user fiddling with the URL
DbField dbField = schema.getFieldByJavaName(field);
if (dbField != null) {
QueryFilter queryFilter = new QueryFilter(dbField, CompareOperator.valueOf(op.toUpperCase()), value);
filters.add(queryFilter); filters.add(queryFilter);
} }
}
return filters; return filters;

View File

@ -59,7 +59,7 @@
<div class="input-group pe-2"> <div class="input-group pe-2">
<!-- Reset page when applying filter to start back at page 1 --> <!-- Reset page when applying filter to start back at page 1 -->
<input type="hidden" name="page" value="1"> <input type="hidden" name="page" value="1">
<input type="hidden" name="pageSize" th:value="${page.getPagination().getPageSize()}"> <input type="hidden" name="pageSize" th:value="${page != null ? page.getPagination().getPageSize() : '50'}">
<input type="hidden" name="query" th:value="${query}"> <input type="hidden" name="query" th:value="${query}">
<input type="hidden" name="filter_field" th:value="${field.getJavaName()}"> <input type="hidden" name="filter_field" th:value="${field.getJavaName()}">
@ -139,7 +139,7 @@
<!-- Reset page when applying filter to start back at page 1 --> <!-- Reset page when applying filter to start back at page 1 -->
<input type="hidden" name="page" value="1"> <input type="hidden" name="page" value="1">
<input type="hidden" name="pageSize" th:value="${page.getPagination().getPageSize()}"> <input type="hidden" name="pageSize" th:value="${page != null ? page.getPagination().getPageSize() : '50'}">
<input type="hidden" name="query" th:value="${query}"> <input type="hidden" name="query" th:value="${query}">
<input type="hidden" name="filter_field" th:value="${field.getJavaName()}"> <input type="hidden" name="filter_field" th:value="${field.getJavaName()}">

View File

@ -47,7 +47,7 @@
<input type="hidden" name="page" value="1"> <input type="hidden" name="page" value="1">
<input type="hidden" name="pageSize" <input type="hidden" name="pageSize"
th:value="${page.getPagination().getPageSize()}"> th:value="${page != null ? page.getPagination().getPageSize() : '50'}">
</form> </form>
<div class="separator mb-4 mt-4"></div> <div class="separator mb-4 mt-4"></div>
@ -67,8 +67,10 @@
</h3> </h3>
</div> </div>
<th:block th:if="${page}">
<div th:replace="~{fragments/table_selectable :: table(results=${page.getResults()}, schema=${schema})}"> <div th:replace="~{fragments/table_selectable :: table(results=${page.getResults()}, schema=${schema})}">
</div> </div>
</th:block>
</div> </div>
</div> </div>
<div th:if="${!schema.getFilterableFields().isEmpty()}" class="col-3"> <div th:if="${!schema.getFilterableFields().isEmpty()}" class="col-3">