From ee1c20b1c63d35eb6b643f151d4056f9e811da3b Mon Sep 17 00:00:00 2001 From: Darin Kelkhoff Date: Mon, 12 Feb 2024 14:38:23 -0600 Subject: [PATCH] CE-847 Add permissions check in runProcess... --- .../qqq/api/actions/ApiImplementation.java | 2 + .../QJavalinApiHandlerPermissionsTest.java | 138 ++++++++++++++++++ .../api/javalin/QJavalinApiHandlerTest.java | 2 +- 3 files changed, 141 insertions(+), 1 deletion(-) create mode 100644 qqq-middleware-api/src/test/java/com/kingsrook/qqq/api/javalin/QJavalinApiHandlerPermissionsTest.java diff --git a/qqq-middleware-api/src/main/java/com/kingsrook/qqq/api/actions/ApiImplementation.java b/qqq-middleware-api/src/main/java/com/kingsrook/qqq/api/actions/ApiImplementation.java index 842ab777..56444250 100644 --- a/qqq-middleware-api/src/main/java/com/kingsrook/qqq/api/actions/ApiImplementation.java +++ b/qqq-middleware-api/src/main/java/com/kingsrook/qqq/api/actions/ApiImplementation.java @@ -992,6 +992,8 @@ public class ApiImplementation runProcessInput.setProcessUUID(processUUID); // todo i don't think runProcessInput.setAsyncJobCallback(); + PermissionsHelper.checkProcessPermissionThrowing(runProcessInput, processName); + ////////////////////// // map input values // ////////////////////// diff --git a/qqq-middleware-api/src/test/java/com/kingsrook/qqq/api/javalin/QJavalinApiHandlerPermissionsTest.java b/qqq-middleware-api/src/test/java/com/kingsrook/qqq/api/javalin/QJavalinApiHandlerPermissionsTest.java new file mode 100644 index 00000000..680c850d --- /dev/null +++ b/qqq-middleware-api/src/test/java/com/kingsrook/qqq/api/javalin/QJavalinApiHandlerPermissionsTest.java @@ -0,0 +1,138 @@ +/* + * QQQ - Low-code Application Framework for Engineers. + * Copyright (C) 2021-2023. Kingsrook, LLC + * 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States + * contact@kingsrook.com + * https://github.com/Kingsrook/ + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package com.kingsrook.qqq.api.javalin; + + +import com.kingsrook.qqq.api.BaseTest; +import com.kingsrook.qqq.api.TestUtils; +import com.kingsrook.qqq.api.actions.ApiImplementation; +import com.kingsrook.qqq.backend.core.exceptions.QInstanceValidationException; +import com.kingsrook.qqq.backend.core.model.metadata.QInstance; +import com.kingsrook.qqq.backend.core.model.metadata.permissions.PermissionLevel; +import com.kingsrook.qqq.backend.core.model.metadata.permissions.QPermissionRules; +import com.kingsrook.qqq.backend.core.model.metadata.processes.QProcessMetaData; +import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData; +import com.kingsrook.qqq.backend.javalin.QJavalinImplementation; +import io.javalin.apibuilder.EndpointGroup; +import kong.unirest.Unirest; +import org.eclipse.jetty.http.HttpStatus; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import static com.kingsrook.qqq.api.javalin.QJavalinApiHandlerTest.assertErrorResponse; + + +/******************************************************************************* + ** Unit test permissions within QJavalinApiHandler + *******************************************************************************/ +class QJavalinApiHandlerPermissionsTest extends BaseTest +{ + private static final int PORT = 6263; + protected static final String BASE_URL = "http://localhost:" + PORT; + + private static final String VERSION = "2023.Q1"; + + protected static QJavalinImplementation qJavalinImplementation; + + + + /******************************************************************************* + ** + *******************************************************************************/ + @BeforeAll + static void beforeAll() throws QInstanceValidationException + { + QInstance qInstance = TestUtils.defineInstance(); + + /////////////////////////////////////////////////// + // turn on permissions on all tables & processes // + /////////////////////////////////////////////////// + for(QTableMetaData table : qInstance.getTables().values()) + { + table.withPermissionRules(new QPermissionRules().withLevel(PermissionLevel.READ_INSERT_EDIT_DELETE_PERMISSIONS)); + } + + for(QProcessMetaData process : qInstance.getProcesses().values()) + { + process.withPermissionRules(new QPermissionRules().withLevel(PermissionLevel.HAS_ACCESS_PERMISSION)); + } + + qJavalinImplementation = new QJavalinImplementation(qInstance); + qJavalinImplementation.startJavalinServer(PORT); + EndpointGroup routes = new QJavalinApiHandler(qInstance).getRoutes(); + qJavalinImplementation.getJavalinService().routes(routes); + } + + + + /******************************************************************************* + ** + *******************************************************************************/ + @BeforeEach + @AfterEach + void beforeAndAfterEach() + { + ApiImplementation.clearCaches(); + } + + + + /******************************************************************************* + ** Before the class (all) runs, start a javalin server. + ** + *******************************************************************************/ + @AfterAll + static void afterAll() + { + qJavalinImplementation.stopJavalinServer(); + } + + + + /******************************************************************************* + ** + *******************************************************************************/ + @Test + void test403s() + { + //////////////////////////// + // tables - single & bulk // + //////////////////////////// + assertErrorResponse(HttpStatus.FORBIDDEN_403, "You do not have permission", Unirest.get(BASE_URL + "/api/" + VERSION + "/order/query").asString()); + assertErrorResponse(HttpStatus.FORBIDDEN_403, "You do not have permission", Unirest.get(BASE_URL + "/api/" + VERSION + "/order/1").asString()); + assertErrorResponse(HttpStatus.FORBIDDEN_403, "You do not have permission", Unirest.post(BASE_URL + "/api/" + VERSION + "/person").asString()); + assertErrorResponse(HttpStatus.FORBIDDEN_403, "You do not have permission", Unirest.post(BASE_URL + "/api/" + VERSION + "/person/bulk").asString()); + assertErrorResponse(HttpStatus.FORBIDDEN_403, "You do not have permission", Unirest.delete(BASE_URL + "/api/" + VERSION + "/person/1").asString()); + assertErrorResponse(HttpStatus.FORBIDDEN_403, "You do not have permission", Unirest.delete(BASE_URL + "/api/" + VERSION + "/person/bulk").asString()); + assertErrorResponse(HttpStatus.FORBIDDEN_403, "You do not have permission", Unirest.patch(BASE_URL + "/api/" + VERSION + "/person/1").asString()); + assertErrorResponse(HttpStatus.FORBIDDEN_403, "You do not have permission", Unirest.patch(BASE_URL + "/api/" + VERSION + "/person/bulk").asString()); + + /////////////// + // processes // + /////////////// + assertErrorResponse(HttpStatus.FORBIDDEN_403, "You do not have permission", Unirest.get(BASE_URL + "/api/" + VERSION + "/person/getPersonInfo").asString()); + assertErrorResponse(HttpStatus.FORBIDDEN_403, "You do not have permission", Unirest.post(BASE_URL + "/api/" + VERSION + "/person/transformPeople").asString()); + } + +} diff --git a/qqq-middleware-api/src/test/java/com/kingsrook/qqq/api/javalin/QJavalinApiHandlerTest.java b/qqq-middleware-api/src/test/java/com/kingsrook/qqq/api/javalin/QJavalinApiHandlerTest.java index ac6b1e9b..f495f51c 100644 --- a/qqq-middleware-api/src/test/java/com/kingsrook/qqq/api/javalin/QJavalinApiHandlerTest.java +++ b/qqq-middleware-api/src/test/java/com/kingsrook/qqq/api/javalin/QJavalinApiHandlerTest.java @@ -1548,7 +1548,7 @@ class QJavalinApiHandlerTest extends BaseTest /******************************************************************************* ** *******************************************************************************/ - private void assertErrorResponse(Integer expectedStatusCode, String expectedErrorMessage, HttpResponse response) + static void assertErrorResponse(Integer expectedStatusCode, String expectedErrorMessage, HttpResponse response) { if(expectedStatusCode != null) {