Skip to content

Commit

Permalink
v1.8.8 (#49)
Browse files Browse the repository at this point in the history
* #44 - DELETE Document API does not work unless a corresponding file exists in S3

* #40 - Add last modified to GET documents and GET document/{id}

* #45 - Metadata records with no corresponding S3 object are causing issues on GET /documents

* #46 - 500 Error in /search endpoint when using large "limit" with "responseFields"

* #48 - File downloads are named using the document ID rather than the original filename

* added POST /documents/{documentId}/actions

* POST /searchFulltext - added pagination
  • Loading branch information
mfriesen authored Sep 25, 2022
1 parent e37eb80 commit 72a54d8
Show file tree
Hide file tree
Showing 97 changed files with 4,122 additions and 1,313 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,10 @@ The following are AWS CloudFormation scripts that can be used to install FormKiQ

| AWS Region | Install Link |
| ------------- | -------------|
| us-east-1 | [Install FormKiQ Core in US-EAST-1 region](https://console.aws.amazon.com/cloudformation/home?region=us-east-1#/stacks/new?stackName=formkiq-core-prod&templateURL=https://formkiq-core-distribution-us-east-1.s3.amazonaws.com/1.8.7/template.yaml)
| us-east-2 | [Install FormKiQ Core in US-EAST-2 region](https://console.aws.amazon.com/cloudformation/home?region=us-east-2#/stacks/new?stackName=formkiq-core-prod&templateURL=https://formkiq-core-distribution-us-east-2.s3.amazonaws.com/1.8.7/template.yaml)
| ca-central-1| [Install FormKiQ Core in CA-CENTRAL-1 region](https://console.aws.amazon.com/cloudformation/home?region=ca-central-1#/stacks/new?stackName=formkiq-core-prod&templateURL=https://formkiq-core-distribution-ca-central-1.s3.amazonaws.com/1.8.7/template.yaml)
| eu-central-1| [Install FormKiQ Core in EU-CENTRAL-1 region](https://console.aws.amazon.com/cloudformation/home?region=eu-central-1#/stacks/new?stackName=formkiq-core-prod&templateURL=https://formkiq-core-distribution-eu-central-1.s3.amazonaws.com/1.8.7/template.yaml)
| us-east-1 | [Install FormKiQ Core in US-EAST-1 region](https://console.aws.amazon.com/cloudformation/home?region=us-east-1#/stacks/new?stackName=formkiq-core-prod&templateURL=https://formkiq-core-distribution-us-east-1.s3.amazonaws.com/1.8.8/template.yaml)
| us-east-2 | [Install FormKiQ Core in US-EAST-2 region](https://console.aws.amazon.com/cloudformation/home?region=us-east-2#/stacks/new?stackName=formkiq-core-prod&templateURL=https://formkiq-core-distribution-us-east-2.s3.amazonaws.com/1.8.8/template.yaml)
| ca-central-1| [Install FormKiQ Core in CA-CENTRAL-1 region](https://console.aws.amazon.com/cloudformation/home?region=ca-central-1#/stacks/new?stackName=formkiq-core-prod&templateURL=https://formkiq-core-distribution-ca-central-1.s3.amazonaws.com/1.8.8/template.yaml)
| eu-central-1| [Install FormKiQ Core in EU-CENTRAL-1 region](https://console.aws.amazon.com/cloudformation/home?region=eu-central-1#/stacks/new?stackName=formkiq-core-prod&templateURL=https://formkiq-core-distribution-eu-central-1.s3.amazonaws.com/1.8.8/template.yaml)

## Architecture

Expand Down
3 changes: 2 additions & 1 deletion actions/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ dependencies {
implementation project(':aws-sns')
implementation project(':document-events')
implementation project(':fkq-lambda-services')
implementation project(':fkq-validation')

testImplementation project(':dynamodb-documents')
testImplementation project(':fkq-test-utils')
testImplementation project(':fkq-plugins')
testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version:'5.9.0'
testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version:'5.9.1'
testImplementation group: 'org.testcontainers', name: 'testcontainers', version: '1.17.3'
}

Expand Down
1 change: 1 addition & 0 deletions actions/config/checkstyle/import-control.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
<allow pkg="com.formkiq.module.actions" />
<allow pkg="com.formkiq.module.documentevents" />
<allow pkg="com.formkiq.module.lambdaservices" />
<allow pkg="com.formkiq.validation" />
<allow pkg="software.amazon.awssdk.services.dynamodb" />
<allow pkg="software.amazon.awssdk.services.dynamodb.model" />
<allow pkg="software.amazon.awssdk.utils" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,16 @@ public interface ActionsService {
List<Map<String, AttributeValue>> saveActions(String siteId, String documentId,
List<Action> actions);

/**
* Save {@link Action}.
*
* @param siteId {@link String}
* @param documentId {@link String}
* @param action {@link Action}
* @param index int
*/
void saveAction(String siteId, String documentId, Action action, int index);

/**
* Update {@link Action} {@link ActionStatus}.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import software.amazon.awssdk.services.dynamodb.model.AttributeValueUpdate;
import software.amazon.awssdk.services.dynamodb.model.BatchWriteItemRequest;
import software.amazon.awssdk.services.dynamodb.model.DeleteItemRequest;
import software.amazon.awssdk.services.dynamodb.model.PutItemRequest;
import software.amazon.awssdk.services.dynamodb.model.PutRequest;
import software.amazon.awssdk.services.dynamodb.model.QueryRequest;
import software.amazon.awssdk.services.dynamodb.model.QueryRequest.Builder;
Expand Down Expand Up @@ -79,6 +80,32 @@ public ActionsServiceDynamoDb(final DynamoDbConnectionBuilder connection,
this.documentTableName = documentsTable;
}

/**
* Build {@link Map} {@link AttributeValue}.
*
* @param siteId {@link String}
* @param documentId {@link String}
* @param action {@link Action}
* @param idx int
* @return {@link Map}
*/
private Map<String, AttributeValue> buildValueMap(final String siteId, final String documentId,
final Action action, final int idx) {

Map<String, AttributeValue> valueMap = new HashMap<>();

String pk = getPk(siteId, documentId);
String sk = getSk(action, idx);
addS(valueMap, PK, pk);
addS(valueMap, SK, sk);
addS(valueMap, "type", action.type().name());
addS(valueMap, "status", action.status().name());
addS(valueMap, "documentId", documentId);
addS(valueMap, "userId", action.userId());
addM(valueMap, "parameters", action.parameters());
return valueMap;
}

@Override
public void deleteActions(final String siteId, final String documentId) {

Expand Down Expand Up @@ -184,6 +211,15 @@ private List<Action> queryActions(final String siteId, final String documentId,
return result.items().stream().map(r -> transform.apply(r)).collect(Collectors.toList());
}

@Override
public void saveAction(final String siteId, final String documentId, final Action action,
final int index) {

Map<String, AttributeValue> valueMap = buildValueMap(siteId, documentId, action, index);
this.dbClient
.putItem(PutItemRequest.builder().tableName(this.documentTableName).item(valueMap).build());
}

@Override
public List<Map<String, AttributeValue>> saveActions(final String siteId, final String documentId,
final List<Action> actions) {
Expand All @@ -194,17 +230,7 @@ public List<Map<String, AttributeValue>> saveActions(final String siteId, final

for (Action action : actions) {

Map<String, AttributeValue> valueMap = new HashMap<>();

String pk = getPk(siteId, documentId);
String sk = getSk(action, idx);
addS(valueMap, PK, pk);
addS(valueMap, SK, sk);
addS(valueMap, "type", action.type().name());
addS(valueMap, "status", action.status().name());
addS(valueMap, "documentId", documentId);
addS(valueMap, "userId", action.userId());
addM(valueMap, "parameters", action.parameters());
Map<String, AttributeValue> valueMap = buildValueMap(siteId, documentId, action, idx);

values.add(valueMap);
idx++;
Expand Down
Original file line number Diff line number Diff line change
@@ -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.actions.services;

import java.util.Collection;
import java.util.List;
import com.formkiq.module.actions.Action;
import com.formkiq.validation.ValidationError;

/**
*
* {@link Action} Validator.
*
*/
public interface ActionsValidator {

/**
* Validates {@link Action}.
*
* @param action {@link Action}
* @return {@link Collection} {@link ValidationError}
*/
Collection<ValidationError> validation(Action action);

/**
* Validates {@link List} {@link Action}.
*
* @param action {@link Action}
* @return {@link List} {@link Collection} {@link ValidationError}
*/
List<Collection<ValidationError>> validation(List<Action> action);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/**
* 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.actions.services;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import com.formkiq.module.actions.Action;
import com.formkiq.module.actions.ActionType;
import com.formkiq.validation.ValidationError;
import com.formkiq.validation.ValidationErrorImpl;

/**
*
* {@link ActionsValidator}.
*
*/
public class ActionsValidatorImpl implements ActionsValidator {

@Override
public Collection<ValidationError> validation(final Action action) {
Collection<ValidationError> errors = new ArrayList<>();

if (action == null) {

errors.add(new ValidationErrorImpl().error("action is required"));

} else {

if (action.type() == null) {

errors.add(new ValidationErrorImpl().key("type").error("'type' is required"));

} else {

Map<String, String> parameters =
action.parameters() != null ? action.parameters() : Collections.emptyMap();
if (ActionType.WEBHOOK.equals(action.type()) && !parameters.containsKey("url")) {
errors.add(
new ValidationErrorImpl().key("parameters.url").error("'url' parameter is required"));
}
}
}

return errors;
}

@Override
public List<Collection<ValidationError>> validation(final List<Action> actions) {
List<Collection<ValidationError>> errors = new ArrayList<>();
actions.forEach(a -> errors.add(validation(a)));
return errors;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/**
* 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.actions.services;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import org.junit.jupiter.api.Test;
import com.formkiq.module.actions.Action;
import com.formkiq.module.actions.ActionType;
import com.formkiq.validation.ValidationError;

class ActionsValidatorTest {

/** {@link ActionsValidator}. */
private ActionsValidator validator = new ActionsValidatorImpl();

@Test
void testValidation01() {
// given
Action action = null;

// when
Collection<ValidationError> errors = this.validator.validation(action);

// then
assertEquals(1, errors.size());
ValidationError error = errors.iterator().next();
assertNull(error.key());
assertEquals("action is required", error.error());
}

@Test
void testValidation02() {
// given
Action action = new Action();

// when
Collection<ValidationError> errors = this.validator.validation(action);

// then
assertEquals(1, errors.size());
ValidationError error = errors.iterator().next();
assertEquals("type", error.key());
assertEquals("'type' is required", error.error());
}

@Test
void testValidation03() {
// given
Action action = new Action().type(ActionType.WEBHOOK);

// when
Collection<ValidationError> errors = this.validator.validation(action);

// then
assertEquals(1, errors.size());
ValidationError error = errors.iterator().next();
assertEquals("parameters.url", error.key());
assertEquals("'url' parameter is required", error.error());
}

@Test
void testValidation04() {
// given
Action action = new Action();
List<Action> actions = Arrays.asList(action);

// when
List<Collection<ValidationError>> errorList = this.validator.validation(actions);

// then
assertEquals(1, errorList.size());

Collection<ValidationError> errors = errorList.get(0);
ValidationError error = errors.iterator().next();
assertEquals("type", error.key());
assertEquals("'type' is required", error.error());
}

@Test
void testValidation05() {
// given
Action action = new Action().type(ActionType.OCR);

// when
Collection<ValidationError> errorList = this.validator.validation(action);

// then
assertEquals(0, errorList.size());
}
}
Loading

0 comments on commit 72a54d8

Please sign in to comment.