mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-18 05:01:07 +00:00
cehckpoint - adding security to openapi spec
This commit is contained in:
@ -75,7 +75,20 @@ public class PermissionsHelper
|
||||
warnAboutPermissionSubTypeForTables(permissionSubType);
|
||||
QTableMetaData table = QContext.getQInstance().getTable(tableName);
|
||||
|
||||
commonCheckPermissionThrowing(getEffectivePermissionRules(table, QContext.getQInstance()), permissionSubType, table.getName(), actionInput);
|
||||
commonCheckPermissionThrowing(getEffectivePermissionRules(table, QContext.getQInstance()), permissionSubType, table.getName());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public static String getTablePermissionName(String tableName, TablePermissionSubType permissionSubType)
|
||||
{
|
||||
QInstance qInstance = QContext.getQInstance();
|
||||
QPermissionRules rules = getEffectivePermissionRules(qInstance.getTable(tableName), qInstance);
|
||||
String permissionBaseName = getEffectivePermissionBaseName(rules, tableName);
|
||||
return (getPermissionName(permissionBaseName, permissionSubType));
|
||||
}
|
||||
|
||||
|
||||
@ -181,7 +194,7 @@ public class PermissionsHelper
|
||||
return;
|
||||
}
|
||||
|
||||
commonCheckPermissionThrowing(effectivePermissionRules, PrivatePermissionSubType.HAS_ACCESS, process.getName(), actionInput);
|
||||
commonCheckPermissionThrowing(effectivePermissionRules, PrivatePermissionSubType.HAS_ACCESS, process.getName());
|
||||
}
|
||||
|
||||
|
||||
@ -210,7 +223,7 @@ public class PermissionsHelper
|
||||
public static void checkAppPermissionThrowing(AbstractActionInput actionInput, String appName) throws QPermissionDeniedException
|
||||
{
|
||||
QAppMetaData app = QContext.getQInstance().getApp(appName);
|
||||
commonCheckPermissionThrowing(getEffectivePermissionRules(app, QContext.getQInstance()), PrivatePermissionSubType.HAS_ACCESS, app.getName(), actionInput);
|
||||
commonCheckPermissionThrowing(getEffectivePermissionRules(app, QContext.getQInstance()), PrivatePermissionSubType.HAS_ACCESS, app.getName());
|
||||
}
|
||||
|
||||
|
||||
@ -239,7 +252,7 @@ public class PermissionsHelper
|
||||
public static void checkReportPermissionThrowing(AbstractActionInput actionInput, String reportName) throws QPermissionDeniedException
|
||||
{
|
||||
QReportMetaData report = QContext.getQInstance().getReport(reportName);
|
||||
commonCheckPermissionThrowing(getEffectivePermissionRules(report, QContext.getQInstance()), PrivatePermissionSubType.HAS_ACCESS, report.getName(), actionInput);
|
||||
commonCheckPermissionThrowing(getEffectivePermissionRules(report, QContext.getQInstance()), PrivatePermissionSubType.HAS_ACCESS, report.getName());
|
||||
}
|
||||
|
||||
|
||||
@ -268,7 +281,7 @@ public class PermissionsHelper
|
||||
public static void checkWidgetPermissionThrowing(AbstractActionInput actionInput, String widgetName) throws QPermissionDeniedException
|
||||
{
|
||||
QWidgetMetaDataInterface widget = QContext.getQInstance().getWidget(widgetName);
|
||||
commonCheckPermissionThrowing(getEffectivePermissionRules(widget, QContext.getQInstance()), PrivatePermissionSubType.HAS_ACCESS, widget.getName(), actionInput);
|
||||
commonCheckPermissionThrowing(getEffectivePermissionRules(widget, QContext.getQInstance()), PrivatePermissionSubType.HAS_ACCESS, widget.getName());
|
||||
}
|
||||
|
||||
|
||||
@ -524,7 +537,7 @@ public class PermissionsHelper
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private static void commonCheckPermissionThrowing(QPermissionRules rules, PermissionSubType permissionSubType, String name, AbstractActionInput actionInput) throws QPermissionDeniedException
|
||||
private static void commonCheckPermissionThrowing(QPermissionRules rules, PermissionSubType permissionSubType, String name) throws QPermissionDeniedException
|
||||
{
|
||||
PermissionSubType effectivePermissionSubType = getEffectivePermissionSubType(rules, permissionSubType);
|
||||
String permissionBaseName = getEffectivePermissionBaseName(rules, name);
|
||||
|
@ -37,14 +37,19 @@ import com.kingsrook.qqq.api.model.openapi.ExampleWithListValue;
|
||||
import com.kingsrook.qqq.api.model.openapi.ExampleWithSingleValue;
|
||||
import com.kingsrook.qqq.api.model.openapi.Info;
|
||||
import com.kingsrook.qqq.api.model.openapi.Method;
|
||||
import com.kingsrook.qqq.api.model.openapi.OAuth2;
|
||||
import com.kingsrook.qqq.api.model.openapi.OAuth2Flow;
|
||||
import com.kingsrook.qqq.api.model.openapi.OpenAPI;
|
||||
import com.kingsrook.qqq.api.model.openapi.Parameter;
|
||||
import com.kingsrook.qqq.api.model.openapi.Path;
|
||||
import com.kingsrook.qqq.api.model.openapi.Response;
|
||||
import com.kingsrook.qqq.api.model.openapi.Schema;
|
||||
import com.kingsrook.qqq.api.model.openapi.SecurityScheme;
|
||||
import com.kingsrook.qqq.api.model.openapi.Server;
|
||||
import com.kingsrook.qqq.api.model.openapi.Tag;
|
||||
import com.kingsrook.qqq.backend.core.actions.AbstractQActionFunction;
|
||||
import com.kingsrook.qqq.backend.core.actions.permissions.PermissionsHelper;
|
||||
import com.kingsrook.qqq.backend.core.actions.permissions.TablePermissionSubType;
|
||||
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||
@ -91,11 +96,22 @@ public class GenerateOpenApiSpecAction extends AbstractQActionFunction<GenerateO
|
||||
openAPI.setTags(new ArrayList<>());
|
||||
openAPI.setPaths(new LinkedHashMap<>());
|
||||
|
||||
LinkedHashMap<Integer, Response> componentResponses = new LinkedHashMap<>();
|
||||
LinkedHashMap<String, Schema> componentSchemas = new LinkedHashMap<>();
|
||||
LinkedHashMap<Integer, Response> componentResponses = new LinkedHashMap<>();
|
||||
LinkedHashMap<String, Schema> componentSchemas = new LinkedHashMap<>();
|
||||
LinkedHashMap<String, SecurityScheme> securitySchemes = new LinkedHashMap<>();
|
||||
openAPI.setComponents(new Components()
|
||||
.withSchemas(componentSchemas)
|
||||
.withResponses(componentResponses)
|
||||
.withSecuritySchemes(securitySchemes)
|
||||
);
|
||||
|
||||
LinkedHashMap<String, String> scopes = new LinkedHashMap<>();
|
||||
securitySchemes.put("OAuth2", new OAuth2()
|
||||
.withFlows(MapBuilder.of("authorizationCode", new OAuth2Flow()
|
||||
.withAuthorizationUrl("https://nutrifresh-one-development.us.auth0.com/authorize")
|
||||
.withTokenUrl("https://nutrifresh-one-development.us.auth0.com/oauth/token")
|
||||
.withScopes(scopes)
|
||||
))
|
||||
);
|
||||
|
||||
componentSchemas.put("baseSearchResultFields", new Schema()
|
||||
@ -131,6 +147,12 @@ public class GenerateOpenApiSpecAction extends AbstractQActionFunction<GenerateO
|
||||
|
||||
List<? extends QFieldMetaData> tableApiFields = new GetTableApiFieldsAction().execute(new GetTableApiFieldsInput().withTableName(tableName).withVersion(version)).getFields();
|
||||
|
||||
String tableReadPermissionName = PermissionsHelper.getTablePermissionName(tableName, TablePermissionSubType.READ);
|
||||
if(StringUtils.hasContent(tableReadPermissionName))
|
||||
{
|
||||
scopes.put(tableReadPermissionName, "Permission to read the " + tableLabel + " table");
|
||||
}
|
||||
|
||||
////////////////////////
|
||||
// tag for this table //
|
||||
////////////////////////
|
||||
@ -224,7 +246,9 @@ public class GenerateOpenApiSpecAction extends AbstractQActionFunction<GenerateO
|
||||
.withContent(MapBuilder.of("application/json", new Content()
|
||||
.withSchema(new Schema().withRef("#/components/schemas/" + tableName + "SearchResult"))
|
||||
))
|
||||
);
|
||||
).withSecurity(ListBuilder.of(MapBuilder.of(
|
||||
"OAuth2", List.of(tableReadPermissionName)
|
||||
)));
|
||||
|
||||
for(QFieldMetaData tableApiField : tableApiFields)
|
||||
{
|
||||
|
@ -23,6 +23,7 @@ package com.kingsrook.qqq.api.model.metadata;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
import com.kingsrook.qqq.api.ApiMiddlewareType;
|
||||
import com.kingsrook.qqq.api.model.APIVersion;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.QMiddlewareInstanceMetaData;
|
||||
@ -40,6 +41,17 @@ public class ApiInstanceMetaData extends QMiddlewareInstanceMetaData
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Constructor
|
||||
**
|
||||
*******************************************************************************/
|
||||
public ApiInstanceMetaData()
|
||||
{
|
||||
setType(ApiMiddlewareType.NAME);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
|
@ -30,9 +30,10 @@ import java.util.Map;
|
||||
*******************************************************************************/
|
||||
public class Components
|
||||
{
|
||||
private Map<String, Example> examples;
|
||||
private Map<String, Schema> schemas;
|
||||
private Map<Integer, Response> responses;
|
||||
private Map<String, Example> examples;
|
||||
private Map<String, Schema> schemas;
|
||||
private Map<Integer, Response> responses;
|
||||
private Map<String, SecurityScheme> securitySchemes;
|
||||
|
||||
|
||||
|
||||
@ -127,4 +128,35 @@ public class Components
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for securitySchemes
|
||||
*******************************************************************************/
|
||||
public Map<String, SecurityScheme> getSecuritySchemes()
|
||||
{
|
||||
return (this.securitySchemes);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for securitySchemes
|
||||
*******************************************************************************/
|
||||
public void setSecuritySchemes(Map<String, SecurityScheme> securitySchemes)
|
||||
{
|
||||
this.securitySchemes = securitySchemes;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Fluent setter for securitySchemes
|
||||
*******************************************************************************/
|
||||
public Components withSecuritySchemes(Map<String, SecurityScheme> securitySchemes)
|
||||
{
|
||||
this.securitySchemes = securitySchemes;
|
||||
return (this);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -41,6 +41,8 @@ public class Method
|
||||
private List<Parameter> parameters;
|
||||
private Map<Integer, Response> responses;
|
||||
|
||||
private List<Map<String, List<String>>> security;
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
@ -303,4 +305,36 @@ public class Method
|
||||
this.responses.put(code, response);
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for security
|
||||
*******************************************************************************/
|
||||
public List<Map<String, List<String>>> getSecurity()
|
||||
{
|
||||
return (this.security);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for security
|
||||
*******************************************************************************/
|
||||
public void setSecurity(List<Map<String, List<String>>> security)
|
||||
{
|
||||
this.security = security;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Fluent setter for security
|
||||
*******************************************************************************/
|
||||
public Method withSecurity(List<Map<String, List<String>>> security)
|
||||
{
|
||||
this.security = security;
|
||||
return (this);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 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.model.openapi;
|
||||
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public class OAuth2 extends SecurityScheme
|
||||
{
|
||||
private Map<String, OAuth2Flow> flows;
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Constructor
|
||||
**
|
||||
*******************************************************************************/
|
||||
public OAuth2()
|
||||
{
|
||||
setType("oauth2");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for flows
|
||||
*******************************************************************************/
|
||||
public Map<String, OAuth2Flow> getFlows()
|
||||
{
|
||||
return (this.flows);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for flows
|
||||
*******************************************************************************/
|
||||
public void setFlows(Map<String, OAuth2Flow> flows)
|
||||
{
|
||||
this.flows = flows;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Fluent setter for flows
|
||||
*******************************************************************************/
|
||||
public OAuth2 withFlows(Map<String, OAuth2Flow> flows)
|
||||
{
|
||||
this.flows = flows;
|
||||
return (this);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,130 @@
|
||||
/*
|
||||
* 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.model.openapi;
|
||||
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public class OAuth2Flow
|
||||
{
|
||||
private String authorizationUrl;
|
||||
private String tokenUrl;
|
||||
private Map<String, String> scopes;
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for authorizationUrl
|
||||
*******************************************************************************/
|
||||
public String getAuthorizationUrl()
|
||||
{
|
||||
return (this.authorizationUrl);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for authorizationUrl
|
||||
*******************************************************************************/
|
||||
public void setAuthorizationUrl(String authorizationUrl)
|
||||
{
|
||||
this.authorizationUrl = authorizationUrl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Fluent setter for authorizationUrl
|
||||
*******************************************************************************/
|
||||
public OAuth2Flow withAuthorizationUrl(String authorizationUrl)
|
||||
{
|
||||
this.authorizationUrl = authorizationUrl;
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for tokenUrl
|
||||
*******************************************************************************/
|
||||
public String getTokenUrl()
|
||||
{
|
||||
return (this.tokenUrl);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for tokenUrl
|
||||
*******************************************************************************/
|
||||
public void setTokenUrl(String tokenUrl)
|
||||
{
|
||||
this.tokenUrl = tokenUrl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Fluent setter for tokenUrl
|
||||
*******************************************************************************/
|
||||
public OAuth2Flow withTokenUrl(String tokenUrl)
|
||||
{
|
||||
this.tokenUrl = tokenUrl;
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for scopes
|
||||
*******************************************************************************/
|
||||
public Map<String, String> getScopes()
|
||||
{
|
||||
return (this.scopes);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for scopes
|
||||
*******************************************************************************/
|
||||
public void setScopes(Map<String, String> scopes)
|
||||
{
|
||||
this.scopes = scopes;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Fluent setter for scopes
|
||||
*******************************************************************************/
|
||||
public OAuth2Flow withScopes(Map<String, String> scopes)
|
||||
{
|
||||
this.scopes = scopes;
|
||||
return (this);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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.model.openapi;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public class SecurityScheme
|
||||
{
|
||||
private String type;
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for type
|
||||
*******************************************************************************/
|
||||
public String getType()
|
||||
{
|
||||
return (this.type);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for type
|
||||
*******************************************************************************/
|
||||
public void setType(String type)
|
||||
{
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Fluent setter for type
|
||||
*******************************************************************************/
|
||||
public SecurityScheme withType(String type)
|
||||
{
|
||||
this.type = type;
|
||||
return (this);
|
||||
}
|
||||
|
||||
}
|
@ -26,6 +26,7 @@ import com.kingsrook.qqq.backend.core.context.QContext;
|
||||
import com.kingsrook.qqq.backend.core.logging.QLogger;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||
import com.kingsrook.qqq.backend.core.model.session.QSession;
|
||||
import com.kingsrook.qqq.backend.core.modules.backend.implementations.memory.MemoryRecordStore;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
||||
@ -39,6 +40,18 @@ public class BaseTest
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@BeforeEach
|
||||
@AfterEach
|
||||
void baseBeforeAndAfterEach()
|
||||
{
|
||||
MemoryRecordStore.fullReset();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
|
@ -22,6 +22,10 @@
|
||||
package com.kingsrook.qqq.api;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
import com.kingsrook.qqq.api.model.APIVersion;
|
||||
import com.kingsrook.qqq.api.model.metadata.ApiInstanceMetaData;
|
||||
import com.kingsrook.qqq.api.model.metadata.tables.ApiTableMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.QBackendMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.DisplayFormat;
|
||||
@ -39,6 +43,8 @@ public class TestUtils
|
||||
public static final String MEMORY_BACKEND_NAME = "memory";
|
||||
private static final String TABLE_NAME_PERSON = "person";
|
||||
|
||||
private static final String API_VERSION = "2023.Q1";
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
@ -51,6 +57,11 @@ public class TestUtils
|
||||
qInstance.addBackend(defineMemoryBackend());
|
||||
qInstance.addTable(defineTablePerson());
|
||||
|
||||
qInstance.withMiddlewareMetaData(new ApiInstanceMetaData()
|
||||
.withCurrentVersion(new APIVersion(API_VERSION))
|
||||
.withSupportedVersions(List.of(new APIVersion(API_VERSION)))
|
||||
);
|
||||
|
||||
return (qInstance);
|
||||
}
|
||||
|
||||
@ -77,6 +88,7 @@ public class TestUtils
|
||||
.withName(TABLE_NAME_PERSON)
|
||||
.withLabel("Person")
|
||||
.withBackendName(MEMORY_BACKEND_NAME)
|
||||
.withMiddlewareMetaData(new ApiTableMetaData().withInitialVersion(API_VERSION))
|
||||
.withPrimaryKeyField("id")
|
||||
.withField(new QFieldMetaData("id", QFieldType.INTEGER).withIsEditable(false))
|
||||
.withField(new QFieldMetaData("createDate", QFieldType.DATE_TIME).withIsEditable(false))
|
||||
|
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* 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.TestUtils;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QInstanceValidationException;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||
import com.kingsrook.qqq.backend.javalin.QJavalinImplementation;
|
||||
import kong.unirest.HttpResponse;
|
||||
import kong.unirest.Unirest;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for QJavalinApiHandler
|
||||
*******************************************************************************/
|
||||
class QJavalinApiHandlerTest
|
||||
{
|
||||
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();
|
||||
qJavalinImplementation = new QJavalinImplementation(qInstance);
|
||||
qJavalinImplementation.startJavalinServer(PORT);
|
||||
qJavalinImplementation.getJavalinService().routes(new QJavalinApiHandler(qInstance).getRoutes());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Before the class (all) runs, start a javalin server.
|
||||
**
|
||||
*******************************************************************************/
|
||||
@AfterAll
|
||||
public static void afterAll()
|
||||
{
|
||||
qJavalinImplementation.stopJavalinServer();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testSpec()
|
||||
{
|
||||
HttpResponse<String> response = Unirest.get(BASE_URL + "/api/" + VERSION + "/openapi.yaml").asString();
|
||||
System.out.println(response.getBody());
|
||||
assertThat(response.getBody())
|
||||
.contains("""
|
||||
title: "QQQ API"
|
||||
""")
|
||||
.contains("""
|
||||
/person/query:
|
||||
""")
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testQuery()
|
||||
{
|
||||
HttpResponse<String> response = Unirest.get(BASE_URL + "/api/" + VERSION + "/person/query").asString();
|
||||
System.out.println(response.getBody());
|
||||
}
|
||||
|
||||
}
|
@ -208,7 +208,7 @@ public class QJavalinImplementation
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
void startJavalinServer(int port)
|
||||
public void startJavalinServer(int port)
|
||||
{
|
||||
// todo port from arg
|
||||
// todo base path from arg? - and then potentially multiple instances too (chosen based on the root path??)
|
||||
@ -221,6 +221,16 @@ public class QJavalinImplementation
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public Javalin getJavalinService()
|
||||
{
|
||||
return (service);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@ -277,7 +287,7 @@ public class QJavalinImplementation
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
void stopJavalinServer()
|
||||
public void stopJavalinServer()
|
||||
{
|
||||
service.stop();
|
||||
}
|
||||
|
Reference in New Issue
Block a user