From 9ab12d60ba07970099420ad326face8a72b4a657 Mon Sep 17 00:00:00 2001 From: Jeff Registre <8570494+jregistr@users.noreply.github.com> Date: Tue, 17 Dec 2024 17:59:21 -0500 Subject: [PATCH] Sync feature release changes (#64) --- .../aws-qbusiness-application.json | 70 +++++++++------ aws-qbusiness-application/resource-role.yaml | 2 + .../qbusiness/application/Translator.java | 27 ++++++ .../application/CreateHandlerTest.java | 9 ++ .../application/ReadHandlerTest.java | 5 ++ .../aws-qbusiness-datasource.json | 31 +++++++ .../qbusiness/datasource/Translator.java | 5 ++ ...ediaExtractionConfigurationTranslator.java | 61 +++++++++++++ .../datasource/CreateHandlerTest.java | 5 ++ .../qbusiness/datasource/ReadHandlerTest.java | 5 ++ .../datasource/UpdateHandlerTest.java | 9 ++ .../aws-qbusiness-plugin.json | 42 +++++++-- .../qbusiness/plugin/AuthConfigHelper.java | 4 + .../amazon/qbusiness/plugin/Translator.java | 7 +- .../qbusiness/plugin/UpdateHandler.java | 5 +- .../amazon/qbusiness/plugin/Utils.java | 34 ++++++++ .../qbusiness/plugin/ReadHandlerTest.java | 86 +++++++++++++++++++ .../aws-qbusiness-webexperience.json | 33 +++++++ .../qbusiness/webexperience/Translator.java | 33 +++++++ .../webexperience/CreateHandlerTest.java | 21 ++++- .../webexperience/ReadHandlerTest.java | 20 +++++ .../webexperience/UpdateHandlerTest.java | 19 ++++ pom.xml | 2 +- 23 files changed, 498 insertions(+), 37 deletions(-) mode change 100755 => 100644 aws-qbusiness-application/aws-qbusiness-application.json create mode 100644 aws-qbusiness-datasource/src/main/java/software/amazon/qbusiness/datasource/translators/MediaExtractionConfigurationTranslator.java mode change 100755 => 100644 aws-qbusiness-plugin/aws-qbusiness-plugin.json create mode 100644 aws-qbusiness-plugin/src/main/java/software/amazon/qbusiness/plugin/Utils.java diff --git a/aws-qbusiness-application/aws-qbusiness-application.json b/aws-qbusiness-application/aws-qbusiness-application.json old mode 100755 new mode 100644 index 4d35490..02d3a3d --- a/aws-qbusiness-application/aws-qbusiness-application.json +++ b/aws-qbusiness-application/aws-qbusiness-application.json @@ -69,7 +69,27 @@ "enum": [ "AWS_IAM_IDP_SAML", "AWS_IAM_IDP_OIDC", - "AWS_IAM_IDC" + "AWS_IAM_IDC", + "AWS_QUICKSIGHT_IDP" + ] + }, + "PersonalizationConfiguration": { + "type": "object", + "properties": { + "PersonalizationControlMode": { + "$ref": "#/definitions/PersonalizationControlMode" + } + }, + "required": [ + "PersonalizationControlMode" + ], + "additionalProperties": false + }, + "PersonalizationControlMode": { + "type": "string", + "enum": [ + "ENABLED", + "DISABLED" ] }, "QAppsConfiguration": { @@ -91,30 +111,26 @@ "DISABLED" ] }, - "SubscriptionType": { - "type": "string", - "enum": [ - "Q_LITE", - "Q_BUSINESS" - ] - }, - "PersonalizationConfiguration": { + "QuickSightConfiguration": { "type": "object", "properties": { - "PersonalizationControlMode": { - "$ref": "#/definitions/PersonalizationControlMode" + "ClientNamespace": { + "type": "string", + "maxLength": 64, + "minLength": 1, + "pattern": "^[a-zA-Z0-9._-]*$" } }, "required": [ - "PersonalizationControlMode" + "ClientNamespace" ], "additionalProperties": false }, - "PersonalizationControlMode": { + "SubscriptionType": { "type": "string", "enum": [ - "ENABLED", - "DISABLED" + "Q_LITE", + "Q_BUSINESS" ] }, "Tag": { @@ -159,7 +175,6 @@ }, "ClientIdsForOIDC": { "type": "array", - "insertionOrder": false, "items": { "type": "string", "maxLength": 255, @@ -198,12 +213,6 @@ "minLength": 10, "pattern": "^arn:(aws|aws-us-gov|aws-cn|aws-iso|aws-iso-b):sso::\\d{12}:application/(sso)?ins-[a-zA-Z0-9-.]{16}/apl-[a-zA-Z0-9]{16}$" }, - "QAppsConfiguration": { - "$ref": "#/definitions/QAppsConfiguration" - }, - "PersonalizationConfiguration": { - "$ref": "#/definitions/PersonalizationConfiguration" - }, "IdentityCenterInstanceArn": { "type": "string", "maxLength": 1224, @@ -213,6 +222,15 @@ "IdentityType": { "$ref": "#/definitions/IdentityType" }, + "PersonalizationConfiguration": { + "$ref": "#/definitions/PersonalizationConfiguration" + }, + "QAppsConfiguration": { + "$ref": "#/definitions/QAppsConfiguration" + }, + "QuickSightConfiguration": { + "$ref": "#/definitions/QuickSightConfiguration" + }, "RoleArn": { "type": "string", "maxLength": 1284, @@ -224,7 +242,6 @@ }, "Tags": { "type": "array", - "insertionOrder": false, "items": { "$ref": "#/definitions/Tag" }, @@ -254,7 +271,8 @@ "/properties/ClientIdsForOIDC", "/properties/EncryptionConfiguration", "/properties/IamIdentityProviderArn", - "/properties/IdentityType" + "/properties/IdentityType", + "/properties/QuickSightConfiguration" ], "primaryIdentifier": [ "/properties/ApplicationId" @@ -268,9 +286,11 @@ "kms:DescribeKey", "qbusiness:CreateApplication", "qbusiness:GetApplication", - "qbusiness:UpdateApplication", "qbusiness:ListTagsForResource", "qbusiness:TagResource", + "qbusiness:UpdateApplication", + "quicksight:DescribeAccountSubscription", + "quicksight:ListNamespaces", "sso:CreateApplication", "sso:DeleteApplication", "sso:DescribeInstance", diff --git a/aws-qbusiness-application/resource-role.yaml b/aws-qbusiness-application/resource-role.yaml index 9068825..fbcbe36 100644 --- a/aws-qbusiness-application/resource-role.yaml +++ b/aws-qbusiness-application/resource-role.yaml @@ -43,6 +43,8 @@ Resources: - "qbusiness:TagResource" - "qbusiness:UntagResource" - "qbusiness:UpdateApplication" + - "quicksight:DescribeAccountSubscription" + - "quicksight:ListNamespaces" - "sso:CreateApplication" - "sso:DeleteApplication" - "sso:DescribeInstance" diff --git a/aws-qbusiness-application/src/main/java/software/amazon/qbusiness/application/Translator.java b/aws-qbusiness-application/src/main/java/software/amazon/qbusiness/application/Translator.java index b583059..0bfc331 100644 --- a/aws-qbusiness-application/src/main/java/software/amazon/qbusiness/application/Translator.java +++ b/aws-qbusiness-application/src/main/java/software/amazon/qbusiness/application/Translator.java @@ -61,6 +61,7 @@ static CreateApplicationRequest translateToCreateRequest( .tags(merged) .qAppsConfiguration(toServiceQAppsConfiguration(model.getQAppsConfiguration())) .personalizationConfiguration(toServicePersonalizationConfiguration(model.getPersonalizationConfiguration())) + .quickSightConfiguration(toQuickSightConfiguration(model.getQuickSightConfiguration())) .build(); } @@ -109,6 +110,7 @@ static ResourceModel translateFromReadResponse(final GetApplicationResponse awsR .qAppsConfiguration(fromServiceQAppsConfiguration(awsResponse.qAppsConfiguration())) .personalizationConfiguration(fromServicePersonalizationConfiguration(awsResponse.personalizationConfiguration())) .autoSubscriptionConfiguration(fromServiceAutoSubscriptionConfiguration(awsResponse.autoSubscriptionConfiguration())) + .quickSightConfiguration(fromQuickSightConfiguration(awsResponse.quickSightConfiguration())) .build(); // TODO: Workaround. This is a readonly field. But it is only returned if customer is using IDC // When that's not the case, let's fill it in with N/A @@ -221,6 +223,30 @@ static software.amazon.awssdk.services.qbusiness.model.PersonalizationConfigurat .build(); } + static QuickSightConfiguration fromQuickSightConfiguration( + software.amazon.awssdk.services.qbusiness.model.QuickSightConfiguration quickSightConfiguration + ) { + if (quickSightConfiguration == null) { + return null; + } + + return QuickSightConfiguration.builder() + .clientNamespace(quickSightConfiguration.clientNamespace()) + .build(); + } + + static software.amazon.awssdk.services.qbusiness.model.QuickSightConfiguration toQuickSightConfiguration( + QuickSightConfiguration modelConfig + ) { + if (modelConfig == null) { + return null; + } + + return software.amazon.awssdk.services.qbusiness.model.QuickSightConfiguration.builder() + .clientNamespace(modelConfig.getClientNamespace()) + .build(); + } + static AutoSubscriptionConfiguration fromServiceAutoSubscriptionConfiguration( software.amazon.awssdk.services.qbusiness.model.AutoSubscriptionConfiguration serviceConfig ) { @@ -350,6 +376,7 @@ static List translateFromListResponse(final ListApplicationsRespo .updatedAt(instantToString(application.updatedAt())) .status(application.statusAsString()) .identityType(application.identityTypeAsString()) + .quickSightConfiguration(fromQuickSightConfiguration(application.quickSightConfiguration())) .build() ) .toList(); diff --git a/aws-qbusiness-application/src/test/java/software/amazon/qbusiness/application/CreateHandlerTest.java b/aws-qbusiness-application/src/test/java/software/amazon/qbusiness/application/CreateHandlerTest.java index fb32376..6213984 100644 --- a/aws-qbusiness-application/src/test/java/software/amazon/qbusiness/application/CreateHandlerTest.java +++ b/aws-qbusiness-application/src/test/java/software/amazon/qbusiness/application/CreateHandlerTest.java @@ -60,6 +60,7 @@ public class CreateHandlerTest extends AbstractTestBase { private static final String APP_ID = "a197dafc-2158-4f93-ab0d-b1c361c39838"; + private static final String CLIENT_NAMESPACE = "client-namespace"; @Mock private AmazonWebServicesClientProxy proxy; @@ -104,6 +105,9 @@ public void setup() { .build()) .iamIdentityProviderArn("arn:aws:iam::123456:oidc-provider/trial-123456.okta.com") .clientIdsForOIDC(List.of("0oaglq4vdnaWau7hW697")) + .quickSightConfiguration(QuickSightConfiguration.builder() + .clientNamespace(CLIENT_NAMESPACE) + .build()) .tags(List.of( Tag.builder().key("TagA").value("ValueA").build() )) @@ -156,6 +160,10 @@ public void handleRequest_SimpleSuccess() { .description(createModel.getDescription()) .displayName(createModel.getDisplayName()) .roleArn(createModel.getRoleArn()) + .quickSightConfiguration( + software.amazon.awssdk.services.qbusiness.model.QuickSightConfiguration.builder() + .clientNamespace(CLIENT_NAMESPACE) + .build()) .build()); // call method under test @@ -171,6 +179,7 @@ proxy, testRequest, new CallbackContext(), proxyClient, logger assertThat(model.getRoleArn()).isEqualTo(createModel.getRoleArn()); assertThat(model.getDescription()).isEqualTo(createModel.getDescription()); assertThat(model.getStatus()).isEqualTo(ApplicationStatus.ACTIVE.toString()); + assertThat(model.getQuickSightConfiguration().getClientNamespace()).isEqualTo(CLIENT_NAMESPACE); ArgumentCaptor createAppReqCaptor = ArgumentCaptor.forClass(CreateApplicationRequest.class); verify(sdkClient).createApplication(createAppReqCaptor.capture()); diff --git a/aws-qbusiness-application/src/test/java/software/amazon/qbusiness/application/ReadHandlerTest.java b/aws-qbusiness-application/src/test/java/software/amazon/qbusiness/application/ReadHandlerTest.java index 3248447..bd5113c 100644 --- a/aws-qbusiness-application/src/test/java/software/amazon/qbusiness/application/ReadHandlerTest.java +++ b/aws-qbusiness-application/src/test/java/software/amazon/qbusiness/application/ReadHandlerTest.java @@ -30,6 +30,7 @@ import software.amazon.awssdk.services.qbusiness.model.AttachmentsControlMode; import software.amazon.awssdk.services.qbusiness.model.AutoSubscriptionConfiguration; import software.amazon.awssdk.services.qbusiness.model.AutoSubscriptionStatus; +import software.amazon.awssdk.services.qbusiness.model.QuickSightConfiguration; import software.amazon.awssdk.services.qbusiness.model.SubscriptionType; import software.amazon.awssdk.services.qbusiness.model.EncryptionConfiguration; import software.amazon.awssdk.services.qbusiness.model.QBusinessException; @@ -124,6 +125,9 @@ public void handleRequest_SimpleSuccess() { .autoSubscribe(AutoSubscriptionStatus.ENABLED.toString()) .defaultSubscriptionType(SubscriptionType.Q_BUSINESS.toString()) .build()) + .quickSightConfiguration(QuickSightConfiguration.builder() + .clientNamespace("client-namespace") + .build()) .build()); when(proxyClient.client().listTagsForResource(any(ListTagsForResourceRequest.class))) .thenReturn(ListTagsForResourceResponse.builder() @@ -161,6 +165,7 @@ proxy, testRequest, new CallbackContext(), proxyClient, logger assertThat(resultModel.getAttachmentsConfiguration().getAttachmentsControlMode()).isEqualTo(AttachmentsControlMode.ENABLED.toString()); assertThat(resultModel.getAutoSubscriptionConfiguration().getAutoSubscribe()).isEqualTo(AutoSubscriptionStatus.ENABLED.toString()); assertThat(resultModel.getAutoSubscriptionConfiguration().getDefaultSubscriptionType()).isEqualTo(SubscriptionType.Q_BUSINESS.toString()); + assertThat(resultModel.getQuickSightConfiguration().getClientNamespace()).isEqualTo("client-namespace"); var tags = resultModel.getTags().stream().map(tag -> Map.entry(tag.getKey(), tag.getValue())).toList(); diff --git a/aws-qbusiness-datasource/aws-qbusiness-datasource.json b/aws-qbusiness-datasource/aws-qbusiness-datasource.json index 81069a4..a8bb32a 100755 --- a/aws-qbusiness-datasource/aws-qbusiness-datasource.json +++ b/aws-qbusiness-datasource/aws-qbusiness-datasource.json @@ -180,6 +180,34 @@ "BEGINS_WITH" ] }, + "ImageExtractionStatus": { + "type": "string", + "enum": [ + "ENABLED", + "DISABLED" + ] + }, + "ImageExtractionConfiguration": { + "type": "object", + "properties": { + "ImageExtractionStatus": { + "$ref": "#/definitions/ImageExtractionStatus" + } + }, + "required": [ + "ImageExtractionStatus" + ], + "additionalProperties": false + }, + "MediaExtractionConfiguration": { + "type": "object", + "properties": { + "ImageExtractionConfiguration": { + "$ref": "#/definitions/ImageExtractionConfiguration" + } + }, + "additionalProperties": false + }, "DocumentEnrichmentConfiguration": { "type": "object", "properties": { @@ -303,6 +331,9 @@ "DocumentEnrichmentConfiguration": { "$ref": "#/definitions/DocumentEnrichmentConfiguration" }, + "MediaExtractionConfiguration": { + "$ref": "#/definitions/MediaExtractionConfiguration" + }, "IndexId": { "type": "string", "maxLength": 36, diff --git a/aws-qbusiness-datasource/src/main/java/software/amazon/qbusiness/datasource/Translator.java b/aws-qbusiness-datasource/src/main/java/software/amazon/qbusiness/datasource/Translator.java index b792fe4..d914c6b 100644 --- a/aws-qbusiness-datasource/src/main/java/software/amazon/qbusiness/datasource/Translator.java +++ b/aws-qbusiness-datasource/src/main/java/software/amazon/qbusiness/datasource/Translator.java @@ -4,6 +4,8 @@ import static software.amazon.qbusiness.datasource.translators.DocumentConverter.convertToMapToDocument; import static software.amazon.qbusiness.datasource.translators.DocumentEnrichmentTranslator.fromServiceDocEnrichmentConf; import static software.amazon.qbusiness.datasource.translators.DocumentEnrichmentTranslator.toServiceDocEnrichmentConf; +import static software.amazon.qbusiness.datasource.translators.MediaExtractionConfigurationTranslator.fromServiceMediaExtractionConfiguration; +import static software.amazon.qbusiness.datasource.translators.MediaExtractionConfigurationTranslator.toServiceMediaExtractionConfiguration; import java.time.Instant; import java.util.Collection; @@ -49,6 +51,7 @@ static CreateDataSourceRequest translateToCreateRequest(final String idempotency .vpcConfiguration(toServiceDataSourceVpcConfiguration(model.getVpcConfiguration())) .configuration(convertToMapToDocument(model.getConfiguration())) .documentEnrichmentConfiguration(toServiceDocEnrichmentConf(model.getDocumentEnrichmentConfiguration())) + .mediaExtractionConfiguration(toServiceMediaExtractionConfiguration(model.getMediaExtractionConfiguration())) .build(); } @@ -89,6 +92,7 @@ static ResourceModel translateFromReadResponse(final GetDataSourceResponse awsRe .vpcConfiguration(fromServiceDataSourceVpcConfiguration(awsResponse.vpcConfiguration())) .configuration(convertDocumentToMap(awsResponse.configuration())) .documentEnrichmentConfiguration(fromServiceDocEnrichmentConf(awsResponse.documentEnrichmentConfiguration())) + .mediaExtractionConfiguration(fromServiceMediaExtractionConfiguration(awsResponse.mediaExtractionConfiguration())) .build(); } @@ -171,6 +175,7 @@ static UpdateDataSourceRequest translateToUpdateRequest(final ResourceModel mode .vpcConfiguration(toServiceDataSourceVpcConfiguration(model.getVpcConfiguration())) .configuration(convertToMapToDocument(model.getConfiguration())) .documentEnrichmentConfiguration(toServiceDocEnrichmentConf(model.getDocumentEnrichmentConfiguration())) + .mediaExtractionConfiguration(toServiceMediaExtractionConfiguration(model.getMediaExtractionConfiguration())) .build(); } diff --git a/aws-qbusiness-datasource/src/main/java/software/amazon/qbusiness/datasource/translators/MediaExtractionConfigurationTranslator.java b/aws-qbusiness-datasource/src/main/java/software/amazon/qbusiness/datasource/translators/MediaExtractionConfigurationTranslator.java new file mode 100644 index 0000000..94a6ed6 --- /dev/null +++ b/aws-qbusiness-datasource/src/main/java/software/amazon/qbusiness/datasource/translators/MediaExtractionConfigurationTranslator.java @@ -0,0 +1,61 @@ +package software.amazon.qbusiness.datasource.translators; + +import software.amazon.qbusiness.datasource.ImageExtractionConfiguration; +import software.amazon.qbusiness.datasource.MediaExtractionConfiguration; + +public final class MediaExtractionConfigurationTranslator { + + private MediaExtractionConfigurationTranslator() { + } + + public static MediaExtractionConfiguration fromServiceMediaExtractionConfiguration( + software.amazon.awssdk.services.qbusiness.model.MediaExtractionConfiguration mediaExtractionConfiguration + ) { + if (mediaExtractionConfiguration == null) { + return null; + } + + return MediaExtractionConfiguration.builder() + .imageExtractionConfiguration( + fromServiceImageExtractionConfiguration(mediaExtractionConfiguration.imageExtractionConfiguration())) + .build(); + } + + public static software.amazon.awssdk.services.qbusiness.model.MediaExtractionConfiguration toServiceMediaExtractionConfiguration( + MediaExtractionConfiguration mediaExtractionConfiguration + ) { + if (mediaExtractionConfiguration == null) { + return null; + } + return software.amazon.awssdk.services.qbusiness.model.MediaExtractionConfiguration.builder() + .imageExtractionConfiguration( + toServiceImageExtractionConfiguration(mediaExtractionConfiguration.getImageExtractionConfiguration())) + .build(); + } + + + static software.amazon.awssdk.services.qbusiness.model.ImageExtractionConfiguration toServiceImageExtractionConfiguration( + ImageExtractionConfiguration imageExtractionConfiguration + ) { + if (imageExtractionConfiguration == null) { + return null; + } + + return software.amazon.awssdk.services.qbusiness.model.ImageExtractionConfiguration.builder() + .imageExtractionStatus(imageExtractionConfiguration.getImageExtractionStatus()) + .build(); + } + + static ImageExtractionConfiguration fromServiceImageExtractionConfiguration( + software.amazon.awssdk.services.qbusiness.model.ImageExtractionConfiguration imageExtractionConfiguration + ) { + if (imageExtractionConfiguration == null) { + return null; + } + + return ImageExtractionConfiguration.builder() + .imageExtractionStatus(imageExtractionConfiguration.imageExtractionStatusAsString()) + .build(); + } + +} diff --git a/aws-qbusiness-datasource/src/test/java/software/amazon/qbusiness/datasource/CreateHandlerTest.java b/aws-qbusiness-datasource/src/test/java/software/amazon/qbusiness/datasource/CreateHandlerTest.java index 8f6ad69..f5159e9 100644 --- a/aws-qbusiness-datasource/src/test/java/software/amazon/qbusiness/datasource/CreateHandlerTest.java +++ b/aws-qbusiness-datasource/src/test/java/software/amazon/qbusiness/datasource/CreateHandlerTest.java @@ -124,6 +124,11 @@ public void setup() { ) .build()) .build()) + .mediaExtractionConfiguration(MediaExtractionConfiguration.builder() + .imageExtractionConfiguration( + ImageExtractionConfiguration.builder() + .imageExtractionStatus("ENABLED").build()) + .build()) .build(); testRequest = ResourceHandlerRequest.builder() diff --git a/aws-qbusiness-datasource/src/test/java/software/amazon/qbusiness/datasource/ReadHandlerTest.java b/aws-qbusiness-datasource/src/test/java/software/amazon/qbusiness/datasource/ReadHandlerTest.java index 15fb407..2aabeef 100644 --- a/aws-qbusiness-datasource/src/test/java/software/amazon/qbusiness/datasource/ReadHandlerTest.java +++ b/aws-qbusiness-datasource/src/test/java/software/amazon/qbusiness/datasource/ReadHandlerTest.java @@ -39,11 +39,13 @@ import software.amazon.awssdk.services.qbusiness.model.QBusinessException; import software.amazon.awssdk.services.qbusiness.model.GetDataSourceRequest; import software.amazon.awssdk.services.qbusiness.model.GetDataSourceResponse; +import software.amazon.awssdk.services.qbusiness.model.ImageExtractionConfiguration; import software.amazon.awssdk.services.qbusiness.model.HookConfiguration; import software.amazon.awssdk.services.qbusiness.model.InlineDocumentEnrichmentConfiguration; import software.amazon.awssdk.services.qbusiness.model.InternalServerException; import software.amazon.awssdk.services.qbusiness.model.ListTagsForResourceRequest; import software.amazon.awssdk.services.qbusiness.model.ListTagsForResourceResponse; +import software.amazon.awssdk.services.qbusiness.model.MediaExtractionConfiguration; import software.amazon.awssdk.services.qbusiness.model.ResourceNotFoundException; import software.amazon.awssdk.services.qbusiness.model.ThrottlingException; import software.amazon.awssdk.services.qbusiness.model.ValidationException; @@ -127,6 +129,9 @@ public void handleRequest_SimpleSuccess() { "Hello", Document.fromString("World"))) ))) ) + .mediaExtractionConfiguration(MediaExtractionConfiguration.builder() + .imageExtractionConfiguration(ImageExtractionConfiguration.builder().imageExtractionStatus("ENABLED").build()) + .build()) .documentEnrichmentConfiguration(DocumentEnrichmentConfiguration.builder() .inlineConfigurations(InlineDocumentEnrichmentConfiguration.builder() .target(DocumentAttributeTarget.builder() diff --git a/aws-qbusiness-datasource/src/test/java/software/amazon/qbusiness/datasource/UpdateHandlerTest.java b/aws-qbusiness-datasource/src/test/java/software/amazon/qbusiness/datasource/UpdateHandlerTest.java index 8cdc9b6..7cfa9b1 100644 --- a/aws-qbusiness-datasource/src/test/java/software/amazon/qbusiness/datasource/UpdateHandlerTest.java +++ b/aws-qbusiness-datasource/src/test/java/software/amazon/qbusiness/datasource/UpdateHandlerTest.java @@ -35,6 +35,7 @@ import software.amazon.awssdk.services.qbusiness.model.DocumentContentOperator; import software.amazon.awssdk.services.qbusiness.model.GetDataSourceRequest; import software.amazon.awssdk.services.qbusiness.model.GetDataSourceResponse; +import software.amazon.awssdk.services.qbusiness.model.ImageExtractionStatus; import software.amazon.awssdk.services.qbusiness.model.ListTagsForResourceRequest; import software.amazon.awssdk.services.qbusiness.model.ListTagsForResourceResponse; import software.amazon.awssdk.services.qbusiness.model.TagResourceRequest; @@ -146,6 +147,10 @@ public void setup() { )) .build() ) + .mediaExtractionConfiguration(MediaExtractionConfiguration.builder() + .imageExtractionConfiguration(ImageExtractionConfiguration.builder() + .imageExtractionStatus("ENABLED").build()) + .build()) .build(); testRequest = ResourceHandlerRequest.builder() @@ -229,6 +234,10 @@ proxy, testRequest, new CallbackContext(), proxyClient, logger var updateInlineConf = updateReqArgument.documentEnrichmentConfiguration().inlineConfigurations().get(0); assertThat(updateInlineConf.documentContentOperator()).isEqualTo(DocumentContentOperator.DELETE); + var updateImageExtractionConfig = updateReqArgument.mediaExtractionConfiguration() + .imageExtractionConfiguration(); + assertThat(updateImageExtractionConfig.imageExtractionStatus()).isEqualTo(ImageExtractionStatus.ENABLED); + var tagResourceRequest = tagReqCaptor.getValue(); Map tagsInTagResourceReq = tagResourceRequest.tags().stream() .collect(Collectors.toMap( diff --git a/aws-qbusiness-plugin/aws-qbusiness-plugin.json b/aws-qbusiness-plugin/aws-qbusiness-plugin.json old mode 100755 new mode 100644 index 2ddffb5..2d158db --- a/aws-qbusiness-plugin/aws-qbusiness-plugin.json +++ b/aws-qbusiness-plugin/aws-qbusiness-plugin.json @@ -100,6 +100,18 @@ "maxLength": 1284, "minLength": 0, "pattern": "^arn:[a-z0-9-\\.]{1,63}:[a-z0-9-\\.]{0,63}:[a-z0-9-\\.]{0,63}:[a-z0-9-\\.]{0,63}:[^/].{0,1023}$" + }, + "AuthorizationUrl": { + "type": "string", + "maxLength": 2048, + "minLength": 1, + "pattern": "^(https?|ftp|file)://([^\\s]*)$" + }, + "TokenUrl": { + "type": "string", + "maxLength": 2048, + "minLength": 1, + "pattern": "^(https?|ftp|file)://([^\\s]*)$" } }, "required": [ @@ -177,7 +189,19 @@ "SALESFORCE", "JIRA", "ZENDESK", - "CUSTOM" + "CUSTOM", + "QUICKSIGHT", + "SERVICENOW_NOW_PLATFORM", + "JIRA_CLOUD", + "SALESFORCE_CRM", + "ZENDESK_SUITE", + "ATLASSIAN_CONFLUENCE", + "GOOGLE_CALENDAR", + "MICROSOFT_TEAMS", + "MICROSOFT_EXCHANGE", + "PAGERDUTY_ADVANCE", + "SMARTSHEET", + "ASANA" ] }, "S3": { @@ -271,7 +295,6 @@ }, "Tags": { "type": "array", - "insertionOrder": false, "items": { "$ref": "#/definitions/Tag" }, @@ -287,7 +310,6 @@ } }, "required": [ - "ApplicationId", "AuthConfiguration", "DisplayName", "Type" @@ -314,8 +336,7 @@ "qbusiness:CreatePlugin", "qbusiness:GetPlugin", "qbusiness:ListTagsForResource", - "qbusiness:TagResource", - "qbusiness:UpdatePlugin" + "qbusiness:TagResource" ] }, "read": { @@ -357,7 +378,16 @@ } }, "tagging": { - "taggable": true + "taggable": true, + "tagUpdatable": true, + "tagOnCreate": true, + "cloudFormationSystemTags": true, + "tagProperty": "/properties/Tags", + "permissions": [ + "qbusiness:UntagResource", + "qbusiness:TagResource", + "qbusiness:ListTagsForResource" + ] }, "sourceUrl": "https://github.com/aws-cloudformation/aws-cloudformation-resource-providers-qbusiness", "additionalProperties": false diff --git a/aws-qbusiness-plugin/src/main/java/software/amazon/qbusiness/plugin/AuthConfigHelper.java b/aws-qbusiness-plugin/src/main/java/software/amazon/qbusiness/plugin/AuthConfigHelper.java index d909f9b..a5870c4 100644 --- a/aws-qbusiness-plugin/src/main/java/software/amazon/qbusiness/plugin/AuthConfigHelper.java +++ b/aws-qbusiness-plugin/src/main/java/software/amazon/qbusiness/plugin/AuthConfigHelper.java @@ -72,6 +72,8 @@ private static OAuth2ClientCredentialConfiguration convertFromServiceOAuth( return OAuth2ClientCredentialConfiguration.builder() .roleArn(serviceOath.roleArn()) .secretArn(serviceOath.secretArn()) + .tokenUrl(serviceOath.tokenUrl()) + .authorizationUrl(serviceOath.authorizationUrl()) .build(); } @@ -96,6 +98,8 @@ private static software.amazon.awssdk.services.qbusiness.model.OAuth2ClientCrede return software.amazon.awssdk.services.qbusiness.model.OAuth2ClientCredentialConfiguration.builder() .roleArn(cfnOath.getRoleArn()) .secretArn(cfnOath.getSecretArn()) + .tokenUrl(cfnOath.getTokenUrl()) + .authorizationUrl(cfnOath.getAuthorizationUrl()) .build(); } diff --git a/aws-qbusiness-plugin/src/main/java/software/amazon/qbusiness/plugin/Translator.java b/aws-qbusiness-plugin/src/main/java/software/amazon/qbusiness/plugin/Translator.java index b9db0e3..c182f32 100644 --- a/aws-qbusiness-plugin/src/main/java/software/amazon/qbusiness/plugin/Translator.java +++ b/aws-qbusiness-plugin/src/main/java/software/amazon/qbusiness/plugin/Translator.java @@ -6,6 +6,7 @@ import java.util.Optional; import java.util.Set; +import com.google.common.collect.ImmutableList; import software.amazon.awssdk.services.qbusiness.model.CreatePluginRequest; import software.amazon.awssdk.services.qbusiness.model.DeletePluginRequest; import software.amazon.awssdk.services.qbusiness.model.GetPluginRequest; @@ -166,8 +167,9 @@ static List translateFromListResponse(final String applicationId, */ static TagResourceRequest tagResourceRequest( final ResourceHandlerRequest request, + final ResourceModel model, final Map addedTags) { - var pluginArn = request.getDesiredResourceState().getPluginArn(); + var pluginArn = Utils.buildPluginArn(request, model); List toTags = Optional.ofNullable(addedTags) .map(Map::entrySet) @@ -195,8 +197,9 @@ static TagResourceRequest tagResourceRequest( */ static UntagResourceRequest untagResourceRequest( final ResourceHandlerRequest request, + final ResourceModel model, final Set removedTags) { - var pluginArn = request.getDesiredResourceState().getPluginArn(); + var pluginArn = Utils.buildPluginArn(request, model); var tagsToRemove = Optional.ofNullable(removedTags) .filter(set -> !set.isEmpty()) .orElse(null); diff --git a/aws-qbusiness-plugin/src/main/java/software/amazon/qbusiness/plugin/UpdateHandler.java b/aws-qbusiness-plugin/src/main/java/software/amazon/qbusiness/plugin/UpdateHandler.java index 51a8290..7439c0f 100644 --- a/aws-qbusiness-plugin/src/main/java/software/amazon/qbusiness/plugin/UpdateHandler.java +++ b/aws-qbusiness-plugin/src/main/java/software/amazon/qbusiness/plugin/UpdateHandler.java @@ -85,7 +85,8 @@ protected ProgressEvent handleRequest( return proxy.initiate("AWS-QBusiness-Plugin::TagResource", proxyClient, progress.getResourceModel(), progress.getCallbackContext()) .translateToServiceRequest(model -> { - return Translator.tagResourceRequest(request, tagsToAdd); + logger.log("Calling tag resource for plugin:%s in app: %s".formatted(model.getPluginId(), model.getApplicationId())); + return Translator.tagResourceRequest(request, model, tagsToAdd); }) .makeServiceCall(this::callTagResource) .progress(); @@ -101,7 +102,7 @@ protected ProgressEvent handleRequest( } return proxy.initiate("AWS-QBusiness-Application::UnTagResource", proxyClient, progress.getResourceModel(), progress.getCallbackContext()) - .translateToServiceRequest(model -> Translator.untagResourceRequest(request, tagsToRemove)) + .translateToServiceRequest(model -> Translator.untagResourceRequest(request, model, tagsToRemove)) .makeServiceCall(this::callUntagResource) .progress(); }) diff --git a/aws-qbusiness-plugin/src/main/java/software/amazon/qbusiness/plugin/Utils.java b/aws-qbusiness-plugin/src/main/java/software/amazon/qbusiness/plugin/Utils.java new file mode 100644 index 0000000..2b76ad3 --- /dev/null +++ b/aws-qbusiness-plugin/src/main/java/software/amazon/qbusiness/plugin/Utils.java @@ -0,0 +1,34 @@ +package software.amazon.qbusiness.plugin; + +import static software.amazon.qbusiness.plugin.Constants.SERVICE_NAME_LOWER; + +import java.util.Locale; + +import lombok.NonNull; +import software.amazon.cloudformation.proxy.ResourceHandlerRequest; + +public class Utils { + // arn:${partition}:qbusiness:${region}:${Account}:application/${ApplicationId}/plugin/${pluginId} + private static final String PLUGIN_ARN_FORMAT = "arn:%s:" + SERVICE_NAME_LOWER + ":%s:%s:application/%s/plugin/%s"; + + private Utils() { + } + + public static String buildPluginArn(final ResourceHandlerRequest request, final ResourceModel model) { + var partition = request.getAwsPartition(); + var region = request.getRegion(); + var accountId = request.getAwsAccountId(); + var applicationId = model.getApplicationId(); + var pluginId = model.getPluginId(); + return buildPluginArn(partition, region, accountId, applicationId, pluginId); + } + + private static String buildPluginArn( + @NonNull final String partition, + @NonNull final String region, + @NonNull final String accountId, + @NonNull final String applicationId, + @NonNull final String pluginId) { + return PLUGIN_ARN_FORMAT.formatted(partition, region, accountId, applicationId, pluginId).toLowerCase(Locale.ENGLISH); + } +} diff --git a/aws-qbusiness-plugin/src/test/java/software/amazon/qbusiness/plugin/ReadHandlerTest.java b/aws-qbusiness-plugin/src/test/java/software/amazon/qbusiness/plugin/ReadHandlerTest.java index 7205ed4..1373c46 100644 --- a/aws-qbusiness-plugin/src/test/java/software/amazon/qbusiness/plugin/ReadHandlerTest.java +++ b/aws-qbusiness-plugin/src/test/java/software/amazon/qbusiness/plugin/ReadHandlerTest.java @@ -55,6 +55,8 @@ public class ReadHandlerTest extends AbstractTestBase { private static final String AWS_PARTITION = "aws"; private static final String ACCOUNT_ID = "123456789012"; private static final String REGION = "us-west-2"; + private static final String AUTH_URL = "https://myDomainName.my.salesforce.com/services/oauth2/authorize"; + private static final String TOKEN_URL = "https://login.salesforce.com/services/oauth2/token"; private AmazonWebServicesClientProxy proxy; @@ -175,6 +177,90 @@ public void handleRequest_SimpleSuccess() { assertThat(resultModel.getUpdatedAt()).isEqualTo(Instant.ofEpochMilli(UPDATED_TIME).toString()); } + + public void handleRequest_withOauthConfig_SimpleSuccess() { + final PluginAuthConfiguration oauthConfig = PluginAuthConfiguration.builder() + .oAuth2ClientCredentialConfiguration(OAuth2ClientCredentialConfiguration.builder() + .roleArn(ROLE_ARN) + .secretArn(SECRET_ARN) + .authorizationUrl(AUTH_URL) + .tokenUrl(TOKEN_URL) + .build()) + .build(); + + final ResourceModel oauthModel = ResourceModel.builder() + .applicationId(APPLICATION_ID) + .pluginId(PLUGIN_ID) + .displayName(PLUGIN_NAME) + .type(PLUGIN_TYPE) + .state(PLUGIN_STATE) + .serverUrl(SERVER_URL) + .pluginArn("a-plugin-arn") + .authConfiguration(oauthConfig) + .createdAt(Instant.ofEpochMilli(CREATED_TIME).toString()) + .updatedAt(Instant.ofEpochMilli(UPDATED_TIME).toString()) + .tags(List.of(Tag.builder() + .key("Tag 1") + .value("Tag 2") + .build())) + .build(); + + final ResourceHandlerRequest oauthRequest = ResourceHandlerRequest.builder() + .awsPartition(AWS_PARTITION) + .region(REGION) + .awsAccountId(ACCOUNT_ID) + .desiredResourceState(oauthModel) + .clientRequestToken(CLIENT_TOKEN) + .build(); + + when(proxyClient.client().getPlugin(any(GetPluginRequest.class))) + .thenReturn(GetPluginResponse.builder() + .applicationId(APPLICATION_ID) + .pluginId(PLUGIN_ID) + .displayName(PLUGIN_NAME) + .type(PLUGIN_TYPE) + .state(PLUGIN_STATE) + .serverUrl(SERVER_URL) + .authConfiguration(cfnAuthConfiguration) + .createdAt(Instant.ofEpochMilli(CREATED_TIME)) + .updatedAt(Instant.ofEpochMilli(UPDATED_TIME)) + .pluginArn("a-plugin-arn") + .build()); + + when(proxyClient.client().listTagsForResource(any(ListTagsForResourceRequest.class))) + .thenReturn(ListTagsForResourceResponse.builder() + .tags(List.of(software.amazon.awssdk.services.qbusiness.model.Tag.builder() + .key("Tag 1") + .value("Tag 2") + .build())) + .build()); + + final ProgressEvent response = underTest.handleRequest(proxy, oauthRequest, new CallbackContext(), proxyClient, + logger); + + verify(qBusinessClient).getPlugin(any(GetPluginRequest.class)); + verify(qBusinessClient).listTagsForResource(any(ListTagsForResourceRequest.class)); + + assertThat(response).isNotNull(); + assertThat(response.getStatus()).isEqualTo(OperationStatus.SUCCESS); + assertThat(response.getCallbackDelaySeconds()).isEqualTo(0); + assertThat(response.getResourceModel()).isEqualTo(request.getDesiredResourceState()); + assertThat(response.getResourceModels()).isNull(); + assertThat(response.getMessage()).isNull(); + assertThat(response.getErrorCode()).isNull(); + + ResourceModel resultModel = response.getResourceModel(); + + assertThat(resultModel.getApplicationId()).isEqualTo(APPLICATION_ID); + assertThat(resultModel.getPluginId()).isEqualTo(PLUGIN_ID); + assertThat(resultModel.getType()).isEqualTo(PLUGIN_TYPE); + assertThat(resultModel.getState()).isEqualTo(PLUGIN_STATE); + assertThat(resultModel.getDisplayName()).isEqualTo(PLUGIN_NAME); + assertThat(resultModel.getAuthConfiguration()).isEqualTo(oauthConfig); + assertThat(resultModel.getCreatedAt()).isEqualTo(Instant.ofEpochMilli(CREATED_TIME).toString()); + assertThat(resultModel.getUpdatedAt()).isEqualTo(Instant.ofEpochMilli(UPDATED_TIME).toString()); + } + private static Stream serviceErrorAndHandlerCodes() { return Stream.of( Arguments.of(ValidationException.builder().build(), HandlerErrorCode.InvalidRequest), diff --git a/aws-qbusiness-webexperience/aws-qbusiness-webexperience.json b/aws-qbusiness-webexperience/aws-qbusiness-webexperience.json index 5e77be7..e3e8bd8 100755 --- a/aws-qbusiness-webexperience/aws-qbusiness-webexperience.json +++ b/aws-qbusiness-webexperience/aws-qbusiness-webexperience.json @@ -111,6 +111,36 @@ "maxLength": 64, "minLength": 1, "pattern": "^(http:\\/\\/|https:\\/\\/)[a-zA-Z0-9-_.]+(?::[0-9]{1,5})?$" + }, + "CustomizationConfiguration": { + "type": "object", + "properties": { + "CustomCSSUrl": { + "type": "string", + "maxLength": 1284, + "minLength": 0, + "pattern": "^(https?://[a-zA-Z0-9-_.+%/]+\\.css)?$" + }, + "LogoUrl": { + "type": "string", + "maxLength": 1284, + "minLength": 0, + "pattern": "^(https?://[a-zA-Z0-9-_.+%/]+\\.(svg|png))?$" + }, + "FontUrl": { + "type": "string", + "maxLength": 1284, + "minLength": 0, + "pattern": "^(https?://[a-zA-Z0-9-_.+%/]+\\.(ttf|woff|woff2|otf))?$" + }, + "FaviconUrl": { + "type": "string", + "maxLength": 1284, + "minLength": 0, + "pattern": "^(https?://[a-zA-Z0-9-_.+%/]+\\.(svg|ico))?$" + } + }, + "additionalProperties": false } }, "properties": { @@ -195,6 +225,9 @@ }, "maxItems": 10, "minItems": 0 + }, + "CustomizationConfiguration": { + "$ref": "#/definitions/CustomizationConfiguration" } }, "required": [ diff --git a/aws-qbusiness-webexperience/src/main/java/software/amazon/qbusiness/webexperience/Translator.java b/aws-qbusiness-webexperience/src/main/java/software/amazon/qbusiness/webexperience/Translator.java index fe2c451..0cede21 100644 --- a/aws-qbusiness-webexperience/src/main/java/software/amazon/qbusiness/webexperience/Translator.java +++ b/aws-qbusiness-webexperience/src/main/java/software/amazon/qbusiness/webexperience/Translator.java @@ -50,6 +50,7 @@ static CreateWebExperienceRequest translateToCreateRequest(final String idempote .welcomeMessage(model.getWelcomeMessage()) .origins(model.getOrigins()) .tags(TagHelper.serviceTagsFromCfnTags(model.getTags())) + .customizationConfiguration(toCustomizationConfiguration(model.getCustomizationConfiguration())) .build(); } @@ -103,6 +104,7 @@ static ResourceModel translateFromReadResponse(final GetWebExperienceResponse aw .createdAt(instantToString(awsResponse.createdAt())) .updatedAt(instantToString(awsResponse.updatedAt())) .origins(awsResponse.origins()) + .customizationConfiguration(fromCustomizationConfiguration(awsResponse.customizationConfiguration())) .build(); } @@ -151,6 +153,7 @@ static UpdateWebExperienceRequest translateToUpdateRequest(final ResourceModel m .roleArn(model.getRoleArn()) .identityProviderConfiguration(toIdentityProviderConfiguration(model.getIdentityProviderConfiguration())) .origins(model.getOrigins()) + .customizationConfiguration(toCustomizationConfiguration(model.getCustomizationConfiguration())) .build(); } @@ -192,6 +195,21 @@ static SamlProviderConfiguration fromSamlProviderConfiguration( .build(); } + static CustomizationConfiguration fromCustomizationConfiguration( + software.amazon.awssdk.services.qbusiness.model.CustomizationConfiguration serviceConfig + ) { + if (serviceConfig == null) { + return null; + } + + return CustomizationConfiguration.builder() + .customCSSUrl(serviceConfig.customCSSUrl()) + .logoUrl(serviceConfig.logoUrl()) + .fontUrl(serviceConfig.fontUrl()) + .faviconUrl(serviceConfig.faviconUrl()) + .build(); + } + static software.amazon.awssdk.services.qbusiness.model.OpenIDConnectProviderConfiguration toOpenIDConnectProviderConfiguration( OpenIDConnectProviderConfiguration modelConfig ) { @@ -231,6 +249,21 @@ static software.amazon.awssdk.services.qbusiness.model.IdentityProviderConfigura .build(); } + static software.amazon.awssdk.services.qbusiness.model.CustomizationConfiguration toCustomizationConfiguration( + CustomizationConfiguration modelConfig + ) { + if (modelConfig == null) { + return null; + } + + return software.amazon.awssdk.services.qbusiness.model.CustomizationConfiguration.builder() + .customCSSUrl(modelConfig.getCustomCSSUrl()) + .logoUrl(modelConfig.getLogoUrl()) + .fontUrl(modelConfig.getFontUrl()) + .faviconUrl(modelConfig.getFaviconUrl()) + .build(); + } + /** * Request to update properties of a previously created resource * diff --git a/aws-qbusiness-webexperience/src/test/java/software/amazon/qbusiness/webexperience/CreateHandlerTest.java b/aws-qbusiness-webexperience/src/test/java/software/amazon/qbusiness/webexperience/CreateHandlerTest.java index 1e47e07..b835f15 100644 --- a/aws-qbusiness-webexperience/src/test/java/software/amazon/qbusiness/webexperience/CreateHandlerTest.java +++ b/aws-qbusiness-webexperience/src/test/java/software/amazon/qbusiness/webexperience/CreateHandlerTest.java @@ -21,7 +21,6 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import org.mockito.ArgumentCaptor; import org.mockito.ArgumentMatcher; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @@ -57,6 +56,10 @@ public class CreateHandlerTest extends AbstractTestBase { private static final String APP_ID = "a197dafc-2158-4f93-ab0d-b1c361c39838"; private static final String WEB_EXPERIENCE_ID = "22222222-1596-4f1a-a3c8-e5f4b33d9fe5"; private static final List ORIGINS_URL = List.of("https://someTestOriginUrl.com/"); + private static final String CUSTOM_CSS_URL = "https://someTest-public.s3.us-west-2.amazonaws.com/test.css"; + private static final String LOGO_URL = "https://someTest-public.s3.us-west-2.amazonaws.com/test.png"; + private static final String FONT_URL = "https://someTest-public.s3.us-west-2.amazonaws.com/test.otf"; + private static final String FAVICON_URL = "https://someTest-public.s3.us-west-2.amazonaws.com/test.ico"; private AmazonWebServicesClientProxy proxy; private ProxyClient proxyClient; @@ -67,6 +70,7 @@ public class CreateHandlerTest extends AbstractTestBase { private Constant testBackOff; private CreateHandler underTest; private IdentityProviderConfiguration identityProviderConfiguration; + private CustomizationConfiguration customizationConfiguration; private AutoCloseable testMocks; @@ -90,6 +94,13 @@ public void setup() { .samlConfiguration(SamlProviderConfiguration.builder().authenticationUrl("https://someTestAuthenticationUrl").build()) .build(); + customizationConfiguration = CustomizationConfiguration.builder() + .customCSSUrl(CUSTOM_CSS_URL) + .logoUrl(LOGO_URL) + .fontUrl(FONT_URL) + .faviconUrl(FAVICON_URL) + .build(); + createModel = ResourceModel.builder() .applicationId(APP_ID) .title("This is a title of the web experience.") @@ -97,6 +108,7 @@ public void setup() { .roleArn("RoleArn") .identityProviderConfiguration(identityProviderConfiguration) .origins(ORIGINS_URL) + .customizationConfiguration(customizationConfiguration) .build(); testRequest = ResourceHandlerRequest.builder() @@ -139,6 +151,12 @@ public void handleRequest_SimpleSuccess() { .roleArn("RoleArn") .defaultEndpoint("Endpoint") .origins(ORIGINS_URL) + .customizationConfiguration(software.amazon.awssdk.services.qbusiness.model.CustomizationConfiguration.builder() + .customCSSUrl(CUSTOM_CSS_URL) + .logoUrl(LOGO_URL) + .fontUrl(FONT_URL) + .faviconUrl(FAVICON_URL) + .build()) .build(); when(qBusinessClient.getWebExperience(any(GetWebExperienceRequest.class))) @@ -163,6 +181,7 @@ proxy, testRequest, new CallbackContext(), proxyClient, logger assertThat(resultModel.getRoleArn()).isEqualTo("RoleArn"); assertThat(resultModel.getDefaultEndpoint()).isEqualTo("Endpoint"); assertThat(resultModel.getOrigins()).isEqualTo(ORIGINS_URL); + assertThat(resultModel.getCustomizationConfiguration()).isEqualTo(customizationConfiguration); verify(qBusinessClient).createWebExperience(any(CreateWebExperienceRequest.class)); diff --git a/aws-qbusiness-webexperience/src/test/java/software/amazon/qbusiness/webexperience/ReadHandlerTest.java b/aws-qbusiness-webexperience/src/test/java/software/amazon/qbusiness/webexperience/ReadHandlerTest.java index a6f7550..2d9d451 100644 --- a/aws-qbusiness-webexperience/src/test/java/software/amazon/qbusiness/webexperience/ReadHandlerTest.java +++ b/aws-qbusiness-webexperience/src/test/java/software/amazon/qbusiness/webexperience/ReadHandlerTest.java @@ -46,6 +46,11 @@ public class ReadHandlerTest extends AbstractTestBase { private static final String APP_ID = "63451660-1596-4f1a-a3c8-e5f4b33d9fe5"; private static final String WEB_EXPERIENCE_ID = "11111111-1596-4f1a-a3c8-e5f4b33d9fe5"; private static final List ORIGINS_URL = List.of("https://someTestOriginUrl.com/"); + private static final String CUSTOM_CSS_URL = "https://someTest-public.s3.us-west-2.amazonaws.com/test.css"; + private static final String LOGO_URL = "https://someTest-public.s3.us-west-2.amazonaws.com/test.png"; + private static final String FONT_URL = "https://someTest-public.s3.us-west-2.amazonaws.com/test.otf"; + private static final String FAVICON_URL = "https://someTest-public.s3.us-west-2.amazonaws.com/test.ico"; + private software.amazon.awssdk.services.qbusiness.model.CustomizationConfiguration customizationConfiguration; private AmazonWebServicesClientProxy proxy; @@ -80,6 +85,13 @@ public void setup() { .region("us-east-1") .stackId("Stack1") .build(); + + customizationConfiguration = software.amazon.awssdk.services.qbusiness.model.CustomizationConfiguration.builder() + .customCSSUrl(CUSTOM_CSS_URL) + .logoUrl(LOGO_URL) + .fontUrl(FONT_URL) + .faviconUrl(FAVICON_URL) + .build(); } @AfterEach @@ -105,6 +117,7 @@ public void handleRequest_SimpleSuccess() { .roleArn("RoleArn") .defaultEndpoint("Endpoint") .origins(ORIGINS_URL) + .customizationConfiguration(customizationConfiguration) .build()); when(proxyClient.client().listTagsForResource(any(ListTagsForResourceRequest.class))) .thenReturn(ListTagsForResourceResponse.builder() @@ -138,6 +151,13 @@ proxy, testRequest, new CallbackContext(), proxyClient, logger assertThat(resultModel.getStatus()).isEqualTo(WebExperienceStatus.ACTIVE.toString()); assertThat(resultModel.getRoleArn()).isEqualTo("RoleArn"); assertThat(resultModel.getDefaultEndpoint()).isEqualTo("Endpoint"); + assertThat(resultModel.getOrigins()).isEqualTo(ORIGINS_URL); + assertThat(resultModel.getCustomizationConfiguration()).isEqualTo(CustomizationConfiguration.builder() + .customCSSUrl(CUSTOM_CSS_URL) + .logoUrl(LOGO_URL) + .fontUrl(FONT_URL) + .faviconUrl(FAVICON_URL) + .build()); var tags = resultModel.getTags().stream().map(tag -> Map.entry(tag.getKey(), tag.getValue())).toList(); assertThat(tags).isEqualTo(List.of( diff --git a/aws-qbusiness-webexperience/src/test/java/software/amazon/qbusiness/webexperience/UpdateHandlerTest.java b/aws-qbusiness-webexperience/src/test/java/software/amazon/qbusiness/webexperience/UpdateHandlerTest.java index cc332ef..1f689fb 100644 --- a/aws-qbusiness-webexperience/src/test/java/software/amazon/qbusiness/webexperience/UpdateHandlerTest.java +++ b/aws-qbusiness-webexperience/src/test/java/software/amazon/qbusiness/webexperience/UpdateHandlerTest.java @@ -51,10 +51,15 @@ public class UpdateHandlerTest extends AbstractTestBase { private static final String APP_ID = "a256a36f-7ae8-47c9-b794-5bb67b78a580"; private static final String WEB_EXPERIENCE_ID = "33333333-7ae8-47c9-b794-5bb67b78a580"; private static final List ORIGINS_URL = List.of("https://someTestOriginUrl.com/"); + private static final String CUSTOM_CSS_URL = "https://someTest-public.s3.us-west-2.amazonaws.com/test.css"; + private static final String LOGO_URL = "https://someTest-public.s3.us-west-2.amazonaws.com/test.png"; + private static final String FONT_URL = "https://someTest-public.s3.us-west-2.amazonaws.com/test.otf"; + private static final String FAVICON_URL = "https://someTest-public.s3.us-west-2.amazonaws.com/test.ico"; private AmazonWebServicesClientProxy proxy; private ProxyClient proxyClient; + private CustomizationConfiguration customizationConfiguration; @Mock private QBusinessClient sdkClient; @@ -81,6 +86,13 @@ public void setup() { underTest = new UpdateHandler(backOffStrategy, tagHelper); + customizationConfiguration = CustomizationConfiguration.builder() + .customCSSUrl(CUSTOM_CSS_URL) + .logoUrl(LOGO_URL) + .fontUrl(FONT_URL) + .faviconUrl(FAVICON_URL) + .build(); + previousModel = ResourceModel.builder() .applicationId(APP_ID) .webExperienceId(WEB_EXPERIENCE_ID) @@ -110,6 +122,7 @@ public void setup() { Tag.builder().key("iamnew").value("overhere").build() )) .origins(ORIGINS_URL) + .customizationConfiguration(customizationConfiguration) .build(); testRequest = ResourceHandlerRequest.builder() @@ -181,6 +194,12 @@ proxy, testRequest, new CallbackContext(), proxyClient, logger assertThat(updateAppRequest.subtitle()).isEqualTo("This is a new subtitle of the web experience."); assertThat(updateAppRequest.roleArn()).isEqualTo("RoleArn"); assertThat(updateAppRequest.origins()).isEqualTo(ORIGINS_URL); + assertThat(updateAppRequest.customizationConfiguration()).isEqualTo(software.amazon.awssdk.services.qbusiness.model.CustomizationConfiguration.builder() + .customCSSUrl(CUSTOM_CSS_URL) + .logoUrl(LOGO_URL) + .fontUrl(FONT_URL) + .faviconUrl(FAVICON_URL) + .build()); verify(sdkClient, times(2)).getWebExperience( argThat((ArgumentMatcher) t -> t.applicationId().equals(APP_ID) && t.webExperienceId().equals(WEB_EXPERIENCE_ID)) diff --git a/pom.xml b/pom.xml index 59b12da..a157e75 100644 --- a/pom.xml +++ b/pom.xml @@ -24,7 +24,7 @@ software.amazon.awssdk bom - 2.29.11 + 2.29.34 pom import