mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-17 20:50:44 +00:00
Merged dev into feature/quartz-scheduler
This commit is contained in:
@ -992,6 +992,8 @@ public class ApiImplementation
|
||||
runProcessInput.setProcessUUID(processUUID);
|
||||
// todo i don't think runProcessInput.setAsyncJobCallback();
|
||||
|
||||
PermissionsHelper.checkProcessPermissionThrowing(runProcessInput, processName);
|
||||
|
||||
//////////////////////
|
||||
// map input values //
|
||||
//////////////////////
|
||||
|
@ -1477,15 +1477,21 @@ public class GenerateOpenApiSpecAction extends AbstractQActionFunction<GenerateO
|
||||
QPossibleValueSource possibleValueSource = QContext.getQInstance().getPossibleValueSource(field.getPossibleValueSourceName());
|
||||
if(QPossibleValueSourceType.ENUM.equals(possibleValueSource.getType()))
|
||||
{
|
||||
List<String> enumValues = new ArrayList<>();
|
||||
List<String> enumMapping = new ArrayList<>();
|
||||
for(QPossibleValue<?> enumValue : possibleValueSource.getEnumValues())
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// by default, we will list all enum values in the docs - but - a field's api-meta-data object can opt out //
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
if(apiFieldMetaData == null || apiFieldMetaData.getListEnumPossibleValues())
|
||||
{
|
||||
enumValues.add(String.valueOf(enumValue.getId()));
|
||||
enumMapping.add(enumValue.getId() + "=" + enumValue.getLabel());
|
||||
List<String> enumValues = new ArrayList<>();
|
||||
List<String> enumMapping = new ArrayList<>();
|
||||
for(QPossibleValue<?> enumValue : possibleValueSource.getEnumValues())
|
||||
{
|
||||
enumValues.add(String.valueOf(enumValue.getId()));
|
||||
enumMapping.add(enumValue.getId() + "=" + enumValue.getLabel());
|
||||
}
|
||||
fieldSchema.setEnumValues(enumValues);
|
||||
fieldSchema.setDescription(fieldSchema.getDescription() + " Value definitions are: " + StringUtils.joinWithCommasAndAnd(enumMapping));
|
||||
}
|
||||
fieldSchema.setEnumValues(enumValues);
|
||||
fieldSchema.setDescription(fieldSchema.getDescription() + " Value definitions are: " + StringUtils.joinWithCommasAndAnd(enumMapping));
|
||||
}
|
||||
else if(QPossibleValueSourceType.TABLE.equals(possibleValueSource.getType()))
|
||||
{
|
||||
|
@ -39,6 +39,7 @@ public class ApiFieldMetaData
|
||||
|
||||
private String apiFieldName;
|
||||
private String description;
|
||||
private boolean listEnumPossibleValues = true;
|
||||
|
||||
private Boolean isExcluded;
|
||||
private String replacedByFieldName;
|
||||
@ -346,4 +347,35 @@ public class ApiFieldMetaData
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for listEnumPossibleValues
|
||||
*******************************************************************************/
|
||||
public boolean getListEnumPossibleValues()
|
||||
{
|
||||
return (this.listEnumPossibleValues);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for listEnumPossibleValues
|
||||
*******************************************************************************/
|
||||
public void setListEnumPossibleValues(boolean listEnumPossibleValues)
|
||||
{
|
||||
this.listEnumPossibleValues = listEnumPossibleValues;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Fluent setter for listEnumPossibleValues
|
||||
*******************************************************************************/
|
||||
public ApiFieldMetaData withListEnumPossibleValues(boolean listEnumPossibleValues)
|
||||
{
|
||||
this.listEnumPossibleValues = listEnumPossibleValues;
|
||||
return (this);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
}
|
@ -1548,7 +1548,7 @@ class QJavalinApiHandlerTest extends BaseTest
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private void assertErrorResponse(Integer expectedStatusCode, String expectedErrorMessage, HttpResponse<String> response)
|
||||
static void assertErrorResponse(Integer expectedStatusCode, String expectedErrorMessage, HttpResponse<String> response)
|
||||
{
|
||||
if(expectedStatusCode != null)
|
||||
{
|
||||
|
@ -44,6 +44,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
@ -334,15 +335,31 @@ class ApiScriptUtilsTest extends BaseTest
|
||||
String jobId = ValueUtils.getValueAsString(((Map<String, ?>) asyncResult).get("jobId"));
|
||||
assertNotNull(jobId);
|
||||
|
||||
SleepUtils.sleep(100, TimeUnit.MILLISECONDS);
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// check every 100 ms or so to see if the process is done - but after 10 loops, //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
for(int i = 0; i < 10; i++)
|
||||
{
|
||||
Serializable result = apiScriptUtils.getProcessStatus(TestUtils.PROCESS_NAME_TRANSFORM_PEOPLE, jobId);
|
||||
|
||||
Serializable result = apiScriptUtils.getProcessStatus(TestUtils.PROCESS_NAME_TRANSFORM_PEOPLE, jobId);
|
||||
assertThat(result).isInstanceOf(List.class);
|
||||
List<Map<String, Object>> resultList = (List<Map<String, Object>>) result;
|
||||
assertEquals(3, resultList.size());
|
||||
if(result instanceof Map map && map.containsKey("jobId"))
|
||||
{
|
||||
System.out.println("Process is still running - sleep and look again...");
|
||||
SleepUtils.sleep(100, TimeUnit.MILLISECONDS);
|
||||
continue;
|
||||
}
|
||||
|
||||
assertThat(resultList.stream().filter(m -> m.get("id").equals(2)).findFirst()).isPresent().get().hasFieldOrPropertyWithValue("statusCode", 200);
|
||||
assertThat(resultList.stream().filter(m -> m.get("id").equals(3)).findFirst()).isPresent().get().hasFieldOrPropertyWithValue("statusCode", 500);
|
||||
assertThat(result).isInstanceOf(List.class);
|
||||
List<Map<String, Object>> resultList = (List<Map<String, Object>>) result;
|
||||
assertEquals(3, resultList.size());
|
||||
|
||||
assertThat(resultList.stream().filter(m -> m.get("id").equals(2)).findFirst()).isPresent().get().hasFieldOrPropertyWithValue("statusCode", 200);
|
||||
assertThat(resultList.stream().filter(m -> m.get("id").equals(3)).findFirst()).isPresent().get().hasFieldOrPropertyWithValue("statusCode", 500);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
fail("Process didn't complete after 10 loops, ~1 second.");
|
||||
}
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user