mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-17 20:50:44 +00:00
Merge remote-tracking branch 'origin/integration/sprint-28' into feature/CTLE-503-optimization-weather-api-data
# Conflicts: # qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/tables/QueryAction.java # qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/metadata/frontend/QFrontendTableMetaData.java # qqq-backend-module-api/src/main/java/com/kingsrook/qqq/backend/module/api/actions/BaseAPIActionUtil.java # qqq-middleware-api/src/main/java/com/kingsrook/qqq/api/actions/QRecordApiAdapter.java
This commit is contained in:
@ -34,6 +34,7 @@ import java.util.Base64;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.GetAction;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.InsertAction;
|
||||
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
@ -634,8 +635,50 @@ public class BaseAPIActionUtil
|
||||
**
|
||||
** Can be overridden if an API uses an authorization type we don't natively support.
|
||||
*******************************************************************************/
|
||||
protected void setupAuthorizationInRequest(HttpRequestBase request) throws QException
|
||||
public void setupAuthorizationInRequest(HttpRequestBase request) throws QException
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// if backend specifies that it uses variants, look for that data in the session //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
if(backendMetaData.getUsesVariants())
|
||||
{
|
||||
QSession session = QContext.getQSession();
|
||||
if(session.getBackendVariants() == null || !session.getBackendVariants().containsKey(backendMetaData.getVariantOptionsTableTypeValue()))
|
||||
{
|
||||
throw (new QException("Could not find Backend Variant information for Backend '" + backendMetaData.getName() + "'"));
|
||||
}
|
||||
|
||||
Serializable variantId = session.getBackendVariants().get(backendMetaData.getVariantOptionsTableTypeValue());
|
||||
GetInput getInput = new GetInput();
|
||||
getInput.setShouldMaskPasswords(false);
|
||||
getInput.setTableName(backendMetaData.getVariantOptionsTableName());
|
||||
getInput.setPrimaryKey(variantId);
|
||||
GetOutput getOutput = new GetAction().execute(getInput);
|
||||
|
||||
QRecord record = getOutput.getRecord();
|
||||
if(record == null)
|
||||
{
|
||||
throw (new QException("Could not find Backend Variant in table " + backendMetaData.getVariantOptionsTableName() + " with id '" + variantId + "'"));
|
||||
}
|
||||
|
||||
if(backendMetaData.getAuthorizationType().equals(AuthorizationType.BASIC_AUTH_USERNAME_PASSWORD))
|
||||
{
|
||||
request.addHeader("Authorization", getBasicAuthenticationHeader(record.getValueString(backendMetaData.getVariantOptionsTableUsernameField()), record.getValueString(backendMetaData.getVariantOptionsTablePasswordField())));
|
||||
}
|
||||
else if(backendMetaData.getAuthorizationType().equals(AuthorizationType.API_KEY_HEADER))
|
||||
{
|
||||
request.addHeader("API-Key", record.getValueString(backendMetaData.getVariantOptionsTableApiKeyField()));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw (new IllegalArgumentException("Unexpected variant authorization type specified: " + backendMetaData.getAuthorizationType()));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// if not using variants, the authorization data will be in the backend meta data object //
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
switch(backendMetaData.getAuthorizationType())
|
||||
{
|
||||
case BASIC_AUTH_API_KEY:
|
||||
@ -781,7 +824,7 @@ public class BaseAPIActionUtil
|
||||
** Helper method to create a value for an Authentication header, using just a
|
||||
** username & password - encoded as Basic + base64(username:password)
|
||||
*******************************************************************************/
|
||||
protected String getBasicAuthenticationHeader(String username, String password)
|
||||
public String getBasicAuthenticationHeader(String username, String password)
|
||||
{
|
||||
return "Basic " + Base64.getEncoder().encodeToString((username + ":" + password).getBytes());
|
||||
}
|
||||
|
@ -66,6 +66,8 @@ public class TestUtils
|
||||
qInstance.addBackend(defineEasypostBackend());
|
||||
qInstance.addTable(defineTableEasypostTracker());
|
||||
|
||||
qInstance.addTable(defineVariant());
|
||||
|
||||
return (qInstance);
|
||||
}
|
||||
|
||||
@ -151,6 +153,29 @@ public class TestUtils
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private static QTableMetaData defineVariant()
|
||||
{
|
||||
return (new QTableMetaData()
|
||||
.withName("variant")
|
||||
.withBackendName(MEMORY_BACKEND_NAME)
|
||||
.withField(new QFieldMetaData("id", QFieldType.INTEGER))
|
||||
.withField(new QFieldMetaData("type", QFieldType.STRING))
|
||||
.withField(new QFieldMetaData("apiKey", QFieldType.STRING))
|
||||
.withField(new QFieldMetaData("username", QFieldType.STRING))
|
||||
.withField(new QFieldMetaData("password", QFieldType.STRING))
|
||||
.withPrimaryKeyField("id")
|
||||
.withBackendDetails(new APITableBackendDetails()
|
||||
.withTablePath("variant")
|
||||
.withTableWrapperObjectName("variant")
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
|
@ -22,12 +22,14 @@
|
||||
package com.kingsrook.qqq.backend.module.api.actions;
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Base64;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.CountAction;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.DeleteAction;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.GetAction;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.InsertAction;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.QueryAction;
|
||||
@ -36,6 +38,7 @@ import com.kingsrook.qqq.backend.core.context.QContext;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.count.CountInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.count.CountOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.delete.DeleteInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.get.GetInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.get.GetOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertInput;
|
||||
@ -59,6 +62,7 @@ import com.kingsrook.qqq.backend.module.api.model.OutboundAPILog;
|
||||
import com.kingsrook.qqq.backend.module.api.model.OutboundAPILogMetaDataProvider;
|
||||
import com.kingsrook.qqq.backend.module.api.model.metadata.APIBackendMetaData;
|
||||
import org.apache.http.Header;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
@ -81,11 +85,21 @@ class BaseAPIActionUtilTest extends BaseTest
|
||||
**
|
||||
*******************************************************************************/
|
||||
@BeforeEach
|
||||
void beforeEach()
|
||||
void beforeEach() throws QException
|
||||
{
|
||||
mockApiUtilsHelper = new MockApiUtilsHelper();
|
||||
mockApiUtilsHelper.setUseMock(true);
|
||||
MockApiActionUtils.mockApiUtilsHelper = mockApiUtilsHelper;
|
||||
|
||||
QueryInput queryInput = new QueryInput();
|
||||
queryInput.setTableName("variant");
|
||||
QueryOutput output = new QueryAction().execute(queryInput);
|
||||
List<Serializable> ids = output.getRecords().stream().map(r -> r.getValue("id")).toList();
|
||||
|
||||
DeleteInput deleteInput = new DeleteInput();
|
||||
deleteInput.setTableName("variant");
|
||||
deleteInput.setPrimaryKeys(ids);
|
||||
new DeleteAction().execute(deleteInput);
|
||||
}
|
||||
|
||||
|
||||
@ -603,6 +617,72 @@ class BaseAPIActionUtilTest extends BaseTest
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testBackendWithVariantsApiKey() throws QException
|
||||
{
|
||||
APIBackendMetaData backend = (APIBackendMetaData) QContext.getQInstance().getBackend(TestUtils.MOCK_BACKEND_NAME);
|
||||
backend.setAuthorizationType(AuthorizationType.API_KEY_HEADER);
|
||||
backend.setUsesVariants(true);
|
||||
backend.setVariantOptionsTableName("variant");
|
||||
backend.setVariantOptionsTableIdField("id");
|
||||
backend.setVariantOptionsTableApiKeyField("apiKey");
|
||||
backend.setVariantOptionsTableTypeValue("API_KEY_TYPE");
|
||||
|
||||
InsertInput insertInput = new InsertInput();
|
||||
insertInput.setTableName("variant");
|
||||
insertInput.setRecords(List.of(new QRecord()
|
||||
.withValue("type", "API_KEY_TYPE")
|
||||
.withValue("apiKey", "abcdefg1234567")));
|
||||
InsertOutput insertOutput = new InsertAction().execute(insertInput);
|
||||
|
||||
QContext.getQSession().setBackendVariants(Map.of("API_KEY_TYPE", insertOutput.getRecords().get(0).getValue("id")));
|
||||
HttpGet httpGet = new HttpGet();
|
||||
BaseAPIActionUtil util = new BaseAPIActionUtil();
|
||||
util.setBackendMetaData(backend);
|
||||
util.setupAuthorizationInRequest(httpGet);
|
||||
Header authHeader = httpGet.getFirstHeader("API-Key");
|
||||
assertTrue(authHeader.getValue().startsWith("abcde"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testBackendWithVariantsUsernamePassword() throws QException
|
||||
{
|
||||
APIBackendMetaData backend = (APIBackendMetaData) QContext.getQInstance().getBackend(TestUtils.MOCK_BACKEND_NAME);
|
||||
backend.setAuthorizationType(AuthorizationType.BASIC_AUTH_USERNAME_PASSWORD);
|
||||
backend.setUsesVariants(true);
|
||||
backend.setVariantOptionsTableName("variant");
|
||||
backend.setVariantOptionsTableIdField("id");
|
||||
backend.setVariantOptionsTableUsernameField("username");
|
||||
backend.setVariantOptionsTablePasswordField("password");
|
||||
backend.setVariantOptionsTableTypeValue("USER_PASS");
|
||||
|
||||
InsertInput insertInput = new InsertInput();
|
||||
insertInput.setTableName("variant");
|
||||
insertInput.setRecords(List.of(new QRecord()
|
||||
.withValue("type", "USER_PASS")
|
||||
.withValue("username", "user")
|
||||
.withValue("password", "pass")));
|
||||
InsertOutput insertOutput = new InsertAction().execute(insertInput);
|
||||
|
||||
QContext.getQSession().setBackendVariants(Map.of("USER_PASS", insertOutput.getRecords().get(0).getValue("id")));
|
||||
HttpGet httpGet = new HttpGet();
|
||||
BaseAPIActionUtil util = new BaseAPIActionUtil();
|
||||
util.setBackendMetaData(backend);
|
||||
util.setupAuthorizationInRequest(httpGet);
|
||||
Header authHeader = httpGet.getFirstHeader("Authorization");
|
||||
assertTrue(authHeader.getValue().equals(util.getBasicAuthenticationHeader("user", "pass")));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
|
Reference in New Issue
Block a user