diff --git a/cwms-data-api/src/main/java/cwms/cda/api/watersupply/AccountingCatalogController.java b/cwms-data-api/src/main/java/cwms/cda/api/watersupply/AccountingCatalogController.java index e7153487f..b61febbc8 100644 --- a/cwms-data-api/src/main/java/cwms/cda/api/watersupply/AccountingCatalogController.java +++ b/cwms-data-api/src/main/java/cwms/cda/api/watersupply/AccountingCatalogController.java @@ -83,6 +83,7 @@ public class AccountingCatalogController implements Handler { private static final String TAG = "Pump Accounting"; private static final String ROW_LIMIT = "row-limit"; private static final String ASCENDING = "ascending"; + private static final int DEFAULT_ROW_LIMIT = 500; private final MetricRegistry metrics; private Timer.Context markAndTime(String subject) { @@ -117,7 +118,7 @@ protected WaterSupplyAccountingDao getWaterSupplyAccountingDao(DSLContext dsl) { @OpenApiParam(name = ASCENDING, description = "Whether or not the entries should be returned " + "in ascending order. Defaults to TRUE.", type = Boolean.class), @OpenApiParam(name = ROW_LIMIT, description = "The maximum number of rows to return. " - + "Defaults to 0, which means no limit.", type = Integer.class) + + "Defaults to " + DEFAULT_ROW_LIMIT + ".", type = Integer.class) }, pathParams = { @OpenApiParam(name = OFFICE, description = "The office ID of the project the " @@ -165,7 +166,15 @@ public void handle(Context ctx) { .getOrDefault(true); final boolean endInclusive = ctx.queryParamAsClass(END_TIME_INCLUSIVE, Boolean.class).getOrDefault(true); final boolean ascending = ctx.queryParamAsClass(ASCENDING, Boolean.class).getOrDefault(true); - final int rowLimit = ctx.queryParamAsClass(ROW_LIMIT, Integer.class).getOrDefault(0); + final int rowLimit = ctx.queryParamAsClass(ROW_LIMIT, Integer.class).getOrDefault(DEFAULT_ROW_LIMIT); + + if (rowLimit == 0) { + CdaError error = new CdaError("Unable to retrieve accounting - " + ROW_LIMIT + " must be greater than 0."); + LOGGER.atSevere().log("Unable to retrieve accounting - " + ROW_LIMIT + " must be greater than 0."); + ctx.status(HttpServletResponse.SC_BAD_REQUEST).json(error); + return; + } + DSLContext dsl = getDslContext(ctx); String formatHeader = ctx.headerAsClass(Header.ACCEPT, String.class).getOrDefault(Formats.JSONV1); diff --git a/cwms-data-api/src/test/java/cwms/cda/api/WaterSupplyAccountingControllerIT.java b/cwms-data-api/src/test/java/cwms/cda/api/WaterSupplyAccountingControllerIT.java index ff62380c5..01e13303e 100644 --- a/cwms-data-api/src/test/java/cwms/cda/api/WaterSupplyAccountingControllerIT.java +++ b/cwms-data-api/src/test/java/cwms/cda/api/WaterSupplyAccountingControllerIT.java @@ -799,6 +799,77 @@ void testStoreNonExistentTransferType() throws Exception { .assertThat() .statusCode(is(HttpServletResponse.SC_BAD_REQUEST)) ; + + given() + .log().ifValidationFails(LogDetail.ALL, true) + .contentType(Formats.JSONV1) + .header(AUTH_HEADER, user.toHeaderValue()) + .queryParam(START_TIME, "2005-04-05T00:00:00Z") + .queryParam(END_TIME, "2335-04-06T00:00:00Z") + .queryParam(START_INCLUSIVE, "true") + .queryParam(END_INCLUSIVE, "true") + .queryParam(ASCENDING, "true") + .queryParam(ROW_LIMIT, 100) + .queryParam(UNIT, "cfs") + .when() + .redirects().follow(true) + .redirects().max(3) + .get("/projects/" + OFFICE_ID + "/" + contract.getWaterUser().getProjectId().getName() + "/water-user/" + + contract.getWaterUser().getEntityName() + "/contracts/" + + contract.getContractId().getName() + "/accounting") + .then() + .log().ifValidationFails(LogDetail.ALL, true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_OK)); + } + + @Test + void testGet0RowLimit() throws Exception { + // 1 Store data + // 2 Retrieve accounting with 0 row limit + // 3 Verify failure from row limit + TestAccounts.KeyUser user = TestAccounts.KeyUser.SPK_NORMAL; + String json = JsonV1.buildObjectMapper().writeValueAsString(waterSupplyAccounting); + + // create pump accounting + given() + .log().ifValidationFails(LogDetail.ALL, true) + .contentType(Formats.JSONV1) + .body(json) + .header(AUTH_HEADER, user.toHeaderValue()) + .when() + .redirects().follow(true) + .redirects().max(3) + .post("/projects/" + OFFICE_ID + "/" + contract.getWaterUser().getProjectId().getName() + "/water-user/" + + contract.getWaterUser().getEntityName() + "/contracts/" + + contract.getContractId().getName() + "/accounting") + .then() + .log().ifValidationFails(LogDetail.ALL, true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_CREATED)) + ; + + given() + .log().ifValidationFails(LogDetail.ALL, true) + .contentType(Formats.JSONV1) + .header(AUTH_HEADER, user.toHeaderValue()) + .queryParam(START_TIME, "2005-04-05T00:00:00Z") + .queryParam(END_TIME, "2335-04-06T00:00:00Z") + .queryParam(START_INCLUSIVE, "true") + .queryParam(END_INCLUSIVE, "true") + .queryParam(ASCENDING, "true") + .queryParam(ROW_LIMIT, 0) + .queryParam(UNIT, "cfs") + .when() + .redirects().follow(true) + .redirects().max(3) + .get("/projects/" + OFFICE_ID + "/" + contract.getWaterUser().getProjectId().getName() + "/water-user/" + + contract.getWaterUser().getEntityName() + "/contracts/" + + contract.getContractId().getName() + "/accounting") + .then() + .log().ifValidationFails(LogDetail.ALL, true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_BAD_REQUEST)); } private static Location buildTestLocation(String name, String locationKind) {