getFormKiqClients(final String siteId) {
+ return Arrays.asList(httpClient, restClient, getApiKeyClient(siteId));
}
/**
@@ -284,7 +318,7 @@ public static boolean isIamAuthentication(final String url) {
*/
private static void loadSsmParameterVariables(final String awsprofile) {
- ssmBuilder = new SsmConnectionBuilder().setCredentials(awsprofile).setRegion(awsregion);
+ ssmBuilder = new SsmConnectionBuilder(false).setCredentials(awsprofile).setRegion(awsregion);
ssmService = new SsmServiceImpl(ssmBuilder);
rootHttpUrl =
@@ -293,6 +327,9 @@ private static void loadSsmParameterVariables(final String awsprofile) {
rootRestUrl =
ssmService.getParameterValue("/formkiq/" + appenvironment + "/api/DocumentsIamUrl");
+ rootKeyUrl =
+ ssmService.getParameterValue("/formkiq/" + appenvironment + "/api/DocumentsKeyUrl");
+
cognitoUserPoolId =
ssmService.getParameterValue("/formkiq/" + appenvironment + "/cognito/UserPoolId");
@@ -370,8 +407,9 @@ private static void setupConfigService(final String awsprofile) {
.getParameterValue("/formkiq/" + appenvironment + "/dynamodb/DocumentsTableName");
dbConnection =
- new DynamoDbConnectionBuilder().setCredentials(awsprofile).setRegion(awsregion);
- configService = new ConfigServiceImpl(dbConnection, documentsTable);
+ new DynamoDbConnectionBuilder(false).setCredentials(awsprofile).setRegion(awsregion);
+ configService = new ConfigServiceDynamoDb(dbConnection, documentsTable);
+ apiKeysService = new ApiKeysServiceDynamoDb(dbConnection, documentsTable);
}
}
diff --git a/lambda-api/src/test/java/com/formkiq/stacks/api/awstest/AwsResourceTest.java b/lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/AwsResourceTest.java
similarity index 84%
rename from lambda-api/src/test/java/com/formkiq/stacks/api/awstest/AwsResourceTest.java
rename to lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/AwsResourceTest.java
index ba78d1b37..49e4fff23 100644
--- a/lambda-api/src/test/java/com/formkiq/stacks/api/awstest/AwsResourceTest.java
+++ b/lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/AwsResourceTest.java
@@ -23,10 +23,11 @@
*/
package com.formkiq.stacks.api.awstest;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.http.HttpResponse;
@@ -40,7 +41,8 @@
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Timeout;
import com.formkiq.aws.cognito.CognitoConnectionBuilder;
import com.formkiq.aws.cognito.CognitoService;
import com.formkiq.stacks.client.FormKiqClientV1;
@@ -65,7 +67,8 @@ public class AwsResourceTest extends AbstractApiTest {
/**
* Test Having Admin add new user to group.
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testAdminAddUserToGroup() {
// given
String email = UUID.randomUUID() + "@formkiq.com";
@@ -99,7 +102,8 @@ public void testAdminAddUserToGroup() {
* @throws URISyntaxException URISyntaxException
* @throws InterruptedException InterruptedException
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testApiDocuments01() throws IOException, URISyntaxException, InterruptedException {
// given
final int year = 2019;
@@ -107,7 +111,7 @@ public void testApiDocuments01() throws IOException, URISyntaxException, Interru
final int day = 15;
LocalDate localDate = LocalDate.of(year, month, day);
- for (FormKiqClientV1 client : getFormKiqClients()) {
+ for (FormKiqClientV1 client : getFormKiqClients(null)) {
// given
Date date = Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
GetDocumentsRequest request = new GetDocumentsRequest().date(date).tz("+0500");
@@ -132,9 +136,10 @@ public void testApiDocuments01() throws IOException, URISyntaxException, Interru
* @throws Exception Exception
*/
@SuppressWarnings("unchecked")
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testPresignedUrl01() throws Exception {
- for (FormKiqClientV1 client : getFormKiqClients()) {
+ for (FormKiqClientV1 client : getFormKiqClients(null)) {
// given
final String documentId = addDocumentWithoutFile(client, null, null);
@@ -175,7 +180,8 @@ public void testPresignedUrl01() throws Exception {
/**
* Test SSM Parameter Store.
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testSsmParameters() {
assertTrue(getParameterStoreValue("/formkiq/" + getAppenvironment() + "/api/DocumentsHttpUrl")
.endsWith(getAwsRegion() + ".amazonaws.com"));
@@ -194,24 +200,39 @@ public void testSsmParameters() {
/**
* Test Having User try and add itself to the admin group. Should fail.
*/
- @Test(expected = NotAuthorizedException.class)
+ @Test
public void testUserAddSelfToAdmin() {
- getAdminCognitoService().getCredentials(login(USER_EMAIL, USER_PASSWORD));
+ try {
+ getAdminCognitoService().getCredentials(login(USER_EMAIL, USER_PASSWORD));
+ fail();
+ } catch (NotAuthorizedException e) {
+ assertTrue(true);
+ }
}
/**
* Test Having User try and add itself to the admin group. Should fail.
*/
- @Test(expected = NotAuthorizedException.class)
+ @Test
public void testFinanceUserAddSelfToAdmin() {
- getAdminCognitoService().getCredentials(login(FINANCE_EMAIL, USER_PASSWORD));
+ try {
+ getAdminCognitoService().getCredentials(login(FINANCE_EMAIL, USER_PASSWORD));
+ fail();
+ } catch (NotAuthorizedException e) {
+ assertTrue(true);
+ }
}
/**
* Test Having User try and add itself to the admin group. Should fail.
*/
- @Test(expected = NotAuthorizedException.class)
+ @Test
public void testReadonlyUserAddSelfToAdmin() {
- getAdminCognitoService().getCredentials(login(READONLY_EMAIL, USER_PASSWORD));
+ try {
+ getAdminCognitoService().getCredentials(login(READONLY_EMAIL, USER_PASSWORD));
+ fail();
+ } catch (NotAuthorizedException e) {
+ assertTrue(true);
+ }
}
}
diff --git a/lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/ChatGptRequestTest.java b/lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/ChatGptRequestTest.java
new file mode 100644
index 000000000..dc3653ce3
--- /dev/null
+++ b/lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/ChatGptRequestTest.java
@@ -0,0 +1,124 @@
+/**
+ * MIT License
+ *
+ * Copyright (c) 2018 - 2020 FormKiQ
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package com.formkiq.stacks.api.awstest;
+
+import static com.formkiq.testutils.aws.FkqDocumentService.addDocument;
+import static com.formkiq.testutils.aws.FkqDocumentService.waitForActionsComplete;
+import static com.formkiq.testutils.aws.FkqDocumentService.waitForDocumentContent;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Timeout;
+import com.formkiq.stacks.client.FormKiqClientV1;
+import com.formkiq.stacks.client.models.AddDocumentAction;
+import com.formkiq.stacks.client.models.Configuration;
+import com.formkiq.stacks.client.models.DocumentActionType;
+import com.formkiq.stacks.client.models.DocumentTags;
+import com.formkiq.stacks.client.requests.AddDocumentActionRequest;
+import com.formkiq.stacks.client.requests.GetDocumentTagsRequest;
+import com.formkiq.stacks.client.requests.UpdateConfigurationRequest;
+import software.amazon.awssdk.utils.IoUtils;
+
+/**
+ *
+ * Integration Test for creating an OCR / ChatGPT actions.
+ *
+ */
+public class ChatGptRequestTest extends AbstractApiTest {
+
+ /** JUnit Test Timeout. */
+ private static final int TEST_TIMEOUT = 120000;
+
+ @BeforeAll
+ public static void beforeClass() throws IOException {
+ AbstractApiTest.beforeClass();
+
+ if (System.getProperty("testchatgptapikey") == null) {
+ throw new IOException("key not set");
+ }
+
+ FormKiqClientV1 client = getFormKiqClients(null).get(0);
+ Configuration config = new Configuration();
+ config.chatGptApiKey(System.getProperty("testchatgptapikey"));
+ try {
+ client.updateConfiguration(new UpdateConfigurationRequest().config(config));
+ } catch (InterruptedException e) {
+ throw new IOException(e);
+ }
+ }
+
+ /**
+ * POST Document OCR using Actions.
+ *
+ * @throws Exception Exception
+ */
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
+ public void testOcrAndChatGpt01() throws Exception {
+
+ // given
+ for (String siteId : Arrays.asList(null, UUID.randomUUID().toString())) {
+
+ for (FormKiqClientV1 client : getFormKiqClients(siteId)) {
+
+ byte[] content = toBytes("/ocr/receipt.png");
+ String documentId = addDocument(client, siteId, "receipt.png", content, "image/png");
+ waitForDocumentContent(client, siteId, documentId);
+
+ // when
+ AddDocumentActionRequest addReq =
+ new AddDocumentActionRequest().siteId(siteId).documentId(documentId)
+ .actions(Arrays.asList(new AddDocumentAction().type(DocumentActionType.OCR),
+ new AddDocumentAction().type(DocumentActionType.DOCUMENTTAGGING)
+ .parameters(Map.of("engine", "chatgpt", "tags",
+ "organization,location,person,subject,sentiment,document type"))));
+ client.addDocumentAction(addReq);
+
+ // then
+ waitForActionsComplete(client, siteId, documentId, DocumentActionType.DOCUMENTTAGGING);
+
+ GetDocumentTagsRequest tagsReq =
+ new GetDocumentTagsRequest().siteId(siteId).documentId(documentId);
+ DocumentTags tags = client.getDocumentTags(tagsReq);
+ assertTrue(
+ tags.tags().stream().filter(r -> r.key().equals("untagged")).findFirst().isEmpty());
+
+ assertTrue(tags.tags().stream().filter(r -> r.key().toLowerCase().equals("person"))
+ .findFirst().isPresent());
+ }
+ }
+ }
+
+ private byte[] toBytes(final String name) throws IOException {
+ try (InputStream is = getClass().getResourceAsStream(name)) {
+ return IoUtils.toByteArray(is);
+ }
+ }
+}
diff --git a/lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/ConfigurationApiKeyRequestTest.java b/lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/ConfigurationApiKeyRequestTest.java
new file mode 100644
index 000000000..5f3e77ea3
--- /dev/null
+++ b/lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/ConfigurationApiKeyRequestTest.java
@@ -0,0 +1,121 @@
+/**
+ * MIT License
+ *
+ * Copyright (c) 2018 - 2020 FormKiQ
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package com.formkiq.stacks.api.awstest;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import java.net.http.HttpResponse;
+import java.util.Arrays;
+import java.util.List;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Timeout;
+import com.formkiq.stacks.client.FormKiqClientV1;
+import com.formkiq.stacks.client.models.ApiKeys;
+import com.formkiq.stacks.client.requests.AddApiKeyRequest;
+import software.amazon.awssdk.services.cognitoidentityprovider.model.AuthenticationResultType;
+
+/**
+ * Process Urls.
+ *
+ * GET /configuration/apiKeys integration tests
+ *
+ *
+ */
+public class ConfigurationApiKeyRequestTest extends AbstractApiTest {
+
+ /** JUnit Test Timeout. */
+ private static final int TEST_TIMEOUT = 20000;
+
+ /**
+ * Test GET /configuration/apiKeys.
+ *
+ * @throws Exception Exception
+ */
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
+ public void testApiKey01() throws Exception {
+ // given
+ String name = "My API";
+ final int expected = 3;
+
+ List clients = getFormKiqClients(null);
+ assertEquals(expected, clients.size());
+
+ for (String siteId : Arrays.asList(null, UUID.randomUUID().toString())) {
+
+ for (FormKiqClientV1 client : Arrays.asList(clients.get(0), clients.get(1))) {
+ AddApiKeyRequest req = new AddApiKeyRequest().siteId(siteId).name(name);
+
+ // when
+ client.addApiKey(req);
+
+ // then
+ ApiKeys apiKeys = client.getApiKeys();
+ assertFalse(apiKeys.apiKeys().isEmpty());
+ }
+
+ // given
+ FormKiqClientV1 c = clients.get(2);
+
+ // when
+ HttpResponse response = c.getApiKeysAsHttpResponse();
+
+ // then
+ assertEquals("401", String.valueOf(response.statusCode()));
+ assertEquals("{\"message\":\"user is unauthorized\"}", response.body());
+ }
+ }
+
+ /**
+ * Test GET /configuration/apiKeys as readuser user.
+ *
+ * @throws Exception Exception
+ */
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
+ public void testApiKey02() throws Exception {
+ // given
+ AuthenticationResultType token = login(FINANCE_EMAIL, USER_PASSWORD);
+ FormKiqClientV1 client = createHttpClient(token);
+
+ // when
+ HttpResponse response = client.getApiKeysAsHttpResponse();
+
+ // then
+ assertEquals("401", String.valueOf(response.statusCode()));
+ assertEquals("{\"message\":\"user is unauthorized\"}", response.body());
+
+ // given
+ AddApiKeyRequest req = new AddApiKeyRequest().name("test");
+
+ // when
+ response = client.addApiKeyAsHttpResponse(req);
+
+ // then
+ assertEquals("401", String.valueOf(response.statusCode()));
+ assertEquals("{\"message\":\"user is unauthorized\"}", response.body());
+ }
+}
diff --git a/lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/ConfigurationRequestTest.java b/lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/ConfigurationRequestTest.java
new file mode 100644
index 000000000..00ff1c512
--- /dev/null
+++ b/lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/ConfigurationRequestTest.java
@@ -0,0 +1,103 @@
+/**
+ * MIT License
+ *
+ * Copyright (c) 2018 - 2020 FormKiQ
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package com.formkiq.stacks.api.awstest;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import java.net.http.HttpResponse;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Timeout;
+import com.formkiq.stacks.client.FormKiqClientV1;
+import com.formkiq.stacks.client.models.Configuration;
+import software.amazon.awssdk.services.cognitoidentityprovider.model.AuthenticationResultType;
+
+/**
+ * Process Urls.
+ *
+ * GET /configuration tests
+ *
+ *
+ */
+public class ConfigurationRequestTest extends AbstractApiTest {
+
+ /** JUnit Test Timeout. */
+ private static final int TEST_TIMEOUT = 20000;
+
+ /**
+ * Test GET /configuration.
+ *
+ * @throws Exception Exception
+ */
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
+ public void testConfigs01() throws Exception {
+
+ // given
+ final int expected = 3;
+ List clients = getFormKiqClients(null);
+ assertEquals(expected, clients.size());
+
+ for (FormKiqClientV1 client : Arrays.asList(clients.get(0), clients.get(1))) {
+
+ // when
+ Configuration c = client.getConfiguration();
+
+ // then
+ assertNotNull(c.chatGptApiKey());
+ }
+
+ // given
+ FormKiqClientV1 fc = clients.get(2);
+
+ // when
+ HttpResponse response = fc.getConfigurationAsHttpResponse();
+
+ // then
+ assertEquals("401", String.valueOf(response.statusCode()));
+ assertEquals("{\"message\":\"user is unauthorized\"}", response.body());
+ }
+
+ /**
+ * Test GET /configuration as readuser user.
+ *
+ * @throws Exception Exception
+ */
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
+ public void testConfigs02() throws Exception {
+ // given
+ AuthenticationResultType token = login(FINANCE_EMAIL, USER_PASSWORD);
+ FormKiqClientV1 client = createHttpClient(token);
+
+ // when
+ HttpResponse response = client.getConfigurationAsHttpResponse();
+
+ // then
+ assertEquals("401", String.valueOf(response.statusCode()));
+ assertEquals("{\"message\":\"user is unauthorized\"}", response.body());
+ }
+}
diff --git a/lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/DocumentsDocumentIdOcrRequestTest.java b/lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/DocumentsDocumentIdOcrRequestTest.java
new file mode 100644
index 000000000..770abc64b
--- /dev/null
+++ b/lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/DocumentsDocumentIdOcrRequestTest.java
@@ -0,0 +1,156 @@
+/**
+ * MIT License
+ *
+ * Copyright (c) 2018 - 2020 FormKiQ
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package com.formkiq.stacks.api.awstest;
+
+import static com.formkiq.testutils.aws.FkqDocumentService.addDocument;
+import static com.formkiq.testutils.aws.FkqDocumentService.waitForDocumentContent;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Timeout;
+import com.formkiq.stacks.client.FormKiqClient;
+import com.formkiq.stacks.client.FormKiqClientV1;
+import com.formkiq.stacks.client.models.AddDocumentAction;
+import com.formkiq.stacks.client.models.DocumentActionType;
+import com.formkiq.stacks.client.models.DocumentActions;
+import com.formkiq.stacks.client.models.DocumentOcr;
+import com.formkiq.stacks.client.requests.AddDocumentActionRequest;
+import com.formkiq.stacks.client.requests.AddDocumentOcrRequest;
+import com.formkiq.stacks.client.requests.GetDocumentActionsRequest;
+import com.formkiq.stacks.client.requests.GetDocumentOcrRequest;
+import software.amazon.awssdk.utils.IoUtils;
+
+/**
+ * GET, OPTIONS, POST, PUT, DELETE /documents/{documentId}/ocr tests.
+ *
+ */
+public class DocumentsDocumentIdOcrRequestTest extends AbstractApiTest {
+
+ /** JUnit Test Timeout. */
+ private static final int TEST_TIMEOUT = 90000;
+
+ /**
+ * POST Document OCR.
+ *
+ * @throws Exception Exception
+ */
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
+ public void testAddOcr01() throws Exception {
+
+ // given
+ for (String siteId : Arrays.asList(null, UUID.randomUUID().toString())) {
+ for (FormKiqClientV1 client : getFormKiqClients(siteId)) {
+
+ byte[] content = toBytes("/ocr/receipt.png");
+ String documentId = addDocument(client, siteId, "receipt.png", content, "image/png");
+ waitForDocumentContent(client, siteId, documentId);
+
+ // when
+ AddDocumentOcrRequest addReq =
+ new AddDocumentOcrRequest().siteId(siteId).documentId(documentId);
+ client.addDocumentOcr(addReq);
+
+ // then
+ DocumentOcr documentOcr = getDocumentOcr(client, siteId, documentId);
+ assertTrue(documentOcr.data().contains("East Repair"));
+ }
+ }
+ }
+
+ /**
+ * POST Document OCR using Actions.
+ *
+ * @throws Exception Exception
+ */
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
+ public void testAddOcr02() throws Exception {
+
+ // given
+ for (String siteId : Arrays.asList(null, UUID.randomUUID().toString())) {
+ for (FormKiqClientV1 client : getFormKiqClients(siteId)) {
+
+ byte[] content = toBytes("/ocr/receipt.png");
+ String documentId = addDocument(client, siteId, "receipt.png", content, "image/png");
+ waitForDocumentContent(client, siteId, documentId);
+
+ // when
+ AddDocumentActionRequest addReq =
+ new AddDocumentActionRequest().siteId(siteId).documentId(documentId)
+ .actions(Arrays.asList(new AddDocumentAction().type(DocumentActionType.OCR)));
+ client.addDocumentAction(addReq);
+
+ // then
+ DocumentOcr documentOcr = getDocumentOcr(client, siteId, documentId);
+ assertTrue(documentOcr.data().contains("East Repair"));
+
+ GetDocumentActionsRequest getReq =
+ new GetDocumentActionsRequest().siteId(siteId).documentId(documentId);
+ DocumentActions actions = client.getDocumentActions(getReq);
+ assertEquals(1, actions.actions().size());
+ assertEquals("complete", actions.actions().get(0).status());
+ }
+ }
+ }
+
+ /**
+ * Wait for {@link DocumentOcr} to have data.
+ *
+ * @param client {@link FormKiqClient}
+ * @param siteId {@link String}
+ * @param documentId {@link String}
+ * @return {@link DocumentOcr}
+ * @throws IOException IOException
+ * @throws InterruptedException InterruptedException
+ */
+ private DocumentOcr getDocumentOcr(final FormKiqClient client, final String siteId,
+ final String documentId) throws IOException, InterruptedException {
+ DocumentOcr documentOcr = null;
+ GetDocumentOcrRequest getReq =
+ new GetDocumentOcrRequest().siteId(siteId).documentId(documentId);
+
+ while (documentOcr == null || documentOcr.data() == null) {
+ try {
+ documentOcr = client.getDocumentOcr(getReq);
+ } catch (IOException e) {
+ // ignore
+ }
+ TimeUnit.SECONDS.sleep(1);
+ }
+
+ return documentOcr;
+ }
+
+ private byte[] toBytes(final String name) throws IOException {
+ try (InputStream is = getClass().getResourceAsStream(name)) {
+ return IoUtils.toByteArray(is);
+ }
+ }
+}
diff --git a/lambda-api/src/test/java/com/formkiq/stacks/api/awstest/DocumentsDocumentIdSyncsRequestTest.java b/lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/DocumentsDocumentIdSyncsRequestTest.java
similarity index 93%
rename from lambda-api/src/test/java/com/formkiq/stacks/api/awstest/DocumentsDocumentIdSyncsRequestTest.java
rename to lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/DocumentsDocumentIdSyncsRequestTest.java
index 51c2a122c..7b5098696 100644
--- a/lambda-api/src/test/java/com/formkiq/stacks/api/awstest/DocumentsDocumentIdSyncsRequestTest.java
+++ b/lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/DocumentsDocumentIdSyncsRequestTest.java
@@ -33,7 +33,8 @@
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Timeout;
import com.formkiq.aws.dynamodb.model.DocumentSyncServiceType;
import com.formkiq.aws.dynamodb.model.DocumentSyncStatus;
import com.formkiq.aws.dynamodb.model.DocumentSyncType;
@@ -74,17 +75,18 @@ private boolean isComplete(final String formkiqType, final DocumentSyncs syncs)
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testGetSyncs01() throws Exception {
String formkiqType = null;
- for (FormKiqClientV1 client : getFormKiqClients()) {
- // given
- Version version = client.getVersion();
- formkiqType = version.type();
+ // given
+ for (String siteId : Arrays.asList(null, UUID.randomUUID().toString())) {
+ for (FormKiqClientV1 client : getFormKiqClients(siteId)) {
- for (String siteId : Arrays.asList(null, UUID.randomUUID().toString())) {
+ Version version = client.getVersion();
+ formkiqType = version.type();
String path = UUID.randomUUID().toString();
String documentId = addDocumentWithoutFile(client, siteId, path);
diff --git a/lambda-api/src/test/java/com/formkiq/stacks/api/awstest/DocumentsDocumentIdTagsRequestTest.java b/lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/DocumentsDocumentIdTagsRequestTest.java
similarity index 93%
rename from lambda-api/src/test/java/com/formkiq/stacks/api/awstest/DocumentsDocumentIdTagsRequestTest.java
rename to lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/DocumentsDocumentIdTagsRequestTest.java
index 20f032a4e..63cddced9 100644
--- a/lambda-api/src/test/java/com/formkiq/stacks/api/awstest/DocumentsDocumentIdTagsRequestTest.java
+++ b/lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/DocumentsDocumentIdTagsRequestTest.java
@@ -23,17 +23,19 @@
*/
package com.formkiq.stacks.api.awstest;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
+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.assertTrue;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.http.HttpResponse;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
-import org.junit.Test;
+import java.util.concurrent.TimeUnit;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Timeout;
import com.formkiq.stacks.client.FormKiqClientV1;
import com.formkiq.stacks.client.models.AddDocumentTag;
import com.formkiq.stacks.client.requests.AddDocumentTagRequest;
@@ -85,11 +87,11 @@ private void deleteDocumentTag(final FormKiqClientV1 client, final String docume
* @throws Exception Exception
*/
@SuppressWarnings("unchecked")
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testDocumentsTags01() throws Exception {
- for (FormKiqClientV1 client : getFormKiqClients()) {
-
+ for (FormKiqClientV1 client : getFormKiqClients(null)) {
// given
String documentId = addDocumentWithoutFile(client, null, null);
AddDocumentTagRequest request =
@@ -138,10 +140,11 @@ public void testDocumentsTags01() throws Exception {
* @throws Exception Exception
*/
@SuppressWarnings("unchecked")
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testDocumentsTags02() throws Exception {
- for (FormKiqClientV1 client : getFormKiqClients()) {
+ for (FormKiqClientV1 client : getFormKiqClients(null)) {
// given
String documentId = addDocumentWithoutFile(client, null, null);
@@ -191,10 +194,11 @@ public void testDocumentsTags02() throws Exception {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testDocumentsTags03() throws Exception {
- for (FormKiqClientV1 client : getFormKiqClients()) {
+ for (FormKiqClientV1 client : getFormKiqClients(null)) {
// given
String documentId = addDocumentWithoutFile(client, null, null);
@@ -268,10 +272,11 @@ public void testDocumentsTags03() throws Exception {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testDocumentsTags04() throws Exception {
- for (FormKiqClientV1 client : getFormKiqClients()) {
+ for (FormKiqClientV1 client : getFormKiqClients(null)) {
// given
String documentId = addDocumentWithoutFile(client, null, null);
@@ -346,10 +351,11 @@ public void testDocumentsTags04() throws Exception {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testDocumentsTags05() throws Exception {
- for (FormKiqClientV1 client : getFormKiqClients()) {
+ for (FormKiqClientV1 client : getFormKiqClients(null)) {
// given
String documentId = addDocumentWithoutFile(client, null, null);
@@ -407,10 +413,11 @@ public void testDocumentsTags05() throws Exception {
* @throws Exception Exception
*/
@SuppressWarnings("unchecked")
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testDocumentsTags06() throws Exception {
- for (FormKiqClientV1 client : getFormKiqClients()) {
+ for (FormKiqClientV1 client : getFormKiqClients(null)) {
// given
String documentId = addDocumentWithoutFile(client, null, null);
@@ -479,8 +486,10 @@ public void testDocumentsTags06() throws Exception {
private void verifyUserId(final Map map) {
if ("testadminuser@formkiq.com".equals(map.get("userId"))) {
assertEquals("testadminuser@formkiq.com", map.get("userId"));
- } else {
+ } else if (map.get("userId").toString().contains(":user/")) {
assertTrue(map.get("userId").toString().contains(":user/"));
+ } else {
+ assertEquals("My API Key", map.get("userId"));
}
}
}
diff --git a/lambda-api/src/test/java/com/formkiq/stacks/api/awstest/DocumentsDocumentIdUploadRequestTest.java b/lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/DocumentsDocumentIdUploadRequestTest.java
similarity index 85%
rename from lambda-api/src/test/java/com/formkiq/stacks/api/awstest/DocumentsDocumentIdUploadRequestTest.java
rename to lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/DocumentsDocumentIdUploadRequestTest.java
index eaa0eaeb2..e4cc3f6a0 100644
--- a/lambda-api/src/test/java/com/formkiq/stacks/api/awstest/DocumentsDocumentIdUploadRequestTest.java
+++ b/lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/DocumentsDocumentIdUploadRequestTest.java
@@ -23,12 +23,14 @@
*/
package com.formkiq.stacks.api.awstest;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
import java.net.http.HttpResponse;
import java.util.Map;
import java.util.UUID;
-import org.junit.Test;
+import java.util.concurrent.TimeUnit;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Timeout;
import com.formkiq.stacks.client.FormKiqClientV1;
import com.formkiq.stacks.client.requests.GetDocumentUploadRequest;
import com.formkiq.stacks.client.requests.OptionsDocumentRequest;
@@ -47,10 +49,11 @@ public class DocumentsDocumentIdUploadRequestTest extends AbstractApiTest {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testGet01() throws Exception {
- for (FormKiqClientV1 client : getFormKiqClients()) {
+ for (FormKiqClientV1 client : getFormKiqClients(null)) {
// given
String documentId = UUID.randomUUID().toString();
GetDocumentUploadRequest request =
@@ -70,9 +73,10 @@ public void testGet01() throws Exception {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testGet02() throws Exception {
- for (FormKiqClientV1 client : getFormKiqClients()) {
+ for (FormKiqClientV1 client : getFormKiqClients(null)) {
// given
String documentId = addDocumentWithoutFile(client, null, null);
GetDocumentUploadRequest request =
@@ -96,9 +100,10 @@ public void testGet02() throws Exception {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testOptions01() throws Exception {
- for (FormKiqClientV1 client : getFormKiqClients()) {
+ for (FormKiqClientV1 client : getFormKiqClients(null)) {
// given
String documentId = UUID.randomUUID().toString();
OptionsDocumentRequest req = new OptionsDocumentRequest().documentId(documentId);
diff --git a/lambda-api/src/test/java/com/formkiq/stacks/api/awstest/DocumentsDocumentIdUrlRequestTest.java b/lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/DocumentsDocumentIdUrlRequestTest.java
similarity index 89%
rename from lambda-api/src/test/java/com/formkiq/stacks/api/awstest/DocumentsDocumentIdUrlRequestTest.java
rename to lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/DocumentsDocumentIdUrlRequestTest.java
index e223b0361..66f230e51 100644
--- a/lambda-api/src/test/java/com/formkiq/stacks/api/awstest/DocumentsDocumentIdUrlRequestTest.java
+++ b/lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/DocumentsDocumentIdUrlRequestTest.java
@@ -23,8 +23,8 @@
*/
package com.formkiq.stacks.api.awstest;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
@@ -32,7 +32,9 @@
import java.net.http.HttpResponse.BodyHandlers;
import java.util.Map;
import java.util.UUID;
-import org.junit.Test;
+import java.util.concurrent.TimeUnit;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Timeout;
import com.formkiq.stacks.client.FormKiqClientV1;
import com.formkiq.stacks.client.requests.GetDocumentContentUrlRequest;
import com.formkiq.stacks.client.requests.OptionsDocumentUploadRequest;
@@ -55,9 +57,10 @@ public class DocumentsDocumentIdUrlRequestTest extends AbstractApiTest {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testGet01() throws Exception {
- for (FormKiqClientV1 client : getFormKiqClients()) {
+ for (FormKiqClientV1 client : getFormKiqClients(null)) {
// given
String documentId = addDocumentWithoutFile(client, null, null);
Thread.sleep(SLEEP * 2);
@@ -70,10 +73,11 @@ public void testGet01() throws Exception {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testOptions01() throws Exception {
- for (FormKiqClientV1 client : getFormKiqClients()) {
+ for (FormKiqClientV1 client : getFormKiqClients(null)) {
// given
String documentId = UUID.randomUUID().toString();
OptionsDocumentUploadRequest req = new OptionsDocumentUploadRequest().documentId(documentId);
diff --git a/lambda-api/src/test/java/com/formkiq/stacks/api/awstest/DocumentsDocumentIdVersionsRequestTest.java b/lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/DocumentsDocumentIdVersionsRequestTest.java
similarity index 87%
rename from lambda-api/src/test/java/com/formkiq/stacks/api/awstest/DocumentsDocumentIdVersionsRequestTest.java
rename to lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/DocumentsDocumentIdVersionsRequestTest.java
index 57c1a2282..75b2385c8 100644
--- a/lambda-api/src/test/java/com/formkiq/stacks/api/awstest/DocumentsDocumentIdVersionsRequestTest.java
+++ b/lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/DocumentsDocumentIdVersionsRequestTest.java
@@ -23,10 +23,12 @@
*/
package com.formkiq.stacks.api.awstest;
-import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
import java.net.http.HttpResponse;
import java.util.UUID;
-import org.junit.Test;
+import java.util.concurrent.TimeUnit;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Timeout;
import com.formkiq.stacks.client.FormKiqClientV1;
import com.formkiq.stacks.client.requests.OptionsDocumentVersionsRequest;
@@ -44,10 +46,11 @@ public class DocumentsDocumentIdVersionsRequestTest extends AbstractApiTest {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testOptions01() throws Exception {
- for (FormKiqClientV1 client : getFormKiqClients()) {
+ for (FormKiqClientV1 client : getFormKiqClients(null)) {
// given
String documentId = UUID.randomUUID().toString();
OptionsDocumentVersionsRequest req =
diff --git a/lambda-api/src/test/java/com/formkiq/stacks/api/awstest/DocumentsRequestTest.java b/lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/DocumentsRequestTest.java
similarity index 92%
rename from lambda-api/src/test/java/com/formkiq/stacks/api/awstest/DocumentsRequestTest.java
rename to lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/DocumentsRequestTest.java
index 4c6f6b843..b74dd70fd 100644
--- a/lambda-api/src/test/java/com/formkiq/stacks/api/awstest/DocumentsRequestTest.java
+++ b/lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/DocumentsRequestTest.java
@@ -24,13 +24,13 @@
package com.formkiq.stacks.api.awstest;
import static com.formkiq.aws.dynamodb.SiteIdKeyGenerator.DEFAULT_SITE_ID;
-import static com.formkiq.aws.services.lambda.services.ConfigService.MAX_DOCUMENTS;
+import static com.formkiq.stacks.dynamodb.ConfigService.MAX_DOCUMENTS;
import static com.formkiq.testutils.aws.FkqDocumentService.waitForDocumentContent;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
@@ -48,10 +48,13 @@
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
+import java.util.concurrent.TimeUnit;
import java.util.function.BiPredicate;
-import org.junit.AfterClass;
-import org.junit.Test;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Timeout;
import com.formkiq.aws.dynamodb.DynamicObject;
+import com.formkiq.aws.dynamodb.objects.MimeType;
import com.formkiq.stacks.client.FormKiqClient;
import com.formkiq.stacks.client.FormKiqClientConnection;
import com.formkiq.stacks.client.FormKiqClientV1;
@@ -77,7 +80,6 @@
import com.formkiq.stacks.client.requests.OptionsDocumentRequest;
import com.formkiq.stacks.client.requests.SearchDocumentsRequest;
import com.formkiq.stacks.client.requests.UpdateDocumentRequest;
-import com.formkiq.stacks.common.formats.MimeType;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.services.cognitoidentityprovider.model.AuthenticationResultType;
@@ -109,7 +111,7 @@ public class DocumentsRequestTest extends AbstractApiTest {
/**
* After Class.
*/
- @AfterClass
+ @AfterAll
public static void afterClass() {
getConfigService().delete(SITEID1);
}
@@ -172,9 +174,10 @@ private DocumentTags getDocumentTags(final FormKiqClient client, final String do
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testDelete01() throws Exception {
- for (FormKiqClientV1 client : getFormKiqClients()) {
+ for (FormKiqClientV1 client : getFormKiqClients(null)) {
// given
String documentId = UUID.randomUUID().toString();
DeleteDocumentRequest request = new DeleteDocumentRequest().documentId(documentId);
@@ -193,9 +196,10 @@ public void testDelete01() throws Exception {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testGet01() throws Exception {
- for (FormKiqClientV1 client : getFormKiqClients()) {
+ for (FormKiqClientV1 client : getFormKiqClients(null)) {
// given
GetDocumentsRequest request = new GetDocumentsRequest().date(new Date());
// when
@@ -213,7 +217,8 @@ public void testGet01() throws Exception {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testGet02() throws Exception {
// given
final String siteId = "finance";
@@ -249,7 +254,8 @@ public void testGet02() throws Exception {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testGet03() throws Exception {
// given
final String siteId = "finance";
@@ -282,7 +288,8 @@ public void testGet03() throws Exception {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testGet04() throws Exception {
// given
final String siteId = "finance";
@@ -309,7 +316,8 @@ public void testGet04() throws Exception {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testGet05() throws Exception {
// given
final String siteId = "finance";
@@ -337,9 +345,10 @@ public void testGet05() throws Exception {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testOptions01() throws Exception {
- for (FormKiqClientV1 client : getFormKiqClients()) {
+ for (FormKiqClientV1 client : getFormKiqClients(null)) {
// given
String documentId = UUID.randomUUID().toString();
OptionsDocumentRequest req = new OptionsDocumentRequest().documentId(documentId);
@@ -358,9 +367,10 @@ public void testOptions01() throws Exception {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testOptions02() throws Exception {
- for (FormKiqClientV1 client : getFormKiqClients()) {
+ for (FormKiqClientV1 client : getFormKiqClients(null)) {
// given
// when
HttpResponse response = client.optionsDocuments();
@@ -376,9 +386,10 @@ public void testOptions02() throws Exception {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testPost01() throws Exception {
- for (FormKiqClientV1 client : getFormKiqClients()) {
+ for (FormKiqClientV1 client : getFormKiqClients(null)) {
// given
AddDocument post =
new AddDocument().contentType("text/plain").content("test data", StandardCharsets.UTF_8);
@@ -466,7 +477,8 @@ private void testPost01Delete(final FormKiqClientV1 client, final String documen
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testPost02() throws Exception {
// given
final String siteId = "finance";
@@ -499,7 +511,8 @@ public void testPost02() throws Exception {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testPost03() throws Exception {
// given
final String siteId = "finance";
@@ -530,7 +543,8 @@ public void testPost03() throws Exception {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testPost04() throws Exception {
// given
final String siteId = "finance";
@@ -563,7 +577,8 @@ public void testPost04() throws Exception {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testPost05() throws Exception {
// given
final String siteId = "finance";
@@ -601,7 +616,8 @@ public void testPost05() throws Exception {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testPost06() throws Exception {
// given
getConfigService().save(SITEID1, new DynamicObject(Map.of(MAX_DOCUMENTS, "1")));
@@ -611,12 +627,12 @@ public void testPost06() throws Exception {
post.contentType("application/pdf");
AddDocumentRequest req = new AddDocumentRequest().document(post).siteId(SITEID1);
- FormKiqClientV1 c = getFormKiqClients().get(0);
+ FormKiqClientV1 c = getFormKiqClients(SITEID1).get(0);
HttpResponse response = c.addDocumentAsHttpResponse(req);
assertEquals(STATUS_CREATED, response.statusCode());
- for (FormKiqClientV1 client : getFormKiqClients()) {
+ for (FormKiqClientV1 client : getFormKiqClients(SITEID1)) {
// when
response = client.addDocumentAsHttpResponse(req);
@@ -632,12 +648,13 @@ public void testPost06() throws Exception {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testPost07() throws Exception {
for (boolean enablePublicEndpoint : Arrays.asList(Boolean.FALSE, Boolean.TRUE)) {
- for (FormKiqClientV1 client : getFormKiqClients()) {
+ for (FormKiqClientV1 client : getFormKiqClients(null)) {
// given
AddDocument post = new AddDocument()
.tags(Arrays.asList(new AddDocumentTag().key("formName").value("Job Application Form")))
@@ -714,10 +731,11 @@ public void testPost07() throws Exception {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testPost08() throws Exception {
// given
- FormKiqClientV1 client = getFormKiqClients().get(0);
+ FormKiqClientV1 client = getFormKiqClients(null).get(0);
String url = getRootHttpUrl() + "/documents";
Map> headers =
@@ -761,9 +779,10 @@ public boolean test(final String t, final String u) {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testPost09() throws Exception {
- for (FormKiqClientV1 client : getFormKiqClients()) {
+ for (FormKiqClientV1 client : getFormKiqClients(null)) {
// given
AddDocument post = new AddDocument().path("something.txt").contentType("text/plain")
.content("test data", StandardCharsets.UTF_8)
@@ -829,12 +848,13 @@ public void testPost09() throws Exception {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testPost10() throws Exception {
// given
String content = "test data";
for (String siteId : Arrays.asList(null, UUID.randomUUID().toString())) {
- for (FormKiqClientV1 client : getFormKiqClients()) {
+ for (FormKiqClientV1 client : getFormKiqClients(siteId)) {
AddDocument post =
new AddDocument().contentType("text/plain").content(content, StandardCharsets.UTF_8)
diff --git a/lambda-api/src/test/java/com/formkiq/stacks/api/awstest/DocumentsSearchRequestTest.java b/lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/DocumentsSearchRequestTest.java
similarity index 88%
rename from lambda-api/src/test/java/com/formkiq/stacks/api/awstest/DocumentsSearchRequestTest.java
rename to lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/DocumentsSearchRequestTest.java
index b519c9092..05909a134 100644
--- a/lambda-api/src/test/java/com/formkiq/stacks/api/awstest/DocumentsSearchRequestTest.java
+++ b/lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/DocumentsSearchRequestTest.java
@@ -23,16 +23,17 @@
*/
package com.formkiq.stacks.api.awstest;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import java.net.http.HttpResponse;
import java.util.Arrays;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Timeout;
import com.formkiq.stacks.client.FormKiqClientV1;
import com.formkiq.stacks.client.models.Document;
import com.formkiq.stacks.client.models.DocumentSearchQuery;
@@ -57,9 +58,10 @@ public class DocumentsSearchRequestTest extends AbstractApiTest {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testDocumentsRawSearch01() throws Exception {
- for (FormKiqClientV1 client : getFormKiqClients()) {
+ for (FormKiqClientV1 client : getFormKiqClients(null)) {
// given
SearchDocumentsRequest req = new SearchDocumentsRequest()
.query(new DocumentSearchQuery().tag(new DocumentSearchTag().key("untagged")));
@@ -79,10 +81,11 @@ public void testDocumentsRawSearch01() throws Exception {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testDocumentsSearch01() throws Exception {
// given
- for (FormKiqClientV1 client : getFormKiqClients()) {
+ for (FormKiqClientV1 client : getFormKiqClients(null)) {
addDocumentWithoutFile(client, null, null);
SearchDocumentsRequest req = new SearchDocumentsRequest()
.query(new DocumentSearchQuery().tag(new DocumentSearchTag().key("untagged")));
@@ -105,9 +108,10 @@ public void testDocumentsSearch01() throws Exception {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testDocumentsSearch02() throws Exception {
- for (FormKiqClientV1 client : getFormKiqClients()) {
+ for (FormKiqClientV1 client : getFormKiqClients(null)) {
// given
String next = "3aa3a255-6a67-4d05-8e67-f7a22b827433";
SearchDocumentsRequest req = new SearchDocumentsRequest()
@@ -131,10 +135,11 @@ public void testDocumentsSearch02() throws Exception {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testDocumentsSearch03() throws Exception {
// given
- for (FormKiqClientV1 client : getFormKiqClients()) {
+ for (FormKiqClientV1 client : getFormKiqClients(null)) {
String documentId = addDocumentWithoutFile(client, null, null);
SearchDocumentsRequest req = new SearchDocumentsRequest().query(new DocumentSearchQuery()
.tag(new DocumentSearchTag().key("untagged")).documentIds(Arrays.asList(documentId)));
@@ -157,10 +162,11 @@ public void testDocumentsSearch03() throws Exception {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testDocumentsSearch04() throws Exception {
// given
- for (FormKiqClientV1 client : getFormKiqClients()) {
+ for (FormKiqClientV1 client : getFormKiqClients(null)) {
addDocumentWithoutFile(client, null, null);
SearchDocumentsRequest req = new SearchDocumentsRequest()
.query(new DocumentSearchQuery().tag(new DocumentSearchTag().key("untagged"))
@@ -179,10 +185,11 @@ public void testDocumentsSearch04() throws Exception {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testDocumentsSearch05() throws Exception {
// given
- for (FormKiqClientV1 client : getFormKiqClients()) {
+ for (FormKiqClientV1 client : getFormKiqClients(null)) {
String documentId = addDocumentWithoutFile(client, null, null);
AddDocumentTagRequest tagRequest =
new AddDocumentTagRequest().documentId(documentId).tagKey("test").tagValue("somevalue");
@@ -223,10 +230,11 @@ public void testDocumentsSearch05() throws Exception {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testDocumentsSearch06() throws Exception {
// given
- for (FormKiqClientV1 client : getFormKiqClients()) {
+ for (FormKiqClientV1 client : getFormKiqClients(null)) {
String documentId = addDocumentWithoutFile(client, null, null);
AddDocumentTagRequest tagRequest =
new AddDocumentTagRequest().documentId(documentId).tagKey("test").tagValue("somevalue");
@@ -264,10 +272,11 @@ public void testDocumentsSearch06() throws Exception {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testDocumentsSearch07() throws Exception {
// given
- for (FormKiqClientV1 client : getFormKiqClients()) {
+ for (FormKiqClientV1 client : getFormKiqClients(null)) {
String tagKey = UUID.randomUUID().toString();
String documentId = addDocumentWithoutFile(client, null, null);
AddDocumentTagRequest tagRequest =
@@ -304,14 +313,15 @@ public void testDocumentsSearch07() throws Exception {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testDocumentsSearch08() throws Exception {
// given
String siteId = null;
String path = "some/thing/else/My Documents.pdf";
String text = "My Documents";
final int limit = 100;
- for (FormKiqClientV1 client : getFormKiqClients()) {
+ for (FormKiqClientV1 client : getFormKiqClients(null)) {
String documentId = addDocumentWithoutFile(client, siteId, path);
SearchDocumentsRequest req = new SearchDocumentsRequest().siteId(siteId)
diff --git a/lambda-api/src/test/java/com/formkiq/stacks/api/awstest/DocumentsUploadRequestTest.java b/lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/DocumentsUploadRequestTest.java
similarity index 86%
rename from lambda-api/src/test/java/com/formkiq/stacks/api/awstest/DocumentsUploadRequestTest.java
rename to lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/DocumentsUploadRequestTest.java
index 41cd00a41..9ba6e819a 100644
--- a/lambda-api/src/test/java/com/formkiq/stacks/api/awstest/DocumentsUploadRequestTest.java
+++ b/lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/DocumentsUploadRequestTest.java
@@ -23,10 +23,10 @@
*/
package com.formkiq.stacks.api.awstest;
-import static com.formkiq.aws.services.lambda.services.ConfigService.MAX_DOCUMENTS;
-import static com.formkiq.aws.services.lambda.services.ConfigService.MAX_DOCUMENT_SIZE_BYTES;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
+import static com.formkiq.stacks.dynamodb.ConfigService.MAX_DOCUMENTS;
+import static com.formkiq.stacks.dynamodb.ConfigService.MAX_DOCUMENT_SIZE_BYTES;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
@@ -37,10 +37,13 @@
import java.util.Arrays;
import java.util.Map;
import java.util.UUID;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.Test;
+import java.util.concurrent.TimeUnit;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Timeout;
import com.formkiq.aws.dynamodb.DynamicObject;
+import com.formkiq.aws.dynamodb.objects.MimeType;
import com.formkiq.stacks.client.FormKiqClientV1;
import com.formkiq.stacks.client.models.AddLargeDocument;
import com.formkiq.stacks.client.models.DocumentContent;
@@ -48,7 +51,6 @@
import com.formkiq.stacks.client.requests.AddLargeDocumentRequest;
import com.formkiq.stacks.client.requests.GetDocumentContentRequest;
import com.formkiq.stacks.client.requests.GetDocumentUploadRequest;
-import com.formkiq.stacks.common.formats.MimeType;
/**
* GET, OPTIONS /documents/upload tests.
@@ -75,7 +77,7 @@ public class DocumentsUploadRequestTest extends AbstractApiTest {
/**
* After Class.
*/
- @AfterClass
+ @AfterAll
public static void afterClass() {
getConfigService().delete(SITEID0);
getConfigService().delete(SITEID1);
@@ -109,7 +111,7 @@ private void assertDocumentContent(final FormKiqClientV1 client, final String do
/**
* before.
*/
- @Before
+ @BeforeEach
public void before() {
getConfigService().delete(SITEID0);
getConfigService().delete(SITEID1);
@@ -120,9 +122,10 @@ public void before() {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testGet01() throws Exception {
- for (FormKiqClientV1 client : getFormKiqClients()) {
+ for (FormKiqClientV1 client : getFormKiqClients(null)) {
// given
String content = "test content";
GetDocumentUploadRequest request =
@@ -160,12 +163,13 @@ public void testGet01() throws Exception {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testGet02() throws Exception {
// given
getConfigService().save(SITEID0, new DynamicObject(Map.of(MAX_DOCUMENT_SIZE_BYTES, "5")));
- for (FormKiqClientV1 client : getFormKiqClients()) {
+ for (FormKiqClientV1 client : getFormKiqClients(SITEID0)) {
GetDocumentUploadRequest request = new GetDocumentUploadRequest().siteId(SITEID0);
@@ -184,7 +188,8 @@ public void testGet02() throws Exception {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testGet03() throws Exception {
// given
final int contentLength = 100;
@@ -193,7 +198,7 @@ public void testGet03() throws Exception {
GetDocumentUploadRequest request =
new GetDocumentUploadRequest().siteId(SITEID0).contentLength(contentLength);
- for (FormKiqClientV1 client : getFormKiqClients()) {
+ for (FormKiqClientV1 client : getFormKiqClients(SITEID0)) {
// when
HttpResponse response = client.getDocumentUploadAsHttpResponse(request);
@@ -210,7 +215,8 @@ public void testGet03() throws Exception {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testGet04() throws Exception {
// given
final int contentLength = 5;
@@ -220,7 +226,7 @@ public void testGet04() throws Exception {
GetDocumentUploadRequest request =
new GetDocumentUploadRequest().siteId(SITEID0).contentLength(contentLength);
- for (FormKiqClientV1 client : getFormKiqClients()) {
+ for (FormKiqClientV1 client : getFormKiqClients(SITEID0)) {
// when
HttpResponse response = client.getDocumentUploadAsHttpResponse(request);
@@ -236,7 +242,8 @@ public void testGet04() throws Exception {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testGet05() throws Exception {
// given
getConfigService().save(SITEID1, new DynamicObject(Map.of(MAX_DOCUMENTS, "1")));
@@ -245,10 +252,10 @@ public void testGet05() throws Exception {
new GetDocumentUploadRequest().siteId(SITEID1).contentLength(1);
HttpResponse response =
- getFormKiqClients().get(0).getDocumentUploadAsHttpResponse(request);
+ getFormKiqClients(SITEID1).get(0).getDocumentUploadAsHttpResponse(request);
assertEquals(STATUS_OK, response.statusCode());
- for (FormKiqClientV1 client : getFormKiqClients()) {
+ for (FormKiqClientV1 client : getFormKiqClients(SITEID1)) {
// when
response = client.getDocumentUploadAsHttpResponse(request);
@@ -265,9 +272,10 @@ public void testGet05() throws Exception {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testOptions01() throws Exception {
- for (FormKiqClientV1 client : getFormKiqClients()) {
+ for (FormKiqClientV1 client : getFormKiqClients(null)) {
// given
// when
HttpResponse response = client.optionsDocumentUpload();
@@ -282,9 +290,10 @@ public void testOptions01() throws Exception {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testPost01() throws Exception {
- for (FormKiqClientV1 client : getFormKiqClients()) {
+ for (FormKiqClientV1 client : getFormKiqClients(null)) {
// given
DocumentTag tag0 = new DocumentTag().key("test").value("this");
AddLargeDocumentRequest request =
diff --git a/lambda-api/src/test/java/com/formkiq/stacks/api/awstest/PrivateWebhooksRequestTest.java b/lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/PrivateWebhooksRequestTest.java
similarity index 88%
rename from lambda-api/src/test/java/com/formkiq/stacks/api/awstest/PrivateWebhooksRequestTest.java
rename to lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/PrivateWebhooksRequestTest.java
index 6c8257eef..84a14752f 100644
--- a/lambda-api/src/test/java/com/formkiq/stacks/api/awstest/PrivateWebhooksRequestTest.java
+++ b/lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/PrivateWebhooksRequestTest.java
@@ -23,18 +23,20 @@
*/
package com.formkiq.stacks.api.awstest;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import java.net.http.HttpHeaders;
import java.net.http.HttpResponse;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Optional;
+import java.util.concurrent.TimeUnit;
import java.util.function.BiPredicate;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Timeout;
import com.formkiq.stacks.client.FormKiqClientV1;
import com.formkiq.stacks.client.HttpService;
import com.formkiq.stacks.client.HttpServiceJava;
@@ -70,9 +72,10 @@ public class PrivateWebhooksRequestTest extends AbstractApiTest {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testOptions01() throws Exception {
- for (FormKiqClientV1 client : getFormKiqClients()) {
+ for (FormKiqClientV1 client : getFormKiqClients(null)) {
assertEquals(STATUS_NO_CONTENT, client.optionsWebhooks().statusCode());
assertEquals(STATUS_NO_CONTENT,
client.optionsWebhooks(new OptionsWebhookRequest().webhookId("1")).statusCode());
@@ -84,9 +87,10 @@ public void testOptions01() throws Exception {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testPublicWebhooks01() throws Exception {
- for (FormKiqClientV1 client : getFormKiqClients()) {
+ for (FormKiqClientV1 client : getFormKiqClients(null)) {
// given
String id = client.addWebhook(new AddWebhookRequest().name("paypal").enabled("private")).id();
String urlpath = getRootHttpUrl() + "/private/webhooks/" + id;
@@ -134,9 +138,10 @@ public boolean test(final String t, final String u) {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testPublicWebhooks02() throws Exception {
- for (FormKiqClientV1 client : getFormKiqClients()) {
+ for (FormKiqClientV1 client : getFormKiqClients(null)) {
// given
String id = client.addWebhook(new AddWebhookRequest().name("paypal").enabled("private")).id();
String urlpath = getRootHttpUrl() + "/private/webhooks/" + id;
diff --git a/lambda-api/src/test/java/com/formkiq/stacks/api/awstest/PublicWebhooksRequestTest.java b/lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/PublicWebhooksRequestTest.java
similarity index 89%
rename from lambda-api/src/test/java/com/formkiq/stacks/api/awstest/PublicWebhooksRequestTest.java
rename to lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/PublicWebhooksRequestTest.java
index ef779a8ab..38094669c 100644
--- a/lambda-api/src/test/java/com/formkiq/stacks/api/awstest/PublicWebhooksRequestTest.java
+++ b/lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/PublicWebhooksRequestTest.java
@@ -23,18 +23,20 @@
*/
package com.formkiq.stacks.api.awstest;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import java.net.http.HttpHeaders;
import java.net.http.HttpResponse;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Optional;
+import java.util.concurrent.TimeUnit;
import java.util.function.BiPredicate;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Timeout;
import com.formkiq.stacks.client.FormKiqClientV1;
import com.formkiq.stacks.client.HttpService;
import com.formkiq.stacks.client.HttpServiceJava;
@@ -74,9 +76,10 @@ public class PublicWebhooksRequestTest extends AbstractApiTest {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testOptions01() throws Exception {
- for (FormKiqClientV1 client : getFormKiqClients()) {
+ for (FormKiqClientV1 client : getFormKiqClients(null)) {
assertEquals(STATUS_NO_CONTENT, client.optionsWebhooks().statusCode());
assertEquals(STATUS_NO_CONTENT,
client.optionsWebhooks(new OptionsWebhookRequest().webhookId("1")).statusCode());
@@ -88,9 +91,10 @@ public void testOptions01() throws Exception {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testPublicWebhooks01() throws Exception {
- for (FormKiqClientV1 client : getFormKiqClients()) {
+ for (FormKiqClientV1 client : getFormKiqClients(null)) {
// given
String id = client.addWebhook(new AddWebhookRequest().name("paypal")).id();
String urlpath = getRootHttpUrl() + "/public/webhooks/" + id;
@@ -136,7 +140,8 @@ public boolean test(final String t, final String u) {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testPublicWebhooks02() throws Exception {
// given
String urlpath = getRootHttpUrl() + "/public/webhooks";
@@ -166,7 +171,8 @@ public boolean test(final String t, final String u) {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testPublicWebhooks03() throws Exception {
// given
String urlpath = getRootHttpUrl() + "/public/webhooks/asdffgdfg";
@@ -196,9 +202,10 @@ public boolean test(final String t, final String u) {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testPublicWebhooks04() throws Exception {
- for (FormKiqClientV1 client : getFormKiqClients()) {
+ for (FormKiqClientV1 client : getFormKiqClients(null)) {
// given
String id = client.addWebhook(new AddWebhookRequest().name("paypal").enabled("private")).id();
String urlpath = getRootHttpUrl() + "/public/webhooks/" + id;
diff --git a/lambda-api/src/test/java/com/formkiq/stacks/api/awstest/SitesRequestTest.java b/lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/SitesRequestTest.java
similarity index 86%
rename from lambda-api/src/test/java/com/formkiq/stacks/api/awstest/SitesRequestTest.java
rename to lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/SitesRequestTest.java
index 2bb007567..9035429ad 100644
--- a/lambda-api/src/test/java/com/formkiq/stacks/api/awstest/SitesRequestTest.java
+++ b/lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/SitesRequestTest.java
@@ -23,11 +23,13 @@
*/
package com.formkiq.stacks.api.awstest;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import java.net.http.HttpResponse;
-import org.junit.Test;
+import java.util.concurrent.TimeUnit;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Timeout;
import com.formkiq.stacks.client.FormKiqClientV1;
import com.formkiq.stacks.client.models.Sites;
import software.amazon.awssdk.services.cognitoidentityprovider.model.AuthenticationResultType;
@@ -51,7 +53,8 @@ public class SitesRequestTest extends AbstractApiTest {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testSites01() throws Exception {
// given
AuthenticationResultType token = login(USER_EMAIL, USER_PASSWORD);
@@ -72,9 +75,9 @@ public void testSites01() throws Exception {
*
* @throws Exception Exception
*/
- @Test // (timeout = TEST_TIMEOUT)
+ @Test
public void testOptions01() throws Exception {
- for (FormKiqClientV1 client : getFormKiqClients()) {
+ for (FormKiqClientV1 client : getFormKiqClients(null)) {
HttpResponse response = client.optionsSites();
assertEquals(HTTP_STATUS_NO_CONTENT, response.statusCode());
assertPreflightedCorsHeaders(response.headers());
diff --git a/lambda-api/src/test/java/com/formkiq/stacks/api/awstest/VersionRequestTest.java b/lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/VersionRequestTest.java
similarity index 81%
rename from lambda-api/src/test/java/com/formkiq/stacks/api/awstest/VersionRequestTest.java
rename to lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/VersionRequestTest.java
index 3cb7bf0ed..b4504c8f5 100644
--- a/lambda-api/src/test/java/com/formkiq/stacks/api/awstest/VersionRequestTest.java
+++ b/lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/VersionRequestTest.java
@@ -23,10 +23,12 @@
*/
package com.formkiq.stacks.api.awstest;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
import java.net.http.HttpResponse;
-import org.junit.Test;
+import java.util.concurrent.TimeUnit;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Timeout;
import com.formkiq.stacks.client.FormKiqClientV1;
/**
@@ -48,10 +50,11 @@ public class VersionRequestTest extends AbstractApiTest {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testVersion01() throws Exception {
// given
- for (FormKiqClientV1 c : getFormKiqClients()) {
+ for (FormKiqClientV1 c : getFormKiqClients(null)) {
assertNotNull(c.getVersion().version());
assertNotNull(c.getVersion().type());
}
@@ -62,9 +65,10 @@ public void testVersion01() throws Exception {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testOptions01() throws Exception {
- for (FormKiqClientV1 client : getFormKiqClients()) {
+ for (FormKiqClientV1 client : getFormKiqClients(null)) {
HttpResponse response = client.optionsVersion();
assertEquals(HTTP_STATUS_NO_CONTENT, response.statusCode());
assertPreflightedCorsHeaders(response.headers());
diff --git a/lambda-api/src/test/java/com/formkiq/stacks/api/awstest/WebhookTagsRequestTest.java b/lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/WebhookTagsRequestTest.java
similarity index 85%
rename from lambda-api/src/test/java/com/formkiq/stacks/api/awstest/WebhookTagsRequestTest.java
rename to lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/WebhookTagsRequestTest.java
index 930a1699e..9cf6763b5 100644
--- a/lambda-api/src/test/java/com/formkiq/stacks/api/awstest/WebhookTagsRequestTest.java
+++ b/lambda-api/src/integration/java/com/formkiq/stacks/api/awstest/WebhookTagsRequestTest.java
@@ -23,11 +23,13 @@
*/
package com.formkiq.stacks.api.awstest;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.UUID;
-import org.junit.Test;
+import java.util.concurrent.TimeUnit;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Timeout;
import com.formkiq.stacks.client.FormKiqClientV1;
import com.formkiq.stacks.client.models.WebhookTag;
import com.formkiq.stacks.client.models.WebhookTags;
@@ -55,9 +57,10 @@ public class WebhookTagsRequestTest extends AbstractApiTest {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testOptions01() throws Exception {
- for (FormKiqClientV1 client : getFormKiqClients()) {
+ for (FormKiqClientV1 client : getFormKiqClients(null)) {
OptionsWebhookTagsRequest req =
new OptionsWebhookTagsRequest().webhookId(UUID.randomUUID().toString());
assertEquals(STATUS_NO_CONTENT, client.optionsWebhookTags(req).statusCode());
@@ -69,9 +72,10 @@ public void testOptions01() throws Exception {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testPublicWebhooks01() throws Exception {
- for (FormKiqClientV1 client : getFormKiqClients()) {
+ for (FormKiqClientV1 client : getFormKiqClients(null)) {
// given
String id = client.addWebhook(new AddWebhookRequest().name("paypal")).id();
diff --git a/lambda-api/src/main/java/com/formkiq/stacks/api/AbstractCoreRequestHandler.java b/lambda-api/src/main/java/com/formkiq/stacks/api/AbstractCoreRequestHandler.java
index 0701bf528..ef3699c8d 100644
--- a/lambda-api/src/main/java/com/formkiq/stacks/api/AbstractCoreRequestHandler.java
+++ b/lambda-api/src/main/java/com/formkiq/stacks/api/AbstractCoreRequestHandler.java
@@ -38,8 +38,6 @@
import com.formkiq.aws.services.lambda.LambdaInputRecord;
import com.formkiq.aws.services.lambda.exceptions.NotFoundException;
import com.formkiq.aws.services.lambda.services.CacheService;
-import com.formkiq.aws.services.lambda.services.ConfigService;
-import com.formkiq.aws.services.lambda.services.ConfigServiceExtension;
import com.formkiq.aws.services.lambda.services.DynamoDbCacheServiceExtension;
import com.formkiq.aws.sns.SnsConnectionBuilder;
import com.formkiq.aws.sqs.SqsConnectionBuilder;
@@ -54,8 +52,12 @@
import com.formkiq.module.actions.services.ActionsServiceExtension;
import com.formkiq.module.lambdaservices.AwsServiceCache;
import com.formkiq.module.lambdaservices.ClassServiceExtension;
+import com.formkiq.module.ocr.DocumentOcrService;
+import com.formkiq.module.ocr.DocumentOcrServiceExtension;
import com.formkiq.plugins.tagschema.DocumentTagSchemaPlugin;
import com.formkiq.plugins.tagschema.DocumentTagSchemaPluginExtension;
+import com.formkiq.stacks.api.handler.ConfigurationRequestHandler;
+import com.formkiq.stacks.api.handler.ConfigurationApiKeysRequestHandler;
import com.formkiq.stacks.api.handler.DocumentIdContentRequestHandler;
import com.formkiq.stacks.api.handler.DocumentIdRequestHandler;
import com.formkiq.stacks.api.handler.DocumentIdUrlRequestHandler;
@@ -95,6 +97,10 @@
import com.formkiq.stacks.api.handler.WebhooksIdRequestHandler;
import com.formkiq.stacks.api.handler.WebhooksRequestHandler;
import com.formkiq.stacks.api.handler.WebhooksTagsRequestHandler;
+import com.formkiq.stacks.dynamodb.ApiKeysService;
+import com.formkiq.stacks.dynamodb.ApiKeysServiceExtension;
+import com.formkiq.stacks.dynamodb.ConfigService;
+import com.formkiq.stacks.dynamodb.ConfigServiceExtension;
import com.formkiq.stacks.dynamodb.DocumentCountService;
import com.formkiq.stacks.dynamodb.DocumentCountServiceExtension;
import com.formkiq.stacks.dynamodb.DocumentSearchService;
@@ -141,6 +147,8 @@ public static void buildUrlMap() {
URL_MAP.put("options", new DocumentsOptionsRequestHandler());
addRequestHandler(new VersionRequestHandler());
addRequestHandler(new SitesRequestHandler());
+ addRequestHandler(new ConfigurationRequestHandler());
+ addRequestHandler(new ConfigurationApiKeysRequestHandler());
addRequestHandler(new DocumentVersionsRequestHandler());
addRequestHandler(new DocumentVersionsKeyRequestHandler());
addRequestHandler(new DocumentTagsRequestHandler());
@@ -189,18 +197,20 @@ public static void configureHandler(final Map map, final Region
final AwsCredentialsProvider credentialsProvider, final Map awsServiceEndpoints,
final DocumentTagSchemaPlugin schemaEvents) {
- DynamoDbConnectionBuilder db =
- new DynamoDbConnectionBuilder().setRegion(region).setCredentials(credentialsProvider)
- .setEndpointOverride(awsServiceEndpoints.get("dynamodb"));
+ final boolean enableAwsXray = "true".equals(map.get("ENABLE_AWS_X_RAY"));
+
+ DynamoDbConnectionBuilder db = new DynamoDbConnectionBuilder(enableAwsXray).setRegion(region)
+ .setCredentials(credentialsProvider)
+ .setEndpointOverride(awsServiceEndpoints.get("dynamodb"));
AwsServiceCache.register(DynamoDbConnectionBuilder.class,
new DynamoDbConnectionBuilderExtension(db));
- SsmConnectionBuilder ssm = new SsmConnectionBuilder().setRegion(region)
+ SsmConnectionBuilder ssm = new SsmConnectionBuilder(enableAwsXray).setRegion(region)
.setCredentials(credentialsProvider).setEndpointOverride(awsServiceEndpoints.get("ssm"));
AwsServiceCache.register(SsmConnectionBuilder.class,
new ClassServiceExtension(ssm));
- SqsConnectionBuilder sqs = new SqsConnectionBuilder().setRegion(region)
+ SqsConnectionBuilder sqs = new SqsConnectionBuilder(enableAwsXray).setRegion(region)
.setCredentials(credentialsProvider).setEndpointOverride(awsServiceEndpoints.get("sqs"));
AwsServiceCache.register(SqsConnectionBuilder.class,
new ClassServiceExtension(sqs));
@@ -212,13 +222,13 @@ public static void configureHandler(final Map map, final Region
new ClassServiceExtension<>(credentialsProvider.resolveCredentials()));
}
- SnsConnectionBuilder sns = new SnsConnectionBuilder().setRegion(region)
+ SnsConnectionBuilder sns = new SnsConnectionBuilder(enableAwsXray).setRegion(region)
.setCredentials(credentialsProvider).setEndpointOverride(awsServiceEndpoints.get("sns"));
AwsServiceCache.register(ActionsNotificationService.class,
new ActionsNotificationServiceExtension(sns));
- S3ConnectionBuilder s3 = new S3ConnectionBuilder().setRegion(region)
+ S3ConnectionBuilder s3 = new S3ConnectionBuilder(enableAwsXray).setRegion(region)
.setCredentials(credentialsProvider).setEndpointOverride(awsServiceEndpoints.get("s3"));
AwsServiceCache.register(ActionsService.class, new ActionsServiceExtension());
@@ -233,7 +243,9 @@ public static void configureHandler(final Map map, final Region
AwsServiceCache.register(DocumentCountService.class, new DocumentCountServiceExtension());
AwsServiceCache.register(FolderIndexProcessor.class, new IndexProcessorExtension());
AwsServiceCache.register(ConfigService.class, new ConfigServiceExtension());
+ AwsServiceCache.register(ApiKeysService.class, new ApiKeysServiceExtension());
AwsServiceCache.register(DocumentSyncService.class, new DocumentSyncServiceExtension());
+ AwsServiceCache.register(DocumentOcrService.class, new DocumentOcrServiceExtension());
awsServices = new CoreAwsServiceCache().environment(map).debug("true".equals(map.get("DEBUG")));
diff --git a/lambda-api/src/main/java/com/formkiq/stacks/api/handler/ConfigurationApiKeysRequestHandler.java b/lambda-api/src/main/java/com/formkiq/stacks/api/handler/ConfigurationApiKeysRequestHandler.java
new file mode 100644
index 000000000..3b819d92e
--- /dev/null
+++ b/lambda-api/src/main/java/com/formkiq/stacks/api/handler/ConfigurationApiKeysRequestHandler.java
@@ -0,0 +1,133 @@
+/**
+ * MIT License
+ *
+ * Copyright (c) 2018 - 2020 FormKiQ
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package com.formkiq.stacks.api.handler;
+
+import static com.formkiq.aws.services.lambda.ApiGatewayRequestEventUtil.getCallingCognitoUsername;
+import static com.formkiq.aws.services.lambda.ApiResponseStatus.SC_OK;
+import java.util.List;
+import java.util.Map;
+import com.amazonaws.services.lambda.runtime.LambdaLogger;
+import com.formkiq.aws.dynamodb.DynamicObject;
+import com.formkiq.aws.services.lambda.ApiAuthorizer;
+import com.formkiq.aws.services.lambda.ApiGatewayRequestEvent;
+import com.formkiq.aws.services.lambda.ApiGatewayRequestEventUtil;
+import com.formkiq.aws.services.lambda.ApiGatewayRequestHandler;
+import com.formkiq.aws.services.lambda.ApiMapResponse;
+import com.formkiq.aws.services.lambda.ApiRequestHandlerResponse;
+import com.formkiq.aws.services.lambda.exceptions.BadException;
+import com.formkiq.aws.services.lambda.exceptions.UnauthorizedException;
+import com.formkiq.module.lambdaservices.AwsServiceCache;
+import com.formkiq.stacks.dynamodb.ApiKeysService;
+
+/** {@link ApiGatewayRequestHandler} for "/configuration/apiKeys". */
+public class ConfigurationApiKeysRequestHandler
+ implements ApiGatewayRequestHandler, ApiGatewayRequestEventUtil {
+
+ /**
+ * constructor.
+ *
+ */
+ public ConfigurationApiKeysRequestHandler() {}
+
+ @Override
+ public void beforeDelete(final LambdaLogger logger, final ApiGatewayRequestEvent event,
+ final ApiAuthorizer authorizer, final AwsServiceCache awsServices) throws Exception {
+ checkPermissions(authorizer);
+ }
+
+ @Override
+ public void beforeGet(final LambdaLogger logger, final ApiGatewayRequestEvent event,
+ final ApiAuthorizer authorizer, final AwsServiceCache awsServices) throws Exception {
+ checkPermissions(authorizer);
+ }
+
+ @Override
+ public void beforePost(final LambdaLogger logger, final ApiGatewayRequestEvent event,
+ final ApiAuthorizer authorizer, final AwsServiceCache awsServices) throws Exception {
+ checkPermissions(authorizer);
+ }
+
+ private void checkPermissions(final ApiAuthorizer authorizer) throws UnauthorizedException {
+ if (!authorizer.isUserAdmin() && !authorizer.isCallerIamUser()
+ && !authorizer.isCallerAssumeRole()) {
+ throw new UnauthorizedException("user is unauthorized");
+ }
+ }
+
+ @Override
+ public ApiRequestHandlerResponse delete(final LambdaLogger logger,
+ final ApiGatewayRequestEvent event, final ApiAuthorizer authorizer,
+ final AwsServiceCache awsservice) throws Exception {
+
+ String apiKey = event.getQueryStringParameter("apiKey");
+
+ ApiKeysService apiKeysService = awsservice.getExtension(ApiKeysService.class);
+ apiKeysService.deleteApiKey(apiKey);
+
+ return new ApiRequestHandlerResponse(SC_OK,
+ new ApiMapResponse(Map.of("message", "ApiKey deleted")));
+ }
+
+ @Override
+ public ApiRequestHandlerResponse get(final LambdaLogger logger,
+ final ApiGatewayRequestEvent event, final ApiAuthorizer authorizer,
+ final AwsServiceCache awsservice) throws Exception {
+
+ ApiKeysService apiKeysService = awsservice.getExtension(ApiKeysService.class);
+
+ List list = apiKeysService.list();
+
+ Map map = Map.of("apiKeys", list);
+ return new ApiRequestHandlerResponse(SC_OK, new ApiMapResponse(map));
+ }
+
+ @Override
+ public String getRequestUrl() {
+ return "/configuration/apiKeys";
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public ApiRequestHandlerResponse post(final LambdaLogger logger,
+ final ApiGatewayRequestEvent event, final ApiAuthorizer authorizer,
+ final AwsServiceCache awsservice) throws Exception {
+
+ String siteId = authorizer.getSiteId();
+
+ ApiKeysService apiKeysService = awsservice.getExtension(ApiKeysService.class);
+ Map body = fromBodyToObject(logger, event, Map.class);
+ String name = body.get("name");
+
+ if (name != null) {
+
+ String userId = getCallingCognitoUsername(event);
+ String apiKey = apiKeysService.createApiKey(siteId, name, userId);
+
+ return new ApiRequestHandlerResponse(SC_OK,
+ new ApiMapResponse(Map.of("name", name, "apiKey", apiKey)));
+ }
+
+ throw new BadException("missing required body parameters");
+ }
+}
diff --git a/lambda-api/src/main/java/com/formkiq/stacks/api/handler/ConfigurationRequestHandler.java b/lambda-api/src/main/java/com/formkiq/stacks/api/handler/ConfigurationRequestHandler.java
new file mode 100644
index 000000000..7aca34aed
--- /dev/null
+++ b/lambda-api/src/main/java/com/formkiq/stacks/api/handler/ConfigurationRequestHandler.java
@@ -0,0 +1,130 @@
+/**
+ * MIT License
+ *
+ * Copyright (c) 2018 - 2020 FormKiQ
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package com.formkiq.stacks.api.handler;
+
+import static com.formkiq.aws.services.lambda.ApiResponseStatus.SC_OK;
+import static com.formkiq.stacks.dynamodb.ConfigService.CHATGPT_API_KEY;
+import static com.formkiq.stacks.dynamodb.ConfigService.MAX_DOCUMENTS;
+import static com.formkiq.stacks.dynamodb.ConfigService.MAX_DOCUMENT_SIZE_BYTES;
+import static com.formkiq.stacks.dynamodb.ConfigService.MAX_WEBHOOKS;
+import java.util.HashMap;
+import java.util.Map;
+import com.amazonaws.services.lambda.runtime.LambdaLogger;
+import com.formkiq.aws.dynamodb.DynamicObject;
+import com.formkiq.aws.services.lambda.ApiAuthorizer;
+import com.formkiq.aws.services.lambda.ApiGatewayRequestEvent;
+import com.formkiq.aws.services.lambda.ApiGatewayRequestEventUtil;
+import com.formkiq.aws.services.lambda.ApiGatewayRequestHandler;
+import com.formkiq.aws.services.lambda.ApiMapResponse;
+import com.formkiq.aws.services.lambda.ApiRequestHandlerResponse;
+import com.formkiq.aws.services.lambda.exceptions.BadException;
+import com.formkiq.aws.services.lambda.exceptions.UnauthorizedException;
+import com.formkiq.module.lambdaservices.AwsServiceCache;
+import com.formkiq.stacks.dynamodb.ConfigService;
+
+/** {@link ApiGatewayRequestHandler} for "/configuration". */
+public class ConfigurationRequestHandler
+ implements ApiGatewayRequestHandler, ApiGatewayRequestEventUtil {
+
+ /**
+ * constructor.
+ *
+ */
+ public ConfigurationRequestHandler() {}
+
+ @Override
+ public void beforeGet(final LambdaLogger logger, final ApiGatewayRequestEvent event,
+ final ApiAuthorizer authorizer, final AwsServiceCache awsServices) throws Exception {
+ checkPermissions(authorizer);
+ }
+
+ @Override
+ public void beforePatch(final LambdaLogger logger, final ApiGatewayRequestEvent event,
+ final ApiAuthorizer authorizer, final AwsServiceCache awsServices) throws Exception {
+ checkPermissions(authorizer);
+ }
+
+ private void checkPermissions(final ApiAuthorizer authorizer) throws UnauthorizedException {
+ if (!authorizer.isUserAdmin() && !authorizer.isCallerIamUser()) {
+ throw new UnauthorizedException("user is unauthorized");
+ }
+ }
+
+ @Override
+ public ApiRequestHandlerResponse get(final LambdaLogger logger,
+ final ApiGatewayRequestEvent event, final ApiAuthorizer authorizer,
+ final AwsServiceCache awsservice) throws Exception {
+
+ String siteId = authorizer.getSiteId();
+ ConfigService configService = awsservice.getExtension(ConfigService.class);
+
+ DynamicObject obj = configService.get(siteId);
+ Map map = new HashMap<>();
+ map.put("chatGptApiKey", obj.getOrDefault(CHATGPT_API_KEY, ""));
+ map.put("maxContentLengthBytes", obj.getOrDefault(MAX_DOCUMENT_SIZE_BYTES, ""));
+ map.put("maxDocuments", obj.getOrDefault(MAX_DOCUMENTS, ""));
+ map.put("maxWebhooks", obj.getOrDefault(MAX_WEBHOOKS, ""));
+
+ return new ApiRequestHandlerResponse(SC_OK, new ApiMapResponse(map));
+ }
+
+ @Override
+ public String getRequestUrl() {
+ return "/configuration";
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public ApiRequestHandlerResponse patch(final LambdaLogger logger,
+ final ApiGatewayRequestEvent event, final ApiAuthorizer authorizer,
+ final AwsServiceCache awsservice) throws Exception {
+
+ String siteId = authorizer.getSiteId();
+
+ Map body = fromBodyToObject(logger, event, Map.class);
+
+ Map map = new HashMap<>();
+ put(map, body, CHATGPT_API_KEY, "chatGptApiKey");
+ put(map, body, MAX_DOCUMENT_SIZE_BYTES, "maxContentLengthBytes");
+ put(map, body, MAX_DOCUMENTS, "maxDocuments");
+ put(map, body, MAX_WEBHOOKS, "maxWebhooks");
+
+ if (!map.isEmpty()) {
+ ConfigService configService = awsservice.getExtension(ConfigService.class);
+ configService.save(siteId, new DynamicObject(map));
+
+ return new ApiRequestHandlerResponse(SC_OK,
+ new ApiMapResponse(Map.of("message", "Config saved")));
+ }
+
+ throw new BadException("missing required body parameters");
+ }
+
+ private void put(final Map map, final Map body,
+ final String mapKey, final String bodyKey) {
+ if (body.containsKey(bodyKey)) {
+ map.put(mapKey, body.get(bodyKey));
+ }
+ }
+}
diff --git a/lambda-api/src/main/java/com/formkiq/stacks/api/handler/DocumentIdContentRequestHandler.java b/lambda-api/src/main/java/com/formkiq/stacks/api/handler/DocumentIdContentRequestHandler.java
index 31ee67ccf..15b78193e 100644
--- a/lambda-api/src/main/java/com/formkiq/stacks/api/handler/DocumentIdContentRequestHandler.java
+++ b/lambda-api/src/main/java/com/formkiq/stacks/api/handler/DocumentIdContentRequestHandler.java
@@ -31,6 +31,7 @@
import com.amazonaws.services.lambda.runtime.LambdaLogger;
import com.formkiq.aws.dynamodb.DynamoDbConnectionBuilder;
import com.formkiq.aws.dynamodb.model.DocumentItem;
+import com.formkiq.aws.dynamodb.objects.MimeType;
import com.formkiq.aws.s3.PresignGetUrlConfig;
import com.formkiq.aws.s3.S3Service;
import com.formkiq.aws.services.lambda.ApiAuthorizer;
@@ -42,7 +43,6 @@
import com.formkiq.aws.services.lambda.ApiResponse;
import com.formkiq.aws.services.lambda.exceptions.NotFoundException;
import com.formkiq.module.lambdaservices.AwsServiceCache;
-import com.formkiq.stacks.common.formats.MimeType;
import com.formkiq.stacks.dynamodb.DocumentService;
import com.formkiq.stacks.dynamodb.DocumentVersionService;
diff --git a/lambda-api/src/main/java/com/formkiq/stacks/api/handler/DocumentIdRequestHandler.java b/lambda-api/src/main/java/com/formkiq/stacks/api/handler/DocumentIdRequestHandler.java
index 38119e7c8..081485a35 100644
--- a/lambda-api/src/main/java/com/formkiq/stacks/api/handler/DocumentIdRequestHandler.java
+++ b/lambda-api/src/main/java/com/formkiq/stacks/api/handler/DocumentIdRequestHandler.java
@@ -23,6 +23,7 @@
*/
package com.formkiq.stacks.api.handler;
+import static com.formkiq.aws.services.lambda.ApiGatewayRequestEventUtil.getCallingCognitoUsername;
import static com.formkiq.aws.dynamodb.SiteIdKeyGenerator.DEFAULT_SITE_ID;
import static com.formkiq.aws.dynamodb.SiteIdKeyGenerator.createDatabaseKey;
import static com.formkiq.aws.dynamodb.SiteIdKeyGenerator.createS3Key;
@@ -48,6 +49,7 @@
import com.formkiq.aws.dynamodb.model.DocumentMetadata;
import com.formkiq.aws.dynamodb.model.DocumentTag;
import com.formkiq.aws.dynamodb.model.DynamicDocumentItem;
+import com.formkiq.aws.dynamodb.objects.DateUtil;
import com.formkiq.aws.s3.S3ObjectMetadata;
import com.formkiq.aws.s3.S3Service;
import com.formkiq.aws.services.lambda.ApiAuthorizer;
@@ -65,7 +67,6 @@
import com.formkiq.aws.services.lambda.services.CacheService;
import com.formkiq.module.lambdaservices.AwsServiceCache;
import com.formkiq.plugins.tagschema.DocumentTagSchemaPlugin;
-import com.formkiq.stacks.dynamodb.DateUtil;
import com.formkiq.stacks.dynamodb.DocumentCountService;
import com.formkiq.stacks.dynamodb.DocumentItemToDynamicDocumentItem;
import com.formkiq.stacks.dynamodb.DocumentService;
diff --git a/lambda-api/src/main/java/com/formkiq/stacks/api/handler/DocumentTagRequestHandler.java b/lambda-api/src/main/java/com/formkiq/stacks/api/handler/DocumentTagRequestHandler.java
index f50dbc4e6..91862dc11 100644
--- a/lambda-api/src/main/java/com/formkiq/stacks/api/handler/DocumentTagRequestHandler.java
+++ b/lambda-api/src/main/java/com/formkiq/stacks/api/handler/DocumentTagRequestHandler.java
@@ -23,6 +23,7 @@
*/
package com.formkiq.stacks.api.handler;
+import static com.formkiq.aws.services.lambda.ApiGatewayRequestEventUtil.getCallingCognitoUsername;
import static com.formkiq.aws.services.lambda.ApiResponseStatus.SC_OK;
import java.util.ArrayList;
import java.util.Arrays;
diff --git a/lambda-api/src/main/java/com/formkiq/stacks/api/handler/DocumentTagsRequestHandler.java b/lambda-api/src/main/java/com/formkiq/stacks/api/handler/DocumentTagsRequestHandler.java
index a9e73bf8c..a65156de2 100644
--- a/lambda-api/src/main/java/com/formkiq/stacks/api/handler/DocumentTagsRequestHandler.java
+++ b/lambda-api/src/main/java/com/formkiq/stacks/api/handler/DocumentTagsRequestHandler.java
@@ -23,6 +23,7 @@
*/
package com.formkiq.stacks.api.handler;
+import static com.formkiq.aws.services.lambda.ApiGatewayRequestEventUtil.getCallingCognitoUsername;
import static com.formkiq.aws.services.lambda.ApiResponseStatus.SC_CREATED;
import static com.formkiq.aws.services.lambda.ApiResponseStatus.SC_OK;
import java.util.ArrayList;
diff --git a/lambda-api/src/main/java/com/formkiq/stacks/api/handler/DocumentsActionsRequestHandler.java b/lambda-api/src/main/java/com/formkiq/stacks/api/handler/DocumentsActionsRequestHandler.java
index 89c0547af..c070d05dc 100644
--- a/lambda-api/src/main/java/com/formkiq/stacks/api/handler/DocumentsActionsRequestHandler.java
+++ b/lambda-api/src/main/java/com/formkiq/stacks/api/handler/DocumentsActionsRequestHandler.java
@@ -23,6 +23,7 @@
*/
package com.formkiq.stacks.api.handler;
+import static com.formkiq.aws.services.lambda.ApiGatewayRequestEventUtil.getCallingCognitoUsername;
import static com.formkiq.aws.services.lambda.ApiResponseStatus.SC_OK;
import java.util.ArrayList;
import java.util.Collection;
diff --git a/lambda-api/src/main/java/com/formkiq/stacks/api/handler/DocumentsIdUploadRequestHandler.java b/lambda-api/src/main/java/com/formkiq/stacks/api/handler/DocumentsIdUploadRequestHandler.java
index 85ce92024..304b491f9 100644
--- a/lambda-api/src/main/java/com/formkiq/stacks/api/handler/DocumentsIdUploadRequestHandler.java
+++ b/lambda-api/src/main/java/com/formkiq/stacks/api/handler/DocumentsIdUploadRequestHandler.java
@@ -23,6 +23,7 @@
*/
package com.formkiq.stacks.api.handler;
+import static com.formkiq.aws.services.lambda.ApiGatewayRequestEventUtil.getCallingCognitoUsername;
import static com.formkiq.aws.services.lambda.ApiResponseStatus.SC_OK;
import java.net.URL;
import java.net.URLDecoder;
diff --git a/lambda-api/src/main/java/com/formkiq/stacks/api/handler/DocumentsOcrRequestHandler.java b/lambda-api/src/main/java/com/formkiq/stacks/api/handler/DocumentsOcrRequestHandler.java
index d7a600d86..5ab7b86f7 100644
--- a/lambda-api/src/main/java/com/formkiq/stacks/api/handler/DocumentsOcrRequestHandler.java
+++ b/lambda-api/src/main/java/com/formkiq/stacks/api/handler/DocumentsOcrRequestHandler.java
@@ -23,10 +23,39 @@
*/
package com.formkiq.stacks.api.handler;
+import static com.formkiq.aws.services.lambda.ApiGatewayRequestEventUtil.getCallingCognitoUsername;
+import static com.formkiq.aws.services.lambda.ApiResponseStatus.SC_NOT_FOUND;
+import static com.formkiq.aws.services.lambda.ApiResponseStatus.SC_OK;
+import static com.formkiq.module.ocr.DocumentOcrService.PREFIX_TEMP_FILES;
+import java.nio.charset.StandardCharsets;
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import com.amazonaws.services.lambda.runtime.LambdaLogger;
+import com.formkiq.aws.dynamodb.DynamicObject;
+import com.formkiq.aws.s3.PresignGetUrlConfig;
+import com.formkiq.aws.s3.S3Service;
+import com.formkiq.aws.services.lambda.ApiAuthorizer;
+import com.formkiq.aws.services.lambda.ApiGatewayRequestEvent;
+import com.formkiq.aws.services.lambda.ApiGatewayRequestEventUtil;
import com.formkiq.aws.services.lambda.ApiGatewayRequestHandler;
+import com.formkiq.aws.services.lambda.ApiMapResponse;
+import com.formkiq.aws.services.lambda.ApiRequestHandlerResponse;
+import com.formkiq.aws.services.lambda.ApiResponseStatus;
+import com.formkiq.aws.services.lambda.exceptions.BadException;
+import com.formkiq.aws.services.lambda.exceptions.NotFoundException;
+import com.formkiq.module.lambdaservices.AwsServiceCache;
+import com.formkiq.module.ocr.DocumentOcrService;
+import com.formkiq.module.ocr.OcrRequest;
+import com.formkiq.module.ocr.OcrScanStatus;
+import com.formkiq.stacks.dynamodb.DocumentService;
/** {@link ApiGatewayRequestHandler} for "/documents/{documentId}/ocr". */
-public class DocumentsOcrRequestHandler extends AbstractPaymentRequiredRequestHandler {
+public class DocumentsOcrRequestHandler
+ implements ApiGatewayRequestHandler, ApiGatewayRequestEventUtil {
/** {@link DocumentsOcrRequestHandler} URL. */
public static final String URL = "/documents/{documentId}/ocr";
@@ -37,8 +66,219 @@ public class DocumentsOcrRequestHandler extends AbstractPaymentRequiredRequestHa
*/
public DocumentsOcrRequestHandler() {}
+ /**
+ * Build Get Response.
+ *
+ * @param obj {@link DynamicObject}
+ * @param documentId {@link String}
+ * @return {@link Map}
+ */
+ private Map buildGetResponse(final DynamicObject obj, final String documentId) {
+ Map map = new HashMap<>();
+ map.put("documentId", documentId);
+
+ if (obj != null) {
+
+ map.put("insertedDate", obj.get("insertedDate"));
+ map.put("contentType", obj.get("contentType"));
+ map.put("userId", obj.get("userId"));
+ map.put("ocrEngine", obj.get("ocrEngine"));
+ map.put("ocrStatus", obj.get("ocrStatus"));
+ }
+
+ return map;
+ }
+
+ @Override
+ public ApiRequestHandlerResponse delete(final LambdaLogger logger,
+ final ApiGatewayRequestEvent event, final ApiAuthorizer authorizer,
+ final AwsServiceCache awsservice) throws Exception {
+
+ ApiMapResponse resp = new ApiMapResponse();
+ String siteId = authorizer.getSiteId();
+ String documentId = event.getPathParameters().get("documentId");
+
+ DocumentOcrService ocrService = awsservice.getExtension(DocumentOcrService.class);
+ ocrService.delete(siteId, documentId);
+
+ return new ApiRequestHandlerResponse(SC_OK, resp);
+ }
+
+ @Override
+ public ApiRequestHandlerResponse get(final LambdaLogger logger,
+ final ApiGatewayRequestEvent event, final ApiAuthorizer authorizer,
+ final AwsServiceCache awsservice) throws Exception {
+
+ ApiResponseStatus status = SC_OK;
+ String siteId = authorizer.getSiteId();
+ String documentId = event.getPathParameters().get("documentId");
+
+ final boolean contentUrl = event.getQueryStringParameters() != null
+ && event.getQueryStringParameters().containsKey("contentUrl");
+
+ final boolean textOnly = event.getQueryStringParameters() != null
+ && event.getQueryStringParameters().containsKey("text");
+
+ DocumentOcrService ocrService = awsservice.getExtension(DocumentOcrService.class);
+
+ DynamicObject obj = ocrService.get(siteId, documentId);
+
+ Map map = buildGetResponse(obj, documentId);
+
+ if (map.containsKey("ocrStatus")) {
+
+ if (map.get("ocrStatus").equals(OcrScanStatus.SUCCESSFUL.name().toLowerCase())) {
+
+ S3Service s3 = awsservice.getExtension(S3Service.class);
+
+ String jobId = obj.getString("jobId");
+
+ List s3Keys = ocrService.getOcrS3Keys(siteId, documentId, jobId);
+ if (s3Keys.isEmpty()) {
+ throw new NotFoundException("OCR results not found");
+ }
+
+ if (contentUrl) {
+
+ List contentUrls = getContentUrls(awsservice, ocrService, s3, s3Keys, textOnly);
+ map.put("contentUrls", contentUrls);
+
+ } else {
+
+ String content = getS3Content(awsservice, ocrService, s3, s3Keys, textOnly);
+ map.put("data", content);
+ }
+
+ }
+
+ } else {
+ status = SC_NOT_FOUND;
+ }
+
+ ApiMapResponse resp = new ApiMapResponse(map);
+ return new ApiRequestHandlerResponse(status, resp);
+ }
+
+ /**
+ * Get S3 Content Urls.
+ *
+ * @param awsservice {@link AwsServiceCache}
+ * @param ocrService {@link DocumentOcrService}
+ * @param s3 {@link S3Service}
+ * @param s3Keys {@link List} {@link String}
+ * @param textOnly boolean
+ * @return {@link List} {@link String}
+ */
+ private List getContentUrls(final AwsServiceCache awsservice,
+ final DocumentOcrService ocrService, final S3Service s3, final List s3Keys,
+ final boolean textOnly) {
+
+ String ocrBucket = awsservice.environment("OCR_S3_BUCKET");
+ List newS3Keys = new ArrayList<>();
+
+ if (textOnly) {
+
+ s3Keys.forEach(s3Key -> {
+ String content = s3.getContentAsString(ocrBucket, s3Key, null);
+ content = ocrService.toText(content);
+
+ String newKey = PREFIX_TEMP_FILES + s3Key;
+ s3.putObject(ocrBucket, newKey, content.getBytes(StandardCharsets.UTF_8), "text/plain");
+
+ newS3Keys.add(newKey);
+ });
+
+ } else {
+ newS3Keys.addAll(s3Keys);
+ }
+
+ PresignGetUrlConfig config = new PresignGetUrlConfig();
+ List contentUrls = newS3Keys.stream().map(
+ s3key -> s3.presignGetUrl(ocrBucket, s3key, Duration.ofHours(1), null, config).toString())
+ .collect(Collectors.toList());
+ return contentUrls;
+ }
+
@Override
public String getRequestUrl() {
return URL;
}
+
+ /**
+ * Get S3 Content.
+ *
+ * @param awsservice {@link AwsServiceCache}
+ * @param ocrService {@link DocumentOcrService}
+ * @param s3 {@link S3Service}
+ * @param s3Keys {@link List} {@link String}
+ * @param textOnly boolean
+ * @return {@link String}
+ */
+ private String getS3Content(final AwsServiceCache awsservice, final DocumentOcrService ocrService,
+ final S3Service s3, final List s3Keys, final boolean textOnly) {
+
+ String ocrBucket = awsservice.environment("OCR_S3_BUCKET");
+ StringBuilder sb = new StringBuilder();
+
+ for (String s3Key : s3Keys) {
+ String content = s3.getContentAsString(ocrBucket, s3Key, null);
+
+ if (textOnly) {
+ content = ocrService.toText(content);
+ }
+
+ sb.append(content);
+ }
+
+ return sb.toString();
+ }
+
+ @Override
+ public ApiRequestHandlerResponse post(final LambdaLogger logger,
+ final ApiGatewayRequestEvent event, final ApiAuthorizer authorizer,
+ final AwsServiceCache awsservice) throws Exception {
+
+ ApiMapResponse resp = new ApiMapResponse();
+ String siteId = authorizer.getSiteId();
+ String documentId = event.getPathParameters().get("documentId");
+
+ DocumentService ds = awsservice.getExtension(DocumentService.class);
+ if (!ds.exists(siteId, documentId)) {
+ throw new NotFoundException("Document " + documentId + " not found.");
+ }
+
+ OcrRequest request = fromBodyToObject(logger, event, OcrRequest.class);
+ String userId = getCallingCognitoUsername(event);
+
+ DocumentOcrService ocrService = awsservice.getExtension(DocumentOcrService.class);
+ ocrService.convert(logger, awsservice, request, siteId, documentId, userId);
+
+ return new ApiRequestHandlerResponse(SC_OK, resp);
+ }
+
+
+ @Override
+ public ApiRequestHandlerResponse put(final LambdaLogger logger,
+ final ApiGatewayRequestEvent event, final ApiAuthorizer authorizer,
+ final AwsServiceCache awsservice) throws Exception {
+
+ ApiMapResponse resp = new ApiMapResponse();
+ String siteId = authorizer.getSiteId();
+ String documentId = event.getPathParameters().get("documentId");
+
+ String userId = getCallingCognitoUsername(event);
+
+ Map map = fromBodyToMap(logger, event);
+ String contentType = (String) map.get("contentType");
+ String content = (String) map.get("content");
+
+ if (contentType == null || content == null) {
+ throw new BadException("'content' and 'contentType' are required");
+ }
+
+ DocumentOcrService ocrService = awsservice.getExtension(DocumentOcrService.class);
+ ocrService.set(awsservice, siteId, documentId, userId, content, contentType);
+
+ return new ApiRequestHandlerResponse(SC_OK, resp);
+ }
}
diff --git a/lambda-api/src/main/java/com/formkiq/stacks/api/handler/DocumentsRequestHandler.java b/lambda-api/src/main/java/com/formkiq/stacks/api/handler/DocumentsRequestHandler.java
index b8d6be509..ee6f7f189 100644
--- a/lambda-api/src/main/java/com/formkiq/stacks/api/handler/DocumentsRequestHandler.java
+++ b/lambda-api/src/main/java/com/formkiq/stacks/api/handler/DocumentsRequestHandler.java
@@ -39,6 +39,7 @@
import com.formkiq.aws.dynamodb.PaginationResults;
import com.formkiq.aws.dynamodb.model.DocumentItem;
import com.formkiq.aws.dynamodb.model.DynamicDocumentItem;
+import com.formkiq.aws.dynamodb.objects.DateUtil;
import com.formkiq.aws.services.lambda.ApiAuthorizer;
import com.formkiq.aws.services.lambda.ApiGatewayRequestEvent;
import com.formkiq.aws.services.lambda.ApiGatewayRequestEventUtil;
@@ -49,7 +50,6 @@
import com.formkiq.aws.services.lambda.exceptions.BadException;
import com.formkiq.aws.services.lambda.services.CacheService;
import com.formkiq.module.lambdaservices.AwsServiceCache;
-import com.formkiq.stacks.dynamodb.DateUtil;
import com.formkiq.stacks.dynamodb.DocumentItemToDynamicDocumentItem;
import com.formkiq.stacks.dynamodb.DocumentService;
diff --git a/lambda-api/src/main/java/com/formkiq/stacks/api/handler/DocumentsRestrictions.java b/lambda-api/src/main/java/com/formkiq/stacks/api/handler/DocumentsRestrictions.java
index ca8fc1ba6..6b034bd2b 100644
--- a/lambda-api/src/main/java/com/formkiq/stacks/api/handler/DocumentsRestrictions.java
+++ b/lambda-api/src/main/java/com/formkiq/stacks/api/handler/DocumentsRestrictions.java
@@ -23,8 +23,8 @@
*/
package com.formkiq.stacks.api.handler;
-import com.formkiq.aws.services.lambda.services.ConfigService;
import com.formkiq.module.lambdaservices.AwsServiceCache;
+import com.formkiq.stacks.dynamodb.ConfigService;
/**
* Interface for providing restrictions around Document.
diff --git a/lambda-api/src/main/java/com/formkiq/stacks/api/handler/DocumentsRestrictionsMaxContentLength.java b/lambda-api/src/main/java/com/formkiq/stacks/api/handler/DocumentsRestrictionsMaxContentLength.java
index 0e4b93c06..0cdbd71ee 100644
--- a/lambda-api/src/main/java/com/formkiq/stacks/api/handler/DocumentsRestrictionsMaxContentLength.java
+++ b/lambda-api/src/main/java/com/formkiq/stacks/api/handler/DocumentsRestrictionsMaxContentLength.java
@@ -23,8 +23,8 @@
*/
package com.formkiq.stacks.api.handler;
-import com.formkiq.aws.services.lambda.services.ConfigService;
import com.formkiq.module.lambdaservices.AwsServiceCache;
+import com.formkiq.stacks.dynamodb.ConfigService;
/**
* {@link DocumentsRestrictions} for Max Number of Documents.
diff --git a/lambda-api/src/main/java/com/formkiq/stacks/api/handler/DocumentsRestrictionsMaxDocuments.java b/lambda-api/src/main/java/com/formkiq/stacks/api/handler/DocumentsRestrictionsMaxDocuments.java
index e066ac669..968d4a5b0 100644
--- a/lambda-api/src/main/java/com/formkiq/stacks/api/handler/DocumentsRestrictionsMaxDocuments.java
+++ b/lambda-api/src/main/java/com/formkiq/stacks/api/handler/DocumentsRestrictionsMaxDocuments.java
@@ -23,8 +23,8 @@
*/
package com.formkiq.stacks.api.handler;
-import com.formkiq.aws.services.lambda.services.ConfigService;
import com.formkiq.module.lambdaservices.AwsServiceCache;
+import com.formkiq.stacks.dynamodb.ConfigService;
import com.formkiq.stacks.dynamodb.DocumentCountService;
/**
diff --git a/lambda-api/src/main/java/com/formkiq/stacks/api/handler/DocumentsUploadRequestHandler.java b/lambda-api/src/main/java/com/formkiq/stacks/api/handler/DocumentsUploadRequestHandler.java
index f5f312a35..209a86e2f 100644
--- a/lambda-api/src/main/java/com/formkiq/stacks/api/handler/DocumentsUploadRequestHandler.java
+++ b/lambda-api/src/main/java/com/formkiq/stacks/api/handler/DocumentsUploadRequestHandler.java
@@ -23,6 +23,7 @@
*/
package com.formkiq.stacks.api.handler;
+import static com.formkiq.aws.services.lambda.ApiGatewayRequestEventUtil.getCallingCognitoUsername;
import static com.formkiq.aws.services.lambda.ApiResponseStatus.SC_OK;
import java.io.UnsupportedEncodingException;
import java.net.URL;
diff --git a/lambda-api/src/main/java/com/formkiq/stacks/api/handler/IndicesFolderMoveRequestHandler.java b/lambda-api/src/main/java/com/formkiq/stacks/api/handler/IndicesFolderMoveRequestHandler.java
index 62fc4fe35..2653c01ca 100644
--- a/lambda-api/src/main/java/com/formkiq/stacks/api/handler/IndicesFolderMoveRequestHandler.java
+++ b/lambda-api/src/main/java/com/formkiq/stacks/api/handler/IndicesFolderMoveRequestHandler.java
@@ -23,6 +23,7 @@
*/
package com.formkiq.stacks.api.handler;
+import static com.formkiq.aws.services.lambda.ApiGatewayRequestEventUtil.getCallingCognitoUsername;
import static com.formkiq.aws.services.lambda.ApiResponseStatus.SC_OK;
import java.io.IOException;
import java.util.ArrayList;
diff --git a/lambda-api/src/main/java/com/formkiq/stacks/api/handler/PublicWebhooksRequestHandler.java b/lambda-api/src/main/java/com/formkiq/stacks/api/handler/PublicWebhooksRequestHandler.java
index 49152b5b7..0b7200c58 100644
--- a/lambda-api/src/main/java/com/formkiq/stacks/api/handler/PublicWebhooksRequestHandler.java
+++ b/lambda-api/src/main/java/com/formkiq/stacks/api/handler/PublicWebhooksRequestHandler.java
@@ -26,7 +26,7 @@
import static com.formkiq.aws.dynamodb.SiteIdKeyGenerator.createDatabaseKey;
import static com.formkiq.aws.services.lambda.ApiResponseStatus.MOVED_PERMANENTLY;
import static com.formkiq.aws.services.lambda.ApiResponseStatus.SC_OK;
-import static com.formkiq.aws.services.lambda.services.ConfigService.DOCUMENT_TIME_TO_LIVE;
+import static com.formkiq.stacks.dynamodb.ConfigService.DOCUMENT_TIME_TO_LIVE;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
@@ -51,9 +51,9 @@
import com.formkiq.aws.services.lambda.exceptions.TooManyRequestsException;
import com.formkiq.aws.services.lambda.exceptions.UnauthorizedException;
import com.formkiq.aws.services.lambda.services.CacheService;
-import com.formkiq.aws.services.lambda.services.ConfigService;
import com.formkiq.module.lambdaservices.AwsServiceCache;
import com.formkiq.stacks.api.CoreAwsServiceCache;
+import com.formkiq.stacks.dynamodb.ConfigService;
import software.amazon.awssdk.utils.StringUtils;
/** {@link ApiGatewayRequestHandler} for "/public/webhooks". */
diff --git a/lambda-api/src/main/java/com/formkiq/stacks/api/handler/SitesRequestHandler.java b/lambda-api/src/main/java/com/formkiq/stacks/api/handler/SitesRequestHandler.java
index 6091b2f5b..b9853aab7 100644
--- a/lambda-api/src/main/java/com/formkiq/stacks/api/handler/SitesRequestHandler.java
+++ b/lambda-api/src/main/java/com/formkiq/stacks/api/handler/SitesRequestHandler.java
@@ -37,10 +37,10 @@
import com.formkiq.aws.services.lambda.ApiGatewayRequestHandler;
import com.formkiq.aws.services.lambda.ApiMapResponse;
import com.formkiq.aws.services.lambda.ApiRequestHandlerResponse;
-import com.formkiq.aws.services.lambda.services.ConfigService;
import com.formkiq.aws.ssm.SsmConnectionBuilder;
import com.formkiq.aws.ssm.SsmService;
import com.formkiq.module.lambdaservices.AwsServiceCache;
+import com.formkiq.stacks.dynamodb.ConfigService;
import software.amazon.awssdk.services.ssm.SsmClient;
/** {@link ApiGatewayRequestHandler} for "/sites". */
diff --git a/lambda-api/src/main/java/com/formkiq/stacks/api/handler/WebhooksRequestHandler.java b/lambda-api/src/main/java/com/formkiq/stacks/api/handler/WebhooksRequestHandler.java
index b9c3ddc2f..e2f77fd4c 100644
--- a/lambda-api/src/main/java/com/formkiq/stacks/api/handler/WebhooksRequestHandler.java
+++ b/lambda-api/src/main/java/com/formkiq/stacks/api/handler/WebhooksRequestHandler.java
@@ -24,9 +24,10 @@
package com.formkiq.stacks.api.handler;
import static com.formkiq.aws.dynamodb.SiteIdKeyGenerator.DEFAULT_SITE_ID;
+import static com.formkiq.aws.services.lambda.ApiGatewayRequestEventUtil.getCallingCognitoUsername;
import static com.formkiq.aws.services.lambda.ApiResponseStatus.SC_OK;
-import static com.formkiq.aws.services.lambda.services.ConfigService.MAX_WEBHOOKS;
-import static com.formkiq.aws.services.lambda.services.ConfigService.WEBHOOK_TIME_TO_LIVE;
+import static com.formkiq.stacks.dynamodb.ConfigService.MAX_WEBHOOKS;
+import static com.formkiq.stacks.dynamodb.ConfigService.WEBHOOK_TIME_TO_LIVE;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.Collection;
@@ -46,10 +47,10 @@
import com.formkiq.aws.services.lambda.ApiRequestHandlerResponse;
import com.formkiq.aws.services.lambda.exceptions.BadException;
import com.formkiq.aws.services.lambda.exceptions.TooManyRequestsException;
-import com.formkiq.aws.services.lambda.services.ConfigService;
import com.formkiq.aws.ssm.SsmService;
import com.formkiq.module.lambdaservices.AwsServiceCache;
import com.formkiq.stacks.api.CoreAwsServiceCache;
+import com.formkiq.stacks.dynamodb.ConfigService;
/** {@link ApiGatewayRequestHandler} for "/webhooks". */
public class WebhooksRequestHandler
diff --git a/lambda-api/src/main/java/com/formkiq/stacks/api/handler/WebhooksTagsRequestHandler.java b/lambda-api/src/main/java/com/formkiq/stacks/api/handler/WebhooksTagsRequestHandler.java
index e3dc04af6..589bc34ad 100644
--- a/lambda-api/src/main/java/com/formkiq/stacks/api/handler/WebhooksTagsRequestHandler.java
+++ b/lambda-api/src/main/java/com/formkiq/stacks/api/handler/WebhooksTagsRequestHandler.java
@@ -23,6 +23,7 @@
*/
package com.formkiq.stacks.api.handler;
+import static com.formkiq.aws.services.lambda.ApiGatewayRequestEventUtil.getCallingCognitoUsername;
import static com.formkiq.aws.services.lambda.ApiResponseStatus.SC_CREATED;
import static com.formkiq.aws.services.lambda.ApiResponseStatus.SC_OK;
import java.util.Arrays;
diff --git a/lambda-api/src/main/resources/cloudformation/api-apikey.yaml b/lambda-api/src/main/resources/cloudformation/api-apikey.yaml
new file mode 100644
index 000000000..834d905b5
--- /dev/null
+++ b/lambda-api/src/main/resources/cloudformation/api-apikey.yaml
@@ -0,0 +1,3974 @@
+#@ load("@ytt:data", "data")
+#@ load("@ytt:assert", "assert")
+#@ load("@ytt:overlay", "overlay")
+#@overlay/match by=overlay.all
+---
+Resources:
+
+ #@overlay/match missing_ok=True
+ DocumentsKeyApi:
+ Type: AWS::ApiGatewayV2::Api
+ Properties:
+ Body:
+ openapi: "3.0.1"
+ info:
+ title:
+ Fn::Sub: "${AWS::StackName} API Key - ${AppEnvironment}"
+ contact:
+ name: FormKiQ
+ url: https://formkiq.com
+ email: support@formkiq.com
+ x-logo:
+ url: https://docs.formkiq.com/docs/latest/_images/formkiq-logo.png
+ backgroundColor: "#FFFFFF"
+ altText: "FormKiQ Logo"
+ license:
+ name: Apache 2.0
+ url: https://www.apache.org/licenses/LICENSE-2.0.html
+ description: "FormKiQ Api Key"
+ version: #@ data.values.version or assert.fail("missing version")
+ paths:
+ /version:
+ get:
+ operationId: GetVersion
+ description: Return the version of FormKiQ
+ tags:
+ - System Management
+ responses:
+ '200':
+ description: "200 OK"
+ headers:
+ Access-Control-Allow-Origin:
+ schema:
+ type: "string"
+ Access-Control-Allow-Methods:
+ schema:
+ type: "string"
+ Access-Control-Allow-Headers:
+ schema:
+ type: "string"
+ content:
+ application/json:
+ schema:
+ "$ref": "#/components/schemas/GetVersionRequest"
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
+ /sites:
+ get:
+ operationId: GetSites
+ description: Returns the list of sites that the user has access to
+ tags:
+ - System Management
+ responses:
+ '200':
+ description: "200 OK"
+ headers:
+ Access-Control-Allow-Origin:
+ schema:
+ type: "string"
+ Access-Control-Allow-Methods:
+ schema:
+ type: "string"
+ Access-Control-Allow-Headers:
+ schema:
+ type: "string"
+ content:
+ application/json:
+ schema:
+ "$ref": "#/components/schemas/GetSitesRequest"
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
+ /configuration:
+ get:
+ operationId: GetConfigs
+ description: Returns the list of sites that the user has access to
+ tags:
+ - System Management
+ parameters:
+ - $ref: '#/components/parameters/siteIdParam'
+ responses:
+ '200':
+ description: "200 OK"
+ headers:
+ Access-Control-Allow-Origin:
+ schema:
+ type: "string"
+ Access-Control-Allow-Methods:
+ schema:
+ type: "string"
+ Access-Control-Allow-Headers:
+ schema:
+ type: "string"
+ content:
+ application/json:
+ schema:
+ "$ref": "#/components/schemas/GetConfigurationResponse"
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
+ patch:
+ operationId: UpdateConfig
+ description: Update the System Management configuration
+ tags:
+ - System Management
+ parameters:
+ - $ref: '#/components/parameters/siteIdParam'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/SetConfigRequest'
+ examples:
+ Config:
+ value:
+ chatGptApiKey: "ABC"
+ maxContentLengthBytes: "1000000"
+ maxDocuments: "1000"
+ maxWebhooks: "10"
+ responses:
+ '200':
+ description: 200 OK
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/SetConfigResponse'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
+ /configuration/apiKeys:
+ get:
+ operationId: GetApiKeys
+ description: Returns the list of ApiKeys
+ tags:
+ - System Management
+ parameters:
+ - $ref: '#/components/parameters/siteIdParam'
+ responses:
+ '200':
+ description: "200 OK"
+ headers:
+ Access-Control-Allow-Origin:
+ schema:
+ type: "string"
+ Access-Control-Allow-Methods:
+ schema:
+ type: "string"
+ Access-Control-Allow-Headers:
+ schema:
+ type: "string"
+ content:
+ application/json:
+ schema:
+ "$ref": "#/components/schemas/GetApiKeysResponse"
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
+ post:
+ operationId: Ã…ddApiKey
+ description: Adds a new API Key
+ tags:
+ - System Management
+ parameters:
+ - $ref: '#/components/parameters/siteIdParam'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AddApiKeyRequest'
+ examples:
+ AddApiKey:
+ value:
+ name: My API Key
+ responses:
+ '200':
+ description: 200 OK
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AddApiKeyResponse'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
+ /configuration/apiKeys/{apiKey}:
+ delete:
+ operationId: DeleteApiKey
+ description: Adds a new API Key
+ tags:
+ - System Management
+ parameters:
+ - $ref: '#/components/parameters/apiKeyParam'
+ - $ref: '#/components/parameters/siteIdParam'
+ responses:
+ '200':
+ description: 200 OK
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DeleteApiKeyResponse'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
+ /tagSchemas:
+ get:
+ operationId: GetTagSchemas
+ description: Returns the list of tagSchemas; ONLY available with FormKiQ Pro and Enterprise
+ tags:
+ - Tag Schema
+ parameters:
+ - $ref: '#/components/parameters/siteIdParam'
+ - $ref: '#/components/parameters/limitParam'
+ - name: "next"
+ in: "query"
+ description: "Next page of results token"
+ schema:
+ type: "string"
+ - name: "previous"
+ in: "query"
+ description: "Previous page of results token"
+ schema:
+ type: "string"
+ responses:
+ '200':
+ description: "200 OK"
+ headers:
+ Access-Control-Allow-Origin:
+ schema:
+ type: "string"
+ Access-Control-Allow-Methods:
+ schema:
+ type: "string"
+ Access-Control-Allow-Headers:
+ schema:
+ type: "string"
+ content:
+ application/json:
+ schema:
+ "$ref": "#/components/schemas/GetTagSchemasRequest"
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
+ post:
+ operationId: AddTagSchema
+ description: Creates a new TagSchema; ONLY available with FormKiQ Pro and Enterprise
+ tags:
+ - Tag Schema
+ parameters:
+ - $ref: '#/components/parameters/siteIdParam'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AddTagSchemaRequest'
+ responses:
+ '201':
+ description: 201 CREATED
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/TagSchemaPostResponse'
+ '400':
+ description: 400 BAD REQUEST
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ErrorsResponse'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi201"
+ /tagSchemas/{tagSchemaId}:
+ get:
+ operationId: GetTagSchema
+ description: Retrieves a TagSchema's details, i.e., metadata; ONLY available with FormKiQ Pro and Enterprise
+ tags:
+ - Tag Schema
+ parameters:
+ - $ref: '#/components/parameters/tagSchemaIdParam'
+ - $ref: '#/components/parameters/siteIdParam'
+ responses:
+ '200':
+ description: 200 OK
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/GetTagSchemaRequest'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
+ delete:
+ operationId: DeleteTagSchema
+ description: Delete a TagSchema; ONLY available with FormKiQ Pro and Enterprise
+ tags:
+ - Tag Schema
+ parameters:
+ - $ref: '#/components/parameters/tagSchemaIdParam'
+ - $ref: '#/components/parameters/siteIdParam'
+ responses:
+ '200':
+ $ref: '#/components/responses/200Cors'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
+ /documents:
+ get:
+ operationId: GetDocuments
+ tags:
+ - Documents
+ description: Returns a list of the most recent documents added, ordered by inserted, descending
+ parameters:
+ - name: "date"
+ in: "query"
+ description: "Fetch documents inserted on a certain date (yyyy-MM-dd)"
+ schema:
+ type: "string"
+ - name: "tz"
+ in: "query"
+ description: "UTC offset to apply to date parameter (IE: -0600)"
+ schema:
+ type: "string"
+ - name: "next"
+ in: "query"
+ description: "Next page of results token"
+ schema:
+ type: "string"
+ - name: "previous"
+ in: "query"
+ description: "Previous page of results token"
+ schema:
+ type: "string"
+ - $ref: '#/components/parameters/siteIdParam'
+ - $ref: '#/components/parameters/limitParam'
+ responses:
+ '200':
+ description: "200 OK"
+ headers:
+ Access-Control-Allow-Origin:
+ schema:
+ type: "string"
+ Access-Control-Allow-Methods:
+ schema:
+ type: "string"
+ Access-Control-Allow-Headers:
+ schema:
+ type: "string"
+ content:
+ application/json:
+ schema:
+ "$ref": "#/components/schemas/GetDocumentsResponse"
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
+ post:
+ operationId: AddDocument
+ description: Creates a new document; body may include document content if less than 5 MB
+ tags:
+ - Documents
+ parameters:
+ - $ref: '#/components/parameters/siteIdParam'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AddDocumentRequest'
+ examples:
+ Simple_File:
+ value:
+ path: test.txt
+ contentType: text/plain
+ isBase64: false
+ content: This is sample data file
+ tags:
+ - key: category
+ value: sample
+ - key: players
+ values: ["111", "222"]
+ metadata:
+ - key: info
+ value: Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
+ Nested_Document:
+ value:
+ path: doc1.txt
+ contentType: text/plain
+ content: This is document1 content
+ tags:
+ - key: type
+ value: document1
+ documents:
+ contentType: text/plain,
+ content: This is sub document1 content,
+ tags:
+ - key: type
+ value: subdocument1
+ Document_with_Webhook:
+ value:
+ path: test.txt
+ contentType: text/plain
+ isBase64: false
+ content: This is sample data file
+ actions:
+ - type: webhook
+ parameters:
+ url:
+ responses:
+ '201':
+ description: 201 CREATED
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AddDocumentResponse'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi201"
+ /documents/{documentId}:
+ get:
+ operationId: GetDocument
+ description: Retrieves a document's details, i.e., metadata
+ tags:
+ - Documents
+ parameters:
+ - $ref: '#/components/parameters/documentIdParam'
+ - $ref: '#/components/parameters/siteIdParam'
+ responses:
+ '200':
+ description: 200 OK
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/GetDocumentResponse'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
+ patch:
+ operationId: UpdateDocument
+ description: Update a document's details, i.e., metadata
+ tags:
+ - Documents
+ parameters:
+ - $ref: '#/components/parameters/documentIdParam'
+ - $ref: '#/components/parameters/siteIdParam'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AddDocumentRequest'
+ examples:
+ Simple_File:
+ value:
+ path: test.txt
+ contentType: text/plain
+ isBase64: false
+ content: This is sample data file
+ tags:
+ - key: category
+ value: sample
+ - key: players
+ values: ["111", "222"]
+ metadata:
+ - key: info
+ value: Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
+ responses:
+ '200':
+ description: 200 OK
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AddDocumentResponse'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
+ delete:
+ operationId: DeleteDocument
+ description: Delete a document
+ tags:
+ - Documents
+ parameters:
+ - $ref: '#/components/parameters/documentIdParam'
+ - $ref: '#/components/parameters/siteIdParam'
+ responses:
+ '200':
+ $ref: '#/components/responses/200Cors'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
+ /documents/{documentId}/versions:
+ get:
+ operationId: GetDocumentVersions
+ description: Get a listing of document content and metadata versions; ONLY available with FormKiQ Pro and Enterprise
+ tags:
+ - Document Versions
+ parameters:
+ - $ref: '#/components/parameters/documentIdParam'
+ - $ref: '#/components/parameters/siteIdParam'
+ - name: next
+ in: query
+ description: "Next page of results token"
+ schema:
+ type: string
+ responses:
+ '200':
+ description: 200 OK
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/GetDocumentVersionsResponse'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
+ put:
+ operationId: SetDocumentVersion
+ description: Set document to a previous document version; ONLY available with FormKiQ Pro and Enterprise
+ tags:
+ - Document Versions
+ parameters:
+ - $ref: '#/components/parameters/documentIdParam'
+ - $ref: '#/components/parameters/siteIdParam'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/SetDocumentVersionRequest'
+ responses:
+ '200':
+ description: 200 OK
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/SetDocumentVersionResponse'
+ '400':
+ description: 400 OK
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ValidationErrorsResponse'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
+ /documents/{documentId}/versions/{versionKey}:
+ delete:
+ operationId: DeleteDocumentVersion
+ description: Delete a specific previous document version; ONLY available with FormKiQ Pro and Enterprise
+ tags:
+ - Document Versions
+ parameters:
+ - $ref: '#/components/parameters/documentIdParam'
+ - $ref: '#/components/parameters/versionKeyPath'
+ responses:
+ '200':
+ $ref: '#/components/responses/200Cors'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
+ /documents/{documentId}/content:
+ get:
+ operationId: GetDocumentContent
+ description: Get a document's contents. Certain content types, text/*, application/json, and application/x-www-form-urlencoded. return the "content" field, while all other content types return a 'contentUrl' for retrieving the content.
+ tags:
+ - Documents
+ parameters:
+ - $ref: '#/components/parameters/documentIdParam'
+ - $ref: '#/components/parameters/siteIdParam'
+ - $ref: '#/components/parameters/versionKeyParam'
+ responses:
+ '200':
+ description: 200 OK
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ Location:
+ $ref: '#/components/headers/Location'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/GetDocumentContentResponse'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
+ /documents/{documentId}/tags:
+ get:
+ operationId: GetDocumentTags
+ description: Get a listing of a document's tags
+ tags:
+ - Document Tags
+ parameters:
+ - $ref: '#/components/parameters/documentIdParam'
+ - $ref: '#/components/parameters/siteIdParam'
+ - $ref: '#/components/parameters/limitParam'
+ - name: next
+ in: query
+ description: "Next page of results token"
+ schema:
+ type: string
+ - name: previous
+ in: query
+ description: "Previous page of results token"
+ schema:
+ type: string
+ responses:
+ '200':
+ description: 200 OK
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/GetDocumentTagsResponse'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
+ post:
+ operationId: AddDocumentTag
+ description: Add a single tag to a document; this endpoint also accepts a different body parameter for adding multiple tags in a single request
+ tags:
+ - Document Tags
+ parameters:
+ - $ref: '#/components/parameters/documentIdParam'
+ - $ref: '#/components/parameters/siteIdParam'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AddDocumentTagRequest'
+ examples:
+ Add_Key_Only_Tag:
+ value:
+ key: category
+ Add_Key_and_Value_Tag:
+ value:
+ key: category
+ value: person
+ Add_Key_and_Values_Tag:
+ value:
+ key: category
+ values: [person,canadian]
+ responses:
+ '201':
+ $ref: '#/components/responses/200Cors'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi201"
+ /documents/{documentId}/tags#:
+ post:
+ operationId: AddDocumentTags
+ description: Add multiple tags to a document; this endpoint also accepts a different body parameter for adding a single tag
+ tags:
+ - Document Tags
+ parameters:
+ - $ref: '#/components/parameters/documentIdParam'
+ - $ref: '#/components/parameters/siteIdParam'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AddDocumentTagsRequest'
+ responses:
+ '201':
+ $ref: '#/components/responses/200Cors'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi201"
+ /documents/{documentId}/tags/{tagKey}:
+ get:
+ operationId: GetDocumentTag
+ description: Get a document tag by using its key
+ tags:
+ - Document Tags
+ parameters:
+ - $ref: '#/components/parameters/documentIdParam'
+ - $ref: '#/components/parameters/tagkeyParam'
+ - $ref: '#/components/parameters/siteIdParam'
+ responses:
+ '200':
+ description: 200 OK
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/GetDocumentTagResponse'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
+ put:
+ operationId: SetDocumentTag
+ description: Update any and all values of a document tag, by using its key; you can supply one tag value or a list of tag values in the request body
+ tags:
+ - Document Tags
+ parameters:
+ - $ref: '#/components/parameters/documentIdParam'
+ - $ref: '#/components/parameters/tagkeyParam'
+ - $ref: '#/components/parameters/siteIdParam'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/SetDocumentTagKeyRequest'
+ responses:
+ '200':
+ $ref: '#/components/responses/200Cors'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
+ delete:
+ operationId: DeleteDocumentTag
+ description: Delete a document tag by using its key
+ tags:
+ - Document Tags
+ parameters:
+ - $ref: '#/components/parameters/documentIdParam'
+ - $ref: '#/components/parameters/tagkeyParam'
+ - $ref: '#/components/parameters/siteIdParam'
+ responses:
+ '200':
+ $ref: '#/components/responses/200Cors'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
+ /documents/{documentId}/tags/{tagKey}/{tagValue}:
+ delete:
+ operationId: DeleteDocumentTagAndValue
+ description: Delete a specific document tag's key/value combination; the request will be ignored if there is no valid key/value combination found
+ tags:
+ - Document Tags
+ parameters:
+ - $ref: '#/components/parameters/documentIdParam'
+ - $ref: '#/components/parameters/tagkeyParam'
+ - $ref: '#/components/parameters/tagvalueParam'
+ - $ref: '#/components/parameters/siteIdParam'
+ responses:
+ '200':
+ $ref: '#/components/responses/200Cors'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
+ /documents/{documentId}/url:
+ get:
+ operationId: GetDocumentUrl
+ description: Returns a URL for the document's contents; this URL will expire (the default is 48 hours)
+ tags:
+ - Documents
+ parameters:
+ - $ref: '#/components/parameters/documentIdParam'
+ - $ref: '#/components/parameters/siteIdParam'
+ - $ref: '#/components/parameters/versionKeyParam'
+ - $ref: '#/components/parameters/durationParam'
+ - name: "inline"
+ in: "query"
+ description: "Set the Content-Disposition to inline"
+ schema:
+ type: boolean
+ default: false
+ responses:
+ '200':
+ description: 200 OK
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/GetDocumentUrlRequest'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
+ /documents/upload:
+ get:
+ operationId: GetDocumentUpload
+ description: Returns a URL that can be used to upload document content and create a new document; this endpoint (whether GET or POST) is required in order to add content that is larger than 5 MB
+ tags:
+ - Documents
+ parameters:
+ - name: path
+ in: query
+ description: The upload file's path
+ schema:
+ type: string
+ - $ref: '#/components/parameters/siteIdParam'
+ - $ref: '#/components/parameters/contentLengthParam'
+ - $ref: '#/components/parameters/durationParam'
+ responses:
+ '200':
+ description: 200 OK
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/GetDocumentUrlRequest'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
+ post:
+ operationId: AddDocumentUpload
+ description: Returns a URL that can be used to upload document content and create a new document, while allowing metadata to also be sent; this endpoint (whether GET or POST) is required in order to add content that is larger than 5 MB
+ tags:
+ - Documents
+ parameters:
+ - $ref: '#/components/parameters/siteIdParam'
+ - $ref: '#/components/parameters/durationParam'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AddDocumentUploadRequest'
+ examples:
+ Simple_File:
+ value:
+ path: test.txt
+ contentType: text/plain
+ isBase64: false
+ content: This is sample data file
+ tags:
+ - key: category
+ value: sample
+ - key: players
+ values: ["111", "222"]
+ metadata:
+ - key: info
+ value: Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
+ responses:
+ '201':
+ description: 201 CREATED
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AddDocumentResponse'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi201"
+ /documents/{documentId}/upload:
+ get:
+ operationId: GetDocumentIdUpload
+ parameters:
+ - $ref: '#/components/parameters/documentIdParam'
+ - $ref: '#/components/parameters/siteIdParam'
+ - $ref: '#/components/parameters/contentLengthParam'
+ - $ref: '#/components/parameters/durationParam'
+ description: Returns a URL that can be used to upload documents for a specific documentId; this endpoint is required in order to add content that is larger than 5 MB. If versions are enabled, this will create a new version of the document.
+ tags:
+ - Documents
+ responses:
+ '200':
+ description: 200 OK
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/GetDocumentUrlRequest'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
+ /search:
+ post:
+ operationId: DocumentSearch
+ description: Document search query request; documents are searched primarily using a document tag key and optional tag value, or if Typesense is enabled, searches on the document path and versioned metadata is also available. An optional documentIds parameter is also available in the DocumentSearchBody to filter, with up to 100 documentIds accepted.
+ tags:
+ - Document Search
+ parameters:
+ - $ref: '#/components/parameters/siteIdParam'
+ - $ref: '#/components/parameters/limitParam'
+ - name: next
+ in: query
+ description: "Next page of results token"
+ schema:
+ type: string
+ - name: previous
+ in: query
+ description: "Previous page of results token"
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DocumentSearchRequest'
+ examples:
+ Search_By_Key:
+ value:
+ query:
+ tag:
+ key: category
+ Search_By_Value:
+ value:
+ query:
+ tag:
+ key: category
+ eq: person
+ Tag_Value_Begins_With:
+ value:
+ query:
+ tag:
+ key: firstname
+ beginsWith: jo
+ Search_By_Value_for_Specific_Documents:
+ value:
+ query:
+ tag:
+ key: category
+ eq: person
+ documentIds: ["1", "2"]
+ responses:
+ '200':
+ description: 200 OK
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DocumentSearchResponse'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/searchLambdaApi200"
+ /searchFulltext:
+ post:
+ operationId: DocumentFulltext
+ description: Document full-text search (and more robust multi-tag search queries, powered by OpenSearch); ONLY available with FormKiQ Enterprise
+ tags:
+ - Advanced Document Search
+ parameters:
+ - $ref: '#/components/parameters/siteIdParam'
+ - $ref: '#/components/parameters/limitParam'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DocumentFulltextRequest'
+ responses:
+ '200':
+ description: 200 OK
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DocumentFulltextResponse'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/fulltextLambdaApi200"
+ /queryFulltext:
+ post:
+ operationId: QueryFulltext
+ description: Endpoint for allowing custom, complex queries using the OpenSearch search API (https://opensearch.org/docs/latest/opensearch/rest-api/search/); ONLY available with FormKiQ Enterprise
+ tags:
+ - Advanced Document Search
+ parameters:
+ - $ref: '#/components/parameters/siteIdParam'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/QueryFulltextRequest'
+ responses:
+ '200':
+ description: 200 OK
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/QueryFulltextResponse'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/fulltextLambdaApi200"
+ /documents/{documentId}/actions:
+ get:
+ operationId: GetDocumentActions
+ description: Get document actions and their status
+ tags:
+ - Document Actions
+ parameters:
+ - $ref: '#/components/parameters/siteIdParam'
+ - $ref: '#/components/parameters/documentIdParam'
+ responses:
+ '200':
+ description: 200 OK
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/GetDocumentActionsResponse'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
+ post:
+ operationId: AddDocumentActions
+ description: Add one or more actions to a document; this appends actions and does not replace previous actions
+ tags:
+ - Document Actions
+ parameters:
+ - $ref: '#/components/parameters/siteIdParam'
+ - $ref: '#/components/parameters/documentIdParam'
+ requestBody:
+ required: false
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AddDocumentActionsRequest'
+ responses:
+ '200':
+ description: 200 OK
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AddDocumentActionsResponse'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
+ /documents/{documentId}/ocr:
+ get:
+ operationId: GetDocumentOcr
+ description: Get a document's optical character recognition (OCR) result, if exists; ONLY available with FormKiQ Pro and Enterprise
+ tags:
+ - OCR
+ parameters:
+ - $ref: '#/components/parameters/siteIdParam'
+ - $ref: '#/components/parameters/documentIdParam'
+ - $ref: '#/components/parameters/contentUrlParam'
+ - $ref: '#/components/parameters/textParam'
+ responses:
+ '200':
+ description: 200 OK
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/GetDocumentOcrResponse'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/ocrLambdaApi200"
+ post:
+ operationId: AddDocumentOcr
+ description: Document optical character recognition (OCR) request; extract text and data from a document; ONLY available with FormKiQ Pro and Enterprise
+ tags:
+ - OCR
+ parameters:
+ - $ref: '#/components/parameters/siteIdParam'
+ - $ref: '#/components/parameters/documentIdParam'
+ requestBody:
+ required: false
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AddDocumentOcrRequest'
+ responses:
+ '200':
+ description: 200 OK
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AddDocumentOcrResponse'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/ocrLambdaApi200"
+ put:
+ operationId: SetDocumentOcr
+ description: Set a document's optical character recognition (OCR) result for a document; ONLY available with FormKiQ Pro and Enterprise
+ tags:
+ - OCR
+ parameters:
+ - $ref: '#/components/parameters/siteIdParam'
+ - $ref: '#/components/parameters/documentIdParam'
+ requestBody:
+ required: false
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/SetDocumentOcrRequest'
+ responses:
+ '200':
+ description: 200 OK
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AddDocumentOcrResponse'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/ocrLambdaApi200"
+ delete:
+ operationId: DeleteDocumentOcr
+ description: Delete a document's optical character recognition (OCR) result, if exists; ONLY available with FormKiQ Pro and Enterprise
+ tags:
+ - OCR
+ parameters:
+ - $ref: '#/components/parameters/siteIdParam'
+ - $ref: '#/components/parameters/documentIdParam'
+ responses:
+ '200':
+ $ref: '#/components/responses/200Cors'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/ocrLambdaApi200"
+ /documents/{documentId}/antivirus:
+ put:
+ operationId: SetAntivirus
+ description: Perform an Anti-Malware / Antivirus scan on a document; ONLY available with FormKiQ Pro and Enterprise
+ tags:
+ - Antivirus
+ parameters:
+ - $ref: '#/components/parameters/siteIdParam'
+ - $ref: '#/components/parameters/documentIdParam'
+ requestBody:
+ required: false
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/SetAntivirusRequest'
+ responses:
+ '200':
+ description: 200 OK
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/SetAntivirusResponse'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/antivirusLambdaApi200"
+ /documents/{documentId}/fulltext:
+ get:
+ operationId: GetDocumentFulltext
+ description: Retrieve an OpenSearch document's details, i.e., metadata
+ tags:
+ - Advanced Document Search
+ parameters:
+ - $ref: '#/components/parameters/documentIdParam'
+ - $ref: '#/components/parameters/siteIdParam'
+ responses:
+ '200':
+ description: 200 OK
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/GetDocumentFulltextResponse'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/fulltextLambdaApi200"
+ delete:
+ operationId: DeleteDocumentFulltext
+ description: Remove full text search for a document from OpenSearch; ONLY available with FormKiQ Enterprise
+ tags:
+ - Advanced Document Search
+ parameters:
+ - $ref: '#/components/parameters/siteIdParam'
+ - $ref: '#/components/parameters/documentIdParam'
+ responses:
+ '200':
+ $ref: '#/components/responses/200Cors'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/fulltextLambdaApi200"
+ put:
+ operationId: SetDocumentFulltext
+ description: Set all text/tags found within a document to OpenSearch; ONLY available with FormKiQ Enterprise
+ tags:
+ - Advanced Document Search
+ parameters:
+ - $ref: '#/components/parameters/siteIdParam'
+ - $ref: '#/components/parameters/documentIdParam'
+ requestBody:
+ required: false
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/SetDocumentFulltextRequest'
+ responses:
+ '200':
+ description: 200 OK
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/SetDocumentFulltextResponse'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/fulltextLambdaApi200"
+ patch:
+ operationId: UpdateDocumentFulltext
+ description: Update a document in OpenSearch; ONLY available with FormKiQ Enterprise
+ tags:
+ - Advanced Document Search
+ parameters:
+ - $ref: '#/components/parameters/siteIdParam'
+ - $ref: '#/components/parameters/documentIdParam'
+ requestBody:
+ required: false
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/UpdateDocumentFulltextRequest'
+ responses:
+ '200':
+ description: 200 OK
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/SetDocumentFulltextResponse'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/fulltextLambdaApi200"
+ /documents/{documentId}/fulltext/tags/{tagKey}:
+ delete:
+ operationId: DeleteDocumentFulltextTag
+ description: Remove document tags from OpenSearch; ONLY available with FormKiQ Enterprise
+ tags:
+ - Advanced Document Search
+ parameters:
+ - $ref: '#/components/parameters/siteIdParam'
+ - $ref: '#/components/parameters/documentIdParam'
+ - $ref: '#/components/parameters/tagkeyParam'
+ responses:
+ '200':
+ $ref: '#/components/responses/200Cors'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/fulltextLambdaApi200"
+ /documents/{documentId}/fulltext/tags/{tagKey}/{tagValue}:
+ delete:
+ operationId: DeleteDocumentFulltextTagAndValue
+ description: Remove document tag/value from OpenSearch; ONLY available with FormKiQ Enterprise
+ tags:
+ - Advanced Document Search
+ parameters:
+ - $ref: '#/components/parameters/siteIdParam'
+ - $ref: '#/components/parameters/documentIdParam'
+ - $ref: '#/components/parameters/tagkeyParam'
+ - $ref: '#/components/parameters/tagvalueParam'
+ responses:
+ '200':
+ $ref: '#/components/responses/200Cors'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/fulltextLambdaApi200"
+ /documents/{documentId}/syncs:
+ get:
+ operationId: GetDocumentSyncs
+ description: Retrieve the document syncs with external services status
+ tags:
+ - Document Synchronization
+ parameters:
+ - $ref: '#/components/parameters/documentIdParam'
+ - $ref: '#/components/parameters/siteIdParam'
+ - $ref: '#/components/parameters/limitParam'
+ responses:
+ '200':
+ description: 200 OK
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/GetDocumentSyncResponse'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
+ /public/documents:
+ post:
+ operationId: PublicAddDocument
+ description: Allow unauthenticated creation of new documents; must be enabled during installation (disabled by default)
+ tags:
+ - Public
+ parameters:
+ - $ref: '#/components/parameters/siteIdParam'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AddDocumentRequest'
+ responses:
+ '201':
+ description: 201 CREATED
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DocumentId'
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi201"
+ /public/webhooks/{webhooks+}:
+ post:
+ operationId: PublicAddWebhook
+ description: Receive an incoming public post to a specified webhook and creates a document based on the data sent; must be enabled during installation (disabled by default)
+ tags:
+ - Public
+ parameters:
+ - $ref: '#/components/parameters/siteIdParam'
+ - $ref: '#/components/parameters/webhooksParam'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ responses:
+ '200':
+ description: 200 OK
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DocumentId'
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
+ /private/webhooks/{webhooks+}:
+ post:
+ operationId: AddWebhookDocument
+ description: Receive an incoming private webhook and creates a document based on the webhook's body; requires authentication
+ tags:
+ - Webhooks
+ parameters:
+ - $ref: '#/components/parameters/siteIdParam'
+ - $ref: '#/components/parameters/webhooksParam'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ responses:
+ '200':
+ description: 200 OK
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DocumentId'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
+ /webhooks:
+ get:
+ operationId: GetWebhooks
+ tags:
+ - Webhooks
+ description: Return a list of webhooks; each webhook's id can be provided to an external service, allowing data to be sent, received, and processed via that webhook
+ parameters:
+ - $ref: '#/components/parameters/siteIdParam'
+ responses:
+ '200':
+ description: "200 OK"
+ headers:
+ Access-Control-Allow-Origin:
+ schema:
+ type: "string"
+ Access-Control-Allow-Methods:
+ schema:
+ type: "string"
+ Access-Control-Allow-Headers:
+ schema:
+ type: "string"
+ content:
+ application/json:
+ schema:
+ "$ref": "#/components/schemas/GetWebhooksResponse"
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
+ post:
+ operationId: AddWebhook
+ description: Create a new webhook; once created, a webhook's id can be provided to an external service, allowing data to be sent, received, and processed via that webhook
+ tags:
+ - Webhooks
+ parameters:
+ - $ref: '#/components/parameters/siteIdParam'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AddWebhookRequest'
+ responses:
+ '201':
+ description: 201 CREATED
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AddWebhookResponse'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi201"
+ /webhooks/{webhookId}:
+ get:
+ operationId: GetWebhook
+ tags:
+ - Webhooks
+ description: Return a webhook's details, i.e., its metadata
+ parameters:
+ - $ref: '#/components/parameters/siteIdParam'
+ - $ref: '#/components/parameters/webhookIdParam'
+ responses:
+ '200':
+ description: "200 OK"
+ headers:
+ Access-Control-Allow-Origin:
+ schema:
+ type: "string"
+ Access-Control-Allow-Methods:
+ schema:
+ type: "string"
+ Access-Control-Allow-Headers:
+ schema:
+ type: "string"
+ content:
+ application/json:
+ schema:
+ "$ref": "#/components/schemas/GetWebhookResponse"
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
+ delete:
+ operationId: DeleteWebhook
+ description: Delete a webhook; this will disable sending, receiving, or processing of data from external services to this webhook
+ tags:
+ - Webhooks
+ parameters:
+ - $ref: '#/components/parameters/webhookIdParam'
+ - $ref: '#/components/parameters/siteIdParam'
+ responses:
+ '200':
+ $ref: '#/components/responses/200Cors'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
+ patch:
+ operationId: UpdateWebhook
+ description: Updates a webhook's details, i.e., its metadata
+ tags:
+ - Webhooks
+ parameters:
+ - $ref: '#/components/parameters/webhookIdParam'
+ - $ref: '#/components/parameters/siteIdParam'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AddWebhookRequest'
+ responses:
+ '200':
+ $ref: '#/components/responses/200Cors'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
+ /webhooks/{webhookId}/tags:
+ get:
+ operationId: GetWebhookTags
+ description: Get a webhook's tags
+ tags:
+ - Webhooks
+ parameters:
+ - $ref: '#/components/parameters/webhookIdParam'
+ - $ref: '#/components/parameters/siteIdParam'
+ responses:
+ '200':
+ description: 200 OK
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/GetWebhookTagsResponse'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
+ post:
+ operationId: AddWebhookTag
+ description: Add a tag to a webhook
+ tags:
+ - Webhooks
+ parameters:
+ - $ref: '#/components/parameters/webhookIdParam'
+ - $ref: '#/components/parameters/siteIdParam'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/GetDocumentTagResponse'
+ examples:
+ Add_Key_Only_Tag:
+ value:
+ key: category
+ Add_Key_and_Value_Tag:
+ value:
+ key: category
+ value: person
+ responses:
+ '201':
+ $ref: '#/components/responses/200Cors'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi201"
+ /onlyoffice/{documentId}/edit:
+ post:
+ operationId: OnlyOfficeDocumentEdit
+ description: Provide ONLYOFFICE integration for editing documents; ONLY available with FormKiQ Enterprise
+ tags:
+ - Onlyoffice
+ parameters:
+ - $ref: '#/components/parameters/siteIdParam'
+ - $ref: '#/components/parameters/documentIdParam'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/OnlyOfficeDocumentEditRequest'
+ responses:
+ '200':
+ description: 200 OK
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/OnlyOfficeDocumentResponse'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/onlyOfficeLambdaApi200"
+ /onlyoffice/new:
+ post:
+ operationId: OnlyOfficeDocumentNew
+ description: Provide ONLYOFFICE integration for the creation of new documents; ONLY available with FormKiQ Enterprise
+ tags:
+ - Onlyoffice
+ parameters:
+ - $ref: '#/components/parameters/siteIdParam'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/OnlyOfficeDocumentNewRequest'
+ responses:
+ '200':
+ description: 200 OK
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/OnlyOfficeDocumentResponse'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/onlyOfficeLambdaApi200"
+ /onlyoffice/{documentId}/save:
+ post:
+ operationId: OnlyOfficeDocumentSave
+ description: Save an updated document for ONLYOFFICE integration. ONLY available with FormKiQ Enterprise
+ tags:
+ - Onlyoffice
+ parameters:
+ - $ref: '#/components/parameters/siteIdParam'
+ - $ref: '#/components/parameters/documentIdParam'
+ responses:
+ '200':
+ description: 200 OK
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/OnlyOfficeDocumentSaveResponse'
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/onlyOfficeLambdaApi200"
+ /indices/{indexType}/move:
+ post:
+ operationId: IndexFolderMove
+ description: Perform an Folder Index Move
+ tags:
+ - Folder Index
+ parameters:
+ - $ref: '#/components/parameters/siteIdParam'
+ - $ref: '#/components/parameters/indexTypeParam'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/IndexFolderMoveRequest'
+ responses:
+ '200':
+ description: 200 OK
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/IndexFolderMoveResponse'
+ '400':
+ description: 400 OK
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ValidationErrorsResponse'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
+ /indices/{indexType}/{indexKey}:
+ delete:
+ operationId: DeleteIndex
+ description: Perform a delete on the Folder Index
+ tags:
+ - Folder Index
+ parameters:
+ - $ref: '#/components/parameters/siteIdParam'
+ - $ref: '#/components/parameters/indexKeyParam'
+ - $ref: '#/components/parameters/indexTypeParam'
+ responses:
+ '200':
+ description: 200 OK
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ '400':
+ description: 400 OK
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ValidationErrorsResponse'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
+ /indices/search:
+ post:
+ operationId: IndexSearch
+ description: Perform a search on a index; this is currently available for both folder and tag indices
+ tags:
+ - Folder Index
+ - Tag Index
+ parameters:
+ - $ref: '#/components/parameters/siteIdParam'
+ - $ref: '#/components/parameters/limitParam'
+ - name: next
+ in: query
+ description: "Next page of results token"
+ schema:
+ type: string
+ - name: previous
+ in: query
+ description: "Previous page of results token"
+ schema:
+ type: string
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/IndexSearchRequest'
+ responses:
+ '200':
+ description: 200 OK
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/IndexSearchResponse'
+ '400':
+ description: 400 OK
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ValidationErrorsResponse'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
+ /esignature/docusign/{documentId}:
+ post:
+ operationId: EsignatureDocusign
+ description: Create a DocuSign E-Signature request; ONLY available with FormKiQ Enterprise
+ tags:
+ - E-Signature
+ parameters:
+ - $ref: '#/components/parameters/siteIdParam'
+ - $ref: '#/components/parameters/documentIdParam'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/EsignatureDocusignRequest'
+ responses:
+ '200':
+ description: 200 OK
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/EsignatureDocusignResponse'
+ '400':
+ description: 400 OK
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ValidationErrorsResponse'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/esignatureLambdaApi200"
+ /esignature/docusign/config:
+ get:
+ operationId: EsignatureDocusignConfig
+ description: Get DocuSign configuration info; ONLY available with FormKiQ Enterprise
+ tags:
+ - E-Signature
+ parameters:
+ - $ref: '#/components/parameters/siteIdParam'
+ responses:
+ '200':
+ description: 200 OK
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/EsignatureDocusignConfigResponse'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/esignatureLambdaApi200"
+ put:
+ operationId: EsignatureSetDocusignConfig
+ description: Set DocuSign configuration, required for integration; ONLY available with FormKiQ Enterprise
+ tags:
+ - E-Signature
+ parameters:
+ - $ref: '#/components/parameters/siteIdParam'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/EsignatureSetDocusignConfigRequest'
+ responses:
+ '200':
+ description: 200 OK
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/EsignatureSetDocusignConfigResponse'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/esignatureLambdaApi200"
+ /esignature/docusign/events:
+ post:
+ operationId: AddEsignatureDocusignEvents
+ description: DocuSign callback URL handler; ONLY available with FormKiQ Enterprise
+ tags:
+ - E-Signature
+ responses:
+ '200':
+ description: 200 OK
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/EsignatureDocusignResponse'
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/esignatureLambdaApi200"
+ components:
+ headers:
+ AccessControlAllowOrigin:
+ schema:
+ type: string
+ AccessControlAllowMethods:
+ schema:
+ type: string
+ AccessControlAllowHeaders:
+ schema:
+ type: string
+ Location:
+ schema:
+ type: string
+ responses:
+ 200Cors:
+ description: 200 OK
+ headers:
+ Access-Control-Allow-Origin:
+ schema:
+ type: string
+ Access-Control-Allow-Methods:
+ schema:
+ type: string
+ Access-Control-Allow-Headers:
+ schema:
+ type: string
+ content: {}
+ parameters:
+ versionKeyPath:
+ name: versionKey
+ in: path
+ description: Version Key
+ required: true
+ schema:
+ type: string
+ versionKeyParam:
+ name: versionKey
+ in: query
+ description: Version Key
+ required: false
+ schema:
+ type: string
+ webhooksParam:
+ name: webhooks+
+ in: path
+ required: true
+ description: Web Hook Param
+ schema:
+ type: string
+ webhookIdParam:
+ name: webhookId
+ in: path
+ required: true
+ description: Web Hook Param
+ schema:
+ type: string
+ siteIdParam:
+ name: siteId
+ in: query
+ description: Site Identifier
+ required: false
+ schema:
+ type: string
+ providerParam:
+ name: provider
+ in: query
+ description: Provider Identifier
+ required: true
+ schema:
+ type: string
+ limitParam:
+ name: limit
+ in: query
+ description: Limit Results
+ required: false
+ schema:
+ type: string
+ default: "10"
+ apiKeyParam:
+ name: apiKey
+ in: path
+ description: API Key
+ required: true
+ schema:
+ type: string
+ documentIdParam:
+ name: documentId
+ in: path
+ description: Document Identifier
+ required: true
+ schema:
+ type: string
+ tagSchemaIdParam:
+ name: tagSchemaId
+ in: path
+ description: Tag Schema Identifier
+ required: true
+ schema:
+ type: string
+ tagkeyParam:
+ name: tagKey
+ in: path
+ description: Tag Key
+ required: true
+ schema:
+ type: string
+ tagvalueParam:
+ name: tagValue
+ in: path
+ description: Tag Key Value
+ required: true
+ schema:
+ type: string
+ contentLengthParam:
+ name: contentLength
+ in: query
+ description: Indicates the size of the entity-body
+ required: false
+ schema:
+ type: integer
+ durationParam:
+ name: duration
+ in: query
+ description: Indicates the number of hours request is valid for
+ schema:
+ type: integer
+ contentUrlParam:
+ name: contentUrl
+ in: query
+ description: Whether to return a "contentUrl", set value to 'true'
+ required: false
+ schema:
+ type: string
+ textParam:
+ name: text
+ in: query
+ description: Returns raw 'text' of OCR content. e.g. AWS Textract returns JSON, setting parameter to 'true' converts JSON to Text
+ required: false
+ schema:
+ type: string
+ indexKeyParam:
+ name: indexKey
+ in: path
+ description: Index Key Identifier
+ required: true
+ schema:
+ type: string
+ indexTypeParam:
+ name: indexType
+ in: path
+ description: Index Type
+ required: true
+ schema:
+ type: string
+ schemas:
+ ValidationErrorsResponse:
+ type: "object"
+ properties:
+ errors:
+ $ref: "#/components/schemas/ValidationErrors"
+ ValidationErrors:
+ type: "array"
+ description: "List of errors"
+ items:
+ $ref: "#/components/schemas/ValidationError"
+ ValidationError:
+ type: "object"
+ properties:
+ key:
+ type: "string"
+ description: "Error Key"
+ error:
+ type: "string"
+ description: "Error Message"
+ IndexFolderMoveRequest:
+ type: "object"
+ properties:
+ source:
+ type: "string"
+ description: "Source path"
+ target:
+ type: "string"
+ description: "Target path"
+ SetDocumentTagKeyRequest:
+ type: "object"
+ properties:
+ value:
+ type: "string"
+ description: "Tag value"
+ values:
+ type: "array"
+ description: "Tag values"
+ items:
+ type: "string"
+ IndexFolderMoveResponse:
+ type: "object"
+ properties:
+ message:
+ type: "string"
+ description: "Folder move message"
+ IndexSearchRequest:
+ type: "object"
+ properties:
+ indexType:
+ type: "string"
+ description: "The name of the index to search"
+ IndexSearchResponse:
+ type: "object"
+ properties:
+ next:
+ type: "string"
+ description: "Next page of results token"
+ previous:
+ type: "string"
+ description: "Previous page of results token"
+ values:
+ $ref: "#/components/schemas/IndexSearchItems"
+ IndexSearchItems:
+ type: "array"
+ description: "List of search results"
+ items:
+ $ref: "#/components/schemas/IndexSearch"
+ IndexSearch:
+ type: "object"
+ properties:
+ value:
+ type: "string"
+ description: "value of index"
+ GetDocumentContentResponse:
+ type: "object"
+ properties:
+ content:
+ type: "string"
+ description: "Document content"
+ contentUrl:
+ type: "string"
+ description: "URL to retrieve document content"
+ contentType:
+ type: "string"
+ description: "Document Content-Type"
+ isBase64:
+ type: "boolean"
+ description: "Is the content Base64-encoded?"
+ GetDocumentVersionsResponse:
+ type: "object"
+ properties:
+ next:
+ type: "string"
+ description: "Next page of results token"
+ versions:
+ $ref: "#/components/schemas/DocumentItemVersions"
+ GetDocumentTagsResponse:
+ type: "object"
+ properties:
+ next:
+ type: "string"
+ description: "Next page of results token"
+ previous:
+ type: "string"
+ description: "Previous page of results token"
+ tags:
+ $ref: "#/components/schemas/DocumentItemTags"
+ SetDocumentVersionRequest:
+ type: "object"
+ properties:
+ versionKey:
+ type: "string"
+ description: "VersionKey returned by the GET /documents/{documentId}/versions to revert to"
+ SetDocumentVersionResponse:
+ type: "object"
+ properties:
+ message:
+ type: "string"
+ description: "Response Message"
+ DocumentItemTags:
+ type: "array"
+ description: "List of tags"
+ items:
+ $ref: "#/components/schemas/GetDocumentTagResponse"
+ DocumentItemVersions:
+ type: "array"
+ description: "List of document versions"
+ items:
+ $ref: "#/components/schemas/DocumentItemVersion"
+ DocumentSearch:
+ type: "object"
+ description: "Document tag search criteria"
+ properties:
+ text:
+ type: "string"
+ description: "Full text search"
+ meta:
+ $ref: "#/components/schemas/DocumentSearchItemMeta"
+ tag:
+ $ref: "#/components/schemas/DocumentSearchItemTag"
+ documentIds:
+ type: array
+ description: "List of DocumentIds to filter search results on"
+ items:
+ type: "string"
+ DocumentId:
+ required:
+ - "documentId"
+ type: "object"
+ properties:
+ documentId:
+ type: "string"
+ format: "uuid"
+ description: "Document Identifier"
+ siteId:
+ type: "string"
+ description: "Site Identifier"
+ AddWebhookResponse:
+ type: "object"
+ properties:
+ id:
+ type: "string"
+ format: "uuid"
+ siteId:
+ type: "string"
+ description: "Site Identifier"
+ AddDocumentResponse:
+ type: "object"
+ properties:
+ documentId:
+ type: "string"
+ format: "uuid"
+ description: "Document Identifier"
+ siteId:
+ type: "string"
+ description: "Site Identifier"
+ uploadUrl:
+ type: "string"
+ description: "Url to upload document to"
+ documents:
+ $ref: "#/components/schemas/AddChildDocumentsResponse"
+ AddChildDocumentsResponse:
+ type: "array"
+ description: "List of child documents"
+ items:
+ $ref: "#/components/schemas/AddChildDocumentResponse"
+ AddChildDocumentResponse:
+ type: "object"
+ properties:
+ documentId:
+ type: "string"
+ description: "Document Identifier"
+ uploadUrl:
+ type: "string"
+ description: "Url to upload document to"
+ GetDocumentUrlRequest:
+ type: "object"
+ properties:
+ documentId:
+ type: "string"
+ description: "Document Identifier"
+ url:
+ type: "string"
+ description: "Document content url"
+ GetDocumentResponse:
+ required:
+ - "documentId"
+ - "path"
+ type: "object"
+ properties:
+ next:
+ type: "string"
+ description: "Next page of results token"
+ previous:
+ type: "string"
+ description: "Previous page of results token"
+ siteId:
+ type: "string"
+ description: "Site Identifier"
+ path:
+ type: "string"
+ description: "Path or Name of document"
+ insertedDate:
+ type: "string"
+ format: "date-time"
+ description: "Inserted Timestamp"
+ lastModifiedDate:
+ type: "string"
+ format: "date-time"
+ description: "Last Modified Timestamp"
+ checksum:
+ type: "string"
+ description: "Document checksum, changes when document file changes"
+ documentId:
+ type: "string"
+ format: "uuid"
+ description: "Document Identifier"
+ contentType:
+ type: "string"
+ description: "Document Content-Type"
+ userId:
+ type: "string"
+ description: "User who added document"
+ contentLength:
+ type: "integer"
+ description: "Document size"
+ versionId:
+ type: "string"
+ description: "Document version"
+ belongsToDocumentId:
+ type: "string"
+ description: "Parent Document Identifier"
+ documents:
+ type: "array"
+ description: "List of related documents"
+ items:
+ type: "object"
+ properties:
+ path:
+ type: "string"
+ description: "Path or Name of document"
+ insertedDate:
+ type: "string"
+ format: "date-time"
+ description: "Inserted Timestamp"
+ lastModifiedDate:
+ type: "string"
+ format: "date-time"
+ description: "Last Modified Timestamp"
+ checksum:
+ type: "string"
+ description: "Document checksum, changes when document file changes"
+ documentId:
+ type: "string"
+ format: "uuid"
+ description: "Document Identifier"
+ contentType:
+ type: "string"
+ description: "Document Content-Type"
+ userId:
+ type: "string"
+ description: "User who added document"
+ contentLength:
+ type: "integer"
+ description: "Document size"
+ versionId:
+ type: "string"
+ description: "Document version"
+ belongsToDocumentId:
+ type: "string"
+ description: "Parent Document Identifier"
+ DocumentFulltextRequest:
+ required:
+ - "query"
+ type: "object"
+ description: "Document full text search"
+ properties:
+ query:
+ $ref: "#/components/schemas/DocumentFulltextSearch"
+ responseFields:
+ $ref: "#/components/schemas/SearchResponseFields"
+ DocumentFulltextSearch:
+ type: "object"
+ description: "Document full text search criteria"
+ properties:
+ page:
+ type: "integer"
+ description: "Result page to return (starting at 1)"
+ text:
+ type: "string"
+ description: "Full text search"
+ tags:
+ $ref: "#/components/schemas/DocumentFulltextTags"
+ DocumentFulltextTags:
+ type: "array"
+ description: "List of search tags"
+ items:
+ $ref: "#/components/schemas/DocumentFulltextTag"
+ DocumentFulltextTag:
+ required:
+ - "key"
+ type: "object"
+ properties:
+ eq:
+ type: "string"
+ description: "Searches for strings that eq"
+ eqOr:
+ type: array
+ description: "Searches for ANY strings that eq"
+ items:
+ type: "string"
+ key:
+ type: "string"
+ description: "Tag key to search"
+ DocumentSearchRequest:
+ required:
+ - "query"
+ type: "object"
+ description: "Document search tag criteria"
+ properties:
+ query:
+ $ref: "#/components/schemas/DocumentSearch"
+ responseFields:
+ $ref: "#/components/schemas/SearchResponseFields"
+ SearchResponseFields:
+ properties:
+ tags:
+ type: "array"
+ items:
+ type: "string"
+ DocumentSearchItemMeta:
+ type: "object"
+ properties:
+ folder:
+ type: "string"
+ description: "Searches for a folder"
+ path:
+ type: "string"
+ description: "Searches for a Path of document"
+ indexType:
+ type: "string"
+ description: "Searches in an index"
+ enum:
+ - folder
+ indexFilterBeginsWith:
+ type: "string"
+ description: "Returns index records that begins with a particular substring"
+ DocumentSearchItemTag:
+ required:
+ - "key"
+ type: "object"
+ properties:
+ beginsWith:
+ type: "string"
+ description: "Searches for strings that begin with"
+ eq:
+ type: "string"
+ description: "Searches for strings that eq"
+ eqOr:
+ type: array
+ description: "Searches for ANY strings that eq"
+ items:
+ type: "string"
+ key:
+ type: "string"
+ description: "Tag key to search"
+ AddWebhookRequest:
+ required:
+ - "name"
+ type: "object"
+ properties:
+ name:
+ type: "string"
+ description: "Name of webhook"
+ ttl:
+ type: "string"
+ description: "Webhook time to live (expiry)"
+ enabled:
+ type: "string"
+ description: "Is webhook enabled"
+ tags:
+ $ref: "#/components/schemas/AddDocumentTags"
+ AddDocumentUploadRequest:
+ required:
+ - "content"
+ type: "object"
+ properties:
+ tagSchemaId:
+ type: "string"
+ description: "Tag Schema Id"
+ path:
+ type: "string"
+ description: "Path or Name of document"
+ tags:
+ $ref: "#/components/schemas/AddDocumentTags"
+ actions:
+ $ref: "#/components/schemas/AddActions"
+ AddDocumentRequest:
+ required:
+ - "content"
+ type: "object"
+ properties:
+ tagSchemaId:
+ type: "string"
+ description: "Tag Schema Id"
+ path:
+ type: "string"
+ description: "Path or Name of document"
+ contentType:
+ type: "string"
+ description: "Document media type"
+ isBase64:
+ type: "boolean"
+ description: "Is the content Base64-encoded?"
+ content:
+ type: "string"
+ description: "Document content"
+ tags:
+ $ref: "#/components/schemas/AddDocumentTags"
+ metadata:
+ $ref: "#/components/schemas/AddDocumentMetadatas"
+ actions:
+ $ref: "#/components/schemas/AddActions"
+ documents:
+ $ref: "#/components/schemas/AddChildDocumentRequest"
+ AddDocumentTagsRequest:
+ type: "object"
+ description: "Add List of document tags"
+ properties:
+ tags:
+ $ref: "#/components/schemas/AddDocumentTags"
+ AddDocumentMetadatas:
+ type: "array"
+ description: "List of document Metadata"
+ items:
+ $ref: "#/components/schemas/AddDocumentMetadata"
+ AddDocumentMetadata:
+ required:
+ - "key"
+ type: "object"
+ description: "Document Metadata (use either 'value' or 'values' not both)"
+ properties:
+ key:
+ type: "string"
+ description: "Metadata key"
+ value:
+ type: "string"
+ description: "Metadata value"
+ values:
+ type: "array"
+ description: "Metadata values"
+ items:
+ type: "string"
+ description: "Metadata value"
+ AddDocumentTags:
+ type: "array"
+ description: "List of document tags"
+ items:
+ $ref: "#/components/schemas/AddDocumentTagRequest"
+ AddDocumentTagRequest:
+ required:
+ - "key"
+ type: "object"
+ description: "List of Document Tags (use either 'value' or 'values' not both)"
+ properties:
+ key:
+ type: "string"
+ description: "Tag key"
+ value:
+ type: "string"
+ description: "Tag value"
+ values:
+ type: "array"
+ description: "Tag values"
+ items:
+ type: "string"
+ description: "Tag value"
+ AddChildDocumentRequest:
+ type: "array"
+ description: "List of child documents"
+ items:
+ $ref: "#/components/schemas/AddChildDocument"
+ AddChildDocument:
+ required:
+ - "content"
+ type: "object"
+ description: "List of related documents"
+ properties:
+ path:
+ type: "string"
+ description: "Path or Name of document"
+ contentType:
+ type: "string"
+ description: "Document Content-Type"
+ isBase64:
+ type: "boolean"
+ description: "Is the content Base64-encoded?"
+ content:
+ type: "string"
+ description: "Document content"
+ DocumentItemVersion:
+ type: "object"
+ properties:
+ path:
+ type: "string"
+ description: "Path or Name of document"
+ insertedDate:
+ type: "string"
+ format: "date-time"
+ description: "Inserted Timestamp"
+ lastModifiedDate:
+ type: "string"
+ format: "date-time"
+ description: "Last Modified Timestamp"
+ checksum:
+ type: "string"
+ description: "Document checksum, changes when document file changes"
+ documentId:
+ type: "string"
+ format: "uuid"
+ description: "Document Identifier"
+ contentType:
+ type: "string"
+ description: "Document Content-Type"
+ userId:
+ type: "string"
+ description: "User who added document"
+ contentLength:
+ type: "integer"
+ description: "Document size"
+ versionId:
+ type: "string"
+ description: "Document version"
+ versionKey:
+ type: "string"
+ description: "Document Version Identifier"
+ GetDocumentTagResponse:
+ required:
+ - "key"
+ - "value"
+ type: "object"
+ properties:
+ insertedDate:
+ type: "string"
+ description: "Inserted Timestamp"
+ documentId:
+ type: "string"
+ description: "Document Identifier"
+ type:
+ type: "string"
+ description: "Tag type"
+ userId:
+ type: "string"
+ description: "User who added document"
+ value:
+ type: "string"
+ description: "Tag value"
+ values:
+ type: "array"
+ description: "Tag values"
+ items:
+ type: "string"
+ description: "Tag value"
+ key:
+ type: "string"
+ description: "Tag key"
+ QueryFulltextRequest:
+ description: OpenSearch search API request (https://opensearch.org/docs/latest/opensearch/rest-api/search/)
+ type: "object"
+ example:
+ query:
+ match:
+ title: "Wind"
+ QueryFulltextResponse:
+ type: "object"
+ properties:
+ result:
+ type: "object"
+ example:
+ result:
+ hits:
+ hits:
+ - _index: ""
+ _id: ""
+ _source:
+ documentId: ""
+ content: ""
+ DocumentFulltextResponse:
+ type: "object"
+ properties:
+ documents:
+ $ref: "#/components/schemas/FulltextSearchItems"
+ FulltextSearchItems:
+ type: "array"
+ description: "List of search result documents"
+ items:
+ $ref: "#/components/schemas/FulltextSearchItem"
+ FulltextSearchItem:
+ type: "object"
+ properties:
+ siteId:
+ type: "string"
+ description: "Site Identifier"
+ path:
+ type: "string"
+ description: "Path or Name of document"
+ insertedDate:
+ type: "string"
+ format: "date-time"
+ description: "Inserted Timestamp"
+ documentId:
+ type: "string"
+ format: "uuid"
+ description: "Document Identifier"
+ contentLength:
+ type: "integer"
+ description: "Document size"
+ createdBy:
+ type: "string"
+ description: "User who added document"
+ tags:
+ type: "object"
+ GetDocumentFulltextResponse:
+ type: "object"
+ properties:
+ siteId:
+ type: "string"
+ description: "Site Identifier"
+ content:
+ type: "string"
+ description: "Content of document"
+ path:
+ type: "string"
+ description: "Path or Name of document"
+ insertedDate:
+ type: "string"
+ format: "date-time"
+ description: "Inserted Timestamp"
+ documentId:
+ type: "string"
+ format: "uuid"
+ description: "Document Identifier"
+ createdBy:
+ type: "string"
+ description: "User who added document"
+ contentLength:
+ type: "integer"
+ description: "Document size"
+ tags:
+ type: "object"
+ metadata:
+ type: "object"
+ GetDocumentSyncResponse:
+ type: "object"
+ properties:
+ next:
+ type: "string"
+ description: "Next page of results token"
+ syncs:
+ $ref: "#/components/schemas/GetDocumentSyncs"
+ GetDocumentSyncs:
+ type: "array"
+ description: "List of document syncs"
+ items:
+ $ref: "#/components/schemas/GetDocumentSync"
+ GetDocumentSync:
+ type: "object"
+ properties:
+ service:
+ type: "string"
+ description: "To which service the data was synced"
+ enum:
+ - TYPESENSE
+ - OPENSEARCH
+ status:
+ type: "string"
+ description: "The status of the sync"
+ enum:
+ - COMPLETE
+ - FAILED
+ type:
+ type: "string"
+ description: "The type of the sync"
+ enum:
+ - METADATA
+ - TAG
+ syncDate:
+ type: "string"
+ format: "date-time"
+ description: "Timestamp of synchronization"
+ userId:
+ type: "string"
+ description: "User who added document"
+ message:
+ type: string
+ description: Document sync message
+ AddDocumentSyncRequest:
+ type: "object"
+ properties:
+ service:
+ type: "string"
+ description: "To which service to sync the data to"
+ enum:
+ - TYPESENSE
+ - OPENSEARCH
+ DocumentSearchResponse:
+ type: "object"
+ properties:
+ next:
+ type: "string"
+ description: "Next page of results token"
+ previous:
+ type: "string"
+ description: "Previous page of results token"
+ documents:
+ $ref: "#/components/schemas/SearchDocumentItems"
+ SearchDocumentItems:
+ type: "array"
+ description: "List of search result documents"
+ items:
+ $ref: "#/components/schemas/SearchDocumentItem"
+ SearchDocumentItem:
+ type: "object"
+ properties:
+ siteId:
+ type: "string"
+ description: "Site Identifier"
+ path:
+ type: "string"
+ description: "Path or Name of document"
+ insertedDate:
+ type: "string"
+ format: "date-time"
+ description: "Inserted Timestamp"
+ lastModifiedDate:
+ type: "string"
+ format: "date-time"
+ description: "Last Modified Timestamp"
+ folder:
+ type: "boolean"
+ description: "Is Result a Document Folder"
+ indexKey:
+ type: "string"
+ description: "populated if search result are from an index"
+ checksum:
+ type: "string"
+ description: "Document checksum, changes when document file changes"
+ documentId:
+ type: "string"
+ format: "uuid"
+ description: "Document Identifier"
+ contentType:
+ type: "string"
+ description: "Document Content-Type"
+ userId:
+ type: "string"
+ description: "User who added document"
+ contentLength:
+ type: "integer"
+ description: "Document size"
+ versionId:
+ type: "string"
+ description: "Document version"
+ matchedTag:
+ $ref: "#/components/schemas/DocumentSearchMatchTag"
+ tags:
+ type: "object"
+ DocumentSearchMatchTag:
+ type: "object"
+ properties:
+ key:
+ type: "string"
+ description: "Tag key"
+ value:
+ type: "string"
+ description: "Tag value"
+ type:
+ type: "string"
+ description: "Tag type"
+ GetDocumentsResponse:
+ type: "object"
+ properties:
+ next:
+ type: "string"
+ description: "Next page of results token"
+ previous:
+ type: "string"
+ description: "Previous page of results token"
+ documents:
+ $ref: "#/components/schemas/DocumentItemResults"
+ DocumentItemResults:
+ type: "array"
+ description: "List of documents"
+ items:
+ $ref: "#/components/schemas/DocumentItemResult"
+ DocumentItemResult:
+ type: "object"
+ properties:
+ siteId:
+ type: "string"
+ description: "Site Identifier"
+ path:
+ type: "string"
+ description: "Path or Name of document"
+ insertedDate:
+ type: "string"
+ format: "date-time"
+ description: "Inserted Timestamp"
+ lastModifiedDate:
+ type: "string"
+ format: "date-time"
+ description: "Last Modified Timestamp"
+ checksum:
+ type: "string"
+ description: "Document checksum, changes when document file changes"
+ documentId:
+ type: "string"
+ format: "uuid"
+ description: "Document Identifier"
+ contentType:
+ type: "string"
+ description: "Document Content-Type"
+ userId:
+ type: "string"
+ description: "User who added document"
+ contentLength:
+ type: "integer"
+ description: "Document size"
+ versionId:
+ type: "string"
+ description: "Document version"
+ GetWebhooksResponse:
+ type: "object"
+ properties:
+ webhooks:
+ $ref: "#/components/schemas/Webhooks"
+ Webhooks:
+ type: "array"
+ description: "List of webhooks"
+ items:
+ $ref: "#/components/schemas/GetWebhookResponse"
+ GetWebhookResponse:
+ type: "object"
+ properties:
+ siteId:
+ type: "string"
+ description: "Site Identifier"
+ name:
+ type: "string"
+ description: "Webhook name"
+ url:
+ type: "string"
+ description: "Webhook url"
+ insertedDate:
+ type: "string"
+ format: "date-time"
+ description: "Inserted Timestamp"
+ id:
+ type: "string"
+ format: "uuid"
+ description: "Webhook Identifier"
+ userId:
+ type: "string"
+ description: "User who added document"
+ GetWebhookTagsResponse:
+ type: "object"
+ properties:
+ next:
+ type: "string"
+ description: "Next page of results token"
+ previous:
+ type: "string"
+ description: "Previous page of results token"
+ tags:
+ $ref: "#/components/schemas/WebhookTagsList"
+ WebhookTagsList:
+ type: "array"
+ description: "List of webhook tags"
+ items:
+ $ref: "#/components/schemas/WebhookTag"
+ WebhookTag:
+ required:
+ - "key"
+ - "value"
+ type: "object"
+ properties:
+ insertedDate:
+ type: "string"
+ description: "Inserted Timestamp"
+ webhookId:
+ type: "string"
+ description: "Webhook Identifier"
+ type:
+ type: "string"
+ description: "Tag type"
+ userId:
+ type: "string"
+ description: "User who added document"
+ value:
+ type: "string"
+ description: "Tag value"
+ key:
+ type: "string"
+ description: "Tag key"
+ GetDocumentActionsResponse:
+ type: "object"
+ properties:
+ actions:
+ $ref: "#/components/schemas/DocumentActionList"
+ DocumentActionList:
+ type: "array"
+ description: "List of document actions"
+ items:
+ $ref: "#/components/schemas/DocumentAction"
+ DocumentAction:
+ type: object
+ properties:
+ status:
+ type: string
+ description: Status of the Document Action
+ type:
+ type: string
+ description: Type of Document Action
+ userId:
+ type: "string"
+ description: "User who requested the Action"
+ parameters:
+ type: "object"
+ description: Action parameters
+ GetDocumentOcrResponse:
+ type: object
+ properties:
+ data:
+ type: string
+ description: OCR text result
+ ocrEngine:
+ type: string
+ description: The OCR technique used
+ ocrStatus:
+ type: string
+ description: The status of the OCR request
+ contentType:
+ type: "string"
+ description: "Document Content-Type"
+ isBase64:
+ type: "boolean"
+ description: "Is the content Base64-encoded?"
+ userId:
+ type: "string"
+ description: "User who requested the OCR"
+ documentId:
+ type: "string"
+ format: "uuid"
+ description: "Document Identifier"
+ AddDocumentActionsResponse:
+ type: object
+ properties:
+ message:
+ type: string
+ description: Document Action message
+ AddDocumentOcrResponse:
+ type: object
+ properties:
+ message:
+ type: string
+ description: OCR processing message
+ SetDocumentFulltextResponse:
+ type: object
+ properties:
+ message:
+ type: string
+ description: Full text processing message
+ SetDocumentFulltextRequest:
+ type: object
+ properties:
+ contentType:
+ type: "string"
+ description: "Document Content-Type"
+ content:
+ type: "string"
+ description: "Document content"
+ contentUrls:
+ type: "array"
+ items:
+ type: "string"
+ description: "URL(s) which contain document content"
+ path:
+ type: "string"
+ description: "Path or Name of document"
+ tags:
+ $ref: "#/components/schemas/AddDocumentTags"
+ metadata:
+ $ref: "#/components/schemas/AddDocumentMetadatas"
+ UpdateDocumentFulltextRequest:
+ type: object
+ properties:
+ path:
+ type: "string"
+ description: "Path or Name of document"
+ content:
+ type: "string"
+ description: "Document content"
+ tags:
+ $ref: "#/components/schemas/AddDocumentTags"
+ SetAntivirusRequest:
+ type: object
+ SetAntivirusResponse:
+ type: object
+ properties:
+ message:
+ type: string
+ description: Antivirus processing message
+ AddDocumentActionsRequest:
+ type: object
+ properties:
+ actions:
+ $ref: "#/components/schemas/AddActions"
+ AddActions:
+ type: array
+ description: "List of Actions"
+ items:
+ $ref: "#/components/schemas/AddAction"
+ AddAction:
+ type: object
+ required:
+ - type
+ properties:
+ type:
+ type: "string"
+ description: Type of Document Action
+ enum:
+ - OCR
+ - FULLTEXT
+ - ANTIVIRUS
+ - WEBHOOK
+ - DOCUMENTTAGGING
+ parameters:
+ $ref: "#/components/schemas/AddActionParameters"
+ AddActionParameters:
+ type: "object"
+ properties:
+ ocrParseTypes:
+ type: "string"
+ description: "OCR: Parse types - TEXT, FORMS, TABLES"
+ addPdfDetectedCharactersAsText:
+ type: "boolean"
+ description: "OCR: For the rewriting of the PDF document, converting any image text to searchable text"
+ url:
+ type: "string"
+ description: "Webhook: Callback URL"
+ characterMax:
+ type: "string"
+ description: "Fulltext: Maximum number of characters (-1 unlimited, Typesense defaults to 2048 characters)"
+ engine:
+ type: "string"
+ description: "DocumentTagging: Engine to use for document tagging generation"
+ enum:
+ - chatgpt
+ tags:
+ description: "DocumentTagging: List of Tags to generate tags for"
+ items:
+ type: "string"
+ AddDocumentOcrRequest:
+ type: object
+ example:
+ parseTypes:
+ - TEXT
+ - FORMS
+ - TABLES
+ properties:
+ parseTypes:
+ type: "array"
+ description: "OCR Parse types - TEXT, FORMS, TABLES"
+ items:
+ type: "string"
+ addPdfDetectedCharactersAsText:
+ type: "boolean"
+ description: "Rewrite PDF document, converting any Image text to searchable text"
+ SetDocumentOcrRequest:
+ required:
+ - "content"
+ type: "object"
+ properties:
+ contentType:
+ type: "string"
+ description: "Document Content-Type"
+ isBase64:
+ type: "boolean"
+ description: "Is the content Base64-encoded?"
+ content:
+ type: "string"
+ description: "Document content"
+ GetVersionRequest:
+ type: object
+ properties:
+ version:
+ type: string
+ description: "FormKiQ version"
+ type:
+ type: string
+ description: "FormKiQ type"
+ modules:
+ type: array
+ description: "List of installed modules"
+ items:
+ type: "string"
+ SetConfigRequest:
+ type: "object"
+ properties:
+ chatGptApiKey:
+ type: "string"
+ description: "ChatGPT Api Key"
+ maxContentLengthBytes:
+ type: "string"
+ description: "Set Maximum Document Content Length in Bytes"
+ maxDocuments:
+ type: "string"
+ description: "Set Maximum number of Documents allowed"
+ maxWebhooks:
+ type: "string"
+ description: "Set Maximum number of Webhooks allowed"
+ SetConfigResponse:
+ type: object
+ properties:
+ message:
+ type: "string"
+ description: "Result message"
+ AddApiKeyRequest:
+ type: object
+ properties:
+ name:
+ type: "string"
+ description: "Name of API Key"
+ AddApiKeyResponse:
+ type: object
+ properties:
+ message:
+ type: "string"
+ description: "Result message"
+ DeleteApiKeyResponse:
+ type: object
+ properties:
+ message:
+ type: "string"
+ description: "Result message"
+ GetApiKeysResponse:
+ type: object
+ properties:
+ apiKeys:
+ $ref: "#/components/schemas/ApiKeys"
+ ApiKeys:
+ type: "array"
+ description: "List of ApiKeys"
+ items:
+ $ref: "#/components/schemas/ApiKey"
+ ApiKey:
+ type: "object"
+ properties:
+ name:
+ type: "string"
+ description: "Name of API Key"
+ apiKey:
+ type: "string"
+ description: "API Key value"
+ userId:
+ type: "string"
+ siteIds:
+ type: "array"
+ items:
+ type: "string"
+ insertedDate:
+ type: "string"
+ format: "date-time"
+ description: "Inserted Timestamp"
+ GetConfigurationResponse:
+ type: object
+ properties:
+ chatGptApiKey:
+ type: "string"
+ description: "ChatGPT API Key"
+ maxContentLengthBytes:
+ type: "string"
+ description: "Set Maximum Document Content Length in Bytes"
+ maxDocuments:
+ type: "string"
+ description: "Set Maximum number of Documents allowed"
+ maxWebhooks:
+ type: "string"
+ description: "Set Maximum number of Webhooks allowed"
+ GetSitesRequest:
+ type: object
+ properties:
+ sites:
+ $ref: "#/components/schemas/Sites"
+ Sites:
+ type: "array"
+ description: "List of sites"
+ items:
+ $ref: "#/components/schemas/Site"
+ Site:
+ type: "object"
+ properties:
+ siteId:
+ type: "string"
+ description: "Site Identifier"
+ permission:
+ type: "string"
+ description: "SiteId permission level"
+ enum:
+ - READ_WRITE
+ - READ_ONLY
+ uploadEmail:
+ type: "string"
+ description: "SiteId document upload email address"
+ TagSchemaPostResponse:
+ type: "object"
+ properties:
+ tagSchemaId:
+ type: "string"
+ format: "uuid"
+ description: "Tag Schema Identifier"
+ ErrorsResponse:
+ type: object
+ properties:
+ errors:
+ $ref: "#/components/schemas/ErrorsList"
+ ErrorsList:
+ type: "array"
+ description: "List of errors"
+ items:
+ $ref: "#/components/schemas/Error"
+ Error:
+ type: "object"
+ properties:
+ key:
+ type: "string"
+ description: "Error Key"
+ error:
+ type: "string"
+ description: "Error Message"
+ GetTagSchemasRequest:
+ type: "object"
+ properties:
+ schemas:
+ $ref: "#/components/schemas/TagSchemas"
+ next:
+ type: "string"
+ previous:
+ type: "string"
+ TagSchemas:
+ type: "array"
+ description: "List of Tag Schemas"
+ items:
+ $ref: "#/components/schemas/TagSchemaSummary"
+ AddTagSchemaRequest:
+ type: "object"
+ properties:
+ name:
+ type: "string"
+ tags:
+ $ref: "#/components/schemas/AddTagSchemaTags"
+ AddTagSchemaTags:
+ type: "object"
+ properties:
+ compositeKeys:
+ type: "array"
+ description: "List of Composite Keys"
+ items:
+ $ref: "#/components/schemas/TagSchemaCompositeKey"
+ required:
+ type: "array"
+ description: "List of Required Tags"
+ items:
+ $ref: "#/components/schemas/TagSchemaRequired"
+ optional:
+ type: "array"
+ description: "List of Optional Tags"
+ items:
+ $ref: "#/components/schemas/TagSchemaOptional"
+ allowAdditionalTags:
+ type: "boolean"
+ default: true
+ TagSchemaSummary:
+ type: "object"
+ properties:
+ tagSchemaId:
+ type: "string"
+ name:
+ type: "string"
+ userId:
+ type: "string"
+ insertedDate:
+ type: "string"
+ format: "date-time"
+ description: "Inserted Timestamp"
+ GetTagSchemaRequest:
+ type: "object"
+ properties:
+ tagSchemaId:
+ type: "string"
+ name:
+ type: "string"
+ userId:
+ type: "string"
+ insertedDate:
+ type: "string"
+ format: "date-time"
+ description: "Inserted Timestamp"
+ tags:
+ type: "object"
+ properties:
+ compositeKeys:
+ type: "array"
+ description: "List of Composite Keys"
+ items:
+ $ref: "#/components/schemas/TagSchemaCompositeKey"
+ required:
+ type: "array"
+ description: "List of Required Tags"
+ items:
+ $ref: "#/components/schemas/TagSchemaRequired"
+ optional:
+ type: "array"
+ description: "List of Optional Tags"
+ items:
+ $ref: "#/components/schemas/TagSchemaOptional"
+ allowAdditionalTags:
+ type: "boolean"
+ default: true
+ TagSchemaCompositeKey:
+ type: "object"
+ properties:
+ key:
+ type: "array"
+ items:
+ type: "string"
+ TagSchemaRequired:
+ type: "object"
+ properties:
+ key:
+ type: "string"
+ defaultValues:
+ type: "array"
+ description: "Default values"
+ items:
+ type: "string"
+ allowedValues:
+ type: "array"
+ description: "Only valid values"
+ items:
+ type: "string"
+ TagSchemaOptional:
+ type: "object"
+ properties:
+ key:
+ type: "string"
+ defaultValues:
+ type: "array"
+ description: "Default values"
+ items:
+ type: "string"
+ allowedValues:
+ type: "array"
+ description: "Only valid values"
+ items:
+ type: "string"
+ OnlyOfficeDocumentNewRequest:
+ description: "ONLYOFFICE New Document Request"
+ properties:
+ extension:
+ type: "string"
+ enum:
+ - DOCX
+ - XLSX
+ - PPTX
+ OnlyOfficeDocumentEditRequest:
+ description: "ONLYOFFICE Edit Document Request"
+ OnlyOfficeDocumentResponse:
+ type: "object"
+ properties:
+ config:
+ type: "object"
+ properties:
+ onlyOfficeUrl:
+ description: "URL of the ONLYOFFICE application"
+ type: "string"
+ token:
+ description: "ONLYOFFICE security token"
+ type: "string"
+ documentType:
+ description: "Type of document (https://api.onlyoffice.com/editors/config/)"
+ type: "string"
+ editorConfig:
+ type: "object"
+ properties:
+ callbackUrl:
+ type: "string"
+ document:
+ type: "object"
+ properties:
+ url:
+ description: "Defines the absolute URL where the source viewed or edited document is stored"
+ type: "string"
+ title:
+ description: "Defines the desired file name for the viewed or edited document"
+ type: "string"
+ key:
+ description: "Defines the unique document identifier used by the service to recognize the document"
+ type: "string"
+ fileType:
+ description: "Defines the type of the file for the source viewed or edited document"
+ type: "string"
+ OnlyOfficeDocumentSaveResponse:
+ type: "object"
+ properties:
+ message:
+ type: "string"
+ EsignatureDocusignRequest:
+ type: "object"
+ properties:
+ emailSubject:
+ type: "string"
+ description: "Email Subject"
+ status:
+ type: "string"
+ description: "The status of the request"
+ enum:
+ - created
+ - sent
+ developmentMode:
+ type: "boolean"
+ description: "Whether to enable developer mode"
+ signers:
+ $ref: "#/components/schemas/EsignatureDocusignSigners"
+ carbonCopies:
+ $ref: "#/components/schemas/EsignatureDocusignCarbonCopies"
+ recipientTabs:
+ $ref: "#/components/schemas/EsignatureDocusignRecipientTabs"
+ EsignatureDocusignSigners:
+ type: "array"
+ description: "List of DocuSign Signers"
+ items:
+ $ref: "#/components/schemas/EsignatureDocusignSigner"
+ EsignatureDocusignSigner:
+ type: "object"
+ properties:
+ name:
+ type: "string"
+ description: "Name of Signer"
+ email:
+ type: "string"
+ description: "Email of Signer"
+ EsignatureDocusignCarbonCopies:
+ type: "array"
+ description: "List of DocuSign Carbon Copies"
+ items:
+ $ref: "#/components/schemas/EsignatureDocusignCarbonCopy"
+ EsignatureDocusignCarbonCopy:
+ type: "object"
+ properties:
+ name:
+ type: "string"
+ description: "Name of Signer"
+ email:
+ type: "string"
+ description: "Email of Signer"
+ EsignatureDocusignRecipientTabs:
+ type: "array"
+ description: "List of DocuSign Recipient Tabs"
+ items:
+ $ref: "#/components/schemas/EsignatureDocusignRecipientTab"
+ EsignatureDocusignRecipientTab:
+ type: "object"
+ properties:
+ type:
+ type: "string"
+ description: "Type of Recipient"
+ enum:
+ - signHere
+ pageNumber:
+ type: "string"
+ description: "Document Page Number"
+ positionX:
+ type: "string"
+ description: "Element X Position"
+ positionY:
+ type: "string"
+ description: "Element Y Position"
+ EsignatureDocusignResponse:
+ type: "object"
+ properties:
+ redirect_url:
+ type: "string"
+ description: "Redirect Url to complete DocuSign workflow"
+ message:
+ type: "string"
+ description: "Result message"
+ EsignatureDocusignConfigResponse:
+ type: "object"
+ properties:
+ configured:
+ type: "boolean"
+ description: "Whether DocuSign is configured"
+ userId:
+ type: "string"
+ description: "DocuSign UserId configured"
+ clientId:
+ type: "string"
+ description: "DocuSign Client configured"
+ EsignatureSetDocusignConfigRequest:
+ type: "object"
+ required:
+ - privateKey
+ - userId
+ - clientId
+ properties:
+ privateKey:
+ type: "string"
+ description: "DocuSign App RSA PRIVATE KEY"
+ userId:
+ type: "string"
+ description: "DocuSign App UserId"
+ clientId:
+ type: "string"
+ description: "DocuSign App Client"
+ EsignatureSetDocusignConfigResponse:
+ type: "object"
+ properties:
+ message:
+ type: "string"
+ description: "Message response"
+ securitySchemes:
+ ApiAuthorization:
+ type: "apiKey"
+ name: "Authorization"
+ in: "header"
+ x-amazon-apigateway-authtype: "Custom API Key"
+ x-amazon-apigateway-authorizer:
+ identitySource: $request.header.Authorization
+ authorizerUri:
+ Fn::Sub: "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ApiKeyAuthorizer.Arn}/invocations"
+ authorizerResultTtlInSeconds: 300
+ authorizerPayloadFormatVersion: "2.0"
+ enableSimpleResponses: true
+ type: request
+ x-amazon-apigateway-integrations:
+ lambdaApi200:
+ uri:
+ Fn::Sub: "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${DocumentsApiRequests.Arn}/invocations"
+ responses:
+ default:
+ statusCode: "200"
+ responseParameters:
+ method.response.header.Access-Control-Allow-Methods: "'*'"
+ method.response.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key'"
+ method.response.header.Access-Control-Allow-Origin: "'*'"
+ passthroughBehavior: "when_no_templates"
+ httpMethod: "POST"
+ type: "aws_proxy"
+ payloadFormatVersion: "1.0"
+ ocrLambdaApi200:
+ uri:
+ Fn::Sub: "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${DocumentsApiRequests.Arn}/invocations"
+ responses:
+ default:
+ statusCode: "200"
+ responseParameters:
+ method.response.header.Access-Control-Allow-Methods: "'*'"
+ method.response.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key'"
+ method.response.header.Access-Control-Allow-Origin: "'*'"
+ passthroughBehavior: "when_no_templates"
+ httpMethod: "POST"
+ type: "aws_proxy"
+ payloadFormatVersion: "1.0"
+ antivirusLambdaApi200:
+ uri:
+ Fn::Sub: "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${DocumentsApiRequests.Arn}/invocations"
+ responses:
+ default:
+ statusCode: "200"
+ responseParameters:
+ method.response.header.Access-Control-Allow-Methods: "'*'"
+ method.response.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key'"
+ method.response.header.Access-Control-Allow-Origin: "'*'"
+ passthroughBehavior: "when_no_templates"
+ httpMethod: "POST"
+ type: "aws_proxy"
+ payloadFormatVersion: "1.0"
+ searchLambdaApi200:
+ uri:
+ Fn::Sub: "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${DocumentsApiRequests.Arn}/invocations"
+ responses:
+ default:
+ statusCode: "200"
+ responseParameters:
+ method.response.header.Access-Control-Allow-Methods: "'*'"
+ method.response.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key'"
+ method.response.header.Access-Control-Allow-Origin: "'*'"
+ passthroughBehavior: "when_no_templates"
+ httpMethod: "POST"
+ type: "aws_proxy"
+ payloadFormatVersion: "1.0"
+ fulltextLambdaApi200:
+ uri:
+ Fn::Sub: "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${DocumentsApiRequests.Arn}/invocations"
+ responses:
+ default:
+ statusCode: "200"
+ responseParameters:
+ method.response.header.Access-Control-Allow-Methods: "'*'"
+ method.response.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key'"
+ method.response.header.Access-Control-Allow-Origin: "'*'"
+ passthroughBehavior: "when_no_templates"
+ httpMethod: "POST"
+ type: "aws_proxy"
+ payloadFormatVersion: "1.0"
+ onlyOfficeLambdaApi200:
+ uri:
+ Fn::Sub: "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${DocumentsApiRequests.Arn}/invocations"
+ responses:
+ default:
+ statusCode: "200"
+ responseParameters:
+ method.response.header.Access-Control-Allow-Methods: "'*'"
+ method.response.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key'"
+ method.response.header.Access-Control-Allow-Origin: "'*'"
+ passthroughBehavior: "when_no_templates"
+ httpMethod: "POST"
+ type: "aws_proxy"
+ payloadFormatVersion: "1.0"
+ esignatureLambdaApi200:
+ uri:
+ Fn::Sub: "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${DocumentsApiRequests.Arn}/invocations"
+ responses:
+ default:
+ statusCode: "200"
+ responseParameters:
+ method.response.header.Access-Control-Allow-Methods: "'*'"
+ method.response.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key'"
+ method.response.header.Access-Control-Allow-Origin: "'*'"
+ passthroughBehavior: "when_no_templates"
+ httpMethod: "POST"
+ type: "aws_proxy"
+ payloadFormatVersion: "1.0"
+ lambdaApi201:
+ uri:
+ Fn::Sub: "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${DocumentsApiRequests.Arn}/invocations"
+ responses:
+ default:
+ statusCode: "201"
+ responseParameters:
+ method.response.header.Access-Control-Allow-Headers: '''Content-Type,X-Amz-Date,Authorization,X-Api-Key'''
+ method.response.header.Access-Control-Allow-Methods: '''*'''
+ method.response.header.Access-Control-Allow-Origin: '''*'''
+ passthroughBehavior: WHEN_NO_TEMPLATES
+ httpMethod: POST
+ type: aws_proxy
+ payloadFormatVersion: "1.0"
+ x-amazon-apigateway-gateway-responses:
+ UNAUTHORIZED:
+ statusCode: 401
+ responseParameters:
+ gatewayresponse.header.Access-Control-Allow-Methods: "'*'"
+ gatewayresponse.header.Access-Control-Allow-Origin: "'*'"
+ gatewayresponse.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key'"
+ x-amazon-apigateway-cors:
+ allowOrigins:
+ - "*"
+ maxAge: 3600
+ allowMethods:
+ - "*"
+ allowHeaders:
+ - "*"
+ tags:
+ - name: Application
+ x-amazon-apigateway-tag-value: "FormKiQ"
+ - name: AppEnvironment
+ x-amazon-apigateway-tag-value:
+ Fn::Sub: "${AppEnvironment}"
diff --git a/lambda-api/src/main/resources/cloudformation/api-iam.yaml b/lambda-api/src/main/resources/cloudformation/api-iam.yaml
index d7d9d8935..e18ccfca4 100644
--- a/lambda-api/src/main/resources/cloudformation/api-iam.yaml
+++ b/lambda-api/src/main/resources/cloudformation/api-iam.yaml
@@ -1,5 +1,6 @@
+#@ load("@ytt:data", "data")
+#@ load("@ytt:assert", "assert")
#@ load("@ytt:overlay", "overlay")
-
#@overlay/match by=overlay.all
---
Resources:
@@ -18,21 +19,21 @@ Resources:
url: https://formkiq.com
email: support@formkiq.com
x-logo:
- url: https://docs.formkiq.com/docs/1.9.0/_images/formkiq-logo.png
+ url: https://docs.formkiq.com/docs/latest/_images/formkiq-logo.png
backgroundColor: "#FFFFFF"
altText: "FormKiQ Logo"
license:
name: Apache 2.0
url: https://www.apache.org/licenses/LICENSE-2.0.html
description: "FormKiQ IAM API"
- version: "1.10.0"
+ version: #@ data.values.version or assert.fail("missing version")
paths:
/version:
get:
operationId: GetVersion
description: Return the version of FormKiQ
tags:
- - Miscellaneous
+ - System Management
responses:
'200':
description: "200 OK"
@@ -51,7 +52,7 @@ Resources:
schema:
"$ref": "#/components/schemas/GetVersionRequest"
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
/sites:
@@ -59,7 +60,7 @@ Resources:
operationId: GetSites
description: Returns the list of sites that the user has access to
tags:
- - Miscellaneous
+ - System Management
responses:
'200':
description: "200 OK"
@@ -78,7 +79,165 @@ Resources:
schema:
"$ref": "#/components/schemas/GetSitesRequest"
security:
- - sigv4: []
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
+ /configuration:
+ get:
+ operationId: GetConfigs
+ description: Returns the list of sites that the user has access to
+ tags:
+ - System Management
+ parameters:
+ - $ref: '#/components/parameters/siteIdParam'
+ responses:
+ '200':
+ description: "200 OK"
+ headers:
+ Access-Control-Allow-Origin:
+ schema:
+ type: "string"
+ Access-Control-Allow-Methods:
+ schema:
+ type: "string"
+ Access-Control-Allow-Headers:
+ schema:
+ type: "string"
+ content:
+ application/json:
+ schema:
+ "$ref": "#/components/schemas/GetConfigurationResponse"
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
+ patch:
+ operationId: UpdateConfig
+ description: Update the System Management configuration
+ tags:
+ - System Management
+ parameters:
+ - $ref: '#/components/parameters/siteIdParam'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/SetConfigRequest'
+ examples:
+ Config:
+ value:
+ chatGptApiKey: "ABC"
+ maxContentLengthBytes: "1000000"
+ maxDocuments: "1000"
+ maxWebhooks: "10"
+ responses:
+ '200':
+ description: 200 OK
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/SetConfigResponse'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
+ /configuration/apiKeys:
+ get:
+ operationId: GetApiKeys
+ description: Returns the list of ApiKeys
+ tags:
+ - System Management
+ parameters:
+ - $ref: '#/components/parameters/siteIdParam'
+ responses:
+ '200':
+ description: "200 OK"
+ headers:
+ Access-Control-Allow-Origin:
+ schema:
+ type: "string"
+ Access-Control-Allow-Methods:
+ schema:
+ type: "string"
+ Access-Control-Allow-Headers:
+ schema:
+ type: "string"
+ content:
+ application/json:
+ schema:
+ "$ref": "#/components/schemas/GetApiKeysResponse"
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
+ post:
+ operationId: Ã…ddApiKey
+ description: Adds a new API Key
+ tags:
+ - System Management
+ parameters:
+ - $ref: '#/components/parameters/siteIdParam'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AddApiKeyRequest'
+ examples:
+ AddApiKey:
+ value:
+ name: My API Key
+ responses:
+ '200':
+ description: 200 OK
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AddApiKeyResponse'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
+ /configuration/apiKeys/{apiKey}:
+ delete:
+ operationId: DeleteApiKey
+ description: Adds a new API Key
+ tags:
+ - System Management
+ parameters:
+ - $ref: '#/components/parameters/apiKeyParam'
+ - $ref: '#/components/parameters/siteIdParam'
+ responses:
+ '200':
+ description: 200 OK
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DeleteApiKeyResponse'
+ security:
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
/tagSchemas:
@@ -118,7 +277,7 @@ Resources:
schema:
"$ref": "#/components/schemas/GetTagSchemasRequest"
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
post:
@@ -162,7 +321,7 @@ Resources:
schema:
$ref: '#/components/schemas/ErrorsResponse'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi201"
/tagSchemas/{tagSchemaId}:
@@ -189,7 +348,7 @@ Resources:
schema:
$ref: '#/components/schemas/GetTagSchemaRequest'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
delete:
@@ -204,7 +363,7 @@ Resources:
'200':
$ref: '#/components/responses/200Cors'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
/documents:
@@ -254,7 +413,7 @@ Resources:
schema:
"$ref": "#/components/schemas/GetDocumentsResponse"
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
post:
@@ -324,7 +483,7 @@ Resources:
schema:
$ref: '#/components/schemas/AddDocumentResponse'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi201"
/documents/{documentId}:
@@ -351,7 +510,7 @@ Resources:
schema:
$ref: '#/components/schemas/GetDocumentResponse'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
patch:
@@ -398,7 +557,7 @@ Resources:
schema:
$ref: '#/components/schemas/AddDocumentResponse'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
delete:
@@ -413,7 +572,7 @@ Resources:
'200':
$ref: '#/components/responses/200Cors'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
/documents/{documentId}/versions:
@@ -445,7 +604,7 @@ Resources:
schema:
$ref: '#/components/schemas/GetDocumentVersionsResponse'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
put:
@@ -483,7 +642,7 @@ Resources:
schema:
$ref: '#/components/schemas/ValidationErrorsResponse'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
/documents/{documentId}/versions/{versionKey}:
@@ -499,7 +658,7 @@ Resources:
'200':
$ref: '#/components/responses/200Cors'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
/documents/{documentId}/content:
@@ -529,7 +688,7 @@ Resources:
schema:
$ref: '#/components/schemas/GetDocumentContentResponse'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
/documents/{documentId}/tags:
@@ -567,7 +726,7 @@ Resources:
schema:
$ref: '#/components/schemas/GetDocumentTagsResponse'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
post:
@@ -600,7 +759,7 @@ Resources:
'201':
$ref: '#/components/responses/200Cors'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi201"
/documents/{documentId}/tags#:
@@ -622,7 +781,7 @@ Resources:
'201':
$ref: '#/components/responses/200Cors'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi201"
/documents/{documentId}/tags/{tagKey}:
@@ -650,7 +809,7 @@ Resources:
schema:
$ref: '#/components/schemas/GetDocumentTagResponse'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
put:
@@ -672,7 +831,7 @@ Resources:
'200':
$ref: '#/components/responses/200Cors'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
delete:
@@ -688,7 +847,7 @@ Resources:
'200':
$ref: '#/components/responses/200Cors'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
/documents/{documentId}/tags/{tagKey}/{tagValue}:
@@ -706,7 +865,7 @@ Resources:
'200':
$ref: '#/components/responses/200Cors'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
/documents/{documentId}/url:
@@ -741,7 +900,7 @@ Resources:
schema:
$ref: '#/components/schemas/GetDocumentUrlRequest'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
/documents/upload:
@@ -774,7 +933,7 @@ Resources:
schema:
$ref: '#/components/schemas/GetDocumentUrlRequest'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
post:
@@ -821,7 +980,7 @@ Resources:
schema:
$ref: '#/components/schemas/AddDocumentResponse'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi201"
/documents/{documentId}/upload:
@@ -850,7 +1009,7 @@ Resources:
schema:
$ref: '#/components/schemas/GetDocumentUrlRequest'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
/search:
@@ -918,7 +1077,7 @@ Resources:
schema:
$ref: '#/components/schemas/DocumentSearchResponse'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/searchLambdaApi200"
/searchFulltext:
@@ -951,7 +1110,7 @@ Resources:
schema:
$ref: '#/components/schemas/DocumentFulltextResponse'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/fulltextLambdaApi200"
/queryFulltext:
@@ -983,7 +1142,7 @@ Resources:
schema:
$ref: '#/components/schemas/QueryFulltextResponse'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/fulltextLambdaApi200"
/documents/{documentId}/actions:
@@ -1010,7 +1169,7 @@ Resources:
schema:
$ref: '#/components/schemas/GetDocumentActionsResponse'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
post:
@@ -1042,7 +1201,7 @@ Resources:
schema:
$ref: '#/components/schemas/AddDocumentActionsResponse'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
/documents/{documentId}/ocr:
@@ -1071,7 +1230,7 @@ Resources:
schema:
$ref: '#/components/schemas/GetDocumentOcrResponse'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/ocrLambdaApi200"
post:
@@ -1103,7 +1262,7 @@ Resources:
schema:
$ref: '#/components/schemas/AddDocumentOcrResponse'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/ocrLambdaApi200"
put:
@@ -1135,7 +1294,7 @@ Resources:
schema:
$ref: '#/components/schemas/AddDocumentOcrResponse'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/ocrLambdaApi200"
delete:
@@ -1150,7 +1309,7 @@ Resources:
'200':
$ref: '#/components/responses/200Cors'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/ocrLambdaApi200"
/documents/{documentId}/antivirus:
@@ -1183,7 +1342,7 @@ Resources:
schema:
$ref: '#/components/schemas/SetAntivirusResponse'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/antivirusLambdaApi200"
/documents/{documentId}/fulltext:
@@ -1210,7 +1369,7 @@ Resources:
schema:
$ref: '#/components/schemas/GetDocumentFulltextResponse'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/fulltextLambdaApi200"
delete:
@@ -1225,7 +1384,7 @@ Resources:
'200':
$ref: '#/components/responses/200Cors'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/fulltextLambdaApi200"
put:
@@ -1257,7 +1416,7 @@ Resources:
schema:
$ref: '#/components/schemas/SetDocumentFulltextResponse'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/fulltextLambdaApi200"
patch:
@@ -1289,7 +1448,7 @@ Resources:
schema:
$ref: '#/components/schemas/SetDocumentFulltextResponse'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/fulltextLambdaApi200"
/documents/{documentId}/fulltext/tags/{tagKey}:
@@ -1306,7 +1465,7 @@ Resources:
'200':
$ref: '#/components/responses/200Cors'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/fulltextLambdaApi200"
/documents/{documentId}/fulltext/tags/{tagKey}/{tagValue}:
@@ -1324,7 +1483,7 @@ Resources:
'200':
$ref: '#/components/responses/200Cors'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/fulltextLambdaApi200"
/documents/{documentId}/syncs:
@@ -1352,7 +1511,7 @@ Resources:
schema:
$ref: '#/components/schemas/GetDocumentSyncResponse'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
/public/documents:
@@ -1446,7 +1605,7 @@ Resources:
schema:
$ref: '#/components/schemas/DocumentId'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
/webhooks:
@@ -1475,7 +1634,7 @@ Resources:
schema:
"$ref": "#/components/schemas/GetWebhooksResponse"
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
post:
@@ -1506,7 +1665,7 @@ Resources:
schema:
$ref: '#/components/schemas/AddWebhookResponse'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi201"
/webhooks/{webhookId}:
@@ -1536,7 +1695,7 @@ Resources:
schema:
"$ref": "#/components/schemas/GetWebhookResponse"
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
delete:
@@ -1551,7 +1710,7 @@ Resources:
'200':
$ref: '#/components/responses/200Cors'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
patch:
@@ -1572,7 +1731,7 @@ Resources:
'200':
$ref: '#/components/responses/200Cors'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
/webhooks/{webhookId}/tags:
@@ -1599,7 +1758,7 @@ Resources:
schema:
$ref: '#/components/schemas/GetWebhookTagsResponse'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
post:
@@ -1628,7 +1787,7 @@ Resources:
'201':
$ref: '#/components/responses/200Cors'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi201"
/onlyoffice/{documentId}/edit:
@@ -1661,7 +1820,7 @@ Resources:
schema:
$ref: '#/components/schemas/OnlyOfficeDocumentResponse'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/onlyOfficeLambdaApi200"
/onlyoffice/new:
@@ -1693,7 +1852,7 @@ Resources:
schema:
$ref: '#/components/schemas/OnlyOfficeDocumentResponse'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/onlyOfficeLambdaApi200"
/onlyoffice/{documentId}/save:
@@ -1757,7 +1916,7 @@ Resources:
schema:
$ref: '#/components/schemas/ValidationErrorsResponse'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
/indices/{indexType}/{indexKey}:
@@ -1787,7 +1946,7 @@ Resources:
schema:
$ref: '#/components/schemas/ValidationErrorsResponse'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
/indices/search:
@@ -1837,7 +1996,7 @@ Resources:
schema:
$ref: '#/components/schemas/ValidationErrorsResponse'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
/esignature/docusign/{documentId}:
@@ -1876,7 +2035,7 @@ Resources:
schema:
$ref: '#/components/schemas/ValidationErrorsResponse'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/esignatureLambdaApi200"
/esignature/docusign/config:
@@ -1902,7 +2061,7 @@ Resources:
schema:
$ref: '#/components/schemas/EsignatureDocusignConfigResponse'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/esignatureLambdaApi200"
put:
@@ -1933,7 +2092,7 @@ Resources:
schema:
$ref: '#/components/schemas/EsignatureSetDocusignConfigResponse'
security:
- - sigv4: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/esignatureLambdaApi200"
/esignature/docusign/events:
@@ -2037,6 +2196,13 @@ Resources:
schema:
type: string
default: "10"
+ apiKeyParam:
+ name: apiKey
+ in: path
+ description: API Key
+ required: true
+ schema:
+ type: string
documentIdParam:
name: documentId
in: path
@@ -2741,6 +2907,9 @@ Resources:
type: "string"
format: "uuid"
description: "Document Identifier"
+ contentLength:
+ type: "integer"
+ description: "Document size"
createdBy:
type: "string"
description: "User who added document"
@@ -2769,6 +2938,9 @@ Resources:
createdBy:
type: "string"
description: "User who added document"
+ contentLength:
+ type: "integer"
+ description: "Document size"
tags:
type: "object"
metadata:
@@ -3156,6 +3328,7 @@ Resources:
- FULLTEXT
- ANTIVIRUS
- WEBHOOK
+ - DOCUMENTTAGGING
parameters:
$ref: "#/components/schemas/AddActionParameters"
AddActionParameters:
@@ -3173,6 +3346,15 @@ Resources:
characterMax:
type: "string"
description: "Fulltext: Maximum number of characters (-1 unlimited, Typesense defaults to 2048 characters)"
+ engine:
+ type: "string"
+ description: "DocumentTagging: Engine to use for document tagging generation"
+ enum:
+ - chatgpt
+ tags:
+ description: "DocumentTagging: List of Tags to generate tags for"
+ items:
+ type: "string"
AddDocumentOcrRequest:
type: object
example:
@@ -3217,6 +3399,89 @@ Resources:
description: "List of installed modules"
items:
type: "string"
+ SetConfigRequest:
+ type: "object"
+ properties:
+ chatGptApiKey:
+ type: "string"
+ description: "ChatGPT Api Key"
+ maxContentLengthBytes:
+ type: "string"
+ description: "Set Maximum Document Content Length in Bytes"
+ maxDocuments:
+ type: "string"
+ description: "Set Maximum number of Documents allowed"
+ maxWebhooks:
+ type: "string"
+ description: "Set Maximum number of Webhooks allowed"
+ SetConfigResponse:
+ type: object
+ properties:
+ message:
+ type: "string"
+ description: "Result message"
+ AddApiKeyRequest:
+ type: object
+ properties:
+ name:
+ type: "string"
+ description: "Name of API Key"
+ AddApiKeyResponse:
+ type: object
+ properties:
+ message:
+ type: "string"
+ description: "Result message"
+ DeleteApiKeyResponse:
+ type: object
+ properties:
+ message:
+ type: "string"
+ description: "Result message"
+ GetApiKeysResponse:
+ type: object
+ properties:
+ apiKeys:
+ $ref: "#/components/schemas/ApiKeys"
+ ApiKeys:
+ type: "array"
+ description: "List of ApiKeys"
+ items:
+ $ref: "#/components/schemas/ApiKey"
+ ApiKey:
+ type: "object"
+ properties:
+ name:
+ type: "string"
+ description: "Name of API Key"
+ apiKey:
+ type: "string"
+ description: "API Key value"
+ userId:
+ type: "string"
+ siteIds:
+ type: "array"
+ items:
+ type: "string"
+ insertedDate:
+ type: "string"
+ format: "date-time"
+ description: "Inserted Timestamp"
+ GetConfigurationResponse:
+ type: object
+ properties:
+ chatGptApiKey:
+ type: "string"
+ description: "ChatGPT API Key"
+ maxContentLengthBytes:
+ type: "string"
+ description: "Set Maximum Document Content Length in Bytes"
+ maxDocuments:
+ type: "string"
+ description: "Set Maximum number of Documents allowed"
+ maxWebhooks:
+ type: "string"
+ description: "Set Maximum number of Webhooks allowed"
GetSitesRequest:
type: object
properties:
@@ -3560,18 +3825,7 @@ Resources:
type: "string"
description: "Message response"
securitySchemes:
- AuthorizationCognito:
- type: oauth2
- flows: {}
- x-amazon-apigateway-authorizer:
- type: jwt
- jwtConfiguration:
- issuer:
- Fn::Sub: https://cognito-idp.${AWS::Region}.amazonaws.com/${CognitoUserPool}
- audience:
- - Fn::Sub: "${CognitoUserPoolClient}"
- identitySource: "$request.header.Authorization"
- sigv4:
+ ApiAuthorization:
type: "apiKey"
name: "Authorization"
in: "header"
diff --git a/lambda-api/src/main/resources/cloudformation/api-key-variables.yaml b/lambda-api/src/main/resources/cloudformation/api-key-variables.yaml
new file mode 100644
index 000000000..eed25154a
--- /dev/null
+++ b/lambda-api/src/main/resources/cloudformation/api-key-variables.yaml
@@ -0,0 +1,11 @@
+#@ load("@ytt:overlay", "overlay")
+
+#@overlay/match by=overlay.all
+---
+Resources:
+ DocumentsKeyApi:
+ Properties:
+ Body:
+ info:
+ #@overlay/replace
+ title: "FormKiQ KEY API"
\ No newline at end of file
diff --git a/lambda-api/src/main/resources/cloudformation/api.yaml b/lambda-api/src/main/resources/cloudformation/api.yaml
index cd2ca5b65..73c4bb7d1 100644
--- a/lambda-api/src/main/resources/cloudformation/api.yaml
+++ b/lambda-api/src/main/resources/cloudformation/api.yaml
@@ -1,5 +1,6 @@
+#@ load("@ytt:data", "data")
+#@ load("@ytt:assert", "assert")
#@ load("@ytt:overlay", "overlay")
-
#@overlay/match by=overlay.all
---
Resources:
@@ -18,21 +19,21 @@ Resources:
url: https://formkiq.com
email: support@formkiq.com
x-logo:
- url: https://docs.formkiq.com/docs/1.9.0/_images/formkiq-logo.png
+ url: https://docs.formkiq.com/docs/latest/_images/formkiq-logo.png
backgroundColor: "#FFFFFF"
altText: "FormKiQ Logo"
license:
name: Apache 2.0
url: https://www.apache.org/licenses/LICENSE-2.0.html
description: "FormKiQ HTTP API"
- version: "1.10.0"
+ version: #@ data.values.version or assert.fail("missing version")
paths:
/version:
get:
operationId: GetVersion
description: Return the version of FormKiQ
tags:
- - Miscellaneous
+ - System Management
responses:
'200':
description: "200 OK"
@@ -51,7 +52,7 @@ Resources:
schema:
"$ref": "#/components/schemas/GetVersionRequest"
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
/sites:
@@ -59,7 +60,7 @@ Resources:
operationId: GetSites
description: Returns the list of sites that the user has access to
tags:
- - Miscellaneous
+ - System Management
responses:
'200':
description: "200 OK"
@@ -78,7 +79,165 @@ Resources:
schema:
"$ref": "#/components/schemas/GetSitesRequest"
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
+ /configuration:
+ get:
+ operationId: GetConfigs
+ description: Returns the list of sites that the user has access to
+ tags:
+ - System Management
+ parameters:
+ - $ref: '#/components/parameters/siteIdParam'
+ responses:
+ '200':
+ description: "200 OK"
+ headers:
+ Access-Control-Allow-Origin:
+ schema:
+ type: "string"
+ Access-Control-Allow-Methods:
+ schema:
+ type: "string"
+ Access-Control-Allow-Headers:
+ schema:
+ type: "string"
+ content:
+ application/json:
+ schema:
+ "$ref": "#/components/schemas/GetConfigurationResponse"
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
+ patch:
+ operationId: UpdateConfig
+ description: Update the System Management configuration
+ tags:
+ - System Management
+ parameters:
+ - $ref: '#/components/parameters/siteIdParam'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/SetConfigRequest'
+ examples:
+ Config:
+ value:
+ chatGptApiKey: "ABC"
+ maxContentLengthBytes: "1000000"
+ maxDocuments: "1000"
+ maxWebhooks: "10"
+ responses:
+ '200':
+ description: 200 OK
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/SetConfigResponse'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
+ /configuration/apiKeys:
+ get:
+ operationId: GetApiKeys
+ description: Returns the list of ApiKeys
+ tags:
+ - System Management
+ parameters:
+ - $ref: '#/components/parameters/siteIdParam'
+ responses:
+ '200':
+ description: "200 OK"
+ headers:
+ Access-Control-Allow-Origin:
+ schema:
+ type: "string"
+ Access-Control-Allow-Methods:
+ schema:
+ type: "string"
+ Access-Control-Allow-Headers:
+ schema:
+ type: "string"
+ content:
+ application/json:
+ schema:
+ "$ref": "#/components/schemas/GetApiKeysResponse"
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
+ post:
+ operationId: Ã…ddApiKey
+ description: Adds a new API Key
+ tags:
+ - System Management
+ parameters:
+ - $ref: '#/components/parameters/siteIdParam'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AddApiKeyRequest'
+ examples:
+ AddApiKey:
+ value:
+ name: My API Key
+ responses:
+ '200':
+ description: 200 OK
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/AddApiKeyResponse'
+ security:
+ - ApiAuthorization: []
+ x-amazon-apigateway-integration:
+ $ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
+ /configuration/apiKeys/{apiKey}:
+ delete:
+ operationId: DeleteApiKey
+ description: Adds a new API Key
+ tags:
+ - System Management
+ parameters:
+ - $ref: '#/components/parameters/apiKeyParam'
+ - $ref: '#/components/parameters/siteIdParam'
+ responses:
+ '200':
+ description: 200 OK
+ headers:
+ Access-Control-Allow-Origin:
+ $ref: '#/components/headers/AccessControlAllowOrigin'
+ Access-Control-Allow-Methods:
+ $ref: '#/components/headers/AccessControlAllowMethods'
+ Access-Control-Allow-Headers:
+ $ref: '#/components/headers/AccessControlAllowHeaders'
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DeleteApiKeyResponse'
+ security:
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
/tagSchemas:
@@ -118,7 +277,7 @@ Resources:
schema:
"$ref": "#/components/schemas/GetTagSchemasRequest"
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
post:
@@ -162,7 +321,7 @@ Resources:
schema:
$ref: '#/components/schemas/ErrorsResponse'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi201"
/tagSchemas/{tagSchemaId}:
@@ -189,7 +348,7 @@ Resources:
schema:
$ref: '#/components/schemas/GetTagSchemaRequest'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
delete:
@@ -204,7 +363,7 @@ Resources:
'200':
$ref: '#/components/responses/200Cors'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
/documents:
@@ -254,7 +413,7 @@ Resources:
schema:
"$ref": "#/components/schemas/GetDocumentsResponse"
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
post:
@@ -324,7 +483,7 @@ Resources:
schema:
$ref: '#/components/schemas/AddDocumentResponse'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi201"
/documents/{documentId}:
@@ -351,7 +510,7 @@ Resources:
schema:
$ref: '#/components/schemas/GetDocumentResponse'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
patch:
@@ -398,7 +557,7 @@ Resources:
schema:
$ref: '#/components/schemas/AddDocumentResponse'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
delete:
@@ -413,7 +572,7 @@ Resources:
'200':
$ref: '#/components/responses/200Cors'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
/documents/{documentId}/versions:
@@ -445,7 +604,7 @@ Resources:
schema:
$ref: '#/components/schemas/GetDocumentVersionsResponse'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
put:
@@ -483,7 +642,7 @@ Resources:
schema:
$ref: '#/components/schemas/ValidationErrorsResponse'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
/documents/{documentId}/versions/{versionKey}:
@@ -499,7 +658,7 @@ Resources:
'200':
$ref: '#/components/responses/200Cors'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
/documents/{documentId}/content:
@@ -529,7 +688,7 @@ Resources:
schema:
$ref: '#/components/schemas/GetDocumentContentResponse'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
/documents/{documentId}/tags:
@@ -567,7 +726,7 @@ Resources:
schema:
$ref: '#/components/schemas/GetDocumentTagsResponse'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
post:
@@ -600,7 +759,7 @@ Resources:
'201':
$ref: '#/components/responses/200Cors'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi201"
/documents/{documentId}/tags#:
@@ -622,7 +781,7 @@ Resources:
'201':
$ref: '#/components/responses/200Cors'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi201"
/documents/{documentId}/tags/{tagKey}:
@@ -650,7 +809,7 @@ Resources:
schema:
$ref: '#/components/schemas/GetDocumentTagResponse'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
put:
@@ -672,7 +831,7 @@ Resources:
'200':
$ref: '#/components/responses/200Cors'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
delete:
@@ -688,7 +847,7 @@ Resources:
'200':
$ref: '#/components/responses/200Cors'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
/documents/{documentId}/tags/{tagKey}/{tagValue}:
@@ -706,7 +865,7 @@ Resources:
'200':
$ref: '#/components/responses/200Cors'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
/documents/{documentId}/url:
@@ -741,7 +900,7 @@ Resources:
schema:
$ref: '#/components/schemas/GetDocumentUrlRequest'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
/documents/upload:
@@ -774,7 +933,7 @@ Resources:
schema:
$ref: '#/components/schemas/GetDocumentUrlRequest'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
post:
@@ -821,7 +980,7 @@ Resources:
schema:
$ref: '#/components/schemas/AddDocumentResponse'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi201"
/documents/{documentId}/upload:
@@ -850,7 +1009,7 @@ Resources:
schema:
$ref: '#/components/schemas/GetDocumentUrlRequest'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
/search:
@@ -918,7 +1077,7 @@ Resources:
schema:
$ref: '#/components/schemas/DocumentSearchResponse'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/searchLambdaApi200"
/searchFulltext:
@@ -951,7 +1110,7 @@ Resources:
schema:
$ref: '#/components/schemas/DocumentFulltextResponse'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/fulltextLambdaApi200"
/queryFulltext:
@@ -983,7 +1142,7 @@ Resources:
schema:
$ref: '#/components/schemas/QueryFulltextResponse'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/fulltextLambdaApi200"
/documents/{documentId}/actions:
@@ -1010,7 +1169,7 @@ Resources:
schema:
$ref: '#/components/schemas/GetDocumentActionsResponse'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
post:
@@ -1042,7 +1201,7 @@ Resources:
schema:
$ref: '#/components/schemas/AddDocumentActionsResponse'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
/documents/{documentId}/ocr:
@@ -1071,7 +1230,7 @@ Resources:
schema:
$ref: '#/components/schemas/GetDocumentOcrResponse'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/ocrLambdaApi200"
post:
@@ -1103,7 +1262,7 @@ Resources:
schema:
$ref: '#/components/schemas/AddDocumentOcrResponse'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/ocrLambdaApi200"
put:
@@ -1135,7 +1294,7 @@ Resources:
schema:
$ref: '#/components/schemas/AddDocumentOcrResponse'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/ocrLambdaApi200"
delete:
@@ -1150,7 +1309,7 @@ Resources:
'200':
$ref: '#/components/responses/200Cors'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/ocrLambdaApi200"
/documents/{documentId}/antivirus:
@@ -1183,7 +1342,7 @@ Resources:
schema:
$ref: '#/components/schemas/SetAntivirusResponse'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/antivirusLambdaApi200"
/documents/{documentId}/fulltext:
@@ -1210,7 +1369,7 @@ Resources:
schema:
$ref: '#/components/schemas/GetDocumentFulltextResponse'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/fulltextLambdaApi200"
delete:
@@ -1225,7 +1384,7 @@ Resources:
'200':
$ref: '#/components/responses/200Cors'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/fulltextLambdaApi200"
put:
@@ -1257,7 +1416,7 @@ Resources:
schema:
$ref: '#/components/schemas/SetDocumentFulltextResponse'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/fulltextLambdaApi200"
patch:
@@ -1289,7 +1448,7 @@ Resources:
schema:
$ref: '#/components/schemas/SetDocumentFulltextResponse'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/fulltextLambdaApi200"
/documents/{documentId}/fulltext/tags/{tagKey}:
@@ -1306,7 +1465,7 @@ Resources:
'200':
$ref: '#/components/responses/200Cors'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/fulltextLambdaApi200"
/documents/{documentId}/fulltext/tags/{tagKey}/{tagValue}:
@@ -1324,7 +1483,7 @@ Resources:
'200':
$ref: '#/components/responses/200Cors'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/fulltextLambdaApi200"
/documents/{documentId}/syncs:
@@ -1352,7 +1511,7 @@ Resources:
schema:
$ref: '#/components/schemas/GetDocumentSyncResponse'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
/public/documents:
@@ -1446,7 +1605,7 @@ Resources:
schema:
$ref: '#/components/schemas/DocumentId'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
/webhooks:
@@ -1475,7 +1634,7 @@ Resources:
schema:
"$ref": "#/components/schemas/GetWebhooksResponse"
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
post:
@@ -1506,7 +1665,7 @@ Resources:
schema:
$ref: '#/components/schemas/AddWebhookResponse'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi201"
/webhooks/{webhookId}:
@@ -1536,7 +1695,7 @@ Resources:
schema:
"$ref": "#/components/schemas/GetWebhookResponse"
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
delete:
@@ -1551,7 +1710,7 @@ Resources:
'200':
$ref: '#/components/responses/200Cors'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
patch:
@@ -1572,7 +1731,7 @@ Resources:
'200':
$ref: '#/components/responses/200Cors'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
/webhooks/{webhookId}/tags:
@@ -1599,7 +1758,7 @@ Resources:
schema:
$ref: '#/components/schemas/GetWebhookTagsResponse'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
post:
@@ -1628,7 +1787,7 @@ Resources:
'201':
$ref: '#/components/responses/200Cors'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi201"
/onlyoffice/{documentId}/edit:
@@ -1661,7 +1820,7 @@ Resources:
schema:
$ref: '#/components/schemas/OnlyOfficeDocumentResponse'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/onlyOfficeLambdaApi200"
/onlyoffice/new:
@@ -1693,7 +1852,7 @@ Resources:
schema:
$ref: '#/components/schemas/OnlyOfficeDocumentResponse'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/onlyOfficeLambdaApi200"
/onlyoffice/{documentId}/save:
@@ -1757,7 +1916,7 @@ Resources:
schema:
$ref: '#/components/schemas/ValidationErrorsResponse'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
/indices/{indexType}/{indexKey}:
@@ -1787,7 +1946,7 @@ Resources:
schema:
$ref: '#/components/schemas/ValidationErrorsResponse'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
/indices/search:
@@ -1837,7 +1996,7 @@ Resources:
schema:
$ref: '#/components/schemas/ValidationErrorsResponse'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/lambdaApi200"
/esignature/docusign/{documentId}:
@@ -1876,7 +2035,7 @@ Resources:
schema:
$ref: '#/components/schemas/ValidationErrorsResponse'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/esignatureLambdaApi200"
/esignature/docusign/config:
@@ -1902,7 +2061,7 @@ Resources:
schema:
$ref: '#/components/schemas/EsignatureDocusignConfigResponse'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/esignatureLambdaApi200"
put:
@@ -1933,7 +2092,7 @@ Resources:
schema:
$ref: '#/components/schemas/EsignatureSetDocusignConfigResponse'
security:
- - AuthorizationCognito: []
+ - ApiAuthorization: []
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/esignatureLambdaApi200"
/esignature/docusign/events:
@@ -2037,6 +2196,13 @@ Resources:
schema:
type: string
default: "10"
+ apiKeyParam:
+ name: apiKey
+ in: path
+ description: API Key
+ required: true
+ schema:
+ type: string
documentIdParam:
name: documentId
in: path
@@ -2741,6 +2907,9 @@ Resources:
type: "string"
format: "uuid"
description: "Document Identifier"
+ contentLength:
+ type: "integer"
+ description: "Document size"
createdBy:
type: "string"
description: "User who added document"
@@ -2769,6 +2938,9 @@ Resources:
createdBy:
type: "string"
description: "User who added document"
+ contentLength:
+ type: "integer"
+ description: "Document size"
tags:
type: "object"
metadata:
@@ -3156,6 +3328,7 @@ Resources:
- FULLTEXT
- ANTIVIRUS
- WEBHOOK
+ - DOCUMENTTAGGING
parameters:
$ref: "#/components/schemas/AddActionParameters"
AddActionParameters:
@@ -3173,6 +3346,15 @@ Resources:
characterMax:
type: "string"
description: "Fulltext: Maximum number of characters (-1 unlimited, Typesense defaults to 2048 characters)"
+ engine:
+ type: "string"
+ description: "DocumentTagging: Engine to use for document tagging generation"
+ enum:
+ - chatgpt
+ tags:
+ description: "DocumentTagging: List of Tags to generate tags for"
+ items:
+ type: "string"
AddDocumentOcrRequest:
type: object
example:
@@ -3217,6 +3399,89 @@ Resources:
description: "List of installed modules"
items:
type: "string"
+ SetConfigRequest:
+ type: "object"
+ properties:
+ chatGptApiKey:
+ type: "string"
+ description: "ChatGPT Api Key"
+ maxContentLengthBytes:
+ type: "string"
+ description: "Set Maximum Document Content Length in Bytes"
+ maxDocuments:
+ type: "string"
+ description: "Set Maximum number of Documents allowed"
+ maxWebhooks:
+ type: "string"
+ description: "Set Maximum number of Webhooks allowed"
+ SetConfigResponse:
+ type: object
+ properties:
+ message:
+ type: "string"
+ description: "Result message"
+ AddApiKeyRequest:
+ type: object
+ properties:
+ name:
+ type: "string"
+ description: "Name of API Key"
+ AddApiKeyResponse:
+ type: object
+ properties:
+ message:
+ type: "string"
+ description: "Result message"
+ DeleteApiKeyResponse:
+ type: object
+ properties:
+ message:
+ type: "string"
+ description: "Result message"
+ GetApiKeysResponse:
+ type: object
+ properties:
+ apiKeys:
+ $ref: "#/components/schemas/ApiKeys"
+ ApiKeys:
+ type: "array"
+ description: "List of ApiKeys"
+ items:
+ $ref: "#/components/schemas/ApiKey"
+ ApiKey:
+ type: "object"
+ properties:
+ name:
+ type: "string"
+ description: "Name of API Key"
+ apiKey:
+ type: "string"
+ description: "API Key value"
+ userId:
+ type: "string"
+ siteIds:
+ type: "array"
+ items:
+ type: "string"
+ insertedDate:
+ type: "string"
+ format: "date-time"
+ description: "Inserted Timestamp"
+ GetConfigurationResponse:
+ type: object
+ properties:
+ chatGptApiKey:
+ type: "string"
+ description: "ChatGPT API Key"
+ maxContentLengthBytes:
+ type: "string"
+ description: "Set Maximum Document Content Length in Bytes"
+ maxDocuments:
+ type: "string"
+ description: "Set Maximum number of Documents allowed"
+ maxWebhooks:
+ type: "string"
+ description: "Set Maximum number of Webhooks allowed"
GetSitesRequest:
type: object
properties:
@@ -3560,7 +3825,7 @@ Resources:
type: "string"
description: "Message response"
securitySchemes:
- AuthorizationCognito:
+ ApiAuthorization:
type: oauth2
flows: {}
x-amazon-apigateway-authorizer:
diff --git a/lambda-api/src/main/resources/cloudformation/template-apikey.yaml b/lambda-api/src/main/resources/cloudformation/template-apikey.yaml
new file mode 100644
index 000000000..7538be631
--- /dev/null
+++ b/lambda-api/src/main/resources/cloudformation/template-apikey.yaml
@@ -0,0 +1,99 @@
+#@ load("@ytt:overlay", "overlay")
+#@ load("@ytt:data", "data")
+#@ load("@ytt:assert", "assert")
+#@overlay/match by=overlay.all
+---
+Resources:
+
+ #@overlay/match missing_ok=True
+ ApiKeyAuthorizer:
+ Type: AWS::Serverless::Function
+ DependsOn:
+ - ApiKeyAuthorizerRole
+ Properties:
+ Handler: com.formkiq.module.lambda.authorizer.apikey.ApiKeyAuthorizerRequestHandler
+ Description: Lambda function that processes ApiKey Authorizer
+ Runtime: provided
+ Timeout:
+ Fn::Sub: "${LambdaTimeout}"
+ MemorySize:
+ Fn::Sub: "${LambdaMemory}"
+ CodeUri: ./formkiq-module-lambda-authorizer-apikey.zip
+ Tracing: Active
+ AutoPublishCodeSha256: #@ data.values.hash or assert.fail("missing version")
+ Environment:
+ Variables:
+ APP_ENVIRONMENT:
+ Fn::Sub: "${AppEnvironment}"
+ DEBUG: false
+ ENABLE_AWS_X_RAY: true
+ DOCUMENTS_TABLE:
+ Fn::Sub: "{{resolve:ssm:/formkiq/${AppEnvironment}/dynamodb/DocumentsTableName}}"
+ FORMKIQ_TYPE:
+ Ref: FormKiQType
+ Role:
+ Fn::GetAtt:
+ - ApiKeyAuthorizerRole
+ - Arn
+ Tags:
+ Application:
+ Fn::Sub: "FormKiQ ${FormKiQType}"
+ AppEnvironment:
+ Fn::Sub: "${AppEnvironment}"
+ StackName:
+ Fn::Sub: "${AWS::StackName}"
+
+ #@overlay/match missing_ok=True
+ ApiKeyAuthorizerInvokePermission:
+ Type: "AWS::Lambda::Permission"
+ DependsOn:
+ - ApiKeyAuthorizer
+ Properties:
+ Action: lambda:InvokeFunction
+ FunctionName:
+ Ref: ApiKeyAuthorizer
+ Principal: apigateway.amazonaws.com
+
+ #@overlay/match missing_ok=True
+ ApiKeyAuthorizerRole:
+ Type: AWS::IAM::Role
+ Properties:
+ Tags:
+ - Key: "Application"
+ Value:
+ Fn::Sub: "FormKiQ ${FormKiQType}"
+ - Key: "AppEnvironment"
+ Value:
+ Fn::Sub: "${AppEnvironment}"
+ AssumeRolePolicyDocument:
+ Version: '2012-10-17'
+ Statement:
+ - Effect: Allow
+ Principal:
+ Service:
+ - lambda.amazonaws.com
+ Action:
+ - sts:AssumeRole
+ Path: /
+ ManagedPolicyArns:
+ - arn:aws:iam::aws:policy/AWSXRayDaemonWriteAccess
+ Policies:
+ -
+ PolicyName: apikeylambdarole
+ PolicyDocument:
+ Version: '2012-10-17'
+ Statement:
+ - Effect: Allow
+ Action:
+ - logs:CreateLogGroup
+ - logs:CreateLogStream
+ - logs:PutLogEvents
+ Resource: "*"
+ - Effect: Allow
+ Action:
+ - dynamodb:BatchGetItem
+ - dynamodb:BatchWriteItem
+ - dynamodb:Get*
+ - dynamodb:Query
+ Resource:
+ - Fn::Sub: "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/{{resolve:ssm:/formkiq/${AppEnvironment}/dynamodb/DocumentsTableName}}"
\ No newline at end of file
diff --git a/lambda-api/src/main/resources/cloudformation/template-ocr.yaml b/lambda-api/src/main/resources/cloudformation/template-ocr.yaml
new file mode 100644
index 000000000..f3db16ae1
--- /dev/null
+++ b/lambda-api/src/main/resources/cloudformation/template-ocr.yaml
@@ -0,0 +1,177 @@
+#@ load("@ytt:overlay", "overlay")
+#@ load("@ytt:data", "data")
+#@ load("@ytt:assert", "assert")
+#@overlay/match by=overlay.all
+---
+Resources:
+
+ #@overlay/match missing_ok=True
+ OcrBucket:
+ Type: AWS::S3::Bucket
+ Properties:
+ BucketName:
+ Fn::Sub: "formkiq-${FormKiQType}-${AppEnvironment}-ocr-${AWS::AccountId}"
+ BucketEncryption:
+ ServerSideEncryptionConfiguration:
+ - ServerSideEncryptionByDefault:
+ SSEAlgorithm: AES256
+ LifecycleConfiguration:
+ Rules:
+ - Id: ExpiryRule
+ Prefix: tempfiles/
+ Status: Enabled
+ ExpirationInDays: 1
+ VersioningConfiguration:
+ Status: Enabled
+ PublicAccessBlockConfiguration:
+ BlockPublicAcls: true
+ IgnorePublicAcls: true
+ BlockPublicPolicy: true
+ RestrictPublicBuckets: true
+ Tags:
+ - Key: "Application"
+ Value:
+ Fn::Sub: "FormKiQ ${FormKiQType}"
+ - Key: "AppEnvironment"
+ Value:
+ Fn::Sub: "${AppEnvironment}"
+ - Key: "StackName"
+ Value:
+ Fn::Sub: "${AWS::StackName}"
+
+ #@overlay/match missing_ok=True
+ OcrBucketParameter:
+ Type: AWS::SSM::Parameter
+ Properties:
+ Description: "OCR S3 Bucket Name"
+ Name:
+ Fn::Sub: "/formkiq/${AppEnvironment}/s3/OcrBucket"
+ Type: String
+ Value:
+ Ref: OcrBucket
+ Tags:
+ Application:
+ Fn::Sub: "FormKiQ ${FormKiQType}"
+ AppEnvironment:
+ Fn::Sub: "${AppEnvironment}"
+ StackName:
+ Fn::Sub: "${AWS::StackName}"
+
+ #@overlay/match missing_ok=True
+ OcrQueue:
+ Type: AWS::SQS::Queue
+ Properties:
+ VisibilityTimeout: 700
+ ReceiveMessageWaitTimeSeconds: 20
+ Tags:
+ - Key: "Application"
+ Value:
+ Fn::Sub: "FormKiQ ${FormKiQType}"
+ - Key: "AppEnvironment"
+ Value:
+ Fn::Sub: "${AppEnvironment}"
+ - Key: "StackName"
+ Value:
+ Fn::Sub: "${AWS::StackName}"
+
+ #@overlay/match missing_ok=True
+ OcrQueuePolicy:
+ Type: AWS::SQS::QueuePolicy
+ DependsOn: OcrQueue
+ Properties:
+ PolicyDocument:
+ Version: '2012-10-17'
+ Id: QueuePolicy
+ Statement:
+ - Sid: LambdaSendMessagesToQueue
+ Effect: Allow
+ Principal:
+ Service:
+ - lambda.amazonaws.com
+ Action: sqs:SendMessage
+ Resource:
+ Fn::GetAtt:
+ - OcrQueue
+ - Arn
+ Queues:
+ - Ref: OcrQueue
+
+ #@overlay/match missing_ok=True
+ OcrQueueParameter:
+ Type: AWS::SSM::Parameter
+ Properties:
+ Description: "Ocr SQS Queue"
+ Name:
+ Fn::Sub: "/formkiq/${AppEnvironment}/sqs/OcrQueue"
+ Type: String
+ Value:
+ Ref: OcrQueue
+ Tags:
+ Application:
+ Fn::Sub: "FormKiQ ${FormKiQType}"
+ AppEnvironment:
+ Fn::Sub: "${AppEnvironment}"
+ StackName:
+ Fn::Sub: "${AWS::StackName}"
+
+ #@overlay/match missing_ok=True
+ OcrQueueUrlParameter:
+ Type: AWS::SSM::Parameter
+ Properties:
+ Description: "Ocr SQS Queue Url"
+ Name:
+ Fn::Sub: "/formkiq/${AppEnvironment}/sqs/OcrQueueUrl"
+ Type: String
+ Value:
+ Fn::GetAtt:
+ - OcrQueue
+ - QueueUrl
+ Tags:
+ Application:
+ Fn::Sub: "FormKiQ ${FormKiQType}"
+ AppEnvironment:
+ Fn::Sub: "${AppEnvironment}"
+ StackName:
+ Fn::Sub: "${AWS::StackName}"
+
+ #@overlay/match missing_ok=True
+ OcrQueueArnParameter:
+ Type: AWS::SSM::Parameter
+ Properties:
+ Description: "Ocr SQS Queue Url"
+ Name:
+ Fn::Sub: "/formkiq/${AppEnvironment}/sqs/OcrQueueArn"
+ Type: String
+ Value:
+ Fn::GetAtt:
+ - OcrQueue
+ - Arn
+ Tags:
+ Application:
+ Fn::Sub: "FormKiQ ${FormKiQType}"
+ AppEnvironment:
+ Fn::Sub: "${AppEnvironment}"
+ StackName:
+ Fn::Sub: "${AWS::StackName}"
+
+Outputs:
+ #@overlay/match missing_ok=True
+ OcrBucket:
+ Value:
+ Ref: OcrBucket
+ #@overlay/match missing_ok=True
+ OcrQueue:
+ Value:
+ Ref: OcrQueue
+ #@overlay/match missing_ok=True
+ OcrQueueUrl:
+ Value:
+ Fn::GetAtt:
+ - OcrQueue
+ - QueueUrl
+ #@overlay/match missing_ok=True
+ OcrQueueArn:
+ Value:
+ Fn::GetAtt:
+ - OcrQueue
+ - Arn
\ No newline at end of file
diff --git a/lambda-api/src/main/resources/cloudformation/template-snippet.yaml b/lambda-api/src/main/resources/cloudformation/template.yaml
similarity index 83%
rename from lambda-api/src/main/resources/cloudformation/template-snippet.yaml
rename to lambda-api/src/main/resources/cloudformation/template.yaml
index d76af5e01..b4549e581 100644
--- a/lambda-api/src/main/resources/cloudformation/template-snippet.yaml
+++ b/lambda-api/src/main/resources/cloudformation/template.yaml
@@ -141,7 +141,7 @@ Resources:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName:
- Fn::Sub: "/${AWS::StackName}/${DocumentsApiRequests}"
+ Fn::Sub: "/aws/vendedlogs/${AWS::StackName}/${DocumentsApiRequests}"
RetentionInDays: 90
Tags:
- Key: "Application"
@@ -164,12 +164,14 @@ Resources:
MemorySize:
Fn::Sub: "${LambdaMemory}"
CodeUri: ./lambda-api-graalvm.zip
+ Tracing: Active
AutoPublishCodeSha256: #@ data.values.hash or assert.fail("missing version")
Environment:
Variables:
APP_ENVIRONMENT:
Fn::Sub: "${AppEnvironment}"
DEBUG: false
+ ENABLE_AWS_X_RAY: true
DOCUMENTS_TABLE:
Fn::Sub: "{{resolve:ssm:/formkiq/${AppEnvironment}/dynamodb/DocumentsTableName}}"
CACHE_TABLE:
@@ -195,6 +197,12 @@ Resources:
Ref: TypesenseApiEndpoint
TYPESENSE_API_KEY:
Ref: TypesenseApiKey
+ OCR_S3_BUCKET:
+ Ref: OcrBucket
+ OCR_SQS_QUEUE_URL:
+ Fn::GetAtt:
+ - OcrQueue
+ - QueueUrl
MODULE_typesense:
Fn::If:
- CreateTypesenseResources
@@ -216,29 +224,39 @@ Resources:
Type: "AWS::Lambda::Permission"
DependsOn:
- DocumentsIamApi
+ - DocumentsKeyApi
- DocumentsApiRequests
Properties:
Action: lambda:InvokeFunction
FunctionName:
Ref: DocumentsApiRequests
Principal: apigateway.amazonaws.com
-
+
DocumentsStageAccessLogs:
Type: AWS::Logs::LogGroup
Properties:
RetentionInDays: 90
LogGroupName:
- Fn::Sub: "/${AWS::StackName}/APIDocumentsHttpAccessLogs"
+ Fn::Sub: "/aws/vendedlogs/${AWS::StackName}/APIDocumentsHttpAccessLogs"
IamDocumentsStageAccessLogs:
Type: AWS::Logs::LogGroup
Properties:
RetentionInDays: 90
LogGroupName:
- Fn::Sub: "/${AWS::StackName}/APIDocumentsIamAccessLogs"
+ Fn::Sub: "/aws/vendedlogs/${AWS::StackName}/APIDocumentsIamAccessLogs"
+
+ KeyDocumentsStageAccessLogs:
+ Type: AWS::Logs::LogGroup
+ Properties:
+ RetentionInDays: 90
+ LogGroupName:
+ Fn::Sub: "/aws/vendedlogs/${AWS::StackName}/APIDocumentsKeyAccessLogs"
DocumentsStage:
Type: AWS::ApiGatewayV2::Stage
+ DependsOn:
+ - DocumentsHttpApi
Properties:
ApiId:
Ref: DocumentsHttpApi
@@ -267,6 +285,8 @@ Resources:
IamDocumentsStage:
Type: AWS::ApiGatewayV2::Stage
+ DependsOn:
+ - DocumentsIamApi
Properties:
ApiId:
Ref: DocumentsIamApi
@@ -293,6 +313,36 @@ Resources:
Stage:
Ref: IamDocumentsStage
+ KeyDocumentsStage:
+ Type: AWS::ApiGatewayV2::Stage
+ DependsOn:
+ - DocumentsKeyApi
+ Properties:
+ ApiId:
+ Ref: DocumentsKeyApi
+ AutoDeploy: true
+ Description:
+ Fn::Sub: "Documents API Key ${AppEnvironment}"
+ StageName: "$default"
+ AccessLogSettings:
+ DestinationArn:
+ Fn::GetAtt:
+ - KeyDocumentsStageAccessLogs
+ - Arn
+ Format: '{ "requestId":"$context.requestId", "ip": "$context.identity.sourceIp", "requestTime":"$context.requestTime", "httpMethod":"$context.httpMethod","routeKey":"$context.routeKey", "status":"$context.status","protocol":"$context.protocol", "integrationStatus": $context.integrationStatus, "integrationLatency": $context.integrationLatency, "responseLength":"$context.responseLength" }'
+
+ KeyDocumentsStageMapping:
+ Condition: HasCertificateStackName
+ Type: 'AWS::ApiGatewayV2::ApiMapping'
+ Properties:
+ DomainName:
+ Fn::ImportValue:
+ Fn::Sub: '${CertificateStackName}-KeyApiDomain'
+ ApiId:
+ Ref: DocumentsKeyApi
+ Stage:
+ Ref: KeyDocumentsStage
+
DocumentsHttpApiIdParameter:
Type: AWS::SSM::Parameter
Properties:
@@ -382,6 +432,7 @@ Resources:
- arn:aws:iam::aws:policy/AmazonAPIGatewayInvokeFullAccess
- arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole
- arn:aws:iam::aws:policy/AmazonElasticFileSystemClientReadWriteAccess
+ - arn:aws:iam::aws:policy/AWSXRayDaemonWriteAccess
Policies:
-
PolicyName: apigatewaylambdarole
@@ -470,6 +521,26 @@ Resources:
- sns:Publish
Resource:
- Fn::Sub: "{{resolve:ssm:/formkiq/${AppEnvironment}/sns/DocumentEventArn}}"
+ - Effect: Allow
+ Action:
+ - s3:GetObject
+ - s3:DeleteObject
+ - s3:ListBucket
+ - s3:PutObject
+ Resource:
+ Fn::Join:
+ - ''
+ - - 'arn:aws:s3:::'
+ - Ref: OcrBucket
+ - "/*"
+ - Effect: Allow
+ Action:
+ - s3:ListBucket
+ Resource:
+ Fn::Join:
+ - ''
+ - - 'arn:aws:s3:::'
+ - Ref: OcrBucket
DocumentsIamApiUrlParameter:
Type: AWS::SSM::Parameter
@@ -511,6 +582,47 @@ Resources:
Fn::Sub: "${AppEnvironment}"
StackName:
Fn::Sub: "${AWS::StackName}"
+
+ DocumentsKeyApiUrlParameter:
+ Type: AWS::SSM::Parameter
+ Properties:
+ Description: "The URL for the API endpoint that uses API Key authorization"
+ Name:
+ Fn::Sub: "/formkiq/${AppEnvironment}/api/DocumentsKeyUrl"
+ Type: String
+ Value:
+ Fn::If:
+ - HasCertificateStackName
+ - Fn::Join:
+ - ''
+ - - 'https://'
+ - Fn::ImportValue:
+ Fn::Sub: '${CertificateStackName}-IamApiDomain'
+ - Fn::Sub: "https://${DocumentsKeyApi}.execute-api.${AWS::Region}.amazonaws.com"
+ Tags:
+ Application:
+ Fn::Sub: "FormKiQ ${FormKiQType}"
+ AppEnvironment:
+ Fn::Sub: "${AppEnvironment}"
+ StackName:
+ Fn::Sub: "${AWS::StackName}"
+
+ DocumentsKeyApiIdParameter:
+ Type: AWS::SSM::Parameter
+ Properties:
+ Description: "The ID for the API endpoint that uses API Key authorization"
+ Name:
+ Fn::Sub: "/formkiq/${AppEnvironment}/api/DocumentsKeyId"
+ Type: String
+ Value:
+ Ref: DocumentsKeyApi
+ Tags:
+ Application:
+ Fn::Sub: "FormKiQ ${FormKiQType}"
+ AppEnvironment:
+ Fn::Sub: "${AppEnvironment}"
+ StackName:
+ Fn::Sub: "${AWS::StackName}"
DocumentsApiRequestsParameter:
Type: AWS::SSM::Parameter
@@ -698,7 +810,18 @@ Outputs:
- - 'https://'
- Fn::ImportValue:
Fn::Sub: '${CertificateStackName}-IamApiDomain'
- - Fn::Sub: "https://${DocumentsIamApi}.execute-api.${AWS::Region}.amazonaws.com"
+ - Fn::Sub: "https://${DocumentsIamApi}.execute-api.${AWS::Region}.amazonaws.com"
+ DocumentsKeyApiUrl:
+ Description: "The endpoint url for the Key API"
+ Value:
+ Fn::If:
+ - HasCertificateStackName
+ - Fn::Join:
+ - ''
+ - - 'https://'
+ - Fn::ImportValue:
+ Fn::Sub: '${CertificateStackName}-KeyApiDomain'
+ - Fn::Sub: "https://${DocumentsKeyApi}.execute-api.${AWS::Region}.amazonaws.com"
DocumentsHttpApiUrl:
Description: "The endpoint url for the Http API"
Value:
diff --git a/lambda-api/src/test/java/com/formkiq/stacks/api/AbstractRequestHandler.java b/lambda-api/src/test/java/com/formkiq/stacks/api/AbstractRequestHandler.java
index 952954ba0..a338b7727 100644
--- a/lambda-api/src/test/java/com/formkiq/stacks/api/AbstractRequestHandler.java
+++ b/lambda-api/src/test/java/com/formkiq/stacks/api/AbstractRequestHandler.java
@@ -30,9 +30,10 @@
import static com.formkiq.testutils.aws.TestServices.AWS_REGION;
import static com.formkiq.testutils.aws.TestServices.BUCKET_NAME;
import static com.formkiq.testutils.aws.TestServices.FORMKIQ_APP_ENVIRONMENT;
+import static com.formkiq.testutils.aws.TestServices.OCR_BUCKET_NAME;
import static com.formkiq.testutils.aws.TestServices.STAGE_BUCKET_NAME;
import static com.formkiq.testutils.aws.TypeSenseExtension.API_KEY;
-import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockserver.integration.ClientAndServer.startClientAndServer;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@@ -214,6 +215,7 @@ public void before() throws Exception {
this.map.put("CACHE_TABLE", CACHE_TABLE);
this.map.put("DOCUMENTS_S3_BUCKET", BUCKET_NAME);
this.map.put("STAGE_DOCUMENTS_S3_BUCKET", STAGE_BUCKET_NAME);
+ this.map.put("OCR_S3_BUCKET", OCR_BUCKET_NAME);
this.map.put("SNS_DOCUMENT_EVENT", snsDocumentEvent);
this.map.put("AWS_REGION", AWS_REGION.toString());
this.map.put("DEBUG", "true");
diff --git a/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentSyncRequestHandlerTest.java b/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentSyncRequestHandlerTest.java
index 1b150d9b1..21320ebd6 100644
--- a/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentSyncRequestHandlerTest.java
+++ b/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentSyncRequestHandlerTest.java
@@ -24,8 +24,8 @@
package com.formkiq.stacks.api;
import static com.formkiq.stacks.dynamodb.DocumentSyncService.MESSAGE_ADDED_METADATA;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
diff --git a/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentsActionsRequestTest.java b/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentsActionsRequestTest.java
index 7458061ac..701253389 100644
--- a/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentsActionsRequestTest.java
+++ b/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentsActionsRequestTest.java
@@ -23,8 +23,8 @@
*/
package com.formkiq.stacks.api;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
diff --git a/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentsFulltextRequestTest.java b/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentsFulltextRequestTest.java
index e18e0f6a6..11e3d5ee9 100644
--- a/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentsFulltextRequestTest.java
+++ b/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentsFulltextRequestTest.java
@@ -23,7 +23,7 @@
*/
package com.formkiq.stacks.api;
-import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.Arrays;
import java.util.Map;
import java.util.UUID;
diff --git a/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentsOcrRequestTest.java b/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentsOcrRequestTest.java
index 0d22bbd62..0da3715ac 100644
--- a/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentsOcrRequestTest.java
+++ b/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentsOcrRequestTest.java
@@ -23,7 +23,7 @@
*/
package com.formkiq.stacks.api;
-import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.Arrays;
import java.util.Map;
import java.util.UUID;
@@ -40,7 +40,7 @@
public class ApiDocumentsOcrRequestTest extends AbstractRequestHandler {
/**
- * DELETE /documents/{documentId}/ocr request.
+ * DELETE /documents/{documentId}/ocr request. TODO Save OCR, the verify deleted.
*
* @throws Exception an error has occurred
*/
@@ -62,7 +62,7 @@ public void testHandleDeleteDocumentOcr01() throws Exception {
final int mapsize = 3;
assertEquals(mapsize, m.size());
- assertEquals("402.0", String.valueOf(m.get("statusCode")));
+ assertEquals("200.0", String.valueOf(m.get("statusCode")));
assertEquals(getHeaders(), "\"headers\":" + GsonUtil.getInstance().toJson(m.get("headers")));
}
}
@@ -89,7 +89,7 @@ public void testHandleGetDocumentOcr01() throws Exception {
final int mapsize = 3;
assertEquals(mapsize, m.size());
- assertEquals("402.0", String.valueOf(m.get("statusCode")));
+ assertEquals("404.0", String.valueOf(m.get("statusCode")));
assertEquals(getHeaders(), "\"headers\":" + GsonUtil.getInstance().toJson(m.get("headers")));
}
}
@@ -117,7 +117,7 @@ public void testHandlePatchDocumentOcr01() throws Exception {
final int mapsize = 3;
assertEquals(mapsize, m.size());
- assertEquals("402.0", String.valueOf(m.get("statusCode")));
+ assertEquals("404.0", String.valueOf(m.get("statusCode")));
assertEquals(getHeaders(), "\"headers\":" + GsonUtil.getInstance().toJson(m.get("headers")));
}
}
@@ -144,7 +144,7 @@ public void testHandlePostDocumentOcr01() throws Exception {
final int mapsize = 3;
assertEquals(mapsize, m.size());
- assertEquals("402.0", String.valueOf(m.get("statusCode")));
+ assertEquals("404.0", String.valueOf(m.get("statusCode")));
assertEquals(getHeaders(), "\"headers\":" + GsonUtil.getInstance().toJson(m.get("headers")));
}
}
diff --git a/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentsOnlyOfficeRequestTest.java b/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentsOnlyOfficeRequestTest.java
index b669f50c0..d9e1f0dae 100644
--- a/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentsOnlyOfficeRequestTest.java
+++ b/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentsOnlyOfficeRequestTest.java
@@ -23,7 +23,7 @@
*/
package com.formkiq.stacks.api;
-import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.Arrays;
import java.util.Map;
import java.util.UUID;
diff --git a/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentsPatchRequestTest.java b/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentsPatchRequestTest.java
index b140c22d3..db44df59c 100644
--- a/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentsPatchRequestTest.java
+++ b/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentsPatchRequestTest.java
@@ -26,10 +26,10 @@
import static com.formkiq.aws.dynamodb.SiteIdKeyGenerator.createDatabaseKey;
import static com.formkiq.stacks.api.handler.DocumentIdRequestHandler.FORMKIQ_DOC_EXT;
import static com.formkiq.testutils.aws.TestServices.STAGE_BUCKET_NAME;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
+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.assertTrue;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
diff --git a/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentsPublicDocumentsRequestTest.java b/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentsPublicDocumentsRequestTest.java
index 9c174859d..6021b7e0f 100644
--- a/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentsPublicDocumentsRequestTest.java
+++ b/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentsPublicDocumentsRequestTest.java
@@ -23,9 +23,9 @@
*/
package com.formkiq.stacks.api;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
+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 java.util.HashMap;
import java.util.List;
import java.util.Map;
diff --git a/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentsRequestTest.java b/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentsRequestTest.java
index 929362324..d066255ee 100644
--- a/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentsRequestTest.java
+++ b/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentsRequestTest.java
@@ -26,11 +26,11 @@
import static com.formkiq.aws.dynamodb.SiteIdKeyGenerator.DEFAULT_SITE_ID;
import static com.formkiq.testutils.aws.TestServices.BUCKET_NAME;
import static com.formkiq.testutils.aws.TestServices.STAGE_BUCKET_NAME;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@@ -59,13 +59,13 @@
import com.formkiq.aws.dynamodb.model.DynamicDocumentItem;
import com.formkiq.aws.dynamodb.model.SearchMetaCriteria;
import com.formkiq.aws.dynamodb.model.SearchQuery;
+import com.formkiq.aws.dynamodb.objects.DateUtil;
import com.formkiq.aws.services.lambda.ApiGatewayRequestEvent;
import com.formkiq.aws.services.lambda.ApiResponseError;
import com.formkiq.lambda.apigateway.util.GsonUtil;
import com.formkiq.module.lambdaservices.AwsServiceCache;
import com.formkiq.plugins.tagschema.DocumentTagSchemaPlugin;
import com.formkiq.plugins.tagschema.DocumentTagSchemaPluginExtension;
-import com.formkiq.stacks.dynamodb.DateUtil;
import com.formkiq.stacks.dynamodb.DocumentItemDynamoDb;
import com.formkiq.stacks.dynamodb.DocumentSearchService;
import com.formkiq.stacks.dynamodb.DocumentService;
diff --git a/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentsSearchFulltextRequestTest.java b/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentsSearchFulltextRequestTest.java
index ee8e0689d..a50d775b6 100644
--- a/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentsSearchFulltextRequestTest.java
+++ b/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentsSearchFulltextRequestTest.java
@@ -23,7 +23,7 @@
*/
package com.formkiq.stacks.api;
-import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.Arrays;
import java.util.Map;
import java.util.UUID;
diff --git a/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentsSearchRequestTest.java b/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentsSearchRequestTest.java
index 5a4e0c005..7141e4fed 100644
--- a/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentsSearchRequestTest.java
+++ b/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentsSearchRequestTest.java
@@ -23,10 +23,10 @@
*/
package com.formkiq.stacks.api;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
+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.assertTrue;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
diff --git a/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentsTagsRequestTest.java b/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentsTagsRequestTest.java
index f9d6e959e..b5e526692 100644
--- a/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentsTagsRequestTest.java
+++ b/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentsTagsRequestTest.java
@@ -25,10 +25,10 @@
import static com.formkiq.stacks.dynamodb.DocumentService.MAX_RESULTS;
import static com.formkiq.testutils.aws.TestServices.getSqsWebsocketQueueUrl;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
+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.assertTrue;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.Arrays;
diff --git a/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentsUploadRequestTest.java b/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentsUploadRequestTest.java
index daaa79e93..7c7f0cbc8 100644
--- a/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentsUploadRequestTest.java
+++ b/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentsUploadRequestTest.java
@@ -23,11 +23,11 @@
*/
package com.formkiq.stacks.api;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -44,7 +44,6 @@
import com.formkiq.aws.dynamodb.model.DocumentTag;
import com.formkiq.aws.services.lambda.ApiGatewayRequestEvent;
import com.formkiq.aws.services.lambda.ApiGatewayRequestEventBuilder;
-import com.formkiq.aws.services.lambda.services.ConfigService;
import com.formkiq.lambda.apigateway.util.GsonUtil;
import com.formkiq.module.actions.Action;
import com.formkiq.module.actions.ActionStatus;
@@ -55,6 +54,7 @@
import com.formkiq.plugins.tagschema.DocumentTagSchemaPluginExtension;
import com.formkiq.stacks.client.models.AddLargeDocument;
import com.formkiq.stacks.client.models.DocumentActionType;
+import com.formkiq.stacks.dynamodb.ConfigService;
import com.formkiq.stacks.dynamodb.DocumentItemDynamoDb;
import com.formkiq.testutils.aws.DynamoDbExtension;
import com.formkiq.testutils.aws.LocalStackExtension;
diff --git a/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentsVersionsRequestTest.java b/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentsVersionsRequestTest.java
index 6d62eafae..268af6e7c 100644
--- a/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentsVersionsRequestTest.java
+++ b/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentsVersionsRequestTest.java
@@ -25,7 +25,7 @@
import static com.formkiq.aws.dynamodb.SiteIdKeyGenerator.createDatabaseKey;
import static com.formkiq.testutils.aws.TestServices.BUCKET_NAME;
-import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Map;
diff --git a/lambda-api/src/test/java/com/formkiq/stacks/api/ApiPrivateWebhooksRequestTest.java b/lambda-api/src/test/java/com/formkiq/stacks/api/ApiPrivateWebhooksRequestTest.java
index 2fe83abbf..f07157eab 100644
--- a/lambda-api/src/test/java/com/formkiq/stacks/api/ApiPrivateWebhooksRequestTest.java
+++ b/lambda-api/src/test/java/com/formkiq/stacks/api/ApiPrivateWebhooksRequestTest.java
@@ -25,8 +25,8 @@
import static com.formkiq.aws.dynamodb.SiteIdKeyGenerator.createDatabaseKey;
import static com.formkiq.testutils.aws.TestServices.STAGE_BUCKET_NAME;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
import java.util.Arrays;
import java.util.Map;
import java.util.UUID;
diff --git a/lambda-api/src/test/java/com/formkiq/stacks/api/ApiPublicWebhooksRequestTest.java b/lambda-api/src/test/java/com/formkiq/stacks/api/ApiPublicWebhooksRequestTest.java
index 6b58a94c2..9762da3a6 100644
--- a/lambda-api/src/test/java/com/formkiq/stacks/api/ApiPublicWebhooksRequestTest.java
+++ b/lambda-api/src/test/java/com/formkiq/stacks/api/ApiPublicWebhooksRequestTest.java
@@ -24,11 +24,11 @@
package com.formkiq.stacks.api;
import static com.formkiq.aws.dynamodb.SiteIdKeyGenerator.createDatabaseKey;
-import static com.formkiq.aws.services.lambda.services.ConfigService.DOCUMENT_TIME_TO_LIVE;
+import static com.formkiq.stacks.dynamodb.ConfigService.DOCUMENT_TIME_TO_LIVE;
import static com.formkiq.testutils.aws.TestServices.STAGE_BUCKET_NAME;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
import java.io.IOException;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
@@ -44,8 +44,8 @@
import com.formkiq.aws.s3.S3ObjectMetadata;
import com.formkiq.aws.services.lambda.ApiGatewayRequestEvent;
import com.formkiq.aws.services.lambda.services.CacheService;
-import com.formkiq.aws.services.lambda.services.ConfigService;
import com.formkiq.lambda.apigateway.util.GsonUtil;
+import com.formkiq.stacks.dynamodb.ConfigService;
import com.formkiq.testutils.aws.DynamoDbExtension;
import com.formkiq.testutils.aws.LocalStackExtension;
diff --git a/lambda-api/src/test/java/com/formkiq/stacks/api/ApiRequestHandlerTest.java b/lambda-api/src/test/java/com/formkiq/stacks/api/ApiRequestHandlerTest.java
index c12d652f9..56d4cf356 100644
--- a/lambda-api/src/test/java/com/formkiq/stacks/api/ApiRequestHandlerTest.java
+++ b/lambda-api/src/test/java/com/formkiq/stacks/api/ApiRequestHandlerTest.java
@@ -24,10 +24,10 @@
package com.formkiq.stacks.api;
import static com.formkiq.aws.dynamodb.SiteIdKeyGenerator.DEFAULT_SITE_ID;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
+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.assertTrue;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
@@ -210,7 +210,7 @@ public void testHandleGetRequest05() throws Exception {
assertEquals(documentId, resp.get("documentId"));
assertEquals(userId, resp.get("userId"));
- assertNotNull(documentId, resp.get("insertedDate"));
+ assertNotNull(resp.get("insertedDate"));
assertEquals(DEFAULT_SITE_ID, resp.get("siteId"));
assertNull(resp.get("next"));
assertNull(resp.get("previous"));
@@ -264,7 +264,7 @@ public void testHandleGetRequest06() throws Exception {
assertEquals(1, children.size());
assertEquals(documentId1, children.get(0).get("documentId"));
- assertNotNull(userId, children.get(0).get("userId"));
+ assertEquals(userId, children.get(0).get("userId"));
assertNotNull(children.get(0).get("belongsToDocumentId"));
assertNotNull(children.get(0).get("insertedDate"));
assertNull(children.get(0).get("siteId"));
diff --git a/lambda-api/src/test/java/com/formkiq/stacks/api/ApiTagSchemasRequestTest.java b/lambda-api/src/test/java/com/formkiq/stacks/api/ApiTagSchemasRequestTest.java
index b37a36d0b..e5a678734 100644
--- a/lambda-api/src/test/java/com/formkiq/stacks/api/ApiTagSchemasRequestTest.java
+++ b/lambda-api/src/test/java/com/formkiq/stacks/api/ApiTagSchemasRequestTest.java
@@ -23,7 +23,7 @@
*/
package com.formkiq.stacks.api;
-import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.Arrays;
import java.util.Map;
import java.util.UUID;
diff --git a/lambda-api/src/test/java/com/formkiq/stacks/api/ApiWebhookIdRequestTest.java b/lambda-api/src/test/java/com/formkiq/stacks/api/ApiWebhookIdRequestTest.java
index 06cfcc67b..ab3f908f8 100644
--- a/lambda-api/src/test/java/com/formkiq/stacks/api/ApiWebhookIdRequestTest.java
+++ b/lambda-api/src/test/java/com/formkiq/stacks/api/ApiWebhookIdRequestTest.java
@@ -24,9 +24,9 @@
package com.formkiq.stacks.api;
import static com.formkiq.testutils.aws.TestServices.FORMKIQ_APP_ENVIRONMENT;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
diff --git a/lambda-api/src/test/java/com/formkiq/stacks/api/ApiWebhooksRequestTest.java b/lambda-api/src/test/java/com/formkiq/stacks/api/ApiWebhooksRequestTest.java
index 32fe3b938..bb40f54cc 100644
--- a/lambda-api/src/test/java/com/formkiq/stacks/api/ApiWebhooksRequestTest.java
+++ b/lambda-api/src/test/java/com/formkiq/stacks/api/ApiWebhooksRequestTest.java
@@ -23,14 +23,14 @@
*/
package com.formkiq.stacks.api;
-import static com.formkiq.aws.services.lambda.services.ConfigService.MAX_WEBHOOKS;
-import static com.formkiq.aws.services.lambda.services.ConfigService.WEBHOOK_TIME_TO_LIVE;
+import static com.formkiq.stacks.dynamodb.ConfigService.MAX_WEBHOOKS;
+import static com.formkiq.stacks.dynamodb.ConfigService.WEBHOOK_TIME_TO_LIVE;
import static com.formkiq.testutils.aws.TestServices.FORMKIQ_APP_ENVIRONMENT;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import java.time.Instant;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
@@ -46,8 +46,8 @@
import com.formkiq.aws.dynamodb.PaginationResults;
import com.formkiq.aws.dynamodb.model.DocumentTag;
import com.formkiq.aws.services.lambda.ApiGatewayRequestEvent;
-import com.formkiq.aws.services.lambda.services.ConfigService;
import com.formkiq.lambda.apigateway.util.GsonUtil;
+import com.formkiq.stacks.dynamodb.ConfigService;
import com.formkiq.stacks.dynamodb.WebhooksService;
import com.formkiq.testutils.aws.DynamoDbExtension;
import com.formkiq.testutils.aws.LocalStackExtension;
diff --git a/lambda-api/src/test/java/com/formkiq/stacks/api/ApiWebhooksTagsRequestTest.java b/lambda-api/src/test/java/com/formkiq/stacks/api/ApiWebhooksTagsRequestTest.java
index df3d14888..46575249b 100644
--- a/lambda-api/src/test/java/com/formkiq/stacks/api/ApiWebhooksTagsRequestTest.java
+++ b/lambda-api/src/test/java/com/formkiq/stacks/api/ApiWebhooksTagsRequestTest.java
@@ -23,8 +23,8 @@
*/
package com.formkiq.stacks.api;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
import java.util.List;
import java.util.Map;
import org.junit.jupiter.api.Test;
diff --git a/lambda-api/src/test/java/com/formkiq/stacks/api/ConfigurationApiKeysRequestTest.java b/lambda-api/src/test/java/com/formkiq/stacks/api/ConfigurationApiKeysRequestTest.java
new file mode 100644
index 000000000..9065fffd9
--- /dev/null
+++ b/lambda-api/src/test/java/com/formkiq/stacks/api/ConfigurationApiKeysRequestTest.java
@@ -0,0 +1,248 @@
+/**
+ * MIT License
+ *
+ * Copyright (c) 2018 - 2020 FormKiQ
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package com.formkiq.stacks.api;
+
+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.assertTrue;
+import java.util.List;
+import java.util.Map;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import com.formkiq.aws.dynamodb.DynamicObject;
+import com.formkiq.aws.services.lambda.ApiGatewayRequestEvent;
+import com.formkiq.aws.services.lambda.ApiGatewayRequestEventBuilder;
+import com.formkiq.lambda.apigateway.util.GsonUtil;
+import com.formkiq.testutils.aws.DynamoDbExtension;
+import com.formkiq.testutils.aws.LocalStackExtension;
+
+/** Unit Tests for request /configuration/apiKeys. */
+@ExtendWith(LocalStackExtension.class)
+@ExtendWith(DynamoDbExtension.class)
+public class ConfigurationApiKeysRequestTest extends AbstractRequestHandler {
+
+ /**
+ * DELETE /configuration/apiKeys request.
+ *
+ * @param siteId {@link String}
+ * @param group {@link String}
+ * @param apiKey {@link String}
+ * @return {@link ApiGatewayRequestEvent}
+ */
+ private ApiGatewayRequestEvent deleteRequest(final String siteId, final String group,
+ final String apiKey) {
+ ApiGatewayRequestEvent event = new ApiGatewayRequestEventBuilder().method("delete")
+ .resource("/configuration/apiKeys").path("/configuration/apiKeys").group(group)
+ .user("joesmith").queryParameters(siteId != null ? Map.of("siteId", siteId) : null)
+ .queryParameters(Map.of("apiKey", apiKey)).build();
+ return event;
+ }
+
+ /**
+ * Get /configuration/apiKeys request.
+ *
+ * @param siteId {@link String}
+ * @param group {@link String}
+ * @return {@link ApiGatewayRequestEvent}
+ */
+ private ApiGatewayRequestEvent getRequest(final String siteId, final String group) {
+ ApiGatewayRequestEvent event = new ApiGatewayRequestEventBuilder().method("get")
+ .resource("/configuration/apiKeys").path("/configuration/apiKeys").group(group)
+ .user("joesmith").queryParameters(siteId != null ? Map.of("siteId", siteId) : null).build();
+ return event;
+ }
+
+ /**
+ * POST /configuration/apiKeys request.
+ *
+ * @param siteId {@link String}
+ * @param group {@link String}
+ * @param body {@link String}
+ * @return {@link ApiGatewayRequestEvent}
+ */
+ private ApiGatewayRequestEvent postRequest(final String siteId, final String group,
+ final String body) {
+ ApiGatewayRequestEvent event =
+ new ApiGatewayRequestEventBuilder().method("post").resource("/configuration/apiKeys")
+ .path("/configuration/apiKeys").group(group).user("joesmith")
+ .queryParameters(siteId != null ? Map.of("siteId", siteId) : null).body(body).build();
+ return event;
+ }
+
+ /**
+ * Delete /configuration/apiKeys default as User.
+ *
+ * @throws Exception an error has occurred
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testHandleDeleteApiKeys01() throws Exception {
+ // given
+ String siteId = null;
+ String group = "default";
+
+ ApiGatewayRequestEvent event = deleteRequest(siteId, group, "ABC");
+
+ // when
+ String response = handleRequest(event);
+
+ // then
+ Map m = GsonUtil.getInstance().fromJson(response, Map.class);
+
+ final int mapsize = 3;
+ assertEquals(mapsize, m.size());
+ assertEquals("401.0", String.valueOf(m.get("statusCode")));
+ assertEquals(getHeaders(), "\"headers\":" + GsonUtil.getInstance().toJson(m.get("headers")));
+ assertEquals("{\"message\":\"user is unauthorized\"}", String.valueOf(m.get("body")));
+ }
+
+ /**
+ * POST /configuration/apiKeys default as User.
+ *
+ * @throws Exception an error has occurred
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testHandlePostApiKeys01() throws Exception {
+ // given
+ String siteId = null;
+ String group = "default";
+
+ String body = GsonUtil.getInstance().toJson(Map.of("name", "test key"));
+ ApiGatewayRequestEvent event = postRequest(siteId, group, body);
+
+ // when
+ String response = handleRequest(event);
+
+ // then
+ Map m = GsonUtil.getInstance().fromJson(response, Map.class);
+
+ final int mapsize = 3;
+ assertEquals(mapsize, m.size());
+ assertEquals("401.0", String.valueOf(m.get("statusCode")));
+ assertEquals(getHeaders(), "\"headers\":" + GsonUtil.getInstance().toJson(m.get("headers")));
+ assertEquals("{\"message\":\"user is unauthorized\"}", String.valueOf(m.get("body")));
+ }
+
+ /**
+ * Get/POST/DELETE /configuration/apiKeys default as Admin.
+ *
+ * @throws Exception an error has occurred
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testHandleGetApiKeys01() throws Exception {
+ // given
+ String siteId = null;
+ String group = "Admins";
+
+ String body = GsonUtil.getInstance().toJson(Map.of("name", "test key"));
+ ApiGatewayRequestEvent eventPost = postRequest(siteId, group, body);
+
+ // when
+ String responsePost = handleRequest(eventPost);
+
+ // then
+ Map mpost = GsonUtil.getInstance().fromJson(responsePost, Map.class);
+ verifyResponse(mpost);
+
+ DynamicObject resp = new DynamicObject(fromJson(mpost.get("body"), Map.class));
+ assertEquals(2, resp.size());
+ assertEquals("test key", resp.getString("name"));
+ assertNotNull(resp.getString("apiKey"));
+
+ // given
+ ApiGatewayRequestEvent eventGet = getRequest(siteId, group);
+
+ // when
+ String responseGet = handleRequest(eventGet);
+
+ // then
+ Map mget = GsonUtil.getInstance().fromJson(responseGet, Map.class);
+ verifyResponse(mget);
+
+ resp = new DynamicObject(fromJson(mget.get("body"), Map.class));
+ List list = resp.getList("apiKeys");
+ assertEquals(1, list.size());
+ String apiKey = list.get(0).get("apiKey").toString();
+ assertTrue(apiKey.contains("**************"));
+ assertEquals("test key", list.get(0).getString("name"));
+ assertNotNull(list.get(0).get("insertedDate"));
+ assertNull(list.get(0).get("PK"));
+ assertNull(list.get(0).get("SK"));
+
+ // given
+ ApiGatewayRequestEvent eventDelete = deleteRequest(siteId, group, apiKey);
+
+ // when
+ String responseDelete = handleRequest(eventDelete);
+
+ // then
+ Map mdelete = GsonUtil.getInstance().fromJson(responseDelete, Map.class);
+ verifyResponse(mdelete);
+
+ responseGet = handleRequest(eventGet);
+ mget = GsonUtil.getInstance().fromJson(responseGet, Map.class);
+ verifyResponse(mget);
+
+ resp = new DynamicObject(fromJson(mget.get("body"), Map.class));
+ list = resp.getList("apiKeys");
+ assertEquals(0, list.size());
+ }
+
+ /**
+ * Get /configuration/apiKeys default as User.
+ *
+ * @throws Exception an error has occurred
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testHandleGetApiKeys02() throws Exception {
+ // given
+ String siteId = null;
+ String group = "default";
+
+ ApiGatewayRequestEvent event = getRequest(siteId, group);
+
+ // when
+ String response = handleRequest(event);
+
+ // then
+ Map m = GsonUtil.getInstance().fromJson(response, Map.class);
+
+ final int mapsize = 3;
+ assertEquals(mapsize, m.size());
+ assertEquals("401.0", String.valueOf(m.get("statusCode")));
+ assertEquals(getHeaders(), "\"headers\":" + GsonUtil.getInstance().toJson(m.get("headers")));
+ assertEquals("{\"message\":\"user is unauthorized\"}", String.valueOf(m.get("body")));
+ }
+
+ private void verifyResponse(final Map m) {
+ final int mapsize = 3;
+ assertEquals(mapsize, m.size());
+ assertEquals("200.0", String.valueOf(m.get("statusCode")));
+ assertEquals(getHeaders(), "\"headers\":" + GsonUtil.getInstance().toJson(m.get("headers")));
+ }
+}
diff --git a/lambda-api/src/test/java/com/formkiq/stacks/api/ConfigurationRequestTest.java b/lambda-api/src/test/java/com/formkiq/stacks/api/ConfigurationRequestTest.java
new file mode 100644
index 000000000..cbf003790
--- /dev/null
+++ b/lambda-api/src/test/java/com/formkiq/stacks/api/ConfigurationRequestTest.java
@@ -0,0 +1,283 @@
+/**
+ * MIT License
+ *
+ * Copyright (c) 2018 - 2020 FormKiQ
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package com.formkiq.stacks.api;
+
+import static com.formkiq.stacks.dynamodb.ConfigService.CHATGPT_API_KEY;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import java.util.Map;
+import java.util.UUID;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import com.formkiq.aws.dynamodb.DynamicObject;
+import com.formkiq.aws.services.lambda.ApiGatewayRequestEvent;
+import com.formkiq.aws.services.lambda.ApiGatewayRequestEventBuilder;
+import com.formkiq.lambda.apigateway.util.GsonUtil;
+import com.formkiq.stacks.dynamodb.ConfigService;
+import com.formkiq.testutils.aws.DynamoDbExtension;
+import com.formkiq.testutils.aws.LocalStackExtension;
+
+/** Unit Tests for request /configuration. */
+@ExtendWith(LocalStackExtension.class)
+@ExtendWith(DynamoDbExtension.class)
+public class ConfigurationRequestTest extends AbstractRequestHandler {
+
+ /**
+ * Get /configuration request.
+ *
+ * @param siteId {@link String}
+ * @param group {@link String}
+ * @return {@link ApiGatewayRequestEvent}
+ */
+ private ApiGatewayRequestEvent getRequest(final String siteId, final String group) {
+ ApiGatewayRequestEvent event = new ApiGatewayRequestEventBuilder().method("get")
+ .resource("/configuration").path("/configuration").group(group).user("joesmith")
+ .queryParameters(siteId != null ? Map.of("siteId", siteId) : null).build();
+ return event;
+ }
+
+ /**
+ * Patch /configuration request.
+ *
+ * @param siteId {@link String}
+ * @param group {@link String}
+ * @param body {@link String}
+ * @return {@link ApiGatewayRequestEvent}
+ */
+ private ApiGatewayRequestEvent patchRequest(final String siteId, final String group,
+ final String body) {
+ ApiGatewayRequestEvent event = new ApiGatewayRequestEventBuilder().method("patch")
+ .resource("/configuration").path("/configuration").group(group).user("joesmith")
+ .queryParameters(siteId != null ? Map.of("siteId", siteId) : null).body(body).build();
+ return event;
+ }
+
+
+ /**
+ * Get /config default as Admin.
+ *
+ * @throws Exception an error has occurred
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testHandleGetSites01() throws Exception {
+ // given
+ String siteId = null;
+ String group = "Admins";
+
+ ConfigService config = getAwsServices().getExtension(ConfigService.class);
+ config.save(siteId, new DynamicObject(Map.of("chatGptApiKey", "somevalue")));
+
+ String body = GsonUtil.getInstance().toJson(Map.of("chatGptApiKey", "anothervalue"));
+ ApiGatewayRequestEvent eventPatch = patchRequest(siteId, group, body);
+
+ ApiGatewayRequestEvent eventGet = getRequest(siteId, group);
+
+ // when
+ String responsePatch = handleRequest(eventPatch);
+ String responseGet = handleRequest(eventGet);
+
+ // then
+ Map mpatch = GsonUtil.getInstance().fromJson(responsePatch, Map.class);
+ verifyResponse(mpatch);
+
+ Map mget = GsonUtil.getInstance().fromJson(responseGet, Map.class);
+ verifyResponse(mget);
+
+ final int expected = 4;
+ DynamicObject resp = new DynamicObject(fromJson(mget.get("body"), Map.class));
+ assertEquals(expected, resp.size());
+ assertEquals("anothervalue", resp.getString("chatGptApiKey"));
+ assertEquals("", resp.getString("maxContentLengthBytes"));
+ assertEquals("", resp.getString("maxDocuments"));
+ assertEquals("", resp.getString("maxWebhooks"));
+ }
+
+ /**
+ * Get /config default as User.
+ *
+ * @throws Exception an error has occurred
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testHandleGetSites02() throws Exception {
+ // given
+ String siteId = null;
+ String group = "default";
+
+ ApiGatewayRequestEvent event = getRequest(siteId, group);
+
+ // when
+ String response = handleRequest(event);
+
+ // then
+ Map m = GsonUtil.getInstance().fromJson(response, Map.class);
+
+ final int mapsize = 3;
+ assertEquals(mapsize, m.size());
+ assertEquals("401.0", String.valueOf(m.get("statusCode")));
+ assertEquals(getHeaders(), "\"headers\":" + GsonUtil.getInstance().toJson(m.get("headers")));
+ assertEquals("{\"message\":\"user is unauthorized\"}", String.valueOf(m.get("body")));
+ }
+
+ /**
+ * Get /config for siteId, Config in default.
+ *
+ * @throws Exception an error has occurred
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testHandleGetSites03() throws Exception {
+ // given
+ String siteId = UUID.randomUUID().toString();
+ String group = "Admins";
+
+ ConfigService config = getAwsServices().getExtension(ConfigService.class);
+ config.save(null, new DynamicObject(Map.of(CHATGPT_API_KEY, "somevalue")));
+
+ ApiGatewayRequestEvent event = getRequest(siteId, group);
+
+ // when
+ String response = handleRequest(event);
+
+ // then
+ Map m = GsonUtil.getInstance().fromJson(response, Map.class);
+
+ verifyResponse(m);
+
+ final int expected = 4;
+ DynamicObject resp = new DynamicObject(fromJson(m.get("body"), Map.class));
+ assertEquals(expected, resp.size());
+ assertEquals("somevalue", resp.getString("chatGptApiKey"));
+ assertEquals("", resp.getString("maxContentLengthBytes"));
+ assertEquals("", resp.getString("maxDocuments"));
+ assertEquals("", resp.getString("maxWebhooks"));
+ }
+
+ /**
+ * Get /config for siteId, Config in siteId.
+ *
+ * @throws Exception an error has occurred
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testHandleGetSites04() throws Exception {
+ // given
+ String siteId = UUID.randomUUID().toString();
+ String group = "Admins";
+
+ ConfigService config = getAwsServices().getExtension(ConfigService.class);
+ config.save(null, new DynamicObject(Map.of(CHATGPT_API_KEY, "somevalue")));
+ config.save(siteId, new DynamicObject(Map.of(CHATGPT_API_KEY, "anothervalue")));
+
+ ApiGatewayRequestEvent event = getRequest(siteId, group);
+
+ // when
+ String response = handleRequest(event);
+
+ // then
+ Map m = GsonUtil.getInstance().fromJson(response, Map.class);
+
+ verifyResponse(m);
+
+ final int expected = 4;
+ DynamicObject resp = new DynamicObject(fromJson(m.get("body"), Map.class));
+ assertEquals(expected, resp.size());
+ assertEquals("anothervalue", resp.getString("chatGptApiKey"));
+ assertEquals("", resp.getString("maxContentLengthBytes"));
+ assertEquals("", resp.getString("maxDocuments"));
+ assertEquals("", resp.getString("maxWebhooks"));
+ }
+
+ /**
+ * PUT /config default as Admin.
+ *
+ * @throws Exception an error has occurred
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testHandlePutSites01() throws Exception {
+ // given
+ String siteId = null;
+ String group = "Admins";
+
+ String body = GsonUtil.getInstance().toJson(Map.of("chatGptApiKey", "anotherkey",
+ "maxContentLengthBytes", "1000000", "maxDocuments", "1000", "maxWebhooks", "5"));
+ ApiGatewayRequestEvent eventPatch = patchRequest(siteId, group, body);
+
+ ApiGatewayRequestEvent eventGet = getRequest(siteId, group);
+
+ // when
+ String responsePatch = handleRequest(eventPatch);
+ String responseGet = handleRequest(eventGet);
+
+ // then
+ Map mpatch = GsonUtil.getInstance().fromJson(responsePatch, Map.class);
+ verifyResponse(mpatch);
+
+ Map mget = GsonUtil.getInstance().fromJson(responseGet, Map.class);
+ verifyResponse(mget);
+
+ final int expected = 4;
+ DynamicObject resp = new DynamicObject(fromJson(mget.get("body"), Map.class));
+ assertEquals(expected, resp.size());
+ assertEquals("anotherkey", resp.getString("chatGptApiKey"));
+ assertEquals("1000000", resp.getString("maxContentLengthBytes"));
+ assertEquals("1000", resp.getString("maxDocuments"));
+ assertEquals("5", resp.getString("maxWebhooks"));
+ }
+
+ /**
+ * PUT /config default as user.
+ *
+ * @throws Exception an error has occurred
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testHandlePutSites02() throws Exception {
+ // given
+ String siteId = null;
+ String group = "default";
+
+ String body =
+ GsonUtil.getInstance().toJson(Map.of("key", "anotherkey", "value", "anothervalue"));
+ ApiGatewayRequestEvent eventPatch = patchRequest(siteId, group, body);
+
+ // when
+ String responsePatch = handleRequest(eventPatch);
+
+ // then
+ final int mapsize = 3;
+ Map m = GsonUtil.getInstance().fromJson(responsePatch, Map.class);
+ assertEquals(mapsize, m.size());
+ assertEquals("401.0", String.valueOf(m.get("statusCode")));
+ assertEquals(getHeaders(), "\"headers\":" + GsonUtil.getInstance().toJson(m.get("headers")));
+ }
+
+ private void verifyResponse(final Map m) {
+ final int mapsize = 3;
+ assertEquals(mapsize, m.size());
+ assertEquals("200.0", String.valueOf(m.get("statusCode")));
+ assertEquals(getHeaders(), "\"headers\":" + GsonUtil.getInstance().toJson(m.get("headers")));
+ }
+}
diff --git a/lambda-api/src/test/java/com/formkiq/stacks/api/DocumentIdContentGetRequestHandlerTest.java b/lambda-api/src/test/java/com/formkiq/stacks/api/DocumentIdContentGetRequestHandlerTest.java
index 337fba24f..1c44d7726 100644
--- a/lambda-api/src/test/java/com/formkiq/stacks/api/DocumentIdContentGetRequestHandlerTest.java
+++ b/lambda-api/src/test/java/com/formkiq/stacks/api/DocumentIdContentGetRequestHandlerTest.java
@@ -26,8 +26,8 @@
import static com.formkiq.aws.dynamodb.SiteIdKeyGenerator.createS3Key;
import static com.formkiq.testutils.aws.TestServices.AWS_REGION;
import static com.formkiq.testutils.aws.TestServices.BUCKET_NAME;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
diff --git a/lambda-api/src/test/java/com/formkiq/stacks/api/DocumentIdUrlGetRequestHandlerTest.java b/lambda-api/src/test/java/com/formkiq/stacks/api/DocumentIdUrlGetRequestHandlerTest.java
index fd394d250..bde761c41 100644
--- a/lambda-api/src/test/java/com/formkiq/stacks/api/DocumentIdUrlGetRequestHandlerTest.java
+++ b/lambda-api/src/test/java/com/formkiq/stacks/api/DocumentIdUrlGetRequestHandlerTest.java
@@ -24,9 +24,9 @@
package com.formkiq.stacks.api;
import static com.formkiq.testutils.aws.TestServices.AWS_REGION;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
diff --git a/lambda-api/src/test/java/com/formkiq/stacks/api/IndicesFolderMoveRequestTest.java b/lambda-api/src/test/java/com/formkiq/stacks/api/IndicesFolderMoveRequestTest.java
index a90ba617e..23e2c1eff 100644
--- a/lambda-api/src/test/java/com/formkiq/stacks/api/IndicesFolderMoveRequestTest.java
+++ b/lambda-api/src/test/java/com/formkiq/stacks/api/IndicesFolderMoveRequestTest.java
@@ -23,7 +23,7 @@
*/
package com.formkiq.stacks.api;
-import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.Arrays;
import java.util.Date;
import java.util.Map;
diff --git a/lambda-api/src/test/java/com/formkiq/stacks/api/IndicesSearchRequestTest.java b/lambda-api/src/test/java/com/formkiq/stacks/api/IndicesSearchRequestTest.java
index 889f0bc98..5e0ea83c9 100644
--- a/lambda-api/src/test/java/com/formkiq/stacks/api/IndicesSearchRequestTest.java
+++ b/lambda-api/src/test/java/com/formkiq/stacks/api/IndicesSearchRequestTest.java
@@ -24,7 +24,7 @@
package com.formkiq.stacks.api;
import static com.formkiq.testutils.aws.DynamoDbExtension.DOCUMENTS_TABLE;
-import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
diff --git a/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentsSitesRequestTest.java b/lambda-api/src/test/java/com/formkiq/stacks/api/SitesRequestTest.java
similarity index 86%
rename from lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentsSitesRequestTest.java
rename to lambda-api/src/test/java/com/formkiq/stacks/api/SitesRequestTest.java
index c42186ffd..8435649d9 100644
--- a/lambda-api/src/test/java/com/formkiq/stacks/api/ApiDocumentsSitesRequestTest.java
+++ b/lambda-api/src/test/java/com/formkiq/stacks/api/SitesRequestTest.java
@@ -24,13 +24,13 @@
package com.formkiq.stacks.api;
import static com.formkiq.aws.dynamodb.SiteIdKeyGenerator.DEFAULT_SITE_ID;
-import static com.formkiq.aws.services.lambda.services.ConfigService.MAX_DOCUMENTS;
-import static com.formkiq.aws.services.lambda.services.ConfigService.MAX_WEBHOOKS;
+import static com.formkiq.stacks.dynamodb.ConfigService.MAX_DOCUMENTS;
+import static com.formkiq.stacks.dynamodb.ConfigService.MAX_WEBHOOKS;
import static com.formkiq.testutils.aws.TestServices.FORMKIQ_APP_ENVIRONMENT;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
+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.assertTrue;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
@@ -38,19 +38,34 @@
import org.junit.jupiter.api.extension.ExtendWith;
import com.formkiq.aws.dynamodb.DynamicObject;
import com.formkiq.aws.services.lambda.ApiGatewayRequestEvent;
-import com.formkiq.aws.services.lambda.services.ConfigService;
+import com.formkiq.aws.services.lambda.ApiGatewayRequestEventBuilder;
import com.formkiq.lambda.apigateway.util.GsonUtil;
+import com.formkiq.stacks.dynamodb.ConfigService;
import com.formkiq.testutils.aws.DynamoDbExtension;
import com.formkiq.testutils.aws.LocalStackExtension;
/** Unit Tests for request /sites. */
@ExtendWith(LocalStackExtension.class)
@ExtendWith(DynamoDbExtension.class)
-public class ApiDocumentsSitesRequestTest extends AbstractRequestHandler {
+public class SitesRequestTest extends AbstractRequestHandler {
/** Email Pattern. */
private static final String EMAIL = "[abcdefghijklmnopqrstuvwxyz0123456789]{8}";
+ /**
+ * Get /esignature/docusign/config request.
+ *
+ * @param siteId {@link String}
+ * @param group {@link String}
+ * @return {@link ApiGatewayRequestEvent}
+ */
+ private ApiGatewayRequestEvent getRequest(final String siteId, final String group) {
+ ApiGatewayRequestEvent event = new ApiGatewayRequestEventBuilder().method("get")
+ .resource("/sites").path("/sites").group(group).user("joesmith")
+ .queryParameters(siteId != null ? Map.of("siteId", siteId) : null).build();
+ return event;
+ }
+
/**
* Get /sites with SES support.
*
@@ -61,7 +76,7 @@ public class ApiDocumentsSitesRequestTest extends AbstractRequestHandler {
public void testHandleGetSites01() throws Exception {
// given
putSsmParameter("/formkiq/" + FORMKIQ_APP_ENVIRONMENT + "/maildomain", "tryformkiq.com");
- ApiGatewayRequestEvent event = toRequestEvent("/request-get-sites01.json");
+ ApiGatewayRequestEvent event = getRequest(null, "default Admins finance");
// when
String response = handleRequest(event);
@@ -120,7 +135,7 @@ public void testHandleGetSites01() throws Exception {
public void testHandleGetSites02() throws Exception {
// given
removeSsmParameter("/formkiq/" + FORMKIQ_APP_ENVIRONMENT + "/maildomain");
- ApiGatewayRequestEvent event = toRequestEvent("/request-get-sites01.json");
+ ApiGatewayRequestEvent event = getRequest(null, "default Admins finance");
// when
String response = handleRequest(event);
@@ -161,8 +176,7 @@ public void testHandleGetSites03() throws Exception {
putSsmParameter("/formkiq/" + FORMKIQ_APP_ENVIRONMENT + "/maildomain", "tryformkiq.com");
removeSsmParameter(
String.format("/formkiq/%s/siteid/%s/email", FORMKIQ_APP_ENVIRONMENT, "default"));
- ApiGatewayRequestEvent event = toRequestEvent("/request-get-sites01.json");
- setCognitoGroup(event, "default_read finance");
+ ApiGatewayRequestEvent event = getRequest(null, "default_read finance");
// when
String response = handleRequest(event);
@@ -212,8 +226,8 @@ public void testHandleGetSites03() throws Exception {
public void testHandleGetSites04() throws Exception {
// given
String siteId = "finance";
- ApiGatewayRequestEvent event = toRequestEvent("/request-get-sites01.json");
- setCognitoGroup(event, siteId);
+ ApiGatewayRequestEvent event = getRequest(siteId, siteId);
+
ConfigService configService = getAwsServices().getExtension(ConfigService.class);
configService.save(siteId, new DynamicObject(Map.of(MAX_DOCUMENTS, "5", MAX_WEBHOOKS, "10")));
diff --git a/lambda-api/src/test/java/com/formkiq/stacks/api/handler/DocumentsRestrictionsMaxContentLengthTest.java b/lambda-api/src/test/java/com/formkiq/stacks/api/handler/DocumentsRestrictionsMaxContentLengthTest.java
index f529bb248..2363c627d 100644
--- a/lambda-api/src/test/java/com/formkiq/stacks/api/handler/DocumentsRestrictionsMaxContentLengthTest.java
+++ b/lambda-api/src/test/java/com/formkiq/stacks/api/handler/DocumentsRestrictionsMaxContentLengthTest.java
@@ -24,8 +24,8 @@
package com.formkiq.stacks.api.handler;
import static com.formkiq.testutils.aws.DynamoDbExtension.DOCUMENTS_TABLE;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.Map;
@@ -36,9 +36,9 @@
import com.formkiq.aws.dynamodb.DynamicObject;
import com.formkiq.aws.dynamodb.DynamoDbConnectionBuilder;
import com.formkiq.aws.dynamodb.DynamoDbConnectionBuilderExtension;
-import com.formkiq.aws.services.lambda.services.ConfigService;
import com.formkiq.module.lambdaservices.AwsServiceCache;
import com.formkiq.stacks.api.CoreAwsServiceCache;
+import com.formkiq.stacks.dynamodb.ConfigService;
import com.formkiq.testutils.aws.DynamoDbExtension;
import com.formkiq.testutils.aws.DynamoDbTestServices;
diff --git a/lambda-api/src/test/resources/ocr/receipt.png b/lambda-api/src/test/resources/ocr/receipt.png
new file mode 100644
index 000000000..dd0ffd842
Binary files /dev/null and b/lambda-api/src/test/resources/ocr/receipt.png differ
diff --git a/lambda-api/src/test/resources/request-get-sites01.json b/lambda-api/src/test/resources/request-get-sites01.json
deleted file mode 100644
index 8137f8300..000000000
--- a/lambda-api/src/test/resources/request-get-sites01.json
+++ /dev/null
@@ -1,131 +0,0 @@
-{
- "version": "1.0",
- "resource": "/sites",
- "path": "/sites",
- "httpMethod": "GET",
- "headers": {
- "Content-Length": "0",
- "Host": "0jau435s9j.execute-api.us-east-1.amazonaws.com",
- "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:78.0) Gecko/20100101 Firefox/78.0",
- "X-Amzn-Trace-Id": "Root=1-5f069100-55e2aba102cf8a5c579dbd65",
- "X-Forwarded-For": "104.246.140.89",
- "X-Forwarded-Port": "443",
- "X-Forwarded-Proto": "https",
- "accept": "application/json, text/plain, */*",
- "accept-encoding": "gzip, deflate, br",
- "accept-language": "en-US,en;q=0.5",
- "authorization": "eyJraWQiOiJLYVBVXC81Y2Jmdk03dXkyWktzaEtyNTNYTWg2emhPS3c1RFR0bVYrRWV2Zz0iLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiI5ZDdlODM1Mi0yMTQyLTQzNjMtOWE2Ni00NWE2NWRhYWEwZGUiLCJjb2duaXRvOmdyb3VwcyI6WyJVc2VycyIsIkFkbWlucyJdLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiY29nbml0bzpwcmVmZXJyZWRfcm9sZSI6ImFybjphd3M6aWFtOjo2MjI2NTM4NjUyNzc6cm9sZVwvZm9ybWtpcS1zdGFja3MtZG9jdW1lbnQtdW5pdHRlc3QtRG8tQWRtaW5Hcm91cFJvbGUtRkQ4M1pHTUtSNktQIiwiaXNzIjoiaHR0cHM6XC9cL2NvZ25pdG8taWRwLnVzLWVhc3QtMS5hbWF6b25hd3MuY29tXC91cy1lYXN0LTFfM3ZXVTBqbkdwIiwiY29nbml0bzp1c2VybmFtZSI6Im1mcmllc2VuQGdtYWlsLmNvbSIsImNvZ25pdG86cm9sZXMiOlsiYXJuOmF3czppYW06OjYyMjY1Mzg2NTI3Nzpyb2xlXC9mb3Jta2lxLXN0YWNrcy1kb2N1bWVudC11bml0dGVzdC1Eby1BZG1pbkdyb3VwUm9sZS1GRDgzWkdNS1I2S1AiXSwiYXVkIjoibWFuMnFpaGIyMGV1bXZyNTVwcWN1dnA2biIsImV2ZW50X2lkIjoiNjY1ZjA3MTctNGZiYy00NTExLTkxMmItNmNiNmY1NjZlMWMwIiwidG9rZW5fdXNlIjoiaWQiLCJhdXRoX3RpbWUiOjE1OTQyNjU4MjYsImV4cCI6MTU5NDI2OTQyNiwiaWF0IjoxNTk0MjY1ODI2LCJlbWFpbCI6Im1mcmllc2VuQGdtYWlsLmNvbSJ9.fvG4okaL6c9dhjCbfaLNHiR9AMW5Dqfe0KIZGsuQ6ELsUZpZ2royqInHW0R8xkAw1NTsgRH4NvDPxwHB7uup3OxK15a1mg0tVZ4rG_bITURsRDa0MHWFl-9cJAbBXkYAfoYCS3eXc9eIZPyzlhXJDzGy-O_UaOArnz1PvbOdgKK_N3jSBm7UaiPhu8ug1hea1P6IFiGYfLPhqsMqhGc8RJdIqQH-oJbDGkyukxyWT-8WFS6jJRZL_L-WPG16Y1xCsuhJdblUjki-pyTJa_0k7P6Rma1h7eBaw-GDzLthdTC4eMZUof-ICNRS6x1qWSY9tA-YOuvahqc5yROUSprAEQ",
- "dnt": "1",
- "origin": "https://d2viwvgttu39g1.cloudfront.net",
- "referer": "https://d2viwvgttu39g1.cloudfront.net/documents/explore"
- },
- "multiValueHeaders": {
- "Content-Length": [
- "0"
- ],
- "Host": [
- "0jau435s9j.execute-api.us-east-1.amazonaws.com"
- ],
- "User-Agent": [
- "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:78.0) Gecko/20100101 Firefox/78.0"
- ],
- "X-Amzn-Trace-Id": [
- "Root=1-5f069100-55e2aba102cf8a5c579dbd65"
- ],
- "X-Forwarded-For": [
- "104.246.140.89"
- ],
- "X-Forwarded-Port": [
- "443"
- ],
- "X-Forwarded-Proto": [
- "https"
- ],
- "accept": [
- "application/json, text/plain, */*"
- ],
- "accept-encoding": [
- "gzip, deflate, br"
- ],
- "accept-language": [
- "en-US,en;q=0.5"
- ],
- "authorization": [
- "eyJraWQiOiJLYVBVXC81Y2Jmdk03dXkyWktzaEtyNTNYTWg2emhPS3c1RFR0bVYrRWV2Zz0iLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiI5ZDdlODM1Mi0yMTQyLTQzNjMtOWE2Ni00NWE2NWRhYWEwZGUiLCJjb2duaXRvOmdyb3VwcyI6WyJVc2VycyIsIkFkbWlucyJdLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiY29nbml0bzpwcmVmZXJyZWRfcm9sZSI6ImFybjphd3M6aWFtOjo2MjI2NTM4NjUyNzc6cm9sZVwvZm9ybWtpcS1zdGFja3MtZG9jdW1lbnQtdW5pdHRlc3QtRG8tQWRtaW5Hcm91cFJvbGUtRkQ4M1pHTUtSNktQIiwiaXNzIjoiaHR0cHM6XC9cL2NvZ25pdG8taWRwLnVzLWVhc3QtMS5hbWF6b25hd3MuY29tXC91cy1lYXN0LTFfM3ZXVTBqbkdwIiwiY29nbml0bzp1c2VybmFtZSI6Im1mcmllc2VuQGdtYWlsLmNvbSIsImNvZ25pdG86cm9sZXMiOlsiYXJuOmF3czppYW06OjYyMjY1Mzg2NTI3Nzpyb2xlXC9mb3Jta2lxLXN0YWNrcy1kb2N1bWVudC11bml0dGVzdC1Eby1BZG1pbkdyb3VwUm9sZS1GRDgzWkdNS1I2S1AiXSwiYXVkIjoibWFuMnFpaGIyMGV1bXZyNTVwcWN1dnA2biIsImV2ZW50X2lkIjoiNjY1ZjA3MTctNGZiYy00NTExLTkxMmItNmNiNmY1NjZlMWMwIiwidG9rZW5fdXNlIjoiaWQiLCJhdXRoX3RpbWUiOjE1OTQyNjU4MjYsImV4cCI6MTU5NDI2OTQyNiwiaWF0IjoxNTk0MjY1ODI2LCJlbWFpbCI6Im1mcmllc2VuQGdtYWlsLmNvbSJ9.fvG4okaL6c9dhjCbfaLNHiR9AMW5Dqfe0KIZGsuQ6ELsUZpZ2royqInHW0R8xkAw1NTsgRH4NvDPxwHB7uup3OxK15a1mg0tVZ4rG_bITURsRDa0MHWFl-9cJAbBXkYAfoYCS3eXc9eIZPyzlhXJDzGy-O_UaOArnz1PvbOdgKK_N3jSBm7UaiPhu8ug1hea1P6IFiGYfLPhqsMqhGc8RJdIqQH-oJbDGkyukxyWT-8WFS6jJRZL_L-WPG16Y1xCsuhJdblUjki-pyTJa_0k7P6Rma1h7eBaw-GDzLthdTC4eMZUof-ICNRS6x1qWSY9tA-YOuvahqc5yROUSprAEQ"
- ],
- "dnt": [
- "1"
- ],
- "origin": [
- "https://d2viwvgttu39g1.cloudfront.net"
- ],
- "referer": [
- "https://d2viwvgttu39g1.cloudfront.net/documents/explore"
- ]
- },
- "queryStringParameters": {
- "date": "2020-07-08",
- "tz": "-05:00"
- },
- "multiValueQueryStringParameters": {
- "date": [
- "2020-07-08"
- ],
- "tz": [
- "-05:00"
- ]
- },
- "requestContext": {
- "accountId": "1111111111111111",
- "apiId": "0jau435s9j",
- "authorizer": {
- "claims": {
- "aud": "man2qihb20eumvr55pqcuvp6n",
- "auth_time": "1594265826",
- "cognito:groups": "[default Admins finance]",
- "cognito:preferred_role": "arn:aws:iam::1111111111111111:role/formkiq-stacks-document-unittest-Do-AdminGroupRole-FD83ZGMKR6KP",
- "cognito:roles": "[arn:aws:iam::1111111111111111:role/formkiq-stacks-document-unittest-Do-AdminGroupRole-FD83ZGMKR6KP]",
- "cognito:username": "test@formkiq.com",
- "email": "test@formkiq.com",
- "email_verified": "true",
- "event_id": "665f0717-4fbc-4511-912b-6cb6f566e1c0",
- "exp": "1594269426",
- "iat": "1594265826",
- "iss": "https://cognito-idp.us-east-1.amazonaws.com/us-east-1_3vWU0jnGp",
- "sub": "9d7e8352-2142-4363-9a66-45a65daaa0de",
- "token_use": "id"
- },
- "scopes": null
- },
- "domainName": "0jau435s9j.execute-api.us-east-1.amazonaws.com",
- "domainPrefix": "0jau435s9j",
- "extendedRequestId": "PYuYDiIrIAMEMGA=",
- "httpMethod": "GET",
- "identity": {
- "accessKey": null,
- "accountId": null,
- "caller": null,
- "cognitoAuthenticationProvider": null,
- "cognitoAuthenticationType": null,
- "cognitoIdentityId": null,
- "cognitoIdentityPoolId": null,
- "principalOrgId": null,
- "sourceIp": "104.246.140.89",
- "user": null,
- "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:78.0) Gecko/20100101 Firefox/78.0",
- "userArn": null
- },
- "path": "/sites",
- "protocol": "HTTP/1.1",
- "requestId": "PYuYDiIrIAMEMGA=",
- "requestTime": "09/Jul/2020:03:37:36 +0000",
- "requestTimeEpoch": 1594265856216,
- "resourceId": "GET /sites",
- "resourcePath": "/sites",
- "stage": "$default"
- },
- "pathParameters": null,
- "stageVariables": null,
- "body": null,
- "isBase64Encoded": false
-}
\ No newline at end of file
diff --git a/lambda-apikey-authorizer/.checkstyle b/lambda-apikey-authorizer/.checkstyle
new file mode 100644
index 000000000..2fd0087df
--- /dev/null
+++ b/lambda-apikey-authorizer/.checkstyle
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lambda-apikey-authorizer/.classpath b/lambda-apikey-authorizer/.classpath
new file mode 100644
index 000000000..66f8050c0
--- /dev/null
+++ b/lambda-apikey-authorizer/.classpath
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lambda-apikey-authorizer/.gitignore b/lambda-apikey-authorizer/.gitignore
new file mode 100644
index 000000000..4a95481e6
--- /dev/null
+++ b/lambda-apikey-authorizer/.gitignore
@@ -0,0 +1,2 @@
+/bin/
+/build/
diff --git a/lambda-apikey-authorizer/.project b/lambda-apikey-authorizer/.project
new file mode 100644
index 000000000..a83619eec
--- /dev/null
+++ b/lambda-apikey-authorizer/.project
@@ -0,0 +1,30 @@
+
+
+ lambda-apikey-authorizer
+ Project core created by Buildship.
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+ net.sf.eclipsecs.core.CheckstyleBuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.buildship.core.gradleprojectnature
+ net.sf.eclipsecs.core.CheckstyleNature
+
+
+
diff --git a/lambda-apikey-authorizer/.settings/org.eclipse.buildship.core.prefs b/lambda-apikey-authorizer/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 000000000..e47955840
--- /dev/null
+++ b/lambda-apikey-authorizer/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,13 @@
+arguments=
+auto.sync=false
+build.scans.enabled=false
+connection.gradle.distribution=GRADLE_DISTRIBUTION(WRAPPER)
+connection.project.dir=
+eclipse.preferences.version=1
+gradle.user.home=
+java.home=
+jvm.arguments=
+offline.mode=false
+override.workspace.settings=false
+show.console.view=false
+show.executions.view=false
diff --git a/lambda-apikey-authorizer/.settings/org.eclipse.core.resources.prefs b/lambda-apikey-authorizer/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 000000000..99f26c020
--- /dev/null
+++ b/lambda-apikey-authorizer/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+encoding/=UTF-8
diff --git a/lambda-apikey-authorizer/.settings/org.eclipse.jdt.core.prefs b/lambda-apikey-authorizer/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 000000000..9ba0f3224
--- /dev/null
+++ b/lambda-apikey-authorizer/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,496 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.codeComplete.argumentPrefixes=
+org.eclipse.jdt.core.codeComplete.argumentSuffixes=
+org.eclipse.jdt.core.codeComplete.fieldPrefixes=
+org.eclipse.jdt.core.codeComplete.fieldSuffixes=
+org.eclipse.jdt.core.codeComplete.localPrefixes=
+org.eclipse.jdt.core.codeComplete.localSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFieldSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes=
+org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled
+org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
+org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull
+org.eclipse.jdt.core.compiler.annotation.nonnull.secondary=
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary=
+org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
+org.eclipse.jdt.core.compiler.annotation.nullable.secondary=
+org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=11
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.doc.comment.support=enabled
+org.eclipse.jdt.core.compiler.problem.APILeak=warning
+org.eclipse.jdt.core.compiler.problem.annotatedTypeArgumentToUnannotated=info
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=warning
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
+org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=warning
+org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=disabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=disabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=public
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning
+org.eclipse.jdt.core.compiler.problem.missingJavadocComments=warning
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=return_tag
+org.eclipse.jdt.core.compiler.problem.missingJavadocTags=warning
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=public
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning
+org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning
+org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
+org.eclipse.jdt.core.compiler.problem.nullReference=warning
+org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
+org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=warning
+org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning
+org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.suppressWarningsNotFullyAnalysed=info
+org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=warning
+org.eclipse.jdt.core.compiler.problem.terminalDeprecation=warning
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentType=warning
+org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict=disabled
+org.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType=info
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=warning
+org.eclipse.jdt.core.compiler.problem.unstableAutoModuleName=warning
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.release=disabled
+org.eclipse.jdt.core.compiler.source=11
+org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
+org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.align_variable_declarations_on_columns=false
+org.eclipse.jdt.core.formatter.align_with_spaces=false
+org.eclipse.jdt.core.formatter.alignment_for_additive_operator=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=16
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_bitwise_operator=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_loops=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression_chain=0
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header=0
+org.eclipse.jdt.core.formatter.alignment_for_logical_operator=16
+org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_module_statements=16
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_multiplicative_operator=16
+org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references=0
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_relational_operator=0
+org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_shift_operator=0
+org.eclipse.jdt.core.formatter.alignment_for_string_concatenation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_type_arguments=0
+org.eclipse.jdt.core.formatter.alignment_for_type_parameters=0
+org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=0
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=0
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=0
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=2
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.align_tags_descriptions_grouped=false
+org.eclipse.jdt.core.formatter.comment.align_tags_names_descriptions=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
+org.eclipse.jdt.core.formatter.comment.count_line_length_from_starting_position=true
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=true
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=false
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.indent_tag_description=false
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert
+org.eclipse.jdt.core.formatter.comment.line_length=100
+org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
+org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
+org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true
+org.eclipse.jdt.core.formatter.indentation.size=2
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_additive_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_bitwise_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert
+org.eclipse.jdt.core.formatter.insert_space_after_logical_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_multiplicative_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_relational_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
+org.eclipse.jdt.core.formatter.insert_space_after_shift_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_string_concatenation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_additive_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_bitwise_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert
+org.eclipse.jdt.core.formatter.insert_space_before_logical_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_multiplicative_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_relational_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_shift_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_string_concatenation=insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=true
+org.eclipse.jdt.core.formatter.join_wrapped_lines=true
+org.eclipse.jdt.core.formatter.keep_annotation_declaration_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.keep_anonymous_type_declaration_on_one_line=one_line_if_empty
+org.eclipse.jdt.core.formatter.keep_code_block_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_enum_constant_declaration_on_one_line=one_line_if_empty
+org.eclipse.jdt.core.formatter.keep_enum_declaration_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.keep_if_then_body_block_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_lambda_body_block_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.keep_loop_body_block_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.keep_method_body_on_one_line=one_line_if_empty
+org.eclipse.jdt.core.formatter.keep_simple_do_while_body_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_simple_for_body_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_simple_getter_setter_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_simple_while_body_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_type_declaration_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.lineSplit=100
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=3
+org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statment=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_method_delcaration=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause=common_lines
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=false
+org.eclipse.jdt.core.formatter.tabulation.char=space
+org.eclipse.jdt.core.formatter.tabulation.size=2
+org.eclipse.jdt.core.formatter.use_on_off_tags=true
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_additive_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_assignment_operator=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_bitwise_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_conditional_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_logical_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_multiplicative_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
+org.eclipse.jdt.core.formatter.wrap_before_relational_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_shift_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_string_concatenation=true
+org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
+org.eclipse.jdt.core.javaFormatter=org.eclipse.jdt.core.defaultJavaFormatter
diff --git a/lambda-apikey-authorizer/.settings/org.eclipse.jdt.ui.prefs b/lambda-apikey-authorizer/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 000000000..c13d929fd
--- /dev/null
+++ b/lambda-apikey-authorizer/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,8 @@
+eclipse.preferences.version=1
+formatter_profile=_GoogleStyle
+formatter_settings_version=16
+org.eclipse.jdt.ui.exception.name=e
+org.eclipse.jdt.ui.gettersetter.use.is=true
+org.eclipse.jdt.ui.keywordthis=true
+org.eclipse.jdt.ui.overrideannotation=true
+org.eclipse.jdt.ui.text.custom_code_templates=
diff --git a/lambda-apikey-authorizer/build.gradle b/lambda-apikey-authorizer/build.gradle
new file mode 100644
index 000000000..a02f08731
--- /dev/null
+++ b/lambda-apikey-authorizer/build.gradle
@@ -0,0 +1,80 @@
+description = "FormKiQ Core - API Key Authorizer"
+
+def moduleName = "formkiq-module-lambda-authorizer-apikey"
+
+dependencies {
+
+ annotationProcessor group: 'com.formkiq', name: 'graalvm-annotations-processor', version: '1.4.0'
+
+ implementation project(':aws-dynamodb')
+ implementation project(':dynamodb-documents')
+ implementation project(':fkq-lambda-services')
+
+ implementation group: 'org.slf4j', name: 'slf4j-simple', version: '2.0.7'
+ implementation group: 'com.amazonaws', name: 'aws-lambda-java-core', version: '1.2.2'
+ implementation group: 'com.google.code.gson', name: 'gson', version: '2.10.1'
+
+ implementation group: 'com.formkiq', name: 'lambda-runtime-graalvm', version:'2.3.1'
+ implementation group: 'com.formkiq', name: 'graalvm-annotations', version: '1.2.0'
+
+ testImplementation project(':fkq-test-utils')
+
+ testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version:'5.9.1'
+ testImplementation group: 'org.testcontainers', name: 'testcontainers', version: '1.17.6'
+ testImplementation group: 'org.testcontainers', name: 'junit-jupiter', version: '1.17.6'
+}
+
+compileJava {
+ options.annotationProcessorPath += configurations.runtimeClasspath
+}
+
+nativeImage {
+ outputFileName = "server"
+ mainClassName = "com.formkiq.lambda.runtime.graalvm.LambdaRuntime"
+ dockerImage = "ghcr.io/graalvm/graalvm-ce:ol9-java17-22.3.1"
+ enableHttp = true
+ enableHttps = true
+ enableStatic = true
+ systemProperty = ["java.net.preferIPv4Stack=true"]
+}
+
+test {
+ failFast = true
+ useJUnitPlatform()
+}
+
+task buildZip(type: Zip) {
+ dependsOn test, graalvmNativeImage
+ inputs.files("${project.projectDir}/runtime/bootstrap", "${buildDir}/graalvm/server")
+ outputs.file("${buildDir}/${moduleName}.zip")
+
+ archiveFileName = "${moduleName}.zip"
+ destinationDirectory = file("${buildDir}")
+ from("${project.projectDir}/runtime") {
+ include 'bootstrap'
+ }
+ from("${buildDir}/graalvm") {
+ include 'server'
+ }
+}
+
+task buildJava11Zip(type: Zip) {
+ from compileJava
+ into('lib') {
+ from configurations.default
+ }
+}
+
+task assembleTemplate {
+ dependsOn buildZip
+ outputs.upToDateWhen { false }
+
+ doLast {
+ copy {
+ from layout.projectDirectory.file("${buildDir}/${moduleName}.zip")
+ into "${buildDir}/distributions/formkiq-core/sam/api"
+ }
+ }
+}
+
+build.dependsOn assembleTemplate
diff --git a/lambda-apikey-authorizer/config/checkstyle/checkstyle.xml b/lambda-apikey-authorizer/config/checkstyle/checkstyle.xml
new file mode 100644
index 000000000..175b5d8a0
--- /dev/null
+++ b/lambda-apikey-authorizer/config/checkstyle/checkstyle.xml
@@ -0,0 +1,243 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/lambda-apikey-authorizer/config/checkstyle/import-control.xml b/lambda-apikey-authorizer/config/checkstyle/import-control.xml
new file mode 100644
index 000000000..99a05ed12
--- /dev/null
+++ b/lambda-apikey-authorizer/config/checkstyle/import-control.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lambda-apikey-authorizer/config/checkstyle/mysuppressions.xml b/lambda-apikey-authorizer/config/checkstyle/mysuppressions.xml
new file mode 100644
index 000000000..b5bb10162
--- /dev/null
+++ b/lambda-apikey-authorizer/config/checkstyle/mysuppressions.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
diff --git a/lambda-apikey-authorizer/runtime/bootstrap b/lambda-apikey-authorizer/runtime/bootstrap
new file mode 100755
index 000000000..8cb383935
--- /dev/null
+++ b/lambda-apikey-authorizer/runtime/bootstrap
@@ -0,0 +1,3 @@
+#!/bin/sh
+set -euo pipefail
+./server
diff --git a/lambda-apikey-authorizer/src/main/java/com/formkiq/module/lambda/authorizer/apikey/ApiKeyAuthorizerRequestHandler.java b/lambda-apikey-authorizer/src/main/java/com/formkiq/module/lambda/authorizer/apikey/ApiKeyAuthorizerRequestHandler.java
new file mode 100644
index 000000000..00cfbbd5c
--- /dev/null
+++ b/lambda-apikey-authorizer/src/main/java/com/formkiq/module/lambda/authorizer/apikey/ApiKeyAuthorizerRequestHandler.java
@@ -0,0 +1,153 @@
+/**
+ * MIT License
+ *
+ * Copyright (c) 2018 - 2020 FormKiQ
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package com.formkiq.module.lambda.authorizer.apikey;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import com.amazonaws.services.lambda.runtime.Context;
+import com.amazonaws.services.lambda.runtime.LambdaLogger;
+import com.amazonaws.services.lambda.runtime.RequestHandler;
+import com.amazonaws.services.lambda.runtime.RequestStreamHandler;
+import com.formkiq.aws.dynamodb.DynamicObject;
+import com.formkiq.aws.dynamodb.DynamoDbConnectionBuilder;
+import com.formkiq.aws.dynamodb.DynamoDbConnectionBuilderExtension;
+import com.formkiq.graalvm.annotations.Reflectable;
+import com.formkiq.module.lambdaservices.AwsServiceCache;
+import com.formkiq.stacks.dynamodb.ApiKeysService;
+import com.formkiq.stacks.dynamodb.ApiKeysServiceExtension;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.utils.IoUtils;
+
+/** {@link RequestHandler} for handling DynamoDb to Tesseract OCR Processor. */
+@Reflectable
+public class ApiKeyAuthorizerRequestHandler implements RequestStreamHandler {
+
+ /** {@link AwsServiceCache}. */
+ private AwsServiceCache awsServices;
+ /** {@link Gson}. */
+ private Gson gson = new GsonBuilder().disableHtmlEscaping().create();
+
+ /**
+ * constructor.
+ *
+ */
+ public ApiKeyAuthorizerRequestHandler() {
+ this(System.getenv(),
+ new DynamoDbConnectionBuilder("true".equals(System.getenv("ENABLE_AWS_X_RAY")))
+ .setRegion(Region.of(System.getenv("AWS_REGION"))));
+ }
+
+ /**
+ * constructor.
+ *
+ * @param map {@link Map}
+ * @param dbConnection {@link DynamoDbConnectionBuilder}
+ */
+ public ApiKeyAuthorizerRequestHandler(final Map map,
+ final DynamoDbConnectionBuilder dbConnection) {
+
+ this.awsServices =
+ new AwsServiceCache().environment(map).debug("true".equals(map.get("DEBUG")));
+
+ AwsServiceCache.register(DynamoDbConnectionBuilder.class,
+ new DynamoDbConnectionBuilderExtension(dbConnection));
+ AwsServiceCache.register(ApiKeysService.class, new ApiKeysServiceExtension());
+ }
+
+ /**
+ * Get {@link AwsServiceCache}.
+ *
+ * @return {@link AwsServiceCache}
+ */
+ public AwsServiceCache getAwsServices() {
+ return this.awsServices;
+ }
+
+ @SuppressWarnings("unchecked")
+ private String getIdentitySource(final Map map) {
+ List identitySource = (List) map.get("identitySource");
+ return !identitySource.isEmpty() ? identitySource.get(0) : null;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public void handleRequest(final InputStream input, final OutputStream output,
+ final Context context) throws IOException {
+
+ LambdaLogger logger = context.getLogger();
+ ApiKeysService apiKeys = this.awsServices.getExtension(ApiKeysService.class);
+
+ String json = IoUtils.toUtf8String(input);
+
+ if (this.awsServices.debug()) {
+ logger.log(json);
+ }
+
+ Map map = this.gson.fromJson(json, Map.class);
+
+ String apiKey = getIdentitySource(map);
+
+ DynamicObject obj = apiKeys.get(apiKey);
+ List siteIds = obj.getStringList("siteIds");
+ boolean isAuthorized = apiKey != null && apiKey.equals(obj.getOrDefault("apiKey", ""));
+
+ String apiKeyName = (String) obj.getOrDefault("name", "");
+ String group = isAuthorized ? "[" + String.join(",", siteIds) + "]" : "[]";
+
+ log(logger, map, isAuthorized, group);
+ Map response = Map.of("isAuthorized", Boolean.valueOf(isAuthorized), "context",
+ Map.of("apiKeyClaims", Map.of("cognito:groups", group, "cognito:username", apiKeyName)));
+
+ OutputStreamWriter writer = new OutputStreamWriter(output, "UTF-8");
+ writer.write(this.gson.toJson(response));
+ writer.close();
+ }
+
+ @SuppressWarnings("unchecked")
+ private void log(final LambdaLogger logger, final Map map,
+ final boolean isAuthorized, final String group) {
+
+ Map requestContext =
+ map.containsKey("requestContext") ? (Map) map.get("requestContext")
+ : Collections.emptyMap();
+ Map http =
+ map.containsKey("http") ? (Map) map.get("http") : Collections.emptyMap();
+
+ String s = String.format(
+ "{\"requestId\": \"%s\",\"ip\": \"%s\",\"requestTime\": \"%s\",\"httpMethod\": \"%s\","
+ + "\"routeKey\": \"%s\","
+ + "\"protocol\": \"%s\",\"siteId\":\"%s\",\"isAuthorized\":\"%s\"}",
+ map.get("requestId"), http.get("sourceIp"), requestContext.get("time"), http.get("method"),
+ map.get("routeKey"), requestContext.get("protocol"), group, String.valueOf(isAuthorized));
+
+ logger.log(s);
+ }
+}
diff --git a/lambda-apikey-authorizer/src/test/java/com/formkiq/module/lambda/authorizer/apikey/ApiKeyAuthorizerRequestHandlerTest.java b/lambda-apikey-authorizer/src/test/java/com/formkiq/module/lambda/authorizer/apikey/ApiKeyAuthorizerRequestHandlerTest.java
new file mode 100644
index 000000000..4d7437310
--- /dev/null
+++ b/lambda-apikey-authorizer/src/test/java/com/formkiq/module/lambda/authorizer/apikey/ApiKeyAuthorizerRequestHandlerTest.java
@@ -0,0 +1,185 @@
+/**
+ * MIT License
+ *
+ * Copyright (c) 2018 - 2020 FormKiQ
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package com.formkiq.module.lambda.authorizer.apikey;
+
+import static com.formkiq.testutils.aws.DynamoDbExtension.DOCUMENTS_TABLE;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import com.amazonaws.services.lambda.runtime.Context;
+import com.formkiq.aws.dynamodb.DynamoDbConnectionBuilder;
+import com.formkiq.module.lambdaservices.AwsServiceCache;
+import com.formkiq.stacks.dynamodb.ApiKeysService;
+import com.formkiq.testutils.aws.DynamoDbExtension;
+import com.formkiq.testutils.aws.DynamoDbTestServices;
+import com.formkiq.testutils.aws.LambdaContextRecorder;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
+/**
+ *
+ * Unit Tests {@link ApiKeyAuthorizerRequestHandler}.
+ *
+ */
+@ExtendWith(DynamoDbExtension.class)
+class ApiKeyAuthorizerRequestHandlerTest {
+
+ /** {@link ApiKeysService}. */
+ private static ApiKeysService apiKeysService;
+ /** {@link Gson}. */
+ private static final Gson GSON = new GsonBuilder().create();
+ /** {@link ApiKeyAuthorizerRequestHandler}. */
+ private static ApiKeyAuthorizerRequestHandler processor;
+
+ @BeforeAll
+ public static void beforeAll() throws Exception {
+
+ DynamoDbConnectionBuilder dbConnection = DynamoDbTestServices.getDynamoDbConnection();
+
+ processor = new ApiKeyAuthorizerRequestHandler(Map.of("DOCUMENTS_TABLE", DOCUMENTS_TABLE),
+ dbConnection);
+
+ AwsServiceCache awsServices = processor.getAwsServices();
+ apiKeysService = awsServices.getExtension(ApiKeysService.class);
+ }
+
+ /** {@link Context}. */
+ private Context context = new LambdaContextRecorder();
+
+ private InputStream getInput(final String apiKey) {
+ List identitySource = apiKey != null ? Arrays.asList(apiKey) : Collections.emptyList();
+ String json = GSON.toJson(Map.of("type", "REQUEST", "identitySource", identitySource));
+
+ InputStream is = new ByteArrayInputStream(json.getBytes(StandardCharsets.UTF_8));
+ return is;
+ }
+
+ /**
+ * Test Invalid API Key.
+ *
+ * @throws Exception Exception
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ void testHandleRequest01() throws Exception {
+ // given
+ String apiKey = UUID.randomUUID().toString();
+
+ try (InputStream is = getInput(apiKey)) {
+
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+
+ // when
+ processor.handleRequest(is, os, this.context);
+
+ // then
+ String response = new String(os.toByteArray(), "UTF-8");
+ Map map = GSON.fromJson(response, Map.class);
+ assertEquals(Boolean.FALSE, map.get("isAuthorized"));
+ Map ctx = (Map) map.get("context");
+ Map claims = (Map) ctx.get("apiKeyClaims");
+ assertEquals("[]", claims.get("cognito:groups"));
+ assertEquals("", claims.get("cognito:username"));
+ }
+ }
+
+ /**
+ * Test VALID API Key.
+ *
+ * @throws Exception Exception
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ void testHandleRequest02() throws Exception {
+ // given
+ for (String siteId : Arrays.asList(null, UUID.randomUUID().toString())) {
+
+ String name = UUID.randomUUID().toString();
+
+ String apiKey = apiKeysService.createApiKey(siteId, name, "joe");
+
+ try (InputStream is = getInput(apiKey)) {
+
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+
+ // when
+ processor.handleRequest(is, os, this.context);
+
+ // then
+ String response = new String(os.toByteArray(), "UTF-8");
+ Map map = GSON.fromJson(response, Map.class);
+ assertEquals(Boolean.TRUE, map.get("isAuthorized"));
+
+ Map ctx = (Map) map.get("context");
+ Map claims = (Map) ctx.get("apiKeyClaims");
+
+ if (siteId != null) {
+ assertEquals("[" + siteId + "]", claims.get("cognito:groups"));
+ } else {
+ assertEquals("[default]", claims.get("cognito:groups"));
+ }
+
+ assertEquals(name, claims.get("cognito:username"));
+ }
+ }
+ }
+
+ /**
+ * Test missing API Key.
+ *
+ * @throws Exception Exception
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ void testHandleRequest03() throws Exception {
+ // given
+ try (InputStream is = getInput(null)) {
+
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+
+ // when
+ processor.handleRequest(is, os, this.context);
+
+ // then
+ String response = new String(os.toByteArray(), "UTF-8");
+ Map map = GSON.fromJson(response, Map.class);
+ assertEquals(Boolean.FALSE, map.get("isAuthorized"));
+
+ Map ctx = (Map) map.get("context");
+ Map claims = (Map) ctx.get("apiKeyClaims");
+ assertEquals("[]", claims.get("cognito:groups"));
+ assertEquals("", claims.get("cognito:username"));
+ }
+ }
+}
diff --git a/lambda-ocr-tesseract/.checkstyle b/lambda-ocr-tesseract/.checkstyle
new file mode 100644
index 000000000..f9b8404e0
--- /dev/null
+++ b/lambda-ocr-tesseract/.checkstyle
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lambda-ocr-tesseract/.classpath b/lambda-ocr-tesseract/.classpath
new file mode 100644
index 000000000..66f8050c0
--- /dev/null
+++ b/lambda-ocr-tesseract/.classpath
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lambda-ocr-tesseract/.gitignore b/lambda-ocr-tesseract/.gitignore
new file mode 100644
index 000000000..4a95481e6
--- /dev/null
+++ b/lambda-ocr-tesseract/.gitignore
@@ -0,0 +1,2 @@
+/bin/
+/build/
diff --git a/lambda-ocr-tesseract/.project b/lambda-ocr-tesseract/.project
new file mode 100644
index 000000000..522c18c99
--- /dev/null
+++ b/lambda-ocr-tesseract/.project
@@ -0,0 +1,30 @@
+
+
+ lambda-ocr-tesseract
+ Project core created by Buildship.
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
+ net.sf.eclipsecs.core.CheckstyleBuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.buildship.core.gradleprojectnature
+ net.sf.eclipsecs.core.CheckstyleNature
+
+
+
diff --git a/lambda-ocr-tesseract/.settings/org.eclipse.buildship.core.prefs b/lambda-ocr-tesseract/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 000000000..e47955840
--- /dev/null
+++ b/lambda-ocr-tesseract/.settings/org.eclipse.buildship.core.prefs
@@ -0,0 +1,13 @@
+arguments=
+auto.sync=false
+build.scans.enabled=false
+connection.gradle.distribution=GRADLE_DISTRIBUTION(WRAPPER)
+connection.project.dir=
+eclipse.preferences.version=1
+gradle.user.home=
+java.home=
+jvm.arguments=
+offline.mode=false
+override.workspace.settings=false
+show.console.view=false
+show.executions.view=false
diff --git a/lambda-ocr-tesseract/.settings/org.eclipse.core.resources.prefs b/lambda-ocr-tesseract/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 000000000..99f26c020
--- /dev/null
+++ b/lambda-ocr-tesseract/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+encoding/=UTF-8
diff --git a/lambda-ocr-tesseract/.settings/org.eclipse.jdt.core.prefs b/lambda-ocr-tesseract/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 000000000..9ba0f3224
--- /dev/null
+++ b/lambda-ocr-tesseract/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,496 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.codeComplete.argumentPrefixes=
+org.eclipse.jdt.core.codeComplete.argumentSuffixes=
+org.eclipse.jdt.core.codeComplete.fieldPrefixes=
+org.eclipse.jdt.core.codeComplete.fieldSuffixes=
+org.eclipse.jdt.core.codeComplete.localPrefixes=
+org.eclipse.jdt.core.codeComplete.localSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFieldSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes=
+org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled
+org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
+org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull
+org.eclipse.jdt.core.compiler.annotation.nonnull.secondary=
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary=
+org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
+org.eclipse.jdt.core.compiler.annotation.nullable.secondary=
+org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=11
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.doc.comment.support=enabled
+org.eclipse.jdt.core.compiler.problem.APILeak=warning
+org.eclipse.jdt.core.compiler.problem.annotatedTypeArgumentToUnannotated=info
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=warning
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
+org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=warning
+org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=disabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=disabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=public
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning
+org.eclipse.jdt.core.compiler.problem.missingJavadocComments=warning
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=return_tag
+org.eclipse.jdt.core.compiler.problem.missingJavadocTags=warning
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=public
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning
+org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning
+org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
+org.eclipse.jdt.core.compiler.problem.nullReference=warning
+org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
+org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=warning
+org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning
+org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.suppressWarningsNotFullyAnalysed=info
+org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=warning
+org.eclipse.jdt.core.compiler.problem.terminalDeprecation=warning
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentType=warning
+org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict=disabled
+org.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType=info
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=warning
+org.eclipse.jdt.core.compiler.problem.unstableAutoModuleName=warning
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.release=disabled
+org.eclipse.jdt.core.compiler.source=11
+org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
+org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.align_variable_declarations_on_columns=false
+org.eclipse.jdt.core.formatter.align_with_spaces=false
+org.eclipse.jdt.core.formatter.alignment_for_additive_operator=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=16
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_bitwise_operator=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_loops=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression_chain=0
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header=0
+org.eclipse.jdt.core.formatter.alignment_for_logical_operator=16
+org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_module_statements=16
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_multiplicative_operator=16
+org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references=0
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_relational_operator=0
+org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_shift_operator=0
+org.eclipse.jdt.core.formatter.alignment_for_string_concatenation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_type_arguments=0
+org.eclipse.jdt.core.formatter.alignment_for_type_parameters=0
+org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=0
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=0
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=0
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=2
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.align_tags_descriptions_grouped=false
+org.eclipse.jdt.core.formatter.comment.align_tags_names_descriptions=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
+org.eclipse.jdt.core.formatter.comment.count_line_length_from_starting_position=true
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=true
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=false
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.indent_tag_description=false
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert
+org.eclipse.jdt.core.formatter.comment.line_length=100
+org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
+org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
+org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true
+org.eclipse.jdt.core.formatter.indentation.size=2
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_additive_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_bitwise_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert
+org.eclipse.jdt.core.formatter.insert_space_after_logical_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_multiplicative_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_relational_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
+org.eclipse.jdt.core.formatter.insert_space_after_shift_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_string_concatenation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_additive_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_bitwise_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert
+org.eclipse.jdt.core.formatter.insert_space_before_logical_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_multiplicative_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_relational_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_shift_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_string_concatenation=insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=true
+org.eclipse.jdt.core.formatter.join_wrapped_lines=true
+org.eclipse.jdt.core.formatter.keep_annotation_declaration_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.keep_anonymous_type_declaration_on_one_line=one_line_if_empty
+org.eclipse.jdt.core.formatter.keep_code_block_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_enum_constant_declaration_on_one_line=one_line_if_empty
+org.eclipse.jdt.core.formatter.keep_enum_declaration_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.keep_if_then_body_block_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_lambda_body_block_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.keep_loop_body_block_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.keep_method_body_on_one_line=one_line_if_empty
+org.eclipse.jdt.core.formatter.keep_simple_do_while_body_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_simple_for_body_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_simple_getter_setter_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_simple_while_body_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_type_declaration_on_one_line=one_line_never
+org.eclipse.jdt.core.formatter.lineSplit=100
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=3
+org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statment=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_method_delcaration=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement=common_lines
+org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause=common_lines
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=false
+org.eclipse.jdt.core.formatter.tabulation.char=space
+org.eclipse.jdt.core.formatter.tabulation.size=2
+org.eclipse.jdt.core.formatter.use_on_off_tags=true
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_additive_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_assignment_operator=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_bitwise_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_conditional_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_logical_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_multiplicative_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
+org.eclipse.jdt.core.formatter.wrap_before_relational_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_shift_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_string_concatenation=true
+org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
+org.eclipse.jdt.core.javaFormatter=org.eclipse.jdt.core.defaultJavaFormatter
diff --git a/lambda-ocr-tesseract/.settings/org.eclipse.jdt.ui.prefs b/lambda-ocr-tesseract/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 000000000..c13d929fd
--- /dev/null
+++ b/lambda-ocr-tesseract/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,8 @@
+eclipse.preferences.version=1
+formatter_profile=_GoogleStyle
+formatter_settings_version=16
+org.eclipse.jdt.ui.exception.name=e
+org.eclipse.jdt.ui.gettersetter.use.is=true
+org.eclipse.jdt.ui.keywordthis=true
+org.eclipse.jdt.ui.overrideannotation=true
+org.eclipse.jdt.ui.text.custom_code_templates=
diff --git a/lambda-ocr-tesseract/build.gradle b/lambda-ocr-tesseract/build.gradle
new file mode 100644
index 000000000..a4e8ea577
--- /dev/null
+++ b/lambda-ocr-tesseract/build.gradle
@@ -0,0 +1,99 @@
+description = "FormKiQ Core - Lambda OCR Tesseract"
+
+def tesseract_version = "5.3.1"
+def moduleName = "formkiq-module-lambda-ocr-tesseract"
+
+dependencies {
+
+ implementation project(':actions')
+ implementation project(':aws-s3')
+ implementation project(':aws-sqs')
+ implementation project(':aws-sns')
+ implementation project(':aws-dynamodb')
+ implementation project(':ocr')
+ implementation project(':fkq-lambda-services')
+ implementation("net.sourceforge.tess4j:tess4j:5.7.0")
+ implementation("org.slf4j:slf4j-simple:2.0.6")
+ implementation group: 'com.amazonaws', name: 'aws-lambda-java-core', version: '1.2.2'
+ implementation group: 'com.google.code.gson', name: 'gson', version: '2.10.1'
+ implementation group: 'net.java.dev.jna', name: 'jna', version: '5.13.0'
+
+
+ testImplementation project(':fkq-test-utils')
+
+ testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version:'5.9.1'
+ testImplementation group: 'org.testcontainers', name: 'testcontainers', version: '1.17.6'
+ testImplementation group: 'org.testcontainers', name: 'junit-jupiter', version: '1.17.6'
+ testImplementation group: 'org.testcontainers', name: 'localstack', version: '1.17.6'
+}
+
+task buildZip(type: Zip) {
+ dependsOn check
+ archiveFileName = "${moduleName}.zip"
+ destinationDirectory = file("${buildDir}")
+ from compileJava
+ from processResources
+ into('lib') {
+ from configurations.runtimeClasspath
+ }
+}
+
+test {
+ failFast = true
+ useJUnitPlatform()
+}
+
+task downloadZipFile(type: Download) {
+ src 'https://github.com/bweigel/aws-lambda-tesseract-layer/releases/download/v5.3.1/tesseract-al2-x86.zip'
+ dest new File(buildDir, 'tesseract-al2-x86.zip')
+ overwrite false
+}
+
+task downloadAndUnzipFile(dependsOn: downloadZipFile, type: Copy) {
+ from zipTree(downloadZipFile.dest)
+ into new File(buildDir, 'tesseract')
+}
+
+task updateTesseractFiles(type: Delete) {
+ dependsOn downloadAndUnzipFile
+ def directory = file("${buildDir}/tesseract/tesseract/share/tessdata/")
+
+ doLast {
+ file("${buildDir}/tesseract/lib/libtesseract.so.5").renameTo(file("${buildDir}/tesseract/lib/libtesseract.so"))
+ directory.eachFile { file ->
+ if (file.name != "eng.traineddata" && file.name != "osd.traineddata") {
+ file.delete()
+ }
+ }
+ }
+}
+
+task buildTesseractLayer(type: Zip) {
+ dependsOn updateTesseractFiles
+ from "${buildDir}/tesseract"
+ archiveFileName.set("layer-tesseract-5.3.1.zip")
+ destinationDir file("$buildDir")
+}
+
+task assembleTemplate {
+ dependsOn buildZip, buildTesseractLayer
+ outputs.upToDateWhen { false }
+
+ doLast {
+ copy {
+ from layout.buildDirectory.dir("${buildDir}/../src/main/resources/cloudformation")
+ include "template*"
+ into "${buildDir}/distributions/formkiq-core/sam/ocr-tesseract"
+ }
+ copy {
+ from layout.projectDirectory.file("${buildDir}/${moduleName}.zip")
+ into "${buildDir}/distributions/formkiq-core/sam/ocr-tesseract"
+ }
+ copy {
+ from layout.projectDirectory.file("${buildDir}/layer-tesseract-${tesseract_version}.zip")
+ into "${buildDir}/distributions/formkiq-core/sam/ocr-tesseract"
+ }
+ }
+}
+
+build.dependsOn assembleTemplate
diff --git a/lambda-ocr-tesseract/config/checkstyle/checkstyle.xml b/lambda-ocr-tesseract/config/checkstyle/checkstyle.xml
new file mode 100644
index 000000000..175b5d8a0
--- /dev/null
+++ b/lambda-ocr-tesseract/config/checkstyle/checkstyle.xml
@@ -0,0 +1,243 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/lambda-ocr-tesseract/config/checkstyle/import-control.xml b/lambda-ocr-tesseract/config/checkstyle/import-control.xml
new file mode 100644
index 000000000..c21c438d0
--- /dev/null
+++ b/lambda-ocr-tesseract/config/checkstyle/import-control.xml
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lambda-ocr-tesseract/config/checkstyle/mysuppressions.xml b/lambda-ocr-tesseract/config/checkstyle/mysuppressions.xml
new file mode 100644
index 000000000..b5bb10162
--- /dev/null
+++ b/lambda-ocr-tesseract/config/checkstyle/mysuppressions.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
diff --git a/lambda-ocr-tesseract/src/main/java/com/formkiq/module/lambda/ocr/tesseract/OcrTesseractProcessor.java b/lambda-ocr-tesseract/src/main/java/com/formkiq/module/lambda/ocr/tesseract/OcrTesseractProcessor.java
new file mode 100644
index 000000000..00f224488
--- /dev/null
+++ b/lambda-ocr-tesseract/src/main/java/com/formkiq/module/lambda/ocr/tesseract/OcrTesseractProcessor.java
@@ -0,0 +1,234 @@
+/**
+ * MIT License
+ *
+ * Copyright (c) 2018 - 2020 FormKiQ
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package com.formkiq.module.lambda.ocr.tesseract;
+
+import static com.formkiq.aws.dynamodb.SiteIdKeyGenerator.createS3Key;
+import static com.formkiq.aws.dynamodb.objects.MimeType.MIME_BMP;
+import static com.formkiq.aws.dynamodb.objects.MimeType.MIME_GIF;
+import static com.formkiq.aws.dynamodb.objects.MimeType.MIME_JPEG;
+import static com.formkiq.aws.dynamodb.objects.MimeType.MIME_JPG;
+import static com.formkiq.aws.dynamodb.objects.MimeType.MIME_PNG;
+import static com.formkiq.aws.dynamodb.objects.MimeType.MIME_TIF;
+import static com.formkiq.aws.dynamodb.objects.MimeType.MIME_TIFF;
+import static com.formkiq.aws.dynamodb.objects.MimeType.MIME_WEBP;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import com.amazonaws.services.lambda.runtime.Context;
+import com.amazonaws.services.lambda.runtime.LambdaLogger;
+import com.amazonaws.services.lambda.runtime.RequestHandler;
+import com.amazonaws.services.lambda.runtime.RequestStreamHandler;
+import com.formkiq.aws.dynamodb.DynamoDbConnectionBuilder;
+import com.formkiq.aws.dynamodb.DynamoDbConnectionBuilderExtension;
+import com.formkiq.aws.dynamodb.objects.MimeType;
+import com.formkiq.aws.s3.S3ConnectionBuilder;
+import com.formkiq.aws.s3.S3Service;
+import com.formkiq.aws.s3.S3ServiceExtension;
+import com.formkiq.aws.sns.SnsConnectionBuilder;
+import com.formkiq.aws.sqs.SqsMessageRecords;
+import com.formkiq.module.actions.ActionStatus;
+import com.formkiq.module.actions.ActionType;
+import com.formkiq.module.actions.services.ActionsNotificationService;
+import com.formkiq.module.actions.services.ActionsNotificationServiceExtension;
+import com.formkiq.module.actions.services.ActionsService;
+import com.formkiq.module.actions.services.ActionsServiceExtension;
+import com.formkiq.module.lambdaservices.AwsServiceCache;
+import com.formkiq.module.ocr.DocumentOcrService;
+import com.formkiq.module.ocr.DocumentOcrServiceExtension;
+import com.formkiq.module.ocr.OcrScanStatus;
+import com.formkiq.module.ocr.OcrSqsMessage;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import net.sourceforge.tess4j.TesseractException;
+import software.amazon.awssdk.auth.credentials.EnvironmentVariableCredentialsProvider;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.utils.IoUtils;
+
+/** {@link RequestHandler} for handling DynamoDb to Tesseract OCR Processor. */
+public class OcrTesseractProcessor implements RequestStreamHandler {
+
+ /** Supported Mime Type. */
+ private static final List SUPPORTED = Arrays.asList(MIME_PNG, MIME_JPEG, MIME_JPG,
+ MIME_TIF, MIME_TIFF, MIME_GIF, MIME_WEBP, MIME_BMP);
+ /** {@link AwsServiceCache}. */
+ private AwsServiceCache awsServices;
+ /** Documents S3 Bucket. */
+ private String documentsBucket;
+ /** {@link Gson}. */
+ private Gson gson = new GsonBuilder().create();
+ /** {@link String}. */
+ private String ocrDocumentsBucket;
+ /** {@link S3Service}. */
+ private S3Service s3Service;
+ /** {@link TesseractWrapper}. */
+ private TesseractWrapper tesseract;
+
+ /**
+ * constructor.
+ *
+ */
+ public OcrTesseractProcessor() {
+ this(System.getenv(),
+ new DynamoDbConnectionBuilder("true".equals(System.getenv("ENABLE_AWS_X_RAY")))
+ .setRegion(Region.of(System.getenv("AWS_REGION"))),
+ new S3ConnectionBuilder("true".equals(System.getenv("ENABLE_AWS_X_RAY")))
+ .setRegion(Region.of(System.getenv("AWS_REGION"))),
+ new SnsConnectionBuilder("true".equals(System.getenv("ENABLE_AWS_X_RAY")))
+ .setCredentials(EnvironmentVariableCredentialsProvider.create())
+ .setRegion(Region.of(System.getenv("AWS_REGION"))),
+ new TesseractWrapperImpl());
+ }
+
+ /**
+ * constructor.
+ *
+ * @param map {@link Map}
+ * @param dbConnection {@link DynamoDbConnectionBuilder}
+ * @param s3Connection {@link S3ConnectionBuilder}
+ * @param snsConnection {@link SnsConnectionBuilder}
+ * @param tesseractWrapper {@link TesseractWrapper}
+ */
+ public OcrTesseractProcessor(final Map map,
+ final DynamoDbConnectionBuilder dbConnection, final S3ConnectionBuilder s3Connection,
+ final SnsConnectionBuilder snsConnection, final TesseractWrapper tesseractWrapper) {
+
+ this.s3Service = new S3Service(s3Connection);
+ this.documentsBucket = map.get("DOCUMENTS_S3_BUCKET");
+ this.ocrDocumentsBucket = map.get("OCR_S3_BUCKET");
+ this.tesseract = tesseractWrapper;
+
+ this.awsServices =
+ new AwsServiceCache().environment(map).debug("true".equals(map.get("DEBUG")));
+
+ AwsServiceCache.register(DynamoDbConnectionBuilder.class,
+ new DynamoDbConnectionBuilderExtension(dbConnection));
+ AwsServiceCache.register(S3Service.class, new S3ServiceExtension(s3Connection));
+ AwsServiceCache.register(DocumentOcrService.class, new DocumentOcrServiceExtension());
+ AwsServiceCache.register(ActionsService.class, new ActionsServiceExtension());
+
+ AwsServiceCache.register(ActionsNotificationService.class,
+ new ActionsNotificationServiceExtension(snsConnection));
+ }
+
+ /**
+ * Get {@link AwsServiceCache}.
+ *
+ * @return {@link AwsServiceCache}
+ */
+ public AwsServiceCache getAwsServices() {
+ return this.awsServices;
+ }
+
+ @Override
+ public void handleRequest(final InputStream input, final OutputStream output,
+ final Context context) throws IOException {
+
+ LambdaLogger logger = context.getLogger();
+
+ String json = IoUtils.toUtf8String(input);
+
+ if (this.awsServices.debug()) {
+ logger.log(json);
+ }
+
+ SqsMessageRecords records = this.gson.fromJson(json, SqsMessageRecords.class);
+
+ DocumentOcrService ocrService = this.awsServices.getExtension(DocumentOcrService.class);
+
+ records.records().forEach(record -> {
+
+ OcrSqsMessage sqsMessage = this.gson.fromJson(record.body(), OcrSqsMessage.class);
+ processRecord(logger, ocrService, sqsMessage);
+
+ });
+ }
+
+ private void processRecord(final LambdaLogger logger, final DocumentOcrService ocrService,
+ final OcrSqsMessage sqsMessage) {
+ String siteId = sqsMessage.siteId();
+ String documentId = sqsMessage.documentId();
+ String jobId = sqsMessage.jobId();
+ String contentType = sqsMessage.contentType();
+
+ String s = String.format(
+ "{\"siteId\": \"%s\",\"documentId\": \"%s\",\"jobId\": \"%s\",\"contentType\":\"%s\"}",
+ siteId, documentId, jobId, contentType);
+ logger.log(s);
+
+
+ try {
+
+ MimeType mt = MimeType.fromContentType(contentType);
+
+ if (!SUPPORTED.contains(mt)) {
+ throw new IOException("unsupported Content-Type: " + contentType);
+ }
+
+ String tmpDirectory =
+ new File("/tmp").exists() ? "/tmp/" : System.getProperty("java.io.tmpdir") + "\\";
+ String documentS3Key = createS3Key(siteId, documentId);
+ File file =
+ new File(tmpDirectory + documentS3Key.replaceAll("/", "_") + "." + mt.getExtension());
+
+ try (InputStream is =
+ this.s3Service.getContentAsInputStream(this.documentsBucket, documentS3Key)) {
+
+ try (OutputStream fileOs = new FileOutputStream(file)) {
+ IoUtils.copy(is, fileOs);
+ }
+
+ String text = this.tesseract.doOcr(file);
+
+ String ocrS3Key = ocrService.getS3Key(siteId, documentId, jobId);
+ this.s3Service.putObject(this.ocrDocumentsBucket, ocrS3Key,
+ text.getBytes(StandardCharsets.UTF_8), "text/plain");
+
+ ocrService.updateOcrScanStatus(this.awsServices, siteId, documentId,
+ OcrScanStatus.SUCCESSFUL);
+
+ logger.log(String.format("setting OCR Scan Status: %s", OcrScanStatus.SUCCESSFUL));
+
+ } finally {
+
+ if (!file.delete()) {
+ file.deleteOnExit();
+ }
+ }
+
+ } catch (IOException | TesseractException | RuntimeException e) {
+ e.printStackTrace();
+ ocrService.updateOcrScanStatus(siteId, documentId, OcrScanStatus.FAILED);
+ logger.log(String.format("setting OCR Scan Status: %s", OcrScanStatus.FAILED));
+
+ ActionsService actionsService = this.awsServices.getExtension(ActionsService.class);
+ actionsService.updateActionStatus(siteId, documentId, ActionType.OCR, ActionStatus.FAILED);
+ }
+ }
+}
diff --git a/lambda-ocr-tesseract/src/main/java/com/formkiq/module/lambda/ocr/tesseract/TesseractWrapper.java b/lambda-ocr-tesseract/src/main/java/com/formkiq/module/lambda/ocr/tesseract/TesseractWrapper.java
new file mode 100644
index 000000000..37268ac67
--- /dev/null
+++ b/lambda-ocr-tesseract/src/main/java/com/formkiq/module/lambda/ocr/tesseract/TesseractWrapper.java
@@ -0,0 +1,44 @@
+/**
+ * MIT License
+ *
+ * Copyright (c) 2018 - 2020 FormKiQ
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package com.formkiq.module.lambda.ocr.tesseract;
+
+import java.io.File;
+import net.sourceforge.tess4j.TesseractException;
+
+/**
+ *
+ * Wrapper for the Tesseract library.
+ *
+ */
+public interface TesseractWrapper {
+
+ /**
+ * Performs OCR operation.
+ *
+ * @param imageFile an image file
+ * @return the recognized text
+ * @throws TesseractException TesseractException
+ */
+ String doOcr(File imageFile) throws TesseractException;
+}
diff --git a/lambda-ocr-tesseract/src/main/java/com/formkiq/module/lambda/ocr/tesseract/TesseractWrapperImpl.java b/lambda-ocr-tesseract/src/main/java/com/formkiq/module/lambda/ocr/tesseract/TesseractWrapperImpl.java
new file mode 100644
index 000000000..595cee608
--- /dev/null
+++ b/lambda-ocr-tesseract/src/main/java/com/formkiq/module/lambda/ocr/tesseract/TesseractWrapperImpl.java
@@ -0,0 +1,50 @@
+/**
+ * MIT License
+ *
+ * Copyright (c) 2018 - 2020 FormKiQ
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package com.formkiq.module.lambda.ocr.tesseract;
+
+import java.io.File;
+import net.sourceforge.tess4j.Tesseract;
+import net.sourceforge.tess4j.TesseractException;
+
+/**
+ *
+ * {@link Tesseract} implement of {@link TesseractWrapper}.
+ *
+ */
+public class TesseractWrapperImpl implements TesseractWrapper {
+
+ @Override
+ public String doOcr(final File imageFile) throws TesseractException {
+
+ Tesseract tesseract = new Tesseract();
+ tesseract.setDatapath("/opt/tesseract/share/tessdata/");
+ tesseract.setLanguage("eng");
+ tesseract.setPageSegMode(1);
+ tesseract.setOcrEngineMode(1);
+
+ String text = tesseract.doOCR(imageFile);
+ return text;
+ }
+
+}
diff --git a/lambda-ocr-tesseract/src/main/resources/cloudformation/template.yaml b/lambda-ocr-tesseract/src/main/resources/cloudformation/template.yaml
new file mode 100644
index 000000000..3d54e6c25
--- /dev/null
+++ b/lambda-ocr-tesseract/src/main/resources/cloudformation/template.yaml
@@ -0,0 +1,200 @@
+#@ load("@ytt:data", "data")
+#@ load("@ytt:assert", "assert")
+---
+AWSTemplateFormatVersion: '2010-09-09'
+Transform: AWS::Serverless-2016-10-31
+Description: FormKiQ - Tesseract
+
+Parameters:
+
+ AppEnvironment:
+ Type: String
+ Description: The Application Environment
+ AllowedPattern: ".+"
+
+ LambdaMemory:
+ Type: Number
+ Description: The amount of memory used by lambda function (MB)
+ Default: 1024
+ MinValue: 128
+ MaxValue: 3008
+
+ LambdaTimeout:
+ Type: String
+ Description: The maximum amount of seconds lambda function will run for (seconds)
+ Default: 600
+
+ FormKiQType:
+ Description: The type of FormKiQ installation
+ Default: "core"
+ Type: String
+ AllowedValues: ["core", "enterprise"]
+
+Resources:
+
+ TesseractProcessorLogGroup:
+ Type: AWS::Logs::LogGroup
+ Properties:
+ LogGroupName:
+ Fn::Sub: "/aws/vendedlogs/${AWS::StackName}/${TesseractProcessor}"
+ RetentionInDays: 90
+
+ TesseractLayer:
+ Type: AWS::Serverless::LayerVersion
+ Properties:
+ Description: Lambda Layer containing Tesseract binary
+ LayerName:
+ Fn::Sub: "${AWS::StackName}-${AppEnvironment}-tesseract-layer"
+ ContentUri: ./layer-tesseract-5.3.1.zip
+
+ TesseractProcessor:
+ Type: AWS::Serverless::Function
+ DependsOn:
+ - TesseractLambdaRolePolicy
+ Properties:
+ Handler: com.formkiq.module.lambda.ocr.tesseract.OcrTesseractProcessor
+ Description: Lambda function to convert document to Tesseract
+ Runtime: java11
+ Timeout:
+ Fn::Sub: "${LambdaTimeout}"
+ MemorySize:
+ Fn::Sub: "${LambdaMemory}"
+ Layers:
+ - Ref: TesseractLayer
+ CodeUri: ./formkiq-module-lambda-ocr-tesseract.zip
+ Tracing: Active
+ AutoPublishCodeSha256: #@ data.values.hash or assert.fail("missing version")
+ Environment:
+ Variables:
+ APP_ENVIRONMENT:
+ Fn::Sub: "${AppEnvironment}"
+ DEBUG: false
+ ENABLE_AWS_X_RAY: true
+ FormKiQType:
+ Ref: FormKiQType
+ DOCUMENTS_TABLE:
+ Fn::Sub: "{{resolve:ssm:/formkiq/${AppEnvironment}/dynamodb/DocumentsTableName}}"
+ DOCUMENTS_S3_BUCKET:
+ Fn::Sub: "{{resolve:ssm:/formkiq/${AppEnvironment}/s3/DocumentsS3Bucket}}"
+ OCR_S3_BUCKET:
+ Fn::Sub: "{{resolve:ssm:/formkiq/${AppEnvironment}/s3/OcrBucket}}"
+ SNS_DOCUMENT_EVENT:
+ Fn::Sub: "{{resolve:ssm:/formkiq/${AppEnvironment}/sns/DocumentEventArn}}"
+ Role:
+ Fn::GetAtt:
+ - TesseractLambdaRole
+ - Arn
+ Tags:
+ AppEnvironment:
+ Fn::Sub: "${AppEnvironment}"
+ Application:
+ Fn::Sub: "FormKiQ ${FormKiQType}"
+ StackName:
+ Fn::Sub: "${AWS::StackName}"
+ Events:
+ OcrSQSEvent:
+ Type: SQS
+ Properties:
+ Queue:
+ Fn::Sub: "{{resolve:ssm:/formkiq/${AppEnvironment}/sqs/OcrQueueArn}}"
+ BatchSize: 1
+
+ TesseractProcessorParameter:
+ Type: AWS::SSM::Parameter
+ Properties:
+ Description: "Lambda for processing records for Tesseract"
+ Name:
+ Fn::Sub: "/formkiq/${AppEnvironment}/lambda/TesseractProcessor"
+ Type: String
+ Value:
+ Ref: TesseractProcessor
+ Tags:
+ Application:
+ Fn::Sub: "FormKiQ ${FormKiQType}"
+ AppEnvironment:
+ Fn::Sub: "${AppEnvironment}"
+ StackName:
+ Fn::Sub: "${AWS::StackName}"
+
+ TesseractLambdaRolePolicy:
+ Type: "AWS::IAM::Policy"
+ Properties:
+ PolicyName: Tesseract-lambdarole
+ Roles:
+ -
+ Ref: "TesseractLambdaRole"
+ PolicyDocument:
+ Version: '2012-10-17'
+ Statement:
+ - Effect: Allow
+ Action:
+ - logs:CreateLogGroup
+ - logs:CreateLogStream
+ - logs:PutLogEvents
+ Resource: "*"
+ - Effect: Allow
+ Action:
+ - s3:GetObject
+ Resource:
+ Fn::Join:
+ - ''
+ - - 'arn:aws:s3:::'
+ - Fn::Sub: "{{resolve:ssm:/formkiq/${AppEnvironment}/s3/DocumentsS3Bucket}}"
+ - "/*"
+ - Effect: Allow
+ Action:
+ - s3:GetObject
+ - s3:PutObject
+ Resource:
+ Fn::Join:
+ - ''
+ - - 'arn:aws:s3:::'
+ - Fn::Sub: "{{resolve:ssm:/formkiq/${AppEnvironment}/s3/OcrBucket}}"
+ - "/*"
+ - Effect: Allow
+ Action:
+ - sqs:ReceiveMessage
+ - sqs:DeleteMessage
+ - sqs:GetQueueAttributes
+ Resource:
+ Fn::Sub: "{{resolve:ssm:/formkiq/${AppEnvironment}/sqs/OcrQueueArn}}"
+ - Effect: Allow
+ Action:
+ - dynamodb:GetItem
+ - dynamodb:PutItem
+ - dynamodb:Query
+ - dynamodb:UpdateItem
+ Resource:
+ - Fn::Sub: "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/{{resolve:ssm:/formkiq/${AppEnvironment}/dynamodb/DocumentsTableName}}"
+ - Effect: Allow
+ Action:
+ - sns:Publish
+ Resource:
+ - Fn::Sub: "{{resolve:ssm:/formkiq/${AppEnvironment}/sns/DocumentEventArn}}"
+
+
+ TesseractLambdaRole:
+ Type: AWS::IAM::Role
+ Properties:
+ Tags:
+ - Key: "Application"
+ Value:
+ Fn::Sub: "FormKiQ ${FormKiQType}"
+ - Key: "AppEnvironment"
+ Value:
+ Fn::Sub: "${AppEnvironment}"
+ - Key: "StackName"
+ Value:
+ Fn::Sub: "${AWS::StackName}"
+ AssumeRolePolicyDocument:
+ Version: '2012-10-17'
+ Statement:
+ - Effect: Allow
+ Principal:
+ Service:
+ - lambda.amazonaws.com
+ Action:
+ - sts:AssumeRole
+ Path: /
+ ManagedPolicyArns:
+ - arn:aws:iam::aws:policy/AWSXRayDaemonWriteAccess
\ No newline at end of file
diff --git a/lambda-ocr-tesseract/src/test/java/com/formkiq/module/lambda/ocr/tesseract/OcrTesseractProcessorTest.java b/lambda-ocr-tesseract/src/test/java/com/formkiq/module/lambda/ocr/tesseract/OcrTesseractProcessorTest.java
new file mode 100644
index 000000000..e53e19bec
--- /dev/null
+++ b/lambda-ocr-tesseract/src/test/java/com/formkiq/module/lambda/ocr/tesseract/OcrTesseractProcessorTest.java
@@ -0,0 +1,235 @@
+/**
+ * MIT License
+ *
+ * Copyright (c) 2018 - 2020 FormKiQ
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package com.formkiq.module.lambda.ocr.tesseract;
+
+import static com.formkiq.aws.dynamodb.SiteIdKeyGenerator.createS3Key;
+import static com.formkiq.testutils.aws.DynamoDbExtension.DOCUMENTS_TABLE;
+import static com.formkiq.testutils.aws.TestServices.BUCKET_NAME;
+import static com.formkiq.testutils.aws.TestServices.OCR_BUCKET_NAME;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import com.amazonaws.services.lambda.runtime.Context;
+import com.formkiq.aws.dynamodb.DynamicObject;
+import com.formkiq.aws.dynamodb.DynamoDbConnectionBuilder;
+import com.formkiq.aws.dynamodb.objects.MimeType;
+import com.formkiq.aws.s3.S3ConnectionBuilder;
+import com.formkiq.aws.s3.S3Service;
+import com.formkiq.aws.sns.SnsConnectionBuilder;
+import com.formkiq.aws.sqs.SqsMessageRecord;
+import com.formkiq.aws.sqs.SqsMessageRecords;
+import com.formkiq.module.actions.Action;
+import com.formkiq.module.actions.ActionStatus;
+import com.formkiq.module.actions.ActionType;
+import com.formkiq.module.actions.services.ActionsService;
+import com.formkiq.module.lambdaservices.AwsServiceCache;
+import com.formkiq.module.ocr.DocumentOcrService;
+import com.formkiq.module.ocr.Ocr;
+import com.formkiq.module.ocr.OcrEngine;
+import com.formkiq.module.ocr.OcrScanStatus;
+import com.formkiq.testutils.aws.DynamoDbExtension;
+import com.formkiq.testutils.aws.DynamoDbTestServices;
+import com.formkiq.testutils.aws.LambdaContextRecorder;
+import com.formkiq.testutils.aws.LocalStackExtension;
+import com.formkiq.testutils.aws.TestServices;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
+/**
+ *
+ * Unit Tests {@link OcrTesseractProcessor}.
+ *
+ */
+@ExtendWith(DynamoDbExtension.class)
+@ExtendWith(LocalStackExtension.class)
+class OcrTesseractProcessorTest {
+
+ /** {@link ActionsService}. */
+ private static ActionsService actionsService;
+ /** {@link Gson}. */
+ private static final Gson GSON = new GsonBuilder().create();
+ /** Ocr Text. */
+ private static final String OCR_TEXT = "this is test data";
+ /** {@link DocumentOcrService}. */
+ private static DocumentOcrService ocrService;
+ /** {@link OcrTesseractProcessor}. */
+ private static OcrTesseractProcessor processor;
+ /** {@link S3Service}. */
+ private static S3Service s3;
+
+ @BeforeAll
+ public static void beforeAll() throws Exception {
+
+ DynamoDbConnectionBuilder dbConnection = DynamoDbTestServices.getDynamoDbConnection();
+ S3ConnectionBuilder s3Connection = TestServices.getS3Connection(null);
+ SnsConnectionBuilder sns = TestServices.getSnsConnection(null);
+
+ TesseractWrapperData wrapper = new TesseractWrapperData(OCR_TEXT);
+ processor = new OcrTesseractProcessor(Map.of("DOCUMENTS_TABLE", DOCUMENTS_TABLE,
+ "DOCUMENTS_S3_BUCKET", BUCKET_NAME, "OCR_S3_BUCKET", OCR_BUCKET_NAME), dbConnection,
+ s3Connection, sns, wrapper);
+
+ AwsServiceCache awsServices = processor.getAwsServices();
+ ocrService = awsServices.getExtension(DocumentOcrService.class);
+ s3 = awsServices.getExtension(S3Service.class);
+ actionsService = awsServices.getExtension(ActionsService.class);
+ }
+
+ /** {@link Context}. */
+ private Context context = new LambdaContextRecorder();
+
+ /**
+ * Test S3 File doesn't exist.
+ *
+ * @throws Exception Exception
+ */
+ @Test
+ void testHandleRequest01() throws Exception {
+ // given
+ for (String siteId : Arrays.asList("default", UUID.randomUUID().toString())) {
+
+ String documentId = UUID.randomUUID().toString();
+ String jobId = UUID.randomUUID().toString();
+
+ List actions = Arrays.asList(new Action().type(ActionType.OCR));
+ actionsService.saveActions(siteId, documentId, actions);
+
+ Ocr ocr = new Ocr().siteId(siteId).documentId(documentId).jobId(jobId)
+ .engine(OcrEngine.TESSERACT).status(OcrScanStatus.REQUESTED);
+ ocrService.save(ocr);
+
+ SqsMessageRecord record = new SqsMessageRecord().body(GSON.toJson(Map.of("siteId", siteId,
+ "documentId", documentId, "jobId", jobId, "contentType", MimeType.MIME_JPEG)));
+ SqsMessageRecords records = new SqsMessageRecords().records(Arrays.asList(record));
+
+ String json = GSON.toJson(records);
+ InputStream is = new ByteArrayInputStream(json.getBytes(StandardCharsets.UTF_8));
+
+ // when
+ processor.handleRequest(is, null, this.context);
+
+ // then
+ DynamicObject obj = ocrService.get(siteId, documentId);
+ assertEquals("failed", obj.get("ocrStatus"));
+
+ actions = actionsService.getActions(siteId, documentId);
+ assertEquals(ActionStatus.FAILED, actions.get(0).status());
+ }
+ }
+
+ /**
+ * Test Successful OCR.
+ *
+ * @throws Exception Exception
+ */
+ @Test
+ void testHandleRequest02() throws Exception {
+ // given
+ for (String siteId : Arrays.asList("default", UUID.randomUUID().toString())) {
+
+ String documentId = UUID.randomUUID().toString();
+ String jobId = UUID.randomUUID().toString();
+
+ List actions = Arrays.asList(new Action().type(ActionType.OCR));
+ actionsService.saveActions(siteId, documentId, actions);
+
+ String documentS3Key = createS3Key(siteId, documentId);
+ s3.putObject(BUCKET_NAME, documentS3Key, "testdata".getBytes(StandardCharsets.UTF_8),
+ "text/plain");
+
+ Ocr ocr = new Ocr().siteId(siteId).documentId(documentId).jobId(jobId)
+ .engine(OcrEngine.TESSERACT).status(OcrScanStatus.REQUESTED);
+ ocrService.save(ocr);
+
+ SqsMessageRecord record =
+ new SqsMessageRecord().body(GSON.toJson(Map.of("siteId", siteId, "documentId", documentId,
+ "jobId", jobId, "contentType", MimeType.MIME_JPEG.getContentType())));
+ SqsMessageRecords records = new SqsMessageRecords().records(Arrays.asList(record));
+
+ String json = GSON.toJson(records);
+ InputStream is = new ByteArrayInputStream(json.getBytes(StandardCharsets.UTF_8));
+
+ // when
+ processor.handleRequest(is, null, this.context);
+
+ // then
+ DynamicObject obj = ocrService.get(siteId, documentId);
+ assertEquals("successful", obj.get("ocrStatus"));
+
+ String ocrS3Key = ocrService.getS3Key(siteId, documentId, jobId);
+ assertEquals(OCR_TEXT, s3.getContentAsString(OCR_BUCKET_NAME, ocrS3Key, null));
+
+ actions = actionsService.getActions(siteId, documentId);
+ assertEquals(ActionStatus.COMPLETE, actions.get(0).status());
+ }
+ }
+
+ /**
+ * Test Content Type unknown.
+ *
+ * @throws Exception Exception
+ */
+ @Test
+ void testHandleRequest03() throws Exception {
+ // given
+ for (String siteId : Arrays.asList("default", UUID.randomUUID().toString())) {
+
+ String documentId = UUID.randomUUID().toString();
+ String jobId = UUID.randomUUID().toString();
+
+ List actions = Arrays.asList(new Action().type(ActionType.OCR));
+ actionsService.saveActions(siteId, documentId, actions);
+
+ Ocr ocr = new Ocr().siteId(siteId).documentId(documentId).jobId(jobId)
+ .engine(OcrEngine.TESSERACT).status(OcrScanStatus.REQUESTED);
+ ocrService.save(ocr);
+
+ SqsMessageRecord record = new SqsMessageRecord().body(GSON.toJson(Map.of("siteId", siteId,
+ "documentId", documentId, "jobId", jobId, "contentType", MimeType.MIME_DOCX)));
+ SqsMessageRecords records = new SqsMessageRecords().records(Arrays.asList(record));
+
+ String json = GSON.toJson(records);
+ InputStream is = new ByteArrayInputStream(json.getBytes(StandardCharsets.UTF_8));
+
+ // when
+ processor.handleRequest(is, null, this.context);
+
+ // then
+ DynamicObject obj = ocrService.get(siteId, documentId);
+ assertEquals("failed", obj.get("ocrStatus"));
+
+ actions = actionsService.getActions(siteId, documentId);
+ assertEquals(ActionStatus.FAILED, actions.get(0).status());
+ }
+ }
+
+}
diff --git a/lambda-ocr-tesseract/src/test/java/com/formkiq/module/lambda/ocr/tesseract/TesseractWrapperData.java b/lambda-ocr-tesseract/src/test/java/com/formkiq/module/lambda/ocr/tesseract/TesseractWrapperData.java
new file mode 100644
index 000000000..7326238da
--- /dev/null
+++ b/lambda-ocr-tesseract/src/test/java/com/formkiq/module/lambda/ocr/tesseract/TesseractWrapperData.java
@@ -0,0 +1,53 @@
+/**
+ * MIT License
+ *
+ * Copyright (c) 2018 - 2020 FormKiQ
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package com.formkiq.module.lambda.ocr.tesseract;
+
+import java.io.File;
+import net.sourceforge.tess4j.TesseractException;
+
+/**
+ *
+ * Return Test data for {@link TesseractWrapper}.
+ *
+ */
+public class TesseractWrapperData implements TesseractWrapper {
+
+ /** {@link String}. */
+ private String data;
+
+ /**
+ * constructor.
+ *
+ * @param s {@link String}
+ */
+ public TesseractWrapperData(final String s) {
+ this.data = s;
+ }
+
+ @Override
+ public String doOcr(final File imageFile) throws TesseractException {
+ return this.data;
+ }
+
+}
diff --git a/lambda-s3/.classpath b/lambda-s3/.classpath
index 66f8050c0..58920f4a9 100644
--- a/lambda-s3/.classpath
+++ b/lambda-s3/.classpath
@@ -3,29 +3,41 @@
-
+
-
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lambda-s3/build.gradle b/lambda-s3/build.gradle
index b889c2795..da483d86e 100644
--- a/lambda-s3/build.gradle
+++ b/lambda-s3/build.gradle
@@ -1,8 +1,32 @@
description = "FormKiQ Core - Lambda S3 to Dynamodb"
+sourceSets {
+ integration {
+ java.srcDir "$projectDir/src/integration/java"
+ resources.srcDir "$projectDir/src/integration/resources"
+ compileClasspath += main.output + test.output
+ runtimeClasspath += main.output + test.output
+ }
+}
+
+configurations {
+ integrationImplementation.extendsFrom testImplementation
+ integrationRuntime.extendsFrom testRuntime
+}
+
+def getCmd() {
+ String os = System.getProperty("os.name").toLowerCase()
+ return os.contains("win") ? "cmd" : "bash"
+}
+
+def getCmdParam() {
+ String os = System.getProperty("os.name").toLowerCase()
+ return os.contains("win") ? "/c" : "-c"
+}
+
dependencies {
- annotationProcessor group: 'com.formkiq', name: 'graalvm-annotations-processor', version: '1.2.0'
+ annotationProcessor group: 'com.formkiq', name: 'graalvm-annotations-processor', version: '1.3.0'
implementation project(':aws-s3')
implementation project(':aws-sns')
@@ -17,29 +41,27 @@ dependencies {
implementation project(':http')
implementation group: 'com.amazonaws', name: 'aws-lambda-java-core', version: '1.2.2'
- implementation group: 'com.google.code.gson', name: 'gson', version: '2.10'
+ implementation group: 'com.google.code.gson', name: 'gson', version: '2.10.1'
implementation group: 'com.formkiq', name: 'lambda-runtime-graalvm', version:'2.3.1'
- implementation group: 'com.formkiq', name: 'graalvm-annotations', version: '1.1.0'
- implementation group: 'com.formkiq.stacks', name: 'client', version:'1.10.0-SNAPSHOT'
+ implementation group: 'com.formkiq', name: 'graalvm-annotations', version: '1.2.0'
+ implementation group: 'com.formkiq.stacks', name: 'client', version:'1.10.0'
- implementation group: 'org.slf4j', name: 'slf4j-simple', version: '2.0.6'
+ implementation group: 'org.slf4j', name: 'slf4j-simple', version: '2.0.7'
testImplementation project(':aws-sqs')
testImplementation project(':fkq-test-utils')
- testImplementation group: 'junit', name: 'junit', version:'4.+'
testImplementation group: 'org.apache.commons', name: 'commons-lang3', version: '3.12.0'
- testImplementation group: 'software.amazon.awssdk', name: 'dynamodb', version: '2.19.2'
- testImplementation group: 'software.amazon.awssdk', name: 's3', version: '2.19.2'
+ testImplementation group: 'software.amazon.awssdk', name: 'dynamodb', version: '2.20.33'
+ testImplementation group: 'software.amazon.awssdk', name: 's3', version: '2.20.33'
testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version:'5.9.1'
- testImplementation group: 'org.junit.vintage', name: 'junit-vintage-engine', version:'5.9.1'
testImplementation group: 'org.testcontainers', name: 'testcontainers', version: '1.17.6'
testImplementation group: 'org.testcontainers', name: 'junit-jupiter', version: '1.17.6'
testImplementation group: 'org.testcontainers', name: 'localstack', version: '1.17.6'
- testImplementation group: 'com.amazonaws', name: 'aws-java-sdk', version: '1.12.370'
- testImplementation group: 'org.mock-server', name: 'mockserver-netty', version: '5.14.0'
+ testImplementation group: 'com.amazonaws', name: 'aws-java-sdk', version: '1.12.436'
+ testImplementation group: 'org.mock-server', name: 'mockserver-netty', version: '5.15.0'
}
compileJava {
@@ -59,14 +81,13 @@ nativeImage {
test {
failFast = true
- exclude 'com/formkiq/stacks/lambda/s3/awstest/**'
useJUnitPlatform()
}
-task testaws(type: Test) {
- description = 'Runs AWS integration tests.'
- outputs.upToDateWhen {false}
- include 'com/formkiq/stacks/lambda/s3/awstest/**'
+task integrationTest(type: Test) {
+ testClassesDirs = sourceSets.integration.output.classesDirs
+ classpath = sourceSets.integration.runtimeClasspath
+ useJUnitPlatform()
}
task buildZip(type: Zip) {
@@ -100,7 +121,7 @@ task assembleTemplate {
}
exec {
- commandLine "bash", "-c", "ytt --data-value hash=${sha256} -f src/main/resources/cloudformation/template-sar.yaml > ${buildDir}/distributions/formkiq-core/sam/storage/template.yaml"
+ commandLine getCmd(), getCmdParam(), "ytt --data-value hash=${sha256} -f src/main/resources/cloudformation/template-sar.yaml > ${buildDir}/distributions/formkiq-core/sam/storage/template.yaml"
}
}
}
diff --git a/lambda-s3/src/test/java/com/formkiq/stacks/lambda/s3/awstest/AbstractAwsTest.java b/lambda-s3/src/integration/java/com/formkiq/stacks/lambda/s3/awstest/AbstractAwsTest.java
similarity index 92%
rename from lambda-s3/src/test/java/com/formkiq/stacks/lambda/s3/awstest/AbstractAwsTest.java
rename to lambda-s3/src/integration/java/com/formkiq/stacks/lambda/s3/awstest/AbstractAwsTest.java
index 2e4191fcd..d022c95ec 100644
--- a/lambda-s3/src/test/java/com/formkiq/stacks/lambda/s3/awstest/AbstractAwsTest.java
+++ b/lambda-s3/src/integration/java/com/formkiq/stacks/lambda/s3/awstest/AbstractAwsTest.java
@@ -23,9 +23,9 @@
*/
package com.formkiq.stacks.lambda.s3.awstest;
-import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
import java.io.IOException;
-import org.junit.BeforeClass;
+import org.junit.jupiter.api.BeforeAll;
import com.formkiq.aws.dynamodb.DynamoDbConnectionBuilder;
import com.formkiq.aws.s3.S3ConnectionBuilder;
import com.formkiq.aws.s3.S3ObjectMetadata;
@@ -94,21 +94,25 @@ public abstract class AbstractAwsTest {
*
* @throws IOException IOException
*/
- @BeforeClass
+ @BeforeAll
public static void beforeClass() throws IOException {
awsregion = Region.of(System.getProperty("testregion"));
String awsprofile = System.getProperty("testprofile");
appenvironment = System.getProperty("testappenvironment");
- sqsBuilder = new SqsConnectionBuilder().setCredentials(awsprofile).setRegion(awsregion);
+ boolean enableAwsXray = false;
+ sqsBuilder =
+ new SqsConnectionBuilder(enableAwsXray).setCredentials(awsprofile).setRegion(awsregion);
- ssmBuilder = new SsmConnectionBuilder().setCredentials(awsprofile).setRegion(awsregion);
+ ssmBuilder =
+ new SsmConnectionBuilder(enableAwsXray).setCredentials(awsprofile).setRegion(awsregion);
final S3ConnectionBuilder s3Builder =
- new S3ConnectionBuilder().setCredentials(awsprofile).setRegion(awsregion);
+ new S3ConnectionBuilder(enableAwsXray).setCredentials(awsprofile).setRegion(awsregion);
- snsBuilder = new SnsConnectionBuilder().setCredentials(awsprofile).setRegion(awsregion);
+ snsBuilder =
+ new SnsConnectionBuilder(enableAwsXray).setCredentials(awsprofile).setRegion(awsregion);
sqsService = new SqsService(sqsBuilder);
s3Service = new S3Service(s3Builder);
@@ -128,7 +132,8 @@ public static void beforeClass() throws IOException {
String documentsTable =
ssmService.getParameterValue("/formkiq/" + appenvironment + "/dynamodb/DocumentsTableName");
- dbConnection = new DynamoDbConnectionBuilder().setCredentials(awsprofile).setRegion(awsregion);
+ dbConnection =
+ new DynamoDbConnectionBuilder(false).setCredentials(awsprofile).setRegion(awsregion);
documentService = new DocumentServiceImpl(dbConnection, documentsTable,
new DocumentVersionServiceNoVersioning());
searchService =
diff --git a/lambda-s3/src/test/java/com/formkiq/stacks/lambda/s3/awstest/AwsResourceTest.java b/lambda-s3/src/integration/java/com/formkiq/stacks/lambda/s3/awstest/AwsResourceTest.java
similarity index 96%
rename from lambda-s3/src/test/java/com/formkiq/stacks/lambda/s3/awstest/AwsResourceTest.java
rename to lambda-s3/src/integration/java/com/formkiq/stacks/lambda/s3/awstest/AwsResourceTest.java
index 72545640a..f4563ee35 100644
--- a/lambda-s3/src/test/java/com/formkiq/stacks/lambda/s3/awstest/AwsResourceTest.java
+++ b/lambda-s3/src/integration/java/com/formkiq/stacks/lambda/s3/awstest/AwsResourceTest.java
@@ -25,11 +25,11 @@
import static com.formkiq.aws.dynamodb.SiteIdKeyGenerator.DEFAULT_SITE_ID;
import static com.formkiq.stacks.dynamodb.DocumentService.MAX_RESULTS;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import java.net.URL;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
@@ -48,8 +48,10 @@
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
+import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Timeout;
import com.formkiq.aws.dynamodb.PaginationResults;
import com.formkiq.aws.dynamodb.model.DocumentItem;
import com.formkiq.aws.dynamodb.model.DocumentTag;
@@ -186,7 +188,8 @@ private String subscribeToSns(final String topicArn, final String queueUrl) {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT * 2)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT * 2)
public void testAddDeleteFile01() throws Exception {
// given
String key = UUID.randomUUID().toString();
@@ -234,7 +237,8 @@ public void testAddDeleteFile01() throws Exception {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testAddDeleteFile02() throws Exception {
// given
final Long contentLength = Long.valueOf(36);
@@ -270,7 +274,8 @@ public void testAddDeleteFile02() throws Exception {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testAddDeleteFile03() throws Exception {
// given
final int statusCode = 200;
@@ -323,7 +328,8 @@ public void testAddDeleteFile03() throws Exception {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testAddDeleteFile04() throws Exception {
// given
String key = UUID.randomUUID().toString();
@@ -459,7 +465,8 @@ public void testStageDocumentNotifications() {
*
* @throws Exception Exception
*/
- @Test(timeout = TEST_TIMEOUT)
+ @Test
+ @Timeout(unit = TimeUnit.SECONDS, value = TEST_TIMEOUT)
public void testUpdateStagingFile01() throws Exception {
// given
final String siteId = DEFAULT_SITE_ID;
diff --git a/lambda-s3/src/test/java/com/formkiq/stacks/lambda/s3/awstest/LambdaFunctionConfigurationComparator.java b/lambda-s3/src/integration/java/com/formkiq/stacks/lambda/s3/awstest/LambdaFunctionConfigurationComparator.java
similarity index 100%
rename from lambda-s3/src/test/java/com/formkiq/stacks/lambda/s3/awstest/LambdaFunctionConfigurationComparator.java
rename to lambda-s3/src/integration/java/com/formkiq/stacks/lambda/s3/awstest/LambdaFunctionConfigurationComparator.java
diff --git a/lambda-s3/src/main/java/com/formkiq/stacks/lambda/s3/DocumentAction.java b/lambda-s3/src/main/java/com/formkiq/stacks/lambda/s3/DocumentAction.java
new file mode 100644
index 000000000..f1ed93582
--- /dev/null
+++ b/lambda-s3/src/main/java/com/formkiq/stacks/lambda/s3/DocumentAction.java
@@ -0,0 +1,47 @@
+/**
+ * MIT License
+ *
+ * Copyright (c) 2018 - 2020 FormKiQ
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package com.formkiq.stacks.lambda.s3;
+
+import java.io.IOException;
+import com.amazonaws.services.lambda.runtime.LambdaLogger;
+import com.formkiq.module.actions.Action;
+
+/**
+ *
+ * Document Action interface.
+ *
+ */
+public interface DocumentAction {
+
+ /**
+ * Run Action.
+ *
+ * @param logger {@link LambdaLogger}
+ * @param siteId {@link String}
+ * @param documentId {@link String}
+ * @param action {@link Action}
+ * @throws IOException IOException
+ */
+ void run(LambdaLogger logger, String siteId, String documentId, Action action) throws IOException;
+}
diff --git a/lambda-s3/src/main/java/com/formkiq/stacks/lambda/s3/DocumentActionsProcessor.java b/lambda-s3/src/main/java/com/formkiq/stacks/lambda/s3/DocumentActionsProcessor.java
index c6ea05028..2cc29b0d3 100644
--- a/lambda-s3/src/main/java/com/formkiq/stacks/lambda/s3/DocumentActionsProcessor.java
+++ b/lambda-s3/src/main/java/com/formkiq/stacks/lambda/s3/DocumentActionsProcessor.java
@@ -36,7 +36,6 @@
import java.net.http.HttpClient.Redirect;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
-import java.net.http.HttpResponse.BodyHandlers;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
@@ -52,6 +51,7 @@
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.formkiq.aws.dynamodb.DbKeys;
import com.formkiq.aws.dynamodb.DynamoDbConnectionBuilder;
+import com.formkiq.aws.dynamodb.DynamoDbConnectionBuilderExtension;
import com.formkiq.aws.dynamodb.DynamoDbService;
import com.formkiq.aws.dynamodb.DynamoDbServiceImpl;
import com.formkiq.aws.dynamodb.SiteIdKeyGenerator;
@@ -60,16 +60,18 @@
import com.formkiq.aws.dynamodb.model.DocumentTag;
import com.formkiq.aws.dynamodb.model.DocumentToFulltextDocument;
import com.formkiq.aws.dynamodb.model.DynamicDocumentItem;
+import com.formkiq.aws.dynamodb.objects.MimeType;
import com.formkiq.aws.s3.PresignGetUrlConfig;
import com.formkiq.aws.s3.S3ConnectionBuilder;
import com.formkiq.aws.s3.S3Service;
+import com.formkiq.aws.s3.S3ServiceExtension;
import com.formkiq.aws.sns.SnsConnectionBuilder;
import com.formkiq.aws.ssm.SsmConnectionBuilder;
import com.formkiq.aws.ssm.SsmService;
import com.formkiq.aws.ssm.SsmServiceCache;
+import com.formkiq.aws.ssm.SsmServiceExtension;
import com.formkiq.graalvm.annotations.Reflectable;
import com.formkiq.graalvm.annotations.ReflectableClass;
-import com.formkiq.graalvm.annotations.ReflectableClasses;
import com.formkiq.graalvm.annotations.ReflectableField;
import com.formkiq.graalvm.annotations.ReflectableImport;
import com.formkiq.module.actions.Action;
@@ -82,6 +84,7 @@
import com.formkiq.module.actions.services.NextActionPredicate;
import com.formkiq.module.documentevents.DocumentEvent;
import com.formkiq.module.lambdaservices.AwsServiceCache;
+import com.formkiq.module.lambdaservices.ClassServiceExtension;
import com.formkiq.module.typesense.TypeSenseService;
import com.formkiq.module.typesense.TypeSenseServiceImpl;
import com.formkiq.stacks.client.FormKiqClientConnection;
@@ -89,14 +92,14 @@
import com.formkiq.stacks.client.models.UpdateFulltext;
import com.formkiq.stacks.client.models.UpdateFulltextTag;
import com.formkiq.stacks.client.requests.AddDocumentOcrRequest;
-import com.formkiq.stacks.client.requests.GetDocumentOcrRequest;
import com.formkiq.stacks.client.requests.OcrParseType;
import com.formkiq.stacks.client.requests.SetDocumentAntivirusRequest;
import com.formkiq.stacks.client.requests.UpdateDocumentFulltextRequest;
-import com.formkiq.stacks.common.formats.MimeType;
+import com.formkiq.stacks.dynamodb.ConfigService;
+import com.formkiq.stacks.dynamodb.ConfigServiceExtension;
import com.formkiq.stacks.dynamodb.DocumentItemToDynamicDocumentItem;
import com.formkiq.stacks.dynamodb.DocumentService;
-import com.formkiq.stacks.dynamodb.DocumentServiceImpl;
+import com.formkiq.stacks.dynamodb.DocumentServiceExtension;
import com.formkiq.stacks.dynamodb.DocumentVersionService;
import com.formkiq.stacks.dynamodb.DocumentVersionServiceDynamoDb;
import com.formkiq.stacks.dynamodb.DocumentVersionServiceExtension;
@@ -112,12 +115,11 @@
@Reflectable
@ReflectableImport(classes = {DocumentEvent.class, DocumentVersionServiceDynamoDb.class,
DocumentVersionServiceNoVersioning.class})
-@ReflectableClasses({
- @ReflectableClass(className = UpdateFulltextTag.class, allPublicConstructors = true,
- fields = {@ReflectableField(name = "key"), @ReflectableField(name = "value"),
- @ReflectableField(name = "values")}),
- @ReflectableClass(className = UpdateFulltext.class, allPublicConstructors = true,
- fields = {@ReflectableField(name = "content"), @ReflectableField(name = "contentUrls")})})
+@ReflectableClass(className = UpdateFulltextTag.class, allPublicConstructors = true,
+ fields = {@ReflectableField(name = "key"), @ReflectableField(name = "value"),
+ @ReflectableField(name = "values")})
+@ReflectableClass(className = UpdateFulltext.class, allPublicConstructors = true,
+ fields = {@ReflectableField(name = "content"), @ReflectableField(name = "contentUrls")})
public class DocumentActionsProcessor implements RequestHandler