mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-18 13:10:44 +00:00
Option (turned on by default, controlled via javalin metadata) to not allow query requests without a limit
This commit is contained in:
@ -1279,6 +1279,11 @@ public class QJavalinImplementation
|
|||||||
queryInput.getFilter().setLimit(limit);
|
queryInput.getFilter().setLimit(limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(queryInput.getFilter() == null || queryInput.getFilter().getLimit() == null)
|
||||||
|
{
|
||||||
|
handleQueryNullLimit(context, queryInput);
|
||||||
|
}
|
||||||
|
|
||||||
List<QueryJoin> queryJoins = processQueryJoinsParam(context);
|
List<QueryJoin> queryJoins = processQueryJoinsParam(context);
|
||||||
queryInput.setQueryJoins(queryJoins);
|
queryInput.setQueryJoins(queryJoins);
|
||||||
|
|
||||||
@ -1299,6 +1304,28 @@ public class QJavalinImplementation
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
**
|
||||||
|
***************************************************************************/
|
||||||
|
private static void handleQueryNullLimit(Context context, QueryInput queryInput)
|
||||||
|
{
|
||||||
|
boolean allowed = javalinMetaData.getQueryWithoutLimitAllowed();
|
||||||
|
if(!allowed)
|
||||||
|
{
|
||||||
|
if(queryInput.getFilter() == null)
|
||||||
|
{
|
||||||
|
queryInput.setFilter(new QQueryFilter());
|
||||||
|
}
|
||||||
|
|
||||||
|
queryInput.getFilter().setLimit(javalinMetaData.getQueryWithoutLimitDefault());
|
||||||
|
LOG.log(javalinMetaData.getQueryWithoutLimitLogLevel(), "Query request did not specify a limit, which is not allowed. Using default instead", null,
|
||||||
|
logPair("defaultLimit", javalinMetaData.getQueryWithoutLimitDefault()),
|
||||||
|
logPair("path", context.path()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
@ -23,6 +23,7 @@ package com.kingsrook.qqq.backend.javalin;
|
|||||||
|
|
||||||
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
import org.apache.logging.log4j.Level;
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
@ -36,6 +37,10 @@ public class QJavalinMetaData
|
|||||||
|
|
||||||
private Function<QJavalinAccessLogger.LogEntry, Boolean> logFilter;
|
private Function<QJavalinAccessLogger.LogEntry, Boolean> logFilter;
|
||||||
|
|
||||||
|
private boolean queryWithoutLimitAllowed = false;
|
||||||
|
private Integer queryWithoutLimitDefault = 1000;
|
||||||
|
private Level queryWithoutLimitLogLevel = Level.INFO;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
@ -143,4 +148,97 @@ public class QJavalinMetaData
|
|||||||
return (this);
|
return (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for queryWithoutLimitAllowed
|
||||||
|
*******************************************************************************/
|
||||||
|
public boolean getQueryWithoutLimitAllowed()
|
||||||
|
{
|
||||||
|
return (this.queryWithoutLimitAllowed);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for queryWithoutLimitAllowed
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setQueryWithoutLimitAllowed(boolean queryWithoutLimitAllowed)
|
||||||
|
{
|
||||||
|
this.queryWithoutLimitAllowed = queryWithoutLimitAllowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for queryWithoutLimitAllowed
|
||||||
|
*******************************************************************************/
|
||||||
|
public QJavalinMetaData withQueryWithoutLimitAllowed(boolean queryWithoutLimitAllowed)
|
||||||
|
{
|
||||||
|
this.queryWithoutLimitAllowed = queryWithoutLimitAllowed;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for queryWithoutLimitDefault
|
||||||
|
*******************************************************************************/
|
||||||
|
public Integer getQueryWithoutLimitDefault()
|
||||||
|
{
|
||||||
|
return (this.queryWithoutLimitDefault);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for queryWithoutLimitDefault
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setQueryWithoutLimitDefault(Integer queryWithoutLimitDefault)
|
||||||
|
{
|
||||||
|
this.queryWithoutLimitDefault = queryWithoutLimitDefault;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for queryWithoutLimitDefault
|
||||||
|
*******************************************************************************/
|
||||||
|
public QJavalinMetaData withQueryWithoutLimitDefault(Integer queryWithoutLimitDefault)
|
||||||
|
{
|
||||||
|
this.queryWithoutLimitDefault = queryWithoutLimitDefault;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for queryWithoutLimitLogLevel
|
||||||
|
*******************************************************************************/
|
||||||
|
public Level getQueryWithoutLimitLogLevel()
|
||||||
|
{
|
||||||
|
return (this.queryWithoutLimitLogLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for queryWithoutLimitLogLevel
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setQueryWithoutLimitLogLevel(Level queryWithoutLimitLogLevel)
|
||||||
|
{
|
||||||
|
this.queryWithoutLimitLogLevel = queryWithoutLimitLogLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for queryWithoutLimitLogLevel
|
||||||
|
*******************************************************************************/
|
||||||
|
public QJavalinMetaData withQueryWithoutLimitLogLevel(Level queryWithoutLimitLogLevel)
|
||||||
|
{
|
||||||
|
this.queryWithoutLimitLogLevel = queryWithoutLimitLogLevel;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,8 @@ import java.util.concurrent.TimeUnit;
|
|||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||||
import com.kingsrook.qqq.backend.core.exceptions.QInstanceValidationException;
|
import com.kingsrook.qqq.backend.core.exceptions.QInstanceValidationException;
|
||||||
|
import com.kingsrook.qqq.backend.core.logging.QCollectingLogger;
|
||||||
|
import com.kingsrook.qqq.backend.core.logging.QLogger;
|
||||||
import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportFormat;
|
import com.kingsrook.qqq.backend.core.model.actions.reporting.ReportFormat;
|
||||||
import com.kingsrook.qqq.backend.core.model.dashboard.widgets.WidgetType;
|
import com.kingsrook.qqq.backend.core.model.dashboard.widgets.WidgetType;
|
||||||
import com.kingsrook.qqq.backend.core.model.metadata.QBackendMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.QBackendMetaData;
|
||||||
@ -45,6 +47,7 @@ import com.kingsrook.qqq.backend.core.utils.JsonUtils;
|
|||||||
import com.kingsrook.qqq.backend.core.utils.SleepUtils;
|
import com.kingsrook.qqq.backend.core.utils.SleepUtils;
|
||||||
import kong.unirest.HttpResponse;
|
import kong.unirest.HttpResponse;
|
||||||
import kong.unirest.Unirest;
|
import kong.unirest.Unirest;
|
||||||
|
import org.apache.logging.log4j.Level;
|
||||||
import org.eclipse.jetty.http.HttpStatus;
|
import org.eclipse.jetty.http.HttpStatus;
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
@ -469,6 +472,101 @@ class QJavalinImplementationTest extends QJavalinTestBase
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** test a table query using an actual filter via POST, with no limit specified,
|
||||||
|
** and with that not being allowed.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Test
|
||||||
|
public void test_dataQueryWithFilterPOSTWithoutLimitNotAllowed() throws QInstanceValidationException
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
qJavalinImplementation.getJavalinMetaData()
|
||||||
|
.withQueryWithoutLimitAllowed(false)
|
||||||
|
.withQueryWithoutLimitDefault(3)
|
||||||
|
.withQueryWithoutLimitLogLevel(Level.WARN);
|
||||||
|
|
||||||
|
QCollectingLogger collectingLogger = QLogger.activateCollectingLoggerForClass(QJavalinImplementation.class);
|
||||||
|
|
||||||
|
String filterJson = """
|
||||||
|
{"criteria":[]}""";
|
||||||
|
|
||||||
|
HttpResponse<String> response = Unirest.post(BASE_URL + "/data/person/query")
|
||||||
|
.field("filter", filterJson)
|
||||||
|
.asString();
|
||||||
|
|
||||||
|
assertEquals(200, response.getStatus());
|
||||||
|
JSONObject jsonObject = JsonUtils.toJSONObject(response.getBody());
|
||||||
|
assertTrue(jsonObject.has("records"));
|
||||||
|
JSONArray records = jsonObject.getJSONArray("records");
|
||||||
|
assertEquals(3, records.length());
|
||||||
|
|
||||||
|
assertThat(collectingLogger.getCollectedMessages())
|
||||||
|
.anyMatch(m -> m.getLevel().equals(Level.WARN) && m.getMessage().contains("Query request did not specify a limit"));
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
QLogger.activateCollectingLoggerForClass(QJavalinImplementation.class);
|
||||||
|
resetMetaDataQueryWithoutLimitSettings();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** test a table query using an actual filter via POST, with no limit specified,
|
||||||
|
** but with that being allowed.
|
||||||
|
**
|
||||||
|
*******************************************************************************/
|
||||||
|
@Test
|
||||||
|
public void test_dataQueryWithFilterPOSTWithoutLimitAllowed() throws QInstanceValidationException
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
qJavalinImplementation.getJavalinMetaData()
|
||||||
|
.withQueryWithoutLimitAllowed(true);
|
||||||
|
|
||||||
|
QCollectingLogger collectingLogger = QLogger.activateCollectingLoggerForClass(QJavalinImplementation.class);
|
||||||
|
|
||||||
|
String filterJson = """
|
||||||
|
{"criteria":[]}""";
|
||||||
|
|
||||||
|
HttpResponse<String> response = Unirest.post(BASE_URL + "/data/person/query")
|
||||||
|
.field("filter", filterJson)
|
||||||
|
.asString();
|
||||||
|
|
||||||
|
assertEquals(200, response.getStatus());
|
||||||
|
JSONObject jsonObject = JsonUtils.toJSONObject(response.getBody());
|
||||||
|
assertTrue(jsonObject.has("records"));
|
||||||
|
JSONArray records = jsonObject.getJSONArray("records");
|
||||||
|
assertEquals(6, records.length());
|
||||||
|
|
||||||
|
assertThat(collectingLogger.getCollectedMessages())
|
||||||
|
.noneMatch(m -> m.getMessage().contains("Query request did not specify a limit"));
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
QLogger.activateCollectingLoggerForClass(QJavalinImplementation.class);
|
||||||
|
resetMetaDataQueryWithoutLimitSettings();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
**
|
||||||
|
***************************************************************************/
|
||||||
|
private void resetMetaDataQueryWithoutLimitSettings()
|
||||||
|
{
|
||||||
|
qJavalinImplementation.getJavalinMetaData()
|
||||||
|
.withQueryWithoutLimitAllowed(false)
|
||||||
|
.withQueryWithoutLimitDefault(1000)
|
||||||
|
.withQueryWithoutLimitLogLevel(Level.INFO);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
@ -102,7 +102,7 @@ public class QJavalinTestBase
|
|||||||
{
|
{
|
||||||
qJavalinImplementation.stopJavalinServer();
|
qJavalinImplementation.stopJavalinServer();
|
||||||
}
|
}
|
||||||
qJavalinImplementation = new QJavalinImplementation(qInstance);
|
qJavalinImplementation = new QJavalinImplementation(qInstance, new QJavalinMetaData());
|
||||||
QJavalinProcessHandler.setAsyncStepTimeoutMillis(250);
|
QJavalinProcessHandler.setAsyncStepTimeoutMillis(250);
|
||||||
qJavalinImplementation.startJavalinServer(PORT);
|
qJavalinImplementation.startJavalinServer(PORT);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user