Skip to content

Commit

Permalink
Added bypassWatermark query parameter for GET /documents/:id/url
Browse files Browse the repository at this point in the history
  • Loading branch information
mfriesen committed Jan 30, 2025
1 parent 8f619c7 commit 02b7ff1
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,12 @@
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.formkiq.aws.dynamodb.ApiPermission;
import com.formkiq.aws.dynamodb.model.DocumentItem;
import com.formkiq.aws.dynamodb.objects.MimeType;
import com.formkiq.aws.dynamodb.objects.Strings;
Expand All @@ -57,6 +60,8 @@
import com.formkiq.stacks.dynamodb.DocumentService;
import com.formkiq.stacks.dynamodb.DocumentVersionService;
import com.formkiq.stacks.dynamodb.attributes.DocumentAttributeValueType;
import com.formkiq.validation.ValidationErrorImpl;
import com.formkiq.validation.ValidationException;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;

/** {@link ApiGatewayRequestHandler} for "/documents/{documentId}/url". */
Expand All @@ -83,12 +88,9 @@ public ApiRequestHandlerResponse get(final ApiGatewayRequestEvent event,
getDocumentItem(awsservice, siteId, documentId, versionKey, versionAttributes);
String versionId = getVersionId(awsservice, versionAttributes, versionKey);

DocumentService documentService = awsservice.getExtension(DocumentService.class);
boolean hasWatermarks = !documentService.findDocumentAttributesByType(siteId, documentId,
DocumentAttributeValueType.WATERMARK, null, 1).getResults().isEmpty();

boolean inline = "true".equals(getParameter(event, "inline"));
URL url = getS3Url(authorization, awsservice, event, item, versionId, inline, hasWatermarks);
boolean bypassWatermark = isBypassWatermark(event, authorization, siteId);
URL url = getS3Url(authorization, awsservice, event, item, versionId, inline, bypassWatermark);

if (url != null) {
if (awsservice.containsExtension(UserActivityPlugin.class)) {
Expand All @@ -102,6 +104,24 @@ public ApiRequestHandlerResponse get(final ApiGatewayRequestEvent event,
: new ApiRequestHandlerResponse(SC_NOT_FOUND, new ApiEmptyResponse());
}

private boolean isBypassWatermark(final ApiGatewayRequestEvent event,
final ApiAuthorization authorization, final String siteId) throws ValidationException {

boolean isBypassWatermark = "true".equals(getParameter(event, "bypassWatermark"));

Collection<ApiPermission> permissions = authorization.getPermissions(siteId);
if (isBypassWatermark) {

if (!permissions.contains(ApiPermission.ADMIN)
&& !permissions.contains(ApiPermission.GOVERN)) {
throw new ValidationException(List
.of(new ValidationErrorImpl().error("user requires 'admin' or 'govern' permission")));
}
}

return isBypassWatermark;
}

private String getVersionKey(final ApiGatewayRequestEvent event) {
String versionKey = getParameter(event, "versionKey");
if (!isEmpty(versionKey) && !versionKey.startsWith("document#")) {
Expand Down Expand Up @@ -145,14 +165,14 @@ public String getRequestUrl() {
* @param item {@link DocumentItem}
* @param versionId {@link String}
* @param inline boolean
* @param hasWatermarks boolean
* @param bypassWatermark boolean
* @return {@link URL}
* @throws URISyntaxException URISyntaxException
* @throws MalformedURLException MalformedURLException
*/
private URL getS3Url(final ApiAuthorization authorization, final AwsServiceCache awsservice,
final ApiGatewayRequestEvent event, final DocumentItem item, final String versionId,
final boolean inline, final boolean hasWatermarks)
final boolean inline, final boolean bypassWatermark)
throws URISyntaxException, MalformedURLException {

final String documentId = item.getDocumentId();
Expand All @@ -162,8 +182,13 @@ private URL getS3Url(final ApiAuthorization authorization, final AwsServiceCache
awsservice.getLogger().debug(
"Finding S3 Url for document '" + item.getDocumentId() + "' version = '" + versionId + "'");

String s3Bucket = hasWatermarks ? awsservice.environment("ACCESS_POINT_S3_BUCKET")
: awsservice.environment("DOCUMENTS_S3_BUCKET");
DocumentService documentService = awsservice.getExtension(DocumentService.class);
boolean hasWatermarks = !documentService.findDocumentAttributesByType(siteId, documentId,
DocumentAttributeValueType.WATERMARK, null, 1).getResults().isEmpty();

String s3Bucket =
!bypassWatermark && hasWatermarks ? awsservice.environment("ACCESS_POINT_S3_BUCKET")
: awsservice.environment("DOCUMENTS_S3_BUCKET");
String filename = getFilename(item);

PresignGetUrlConfig config = new PresignGetUrlConfig();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
*/
package com.formkiq.stacks.api.handler;

import static com.formkiq.aws.dynamodb.SiteIdKeyGenerator.DEFAULT_SITE_ID;
import static com.formkiq.testutils.aws.TestServices.ACCESS_POINT_S3_BUCKET;
import static com.formkiq.testutils.aws.TestServices.AWS_REGION;
import static com.formkiq.testutils.aws.TestServices.BUCKET_NAME;
Expand Down Expand Up @@ -127,7 +128,7 @@ public void testHandleGetDocumentContent01() throws Exception {

// when
GetDocumentUrlResponse resp =
this.documentsApi.getDocumentUrl(documentId, siteId, null, null, null, null);
this.documentsApi.getDocumentUrl(documentId, siteId, null, null, null, null, null);

// then
assertNotNull(resp);
Expand Down Expand Up @@ -165,7 +166,7 @@ public void testHandleGetDocumentContent02() throws Exception {

// when
GetDocumentUrlResponse resp =
this.documentsApi.getDocumentUrl(documentId, siteId, null, duration, null, null);
this.documentsApi.getDocumentUrl(documentId, siteId, null, duration, null, null, null);

// then
assertNotNull(resp);
Expand Down Expand Up @@ -193,7 +194,7 @@ public void testHandleGetDocumentContent03() {

// when
try {
this.documentsApi.getDocumentUrl(documentId, siteId, null, null, null, null);
this.documentsApi.getDocumentUrl(documentId, siteId, null, null, null, null, null);
fail();
} catch (ApiException e) {
// then
Expand Down Expand Up @@ -234,7 +235,7 @@ public void testHandleGetDocumentContent04() throws Exception {

// when
GetDocumentUrlResponse resp =
this.documentsApi.getDocumentUrl(documentId, siteId, null, duration, null, null);
this.documentsApi.getDocumentUrl(documentId, siteId, null, duration, null, null, null);

// then
assertNotNull(resp);
Expand Down Expand Up @@ -284,7 +285,7 @@ public void testHandleGetDocumentContent05() throws Exception {

// when
GetDocumentUrlResponse resp =
this.documentsApi.getDocumentUrl(documentId, siteId, null, null, null, null);
this.documentsApi.getDocumentUrl(documentId, siteId, null, null, null, null, null);

// then
assertNotNull(resp);
Expand All @@ -303,25 +304,11 @@ public void testHandleGetDocumentContent06() throws Exception {
// given
setBearerToken(siteId);

Watermark watermark1 = new Watermark().text("watermark1");
this.attributesApi.addAttribute(new AddAttributeRequest().attribute(new AddAttribute()
.key("wm1").dataType(AttributeDataType.WATERMARK).watermark(watermark1)), siteId);

Watermark watermark2 = new Watermark().text("watermark2");
this.attributesApi.addAttribute(new AddAttributeRequest().attribute(new AddAttribute()
.key("wm2").dataType(AttributeDataType.WATERMARK).watermark(watermark2)), siteId);

AddDocumentRequest req = new AddDocumentRequest().content("test content")
.addAttributesItem(
new AddDocumentAttribute(new AddDocumentAttributeStandard().key("wm1")))
.addAttributesItem(
new AddDocumentAttribute(new AddDocumentAttributeStandard().key("wm2")));

String documentId = this.documentsApi.addDocument(req, siteId, null).getDocumentId();
String documentId = addDocumentWithWatermarks(siteId);

// when
GetDocumentUrlResponse resp =
this.documentsApi.getDocumentUrl(documentId, siteId, null, null, null, null);
this.documentsApi.getDocumentUrl(documentId, siteId, null, null, null, null, null);

// then
assertNotNull(resp);
Expand All @@ -330,6 +317,78 @@ public void testHandleGetDocumentContent06() throws Exception {
}
}

/**
* /documents/{documentId}/url with watermarks and ByPassWatermark as Admin/govern.
*
* @throws Exception an error has occurred
*/
@Test
public void testHandleGetDocumentContent07() throws Exception {
for (String siteId : Arrays.asList(DEFAULT_SITE_ID, ID.uuid())) {
// given
setBearerToken(siteId);
String documentId = addDocumentWithWatermarks(siteId);

for (String[] groups : Arrays.asList(new String[] {siteId, "admins"},
new String[] {siteId, siteId + "_govern"})) {
setBearerToken(groups);

// when
GetDocumentUrlResponse resp = this.documentsApi.getDocumentUrl(documentId, siteId, null,
null, null, null, Boolean.TRUE);

// then
assertNotNull(resp);
assertNotNull(resp.getUrl());
assertS3Url(resp, BUCKET_NAME, DEFAULT_SITE_ID.equals(siteId) ? null : siteId, documentId);
}
}
}

/**
* /documents/{documentId}/url with watermarks and ByPassWatermark without permissions.
*
* @throws Exception an error has occurred
*/
@Test
public void testHandleGetDocumentContent08() throws Exception {
for (String siteId : Arrays.asList(null, ID.uuid())) {
// given
setBearerToken(siteId);

String documentId = addDocumentWithWatermarks(siteId);

// when
try {
this.documentsApi.getDocumentUrl(documentId, siteId, null, null, null, null, Boolean.TRUE);
fail();
} catch (ApiException e) {
// then
assertEquals(ApiResponseStatus.SC_BAD_REQUEST.getStatusCode(), e.getCode());
assertEquals("{\"errors\":[{\"error\":\"user requires 'admin' or 'govern' permission\"}]}",
e.getResponseBody());
}
}
}

private String addDocumentWithWatermarks(final String siteId) throws ApiException {
Watermark watermark1 = new Watermark().text("watermark1");
this.attributesApi.addAttribute(new AddAttributeRequest().attribute(
new AddAttribute().key("wm1").dataType(AttributeDataType.WATERMARK).watermark(watermark1)),
siteId);

Watermark watermark2 = new Watermark().text("watermark2");
this.attributesApi.addAttribute(new AddAttributeRequest().attribute(
new AddAttribute().key("wm2").dataType(AttributeDataType.WATERMARK).watermark(watermark2)),
siteId);

AddDocumentRequest req = new AddDocumentRequest().content("test content")
.addAttributesItem(new AddDocumentAttribute(new AddDocumentAttributeStandard().key("wm1")))
.addAttributesItem(new AddDocumentAttribute(new AddDocumentAttributeStandard().key("wm2")));

return this.documentsApi.addDocument(req, siteId, null).getDocumentId();
}

private void assertS3Url(final GetDocumentUrlResponse resp, final String bucket,
final String siteId, final String documentId) {
assertNotNull(resp.getUrl());
Expand Down

0 comments on commit 02b7ff1

Please sign in to comment.