diff --git a/qqq-backend-module-api/src/main/java/com/kingsrook/qqq/backend/module/api/actions/BaseAPIActionUtil.java b/qqq-backend-module-api/src/main/java/com/kingsrook/qqq/backend/module/api/actions/BaseAPIActionUtil.java index a6defe5e..cb67fa5a 100644 --- a/qqq-backend-module-api/src/main/java/com/kingsrook/qqq/backend/module/api/actions/BaseAPIActionUtil.java +++ b/qqq-backend-module-api/src/main/java/com/kingsrook/qqq/backend/module/api/actions/BaseAPIActionUtil.java @@ -787,7 +787,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()); } diff --git a/qqq-backend-module-api/src/test/java/com/kingsrook/qqq/backend/module/api/TestUtils.java b/qqq-backend-module-api/src/test/java/com/kingsrook/qqq/backend/module/api/TestUtils.java index 72c5094d..3de63044 100644 --- a/qqq-backend-module-api/src/test/java/com/kingsrook/qqq/backend/module/api/TestUtils.java +++ b/qqq-backend-module-api/src/test/java/com/kingsrook/qqq/backend/module/api/TestUtils.java @@ -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") + ) + ); + } + + + /******************************************************************************* ** *******************************************************************************/ diff --git a/qqq-backend-module-api/src/test/java/com/kingsrook/qqq/backend/module/api/actions/BaseAPIActionUtilTest.java b/qqq-backend-module-api/src/test/java/com/kingsrook/qqq/backend/module/api/actions/BaseAPIActionUtilTest.java index 7ec5dc3d..809e56b7 100644 --- a/qqq-backend-module-api/src/test/java/com/kingsrook/qqq/backend/module/api/actions/BaseAPIActionUtilTest.java +++ b/qqq-backend-module-api/src/test/java/com/kingsrook/qqq/backend/module/api/actions/BaseAPIActionUtilTest.java @@ -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 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"))); + } + + + /******************************************************************************* ** *******************************************************************************/