From 69a3262d4d2a14915dc1f9d0faf221321be3158a Mon Sep 17 00:00:00 2001 From: Dan Klco Date: Thu, 7 Nov 2019 17:15:58 -0500 Subject: [PATCH 1/4] Try numero dos for a marketo form component. This time with 110% more embed and a whole framework around creating cloud configs without hating yourself --- bundle/pom.xml | 2 + .../cloudconfig/CloudConfiguration.java | 63 ++++++ .../cloudconfig/CloudConfigurationList.java | 44 ++++ .../impl/CloudConfigurationImpl.java | 66 ++++++ .../impl/CloudConfigurationListImpl.java | 68 ++++++ .../impl/CreateCloudConfigServlet.java | 104 +++++++++ .../adobe/acs/commons/marketo/FormValue.java | 40 ++++ .../marketo/MarketoClientConfiguration.java | 48 ++++ .../MarketoClientConfigurationManager.java | 29 +++ .../acs/commons/marketo/MarketoForm.java | 51 +++++ .../commons/marketo/client/MarketoClient.java | 61 +++++ .../commons/marketo/client/MarketoError.java | 40 ++++ .../commons/marketo/client/MarketoField.java | 40 ++++ .../commons/marketo/client/MarketoForm.java | 63 ++++++ .../marketo/client/MarketoResponse.java | 58 +++++ .../client/impl/MarketoClientImpl.java | 144 ++++++++++++ .../client/impl/MarketoFieldResponse.java | 27 +++ .../client/impl/MarketoFormResponse.java | 26 +++ .../commons/marketo/impl/FormValueImpl.java | 60 +++++ .../impl/MarketoClientConfigurationImpl.java | 104 +++++++++ ...MarketoClientConfigurationManagerImpl.java | 64 ++++++ .../marketo/impl/MarketoFieldDataSource.java | 124 ++++++++++ .../marketo/impl/MarketoFormDataSource.java | 131 +++++++++++ .../commons/marketo/impl/MarketoFormImpl.java | 146 ++++++++++++ .../impl/CloudConfigurationListImplTest.java | 88 ++++++++ .../impl/CreateCloudConfigServletTest.java | 101 +++++++++ .../impl/StaticResponseMarketoClient.java | 54 +++++ .../client/impl/TestMarketoClient.java | 127 +++++++++++ .../marketo/impl/TestFormValueImpl.java | 67 ++++++ .../impl/TestMarketoClientConfiguration.java | 86 +++++++ .../impl/TestMarketoFieldDataSource.java | 98 ++++++++ .../impl/TestMarketoFormDataSource.java | 98 ++++++++ .../marketo/impl/TestMarketoFormImpl.java | 93 ++++++++ .../acs/commons/cloudconfig/cloudconfig.json | 14 ++ .../acs/commons/marketo/cloudconfig.json | 14 ++ .../acs/commons/marketo/field-response.json | 15 ++ .../acs/commons/marketo/form-response.json | 43 ++++ .../adobe/acs/commons/marketo/formvalue.json | 24 ++ .../com/adobe/acs/commons/marketo/pages.json | 91 ++++++++ .../acs/commons/marketo/response-error.json | 11 + .../commons/marketo/response-noassets.json | 8 + .../commons/marketo/response-notsuccess.json | 6 + .../acs/commons/marketo/token-response.json | 6 + .../main/content/META-INF/vault/filter.xml | 1 + .../content/embeddable/.content.xml | 3 + .../content/embeddable/marketo/.content.xml | 6 + .../marketo/_cq_dialog/.content.xml | 211 ++++++++++++++++++ .../content/embeddable/marketo/marketo.html | 35 +++ .../cloudconfig/clientlib/.content.xml | 5 + .../utilities/cloudconfig/clientlib/css.txt | 17 ++ .../utilities/cloudconfig/clientlib/delete.js | 58 +++++ .../utilities/cloudconfig/clientlib/js.txt | 17 ++ .../cloudconfig/clientlib/summary.css | 19 ++ .../cloudconfig/cloudconfiglist/.content.xml | 7 + .../cloudconfiglist/cloudconfiglist.html | 44 ++++ .../cloudconfig/marketo/.content.xml | 7 + .../marketo/_cq_dialog/.content.xml | 74 ++++++ .../utilities/cloudconfig/marketo/marketo.jsp | 18 ++ .../content/cloudservice/console/.content.xml | 42 ++++ .../content/cloudservice/create/.content.xml | 161 +++++++++++++ .../content/cloudservice/thumb.png | Bin 0 -> 1042 bytes .../utilities/marketocloudconfig/.content.xml | 11 + .../nav/tools/cloudservices/.content.xml | 3 + .../tools/cloudservices/marketo/.content.xml | 8 + 64 files changed, 3394 insertions(+) create mode 100644 bundle/src/main/java/com/adobe/acs/commons/cloudconfig/CloudConfiguration.java create mode 100644 bundle/src/main/java/com/adobe/acs/commons/cloudconfig/CloudConfigurationList.java create mode 100644 bundle/src/main/java/com/adobe/acs/commons/cloudconfig/impl/CloudConfigurationImpl.java create mode 100644 bundle/src/main/java/com/adobe/acs/commons/cloudconfig/impl/CloudConfigurationListImpl.java create mode 100644 bundle/src/main/java/com/adobe/acs/commons/cloudconfig/impl/CreateCloudConfigServlet.java create mode 100644 bundle/src/main/java/com/adobe/acs/commons/marketo/FormValue.java create mode 100644 bundle/src/main/java/com/adobe/acs/commons/marketo/MarketoClientConfiguration.java create mode 100644 bundle/src/main/java/com/adobe/acs/commons/marketo/MarketoClientConfigurationManager.java create mode 100644 bundle/src/main/java/com/adobe/acs/commons/marketo/MarketoForm.java create mode 100644 bundle/src/main/java/com/adobe/acs/commons/marketo/client/MarketoClient.java create mode 100644 bundle/src/main/java/com/adobe/acs/commons/marketo/client/MarketoError.java create mode 100644 bundle/src/main/java/com/adobe/acs/commons/marketo/client/MarketoField.java create mode 100644 bundle/src/main/java/com/adobe/acs/commons/marketo/client/MarketoForm.java create mode 100644 bundle/src/main/java/com/adobe/acs/commons/marketo/client/MarketoResponse.java create mode 100644 bundle/src/main/java/com/adobe/acs/commons/marketo/client/impl/MarketoClientImpl.java create mode 100644 bundle/src/main/java/com/adobe/acs/commons/marketo/client/impl/MarketoFieldResponse.java create mode 100644 bundle/src/main/java/com/adobe/acs/commons/marketo/client/impl/MarketoFormResponse.java create mode 100644 bundle/src/main/java/com/adobe/acs/commons/marketo/impl/FormValueImpl.java create mode 100644 bundle/src/main/java/com/adobe/acs/commons/marketo/impl/MarketoClientConfigurationImpl.java create mode 100644 bundle/src/main/java/com/adobe/acs/commons/marketo/impl/MarketoClientConfigurationManagerImpl.java create mode 100644 bundle/src/main/java/com/adobe/acs/commons/marketo/impl/MarketoFieldDataSource.java create mode 100644 bundle/src/main/java/com/adobe/acs/commons/marketo/impl/MarketoFormDataSource.java create mode 100644 bundle/src/main/java/com/adobe/acs/commons/marketo/impl/MarketoFormImpl.java create mode 100644 bundle/src/test/java/com/adobe/acs/commons/cloudconfig/impl/CloudConfigurationListImplTest.java create mode 100644 bundle/src/test/java/com/adobe/acs/commons/cloudconfig/impl/CreateCloudConfigServletTest.java create mode 100644 bundle/src/test/java/com/adobe/acs/commons/marketo/client/impl/StaticResponseMarketoClient.java create mode 100644 bundle/src/test/java/com/adobe/acs/commons/marketo/client/impl/TestMarketoClient.java create mode 100644 bundle/src/test/java/com/adobe/acs/commons/marketo/impl/TestFormValueImpl.java create mode 100644 bundle/src/test/java/com/adobe/acs/commons/marketo/impl/TestMarketoClientConfiguration.java create mode 100644 bundle/src/test/java/com/adobe/acs/commons/marketo/impl/TestMarketoFieldDataSource.java create mode 100644 bundle/src/test/java/com/adobe/acs/commons/marketo/impl/TestMarketoFormDataSource.java create mode 100644 bundle/src/test/java/com/adobe/acs/commons/marketo/impl/TestMarketoFormImpl.java create mode 100644 bundle/src/test/resources/com/adobe/acs/commons/cloudconfig/cloudconfig.json create mode 100644 bundle/src/test/resources/com/adobe/acs/commons/marketo/cloudconfig.json create mode 100644 bundle/src/test/resources/com/adobe/acs/commons/marketo/field-response.json create mode 100644 bundle/src/test/resources/com/adobe/acs/commons/marketo/form-response.json create mode 100644 bundle/src/test/resources/com/adobe/acs/commons/marketo/formvalue.json create mode 100644 bundle/src/test/resources/com/adobe/acs/commons/marketo/pages.json create mode 100644 bundle/src/test/resources/com/adobe/acs/commons/marketo/response-error.json create mode 100644 bundle/src/test/resources/com/adobe/acs/commons/marketo/response-noassets.json create mode 100644 bundle/src/test/resources/com/adobe/acs/commons/marketo/response-notsuccess.json create mode 100644 bundle/src/test/resources/com/adobe/acs/commons/marketo/token-response.json create mode 100644 ui.apps/src/main/content/jcr_root/apps/acs-commons/components/content/embeddable/.content.xml create mode 100644 ui.apps/src/main/content/jcr_root/apps/acs-commons/components/content/embeddable/marketo/.content.xml create mode 100644 ui.apps/src/main/content/jcr_root/apps/acs-commons/components/content/embeddable/marketo/_cq_dialog/.content.xml create mode 100644 ui.apps/src/main/content/jcr_root/apps/acs-commons/components/content/embeddable/marketo/marketo.html create mode 100644 ui.apps/src/main/content/jcr_root/apps/acs-commons/components/utilities/cloudconfig/clientlib/.content.xml create mode 100644 ui.apps/src/main/content/jcr_root/apps/acs-commons/components/utilities/cloudconfig/clientlib/css.txt create mode 100644 ui.apps/src/main/content/jcr_root/apps/acs-commons/components/utilities/cloudconfig/clientlib/delete.js create mode 100644 ui.apps/src/main/content/jcr_root/apps/acs-commons/components/utilities/cloudconfig/clientlib/js.txt create mode 100644 ui.apps/src/main/content/jcr_root/apps/acs-commons/components/utilities/cloudconfig/clientlib/summary.css create mode 100644 ui.apps/src/main/content/jcr_root/apps/acs-commons/components/utilities/cloudconfig/cloudconfiglist/.content.xml create mode 100644 ui.apps/src/main/content/jcr_root/apps/acs-commons/components/utilities/cloudconfig/cloudconfiglist/cloudconfiglist.html create mode 100644 ui.apps/src/main/content/jcr_root/apps/acs-commons/components/utilities/cloudconfig/marketo/.content.xml create mode 100644 ui.apps/src/main/content/jcr_root/apps/acs-commons/components/utilities/cloudconfig/marketo/_cq_dialog/.content.xml create mode 100644 ui.apps/src/main/content/jcr_root/apps/acs-commons/components/utilities/cloudconfig/marketo/marketo.jsp create mode 100644 ui.apps/src/main/content/jcr_root/apps/acs-commons/content/cloudservice/console/.content.xml create mode 100644 ui.apps/src/main/content/jcr_root/apps/acs-commons/content/cloudservice/create/.content.xml create mode 100644 ui.apps/src/main/content/jcr_root/apps/acs-commons/content/cloudservice/thumb.png create mode 100644 ui.apps/src/main/content/jcr_root/apps/acs-commons/templates/utilities/marketocloudconfig/.content.xml create mode 100644 ui.apps/src/main/content/jcr_root/apps/cq/core/content/nav/tools/cloudservices/.content.xml create mode 100644 ui.apps/src/main/content/jcr_root/apps/cq/core/content/nav/tools/cloudservices/marketo/.content.xml diff --git a/bundle/pom.xml b/bundle/pom.xml index 6491115170..b3cd25901f 100644 --- a/bundle/pom.xml +++ b/bundle/pom.xml @@ -74,6 +74,8 @@ * + com.adobe.acs.commons.cloudconfig, + com.adobe.acs.commons.marketo, com.adobe.acs.commons.redirectmaps.models, com.adobe.acs.commons.version.model, com.adobe.acs.commons.wcm.comparisons.model, diff --git a/bundle/src/main/java/com/adobe/acs/commons/cloudconfig/CloudConfiguration.java b/bundle/src/main/java/com/adobe/acs/commons/cloudconfig/CloudConfiguration.java new file mode 100644 index 0000000000..36440ea341 --- /dev/null +++ b/bundle/src/main/java/com/adobe/acs/commons/cloudconfig/CloudConfiguration.java @@ -0,0 +1,63 @@ +/* + * #%L + * ACS AEM Commons Bundle + * %% + * Copyright (C) 2019 Adobe + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package com.adobe.acs.commons.cloudconfig; + +import org.osgi.annotation.versioning.ConsumerType; + +import com.drew.lang.annotations.NotNull; + +/** + * Defines the {@code CloudConfiguration} Sling Model used for the cloudconfig + * component. + */ +@ConsumerType +public interface CloudConfiguration { + + /** + * Get the path of the configuration containing the cloud configuration instance + * + * @return the path of the configuration containing the cloud configuration + * instance + */ + @NotNull + default String getConfigPath() { + throw new UnsupportedOperationException(); + } + + /** + * Get the path of the cloud configuration instance + * + * @return the path of the cloud configuration instance + */ + @NotNull + default String getItemPath() { + throw new UnsupportedOperationException(); + } + + /** + * Get the title of the cloud configuration instance + * + * @return the title of the cloud configuration instance + */ + @NotNull + default String getTitle() { + throw new UnsupportedOperationException(); + } +} diff --git a/bundle/src/main/java/com/adobe/acs/commons/cloudconfig/CloudConfigurationList.java b/bundle/src/main/java/com/adobe/acs/commons/cloudconfig/CloudConfigurationList.java new file mode 100644 index 0000000000..bf5cc3ae91 --- /dev/null +++ b/bundle/src/main/java/com/adobe/acs/commons/cloudconfig/CloudConfigurationList.java @@ -0,0 +1,44 @@ +/* + * #%L + * ACS AEM Commons Bundle + * %% + * Copyright (C) 2019 Adobe + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package com.adobe.acs.commons.cloudconfig; + +import java.util.List; + +import org.osgi.annotation.versioning.ConsumerType; + +import com.drew.lang.annotations.NotNull; + +/** + * Defines the {@code CloudConfigurationList} Sling Model used for the cloudconfig component. + * + */ +@ConsumerType +public interface CloudConfigurationList { + + /** + * Retrieve the list of CloudConfigurations for the specified request. + * + * @return the list of {@code CloudConfiguration}s + */ + @NotNull + default List getCloudConfigurations() { + throw new UnsupportedOperationException(); + } +} diff --git a/bundle/src/main/java/com/adobe/acs/commons/cloudconfig/impl/CloudConfigurationImpl.java b/bundle/src/main/java/com/adobe/acs/commons/cloudconfig/impl/CloudConfigurationImpl.java new file mode 100644 index 0000000000..be1129347a --- /dev/null +++ b/bundle/src/main/java/com/adobe/acs/commons/cloudconfig/impl/CloudConfigurationImpl.java @@ -0,0 +1,66 @@ +/* + * #%L + * ACS AEM Commons Bundle + * %% + * Copyright (C) 2019 Adobe + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package com.adobe.acs.commons.cloudconfig.impl; + +import java.util.Optional; + +import javax.inject.Named; + +import org.apache.sling.api.resource.Resource; +import org.apache.sling.models.annotations.Model; +import org.apache.sling.models.annotations.injectorspecific.InjectionStrategy; +import org.apache.sling.models.annotations.injectorspecific.ValueMapValue; + +import com.adobe.acs.commons.cloudconfig.CloudConfiguration; +import com.drew.lang.annotations.NotNull; + +@Model(adaptables = Resource.class, adapters = { CloudConfiguration.class }) +public class CloudConfigurationImpl implements CloudConfiguration { + + private String configPath; + private String path; + + @ValueMapValue(injectionStrategy = InjectionStrategy.OPTIONAL) + @Named("jcr:content/jcr:title") + private String title; + + public CloudConfigurationImpl(Resource resource) { + path = resource.getPath(); + configPath = Optional.ofNullable(resource.getParent()).map(Resource::getParent).map(Resource::getPath).orElse(""); + } + + @NotNull + @Override + public String getConfigPath() { + return configPath; + } + + @NotNull + @Override + public String getItemPath() { + return path; + } + + @NotNull + @Override + public String getTitle() { + return title; + } +} diff --git a/bundle/src/main/java/com/adobe/acs/commons/cloudconfig/impl/CloudConfigurationListImpl.java b/bundle/src/main/java/com/adobe/acs/commons/cloudconfig/impl/CloudConfigurationListImpl.java new file mode 100644 index 0000000000..0783fe8aac --- /dev/null +++ b/bundle/src/main/java/com/adobe/acs/commons/cloudconfig/impl/CloudConfigurationListImpl.java @@ -0,0 +1,68 @@ +/* + * #%L + * ACS AEM Commons Bundle + * %% + * Copyright (C) 2019 Adobe + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package com.adobe.acs.commons.cloudconfig.impl; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import javax.jcr.query.Query; + +import org.apache.commons.lang3.StringUtils; +import org.apache.sling.api.SlingHttpServletRequest; +import org.apache.sling.models.annotations.Model; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.adobe.acs.commons.cloudconfig.CloudConfiguration; +import com.adobe.acs.commons.cloudconfig.CloudConfigurationList; +import com.drew.lang.annotations.NotNull; + +@Model(adaptables = SlingHttpServletRequest.class, adapters = { CloudConfigurationList.class }) +public class CloudConfigurationListImpl implements CloudConfigurationList { + + private static final Logger log = LoggerFactory.getLogger(CloudConfigurationListImpl.class); + + private List configs = new ArrayList<>(); + + public CloudConfigurationListImpl(SlingHttpServletRequest slingRequest) { + + String template = Optional.ofNullable(slingRequest.getRequestPathInfo().getSuffix()).orElse(""); + + if (StringUtils.isNotBlank(template)) { + String query = "SELECT * FROM [cq:Page] WHERE ISDESCENDANTNODE([/conf]) AND [jcr:content/cq:template]='" + + template.replace("'", "''") + "'"; + log.debug("Finding cloud configuerations with: {}", query); + + slingRequest.getResourceResolver().findResources(query, Query.JCR_SQL2).forEachRemaining(ccr -> { + configs.add(ccr.adaptTo(CloudConfiguration.class)); + }); + } else { + log.debug("Suffix not specified"); + + } + } + + @NotNull + @Override + public List getCloudConfigurations() { + return configs; + } +} diff --git a/bundle/src/main/java/com/adobe/acs/commons/cloudconfig/impl/CreateCloudConfigServlet.java b/bundle/src/main/java/com/adobe/acs/commons/cloudconfig/impl/CreateCloudConfigServlet.java new file mode 100644 index 0000000000..015f783768 --- /dev/null +++ b/bundle/src/main/java/com/adobe/acs/commons/cloudconfig/impl/CreateCloudConfigServlet.java @@ -0,0 +1,104 @@ +/* + * #%L + * ACS AEM Commons Bundle + * %% + * Copyright (C) 2019 Adobe + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package com.adobe.acs.commons.cloudconfig.impl; + +import java.io.IOException; +import java.util.Collections; + +import javax.annotation.Nonnull; +import javax.servlet.Servlet; + +import org.apache.commons.lang3.StringUtils; +import org.apache.sling.api.SlingHttpServletRequest; +import org.apache.sling.api.SlingHttpServletResponse; +import org.apache.sling.api.resource.Resource; +import org.apache.sling.api.resource.ResourceResolver; +import org.apache.sling.api.resource.ResourceUtil; +import org.apache.sling.api.servlets.HttpConstants; +import org.apache.sling.api.servlets.SlingAllMethodsServlet; +import org.apache.sling.servlets.post.HtmlResponse; +import org.osgi.service.component.annotations.Component; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.adobe.aemds.guide.utils.JcrResourceConstants; +import com.day.cq.commons.jcr.JcrConstants; +import com.day.cq.wcm.api.Page; +import com.day.cq.wcm.api.PageManager; +import com.day.cq.wcm.api.WCMException; + +@Component(service = Servlet.class, property = { "sling.servlet.methods=" + HttpConstants.METHOD_POST, + "sling.servlet.paths=/bin/acscommons/createcloudconfig" }) +public class CreateCloudConfigServlet extends SlingAllMethodsServlet { + + private static final long serialVersionUID = -397622433323474345L; + private static final Logger log = LoggerFactory.getLogger(CreateCloudConfigServlet.class); + + @Override + protected void doPost(@Nonnull SlingHttpServletRequest request, @Nonnull SlingHttpServletResponse response) + throws IOException { + ResourceResolver resolver = request.getResourceResolver(); + PageManager pageManager = resolver.adaptTo(PageManager.class); + + HtmlResponse resp = new HtmlResponse(); + + if (pageManager == null) { + resp.setError(new IOException("Unable to get page manager")); + } else { + + String configPath = getParam(request, "configPath"); + Resource cloudConfigFolder = ResourceUtil.getOrCreateResource(resolver, configPath + "/settings/cloudconfigs", + Collections.singletonMap(JcrConstants.JCR_PRIMARYTYPE, JcrResourceConstants.NT_SLING_FOLDER), + JcrResourceConstants.NT_SLING_FOLDER, false); + log.debug("Creating Cloud Config in: {}", cloudConfigFolder); + + resp.setParentLocation(cloudConfigFolder.getPath()); + + // create a new page + Page page; + try { + page = pageManager.create(cloudConfigFolder.getPath(), getParam(request, "name"), getParam(request, "template"), + getParam(request, "title")); + resp.setPath(page.getPath()); + resp.setLocation(page.getPath()); + resp.setStatus(200, "Created Cloud Configuration"); + log.debug("Created configuration: {}", page.getPath()); + resolver.commit(); + } catch (WCMException e) { + resp.setError(e); + } + + } + response.setContentType("text/plain"); + resp.send(response, true); + + } + + private String getParam(SlingHttpServletRequest request, String param) throws IOException { + String value = request.getParameter(param); + if (StringUtils.isBlank(value)) { + throw new IOException("Parameter " + param + " must not be blank"); + } else { + log.debug("Loaded {} for parameter {}", value, param); + } + return value; + } + +} diff --git a/bundle/src/main/java/com/adobe/acs/commons/marketo/FormValue.java b/bundle/src/main/java/com/adobe/acs/commons/marketo/FormValue.java new file mode 100644 index 0000000000..481d78fb4d --- /dev/null +++ b/bundle/src/main/java/com/adobe/acs/commons/marketo/FormValue.java @@ -0,0 +1,40 @@ +/* + * #%L + * ACS AEM Commons Bundle + * %% + * Copyright (C) 2019 Adobe + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package com.adobe.acs.commons.marketo; + +/** + * A Model representing setting a form value in the Marketo form. + */ +public interface FormValue { + + + default String getName() { + throw new UnsupportedOperationException(); + } + + default String getSource() { + throw new UnsupportedOperationException(); + } + + default String getValue() { + throw new UnsupportedOperationException(); + } + +} diff --git a/bundle/src/main/java/com/adobe/acs/commons/marketo/MarketoClientConfiguration.java b/bundle/src/main/java/com/adobe/acs/commons/marketo/MarketoClientConfiguration.java new file mode 100644 index 0000000000..ffaad7bc24 --- /dev/null +++ b/bundle/src/main/java/com/adobe/acs/commons/marketo/MarketoClientConfiguration.java @@ -0,0 +1,48 @@ +/* + * #%L + * ACS AEM Commons Bundle + * %% + * Copyright (C) 2019 Adobe + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package com.adobe.acs.commons.marketo; + +/** + * A Model retrieving the configuration for interacting with the Marketo REST + * API + */ +public interface MarketoClientConfiguration { + + default String getClientId() { + throw new UnsupportedOperationException(); + } + + default String getClientSecret() { + throw new UnsupportedOperationException(); + } + + default String getEndpointHost() { + throw new UnsupportedOperationException(); + } + + default String getMunchkinId() { + throw new UnsupportedOperationException(); + } + + default String getServerInstance() { + throw new UnsupportedOperationException(); + } + +} diff --git a/bundle/src/main/java/com/adobe/acs/commons/marketo/MarketoClientConfigurationManager.java b/bundle/src/main/java/com/adobe/acs/commons/marketo/MarketoClientConfigurationManager.java new file mode 100644 index 0000000000..b1662874bc --- /dev/null +++ b/bundle/src/main/java/com/adobe/acs/commons/marketo/MarketoClientConfigurationManager.java @@ -0,0 +1,29 @@ +/* + * #%L + * ACS AEM Commons Bundle + * %% + * Copyright (C) 2019 Adobe + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package com.adobe.acs.commons.marketo; + +/** + * A Model for retrieving a MarketoClientConfiguration for a particular request. + */ +public interface MarketoClientConfigurationManager { + default MarketoClientConfiguration getConfiguration() { + throw new UnsupportedOperationException(); + } +} diff --git a/bundle/src/main/java/com/adobe/acs/commons/marketo/MarketoForm.java b/bundle/src/main/java/com/adobe/acs/commons/marketo/MarketoForm.java new file mode 100644 index 0000000000..9caf191d49 --- /dev/null +++ b/bundle/src/main/java/com/adobe/acs/commons/marketo/MarketoForm.java @@ -0,0 +1,51 @@ +/* + * #%L + * ACS AEM Commons Bundle + * %% + * Copyright (C) 2019 Adobe + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package com.adobe.acs.commons.marketo; + +/** + * Model for retrieving the configuration values for the Marketo form component + */ +public interface MarketoForm { + + default String getFormId() { + throw new UnsupportedOperationException(); + } + + default String getHidden() { + throw new UnsupportedOperationException(); + } + + default String getScript() { + throw new UnsupportedOperationException(); + } + + default String getSuccessUrl() { + throw new UnsupportedOperationException(); + } + + default String getValues() { + throw new UnsupportedOperationException(); + } + + default boolean isEdit() { + throw new UnsupportedOperationException(); + } + +} diff --git a/bundle/src/main/java/com/adobe/acs/commons/marketo/client/MarketoClient.java b/bundle/src/main/java/com/adobe/acs/commons/marketo/client/MarketoClient.java new file mode 100644 index 0000000000..42d8eec4c5 --- /dev/null +++ b/bundle/src/main/java/com/adobe/acs/commons/marketo/client/MarketoClient.java @@ -0,0 +1,61 @@ +/* + * #%L + * ACS AEM Commons Bundle + * %% + * Copyright (C) 2019 Adobe + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package com.adobe.acs.commons.marketo.client; + +import java.io.IOException; +import java.util.List; + +import javax.annotation.Nonnull; + +import com.adobe.acs.commons.marketo.MarketoClientConfiguration; + +/** + * A client for interacting with Marketo's API. + */ +public interface MarketoClient { + + /** + * Retrieve an API token used for interacting with the Marketo API. + * + * @param config the configuration to use to retrieve the token + * @return a valid Marketo API Token + * @throws IOException an error occurs retrieving the token + */ + public @Nonnull String getApiToken(@Nonnull MarketoClientConfiguration config) throws IOException; + + /** + * Retrieve all of the available forms from the current organization in Marketo. + * + * @param config the configuration for this request + * @return the full list of available forms + * @throws IOException an exception occurs interacting with the API + */ + public @Nonnull List getForms(@Nonnull MarketoClientConfiguration config) throws IOException; + + /** + * Retrieve all of the available forms from the current organization in Marketo. + * + * @param config the configuration for this request + * @return the full list of available forms + * @throws IOException an exception occurs interacting with the API + */ + public @Nonnull List getFields(@Nonnull MarketoClientConfiguration config) throws IOException; + +} diff --git a/bundle/src/main/java/com/adobe/acs/commons/marketo/client/MarketoError.java b/bundle/src/main/java/com/adobe/acs/commons/marketo/client/MarketoError.java new file mode 100644 index 0000000000..0a57a8a345 --- /dev/null +++ b/bundle/src/main/java/com/adobe/acs/commons/marketo/client/MarketoError.java @@ -0,0 +1,40 @@ +/* + * #%L + * ACS AEM Commons Bundle + * %% + * Copyright (C) 2019 Adobe + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package com.adobe.acs.commons.marketo.client; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +/** + * A model representing an error from Marketo. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +public class MarketoError { + + private String message; + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + +} diff --git a/bundle/src/main/java/com/adobe/acs/commons/marketo/client/MarketoField.java b/bundle/src/main/java/com/adobe/acs/commons/marketo/client/MarketoField.java new file mode 100644 index 0000000000..80b328320a --- /dev/null +++ b/bundle/src/main/java/com/adobe/acs/commons/marketo/client/MarketoField.java @@ -0,0 +1,40 @@ +/* + * #%L + * ACS AEM Commons Bundle + * %% + * Copyright (C) 2019 Adobe + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package com.adobe.acs.commons.marketo.client; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +/** + * A model representing a field in Marketo. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +public class MarketoField { + + private String id; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + +} diff --git a/bundle/src/main/java/com/adobe/acs/commons/marketo/client/MarketoForm.java b/bundle/src/main/java/com/adobe/acs/commons/marketo/client/MarketoForm.java new file mode 100644 index 0000000000..c79e2e5816 --- /dev/null +++ b/bundle/src/main/java/com/adobe/acs/commons/marketo/client/MarketoForm.java @@ -0,0 +1,63 @@ +/* + * #%L + * ACS AEM Commons Bundle + * %% + * Copyright (C) 2019 Adobe + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package com.adobe.acs.commons.marketo.client; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +/** + * Represents a form from the Marketo API. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +public class MarketoForm { + + private int id; + + private String locale; + + private String name; + + public int getId() { + return id; + } + public String getLocale() { + return locale; + } + public String getName() { + return name; + } + + public void setId(int id) { + this.id = id; + } + + public void setLocale(String locale) { + this.locale = locale; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public String toString() { + return "MarketoForm [id=" + getId() + ", locale=" + getLocale() + ", name=" + getName() + "]"; + } + +} diff --git a/bundle/src/main/java/com/adobe/acs/commons/marketo/client/MarketoResponse.java b/bundle/src/main/java/com/adobe/acs/commons/marketo/client/MarketoResponse.java new file mode 100644 index 0000000000..d4d990f373 --- /dev/null +++ b/bundle/src/main/java/com/adobe/acs/commons/marketo/client/MarketoResponse.java @@ -0,0 +1,58 @@ +/* + * #%L + * ACS AEM Commons Bundle + * %% + * Copyright (C) 2019 Adobe + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package com.adobe.acs.commons.marketo.client; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +/** + * Container object for a Marketo REST API response. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +public class MarketoResponse { + + private MarketoError[] errors; + private T[] result; + private boolean success; + + public MarketoError[] getErrors() { + return errors != null ? errors.clone() : null; + } + + public T[] getResult() { + return result != null ? result.clone() : null; + } + + public boolean isSuccess() { + return success; + } + + public void setErrors(MarketoError[] errors) { + this.errors = errors.clone(); + } + + public void setResult(T[] result) { + this.result = result.clone(); + } + + public void setSuccess(boolean success) { + this.success = success; + } + +} diff --git a/bundle/src/main/java/com/adobe/acs/commons/marketo/client/impl/MarketoClientImpl.java b/bundle/src/main/java/com/adobe/acs/commons/marketo/client/impl/MarketoClientImpl.java new file mode 100644 index 0000000000..ac32783e0e --- /dev/null +++ b/bundle/src/main/java/com/adobe/acs/commons/marketo/client/impl/MarketoClientImpl.java @@ -0,0 +1,144 @@ +/* + * #%L + * ACS AEM Commons Bundle + * %% + * Copyright (C) 2019 Adobe + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package com.adobe.acs.commons.marketo.client.impl; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.http.auth.AUTH; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.osgi.service.component.annotations.Component; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.adobe.acs.commons.marketo.MarketoClientConfiguration; +import com.adobe.acs.commons.marketo.client.MarketoClient; +import com.adobe.acs.commons.marketo.client.MarketoError; +import com.adobe.acs.commons.marketo.client.MarketoField; +import com.adobe.acs.commons.marketo.client.MarketoForm; +import com.adobe.acs.commons.marketo.client.MarketoResponse; +import com.fasterxml.jackson.databind.ObjectMapper; + +/** + * Implementation of the MarketoClient using the REST API. + */ +@Component(service = MarketoClient.class) +public class MarketoClientImpl implements MarketoClient { + + private static final Logger log = LoggerFactory.getLogger(MarketoClientImpl.class); + + private static final int PAGE_SIZE = 200; + + private ObjectMapper mapper = new ObjectMapper(); + + protected @Nonnull String getApiResponse(@Nonnull String url, String bearerToken) throws IOException { + try (CloseableHttpClient httpClient = HttpClients.createDefault()) { + HttpGet httpGet = new HttpGet(url); + if (StringUtils.isNotBlank(bearerToken)) { + httpGet.setHeader(AUTH.WWW_AUTH_RESP, "Bearer " + bearerToken); + } + try (CloseableHttpResponse httpResponse = httpClient.execute(httpGet)) { + try (InputStream content = httpResponse.getEntity().getContent()) { + return IOUtils.toString(content, StandardCharsets.UTF_8); + } + } + } + } + + public @Nonnull String getApiToken(@Nonnull MarketoClientConfiguration config) throws IOException { + log.trace("getApiToken"); + String url = String.format( + "https://%s/identity/oauth/token?grant_type=client_credentials&client_id=%s&client_secret=%s", + config.getEndpointHost(), config.getClientId(), config.getClientSecret()); + String response = getApiResponse(url, null); + Map responseData = mapper.readValue(response, Map.class); + return (String) responseData.get("access_token"); + + } + + @Override + public List getFields(MarketoClientConfiguration config) throws IOException { + String apiToken = getApiToken(config); + List fields = new ArrayList<>(); + + String base = String.format("https://%s/rest/asset/v1/form/fields.json?", config.getEndpointHost()); + + for (int i = 0; true; i++) { + MarketoField[] page = getApiPage(base, apiToken, i, MarketoFieldResponse.class); + if (page == null || page.length == 0) { + break; + } else { + Arrays.stream(page).forEach(fields::add); + } + } + return fields; + } + + private @Nullable > T[] getApiPage(@Nonnull String urlBase, @Nonnull String token, + int page, Class responseType) throws IOException { + log.trace("getApiPage({})", page); + int offset = PAGE_SIZE * page; + + String url = String.format("%smaxReturn=%s&offset=%s", urlBase, PAGE_SIZE, offset); + + String responseText = getApiResponse(url, token); + MarketoResponse response = mapper.readValue(responseText, responseType); + if (response.getErrors() != null && response.getErrors().length > 0) { + throw new IOException("Retrieved errors in response: " + + Arrays.stream(response.getErrors()).map(MarketoError::getMessage).collect(Collectors.joining(", "))); + } + if (!response.isSuccess()) { + throw new IOException("Retrieved non-success response"); + } + return response.getResult(); + } + + @Override + public List getForms(@Nonnull MarketoClientConfiguration config) throws IOException { + String apiToken = getApiToken(config); + List forms = new ArrayList<>(); + String base = String.format("https://%s/rest/asset/v1/forms.json?status=approved&", config.getEndpointHost()); + for (int i = 0; true; i++) { + + MarketoForm[] page = getApiPage(base, apiToken, i, MarketoFormResponse.class); + if (page == null || page.length == 0) { + break; + } else { + Arrays.stream(page).forEach(forms::add); + } + } + return forms; + } + +} diff --git a/bundle/src/main/java/com/adobe/acs/commons/marketo/client/impl/MarketoFieldResponse.java b/bundle/src/main/java/com/adobe/acs/commons/marketo/client/impl/MarketoFieldResponse.java new file mode 100644 index 0000000000..4f908a8231 --- /dev/null +++ b/bundle/src/main/java/com/adobe/acs/commons/marketo/client/impl/MarketoFieldResponse.java @@ -0,0 +1,27 @@ +/* + * #%L + * ACS AEM Commons Bundle + * %% + * Copyright (C) 2019 Adobe + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package com.adobe.acs.commons.marketo.client.impl; + +import com.adobe.acs.commons.marketo.client.MarketoField; +import com.adobe.acs.commons.marketo.client.MarketoResponse; + +public class MarketoFieldResponse extends MarketoResponse { + +} diff --git a/bundle/src/main/java/com/adobe/acs/commons/marketo/client/impl/MarketoFormResponse.java b/bundle/src/main/java/com/adobe/acs/commons/marketo/client/impl/MarketoFormResponse.java new file mode 100644 index 0000000000..50b839fe52 --- /dev/null +++ b/bundle/src/main/java/com/adobe/acs/commons/marketo/client/impl/MarketoFormResponse.java @@ -0,0 +1,26 @@ +/* + * #%L + * ACS AEM Commons Bundle + * %% + * Copyright (C) 2019 Adobe + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package com.adobe.acs.commons.marketo.client.impl; + +import com.adobe.acs.commons.marketo.client.MarketoForm; +import com.adobe.acs.commons.marketo.client.MarketoResponse; + +public class MarketoFormResponse extends MarketoResponse { +} diff --git a/bundle/src/main/java/com/adobe/acs/commons/marketo/impl/FormValueImpl.java b/bundle/src/main/java/com/adobe/acs/commons/marketo/impl/FormValueImpl.java new file mode 100644 index 0000000000..dd691dd60d --- /dev/null +++ b/bundle/src/main/java/com/adobe/acs/commons/marketo/impl/FormValueImpl.java @@ -0,0 +1,60 @@ +/* + * #%L + * ACS AEM Commons Bundle + * %% + * Copyright (C) 2019 Adobe + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package com.adobe.acs.commons.marketo.impl; + +import org.apache.commons.lang3.StringEscapeUtils; +import org.apache.sling.api.SlingHttpServletRequest; +import org.apache.sling.api.resource.Resource; +import org.apache.sling.models.annotations.Model; +import org.apache.sling.models.annotations.injectorspecific.ValueMapValue; + +import com.adobe.acs.commons.marketo.FormValue; + +/** + * A Model for representing setting a form value in the Marketo form. + */ +@Model(adaptables = { Resource.class, SlingHttpServletRequest.class }, adapters = { FormValue.class }) +public class FormValueImpl implements FormValue { + + @ValueMapValue + private String name; + + @ValueMapValue + private String source; + + @ValueMapValue + private String value; + + @Override + public String getName() { + return StringEscapeUtils.escapeEcmaScript(name); + } + + @Override + public String getSource() { + return source; + } + + @Override + public String getValue() { + return StringEscapeUtils.escapeEcmaScript(value); + } + +} diff --git a/bundle/src/main/java/com/adobe/acs/commons/marketo/impl/MarketoClientConfigurationImpl.java b/bundle/src/main/java/com/adobe/acs/commons/marketo/impl/MarketoClientConfigurationImpl.java new file mode 100644 index 0000000000..d0b1211e37 --- /dev/null +++ b/bundle/src/main/java/com/adobe/acs/commons/marketo/impl/MarketoClientConfigurationImpl.java @@ -0,0 +1,104 @@ +/* + * #%L + * ACS AEM Commons Bundle + * %% + * Copyright (C) 2019 Adobe + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package com.adobe.acs.commons.marketo.impl; + +import org.apache.sling.api.resource.Resource; +import org.apache.sling.models.annotations.Model; +import org.apache.sling.models.annotations.injectorspecific.ValueMapValue; + +import com.adobe.acs.commons.marketo.MarketoClientConfiguration; + +/** + * A Model retrieving the configuration for interacting with the Marketo REST API + */ +@Model(adaptables = Resource.class, adapters=MarketoClientConfiguration.class) +public class MarketoClientConfigurationImpl implements MarketoClientConfiguration { + + @ValueMapValue + private String clientId; + + @ValueMapValue + private String clientSecret; + + @ValueMapValue + private String endpointHost; + + @ValueMapValue + private String munchkinId; + + @ValueMapValue + private String serverInstance; + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + MarketoClientConfigurationImpl other = (MarketoClientConfigurationImpl) obj; + if (clientId == null) { + if (other.clientId != null) { + return false; + } + } else if (!clientId.equals(other.clientId)) { + return false; + } + return true; + } + + @Override + public String getClientId() { + return clientId; + } + + @Override + public String getClientSecret() { + return clientSecret; + } + + @Override + public String getEndpointHost() { + return endpointHost; + } + + @Override + public String getMunchkinId() { + return munchkinId; + } + + @Override + public String getServerInstance() { + return serverInstance; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((clientId == null) ? 0 : clientId.hashCode()); + return result; + } + +} diff --git a/bundle/src/main/java/com/adobe/acs/commons/marketo/impl/MarketoClientConfigurationManagerImpl.java b/bundle/src/main/java/com/adobe/acs/commons/marketo/impl/MarketoClientConfigurationManagerImpl.java new file mode 100644 index 0000000000..2a0f42a831 --- /dev/null +++ b/bundle/src/main/java/com/adobe/acs/commons/marketo/impl/MarketoClientConfigurationManagerImpl.java @@ -0,0 +1,64 @@ +/* + * #%L + * ACS AEM Commons Bundle + * %% + * Copyright (C) 2019 Adobe + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package com.adobe.acs.commons.marketo.impl; + +import org.apache.sling.api.SlingHttpServletRequest; +import org.apache.sling.api.resource.Resource; +import org.apache.sling.caconfig.resource.ConfigurationResourceResolver; +import org.apache.sling.models.annotations.Model; +import org.apache.sling.models.annotations.injectorspecific.OSGiService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.adobe.acs.commons.marketo.MarketoClientConfiguration; +import com.adobe.acs.commons.marketo.MarketoClientConfigurationManager; +import com.day.cq.commons.jcr.JcrConstants; + +@Model(adaptables = { SlingHttpServletRequest.class }, adapters = { MarketoClientConfigurationManager.class }) +public class MarketoClientConfigurationManagerImpl implements MarketoClientConfigurationManager { + + private static final Logger log = LoggerFactory.getLogger(MarketoClientConfigurationManagerImpl.class); + + @OSGiService + private ConfigurationResourceResolver configRsrcRslvr; + + private Resource resource; + + public MarketoClientConfigurationManagerImpl(SlingHttpServletRequest slingRequest) { + if (slingRequest.getResource().getPath().startsWith("/content")) { + resource = slingRequest.getResource(); + } else { + resource = slingRequest.getRequestPathInfo().getSuffixResource(); + } + } + + @Override + public MarketoClientConfiguration getConfiguration() { + log.trace("getConfiguration"); + log.debug("Using context path: {}", configRsrcRslvr.getContextPath(resource)); + return configRsrcRslvr.getResourceCollection(resource, "settings", "cloudconfigs").stream().filter(c -> { + boolean matches = "/apps/acs-commons/templates/utilities/marketocloudconfig" + .equals(c.getValueMap().get("jcr:content/cq:template", "")); + log.debug("Resource: {} matches: {}", c, matches); + return matches; + }).findFirst().map(c -> c.getChild(JcrConstants.JCR_CONTENT)).map(c -> c.adaptTo(MarketoClientConfiguration.class)) + .orElse(null); + } +} diff --git a/bundle/src/main/java/com/adobe/acs/commons/marketo/impl/MarketoFieldDataSource.java b/bundle/src/main/java/com/adobe/acs/commons/marketo/impl/MarketoFieldDataSource.java new file mode 100644 index 0000000000..b78cb9de4f --- /dev/null +++ b/bundle/src/main/java/com/adobe/acs/commons/marketo/impl/MarketoFieldDataSource.java @@ -0,0 +1,124 @@ +/* + * #%L + * ACS AEM Commons Bundle + * %% + * Copyright (C) 2019 Adobe + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package com.adobe.acs.commons.marketo.impl; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +import javax.annotation.Nonnull; +import javax.jcr.RepositoryException; +import javax.servlet.Servlet; + +import org.apache.sling.api.SlingHttpServletRequest; +import org.apache.sling.api.SlingHttpServletResponse; +import org.apache.sling.api.resource.Resource; +import org.apache.sling.api.resource.ResourceMetadata; +import org.apache.sling.api.servlets.ServletResolverConstants; +import org.apache.sling.api.servlets.SlingSafeMethodsServlet; +import org.apache.sling.api.wrappers.ValueMapDecorator; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.adobe.acs.commons.marketo.MarketoClientConfiguration; +import com.adobe.acs.commons.marketo.MarketoClientConfigurationManager; +import com.adobe.acs.commons.marketo.client.MarketoClient; +import com.adobe.acs.commons.marketo.client.MarketoField; +import com.adobe.granite.ui.components.ds.DataSource; +import com.adobe.granite.ui.components.ds.SimpleDataSource; +import com.adobe.granite.ui.components.ds.ValueMapResource; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; + +/** + * Used to drive the list of Form ID options for the Marketo Form component + * dialog. + */ +@Component(service = Servlet.class, property = { ServletResolverConstants.SLING_SERVLET_METHODS + "=GET", + ServletResolverConstants.SLING_SERVLET_RESOURCE_TYPES + + "=acs-commons/components/content/marketo-form/field-data-source" }) +public class MarketoFieldDataSource extends SlingSafeMethodsServlet { + + private static final Logger log = LoggerFactory.getLogger(MarketoFieldDataSource.class); + + private static final long serialVersionUID = -4047967365420628578L; + + private transient MarketoClient client; + + + private transient LoadingCache> formCache = CacheBuilder.newBuilder() + .expireAfterWrite(10, TimeUnit.MINUTES).build(new CacheLoader>() { + public List load(MarketoClientConfiguration config) throws Exception { + return client.getFields(config); + } + }); + + @Reference + public void bindMarketoClient(MarketoClient client) { + this.client = client; + } + + @Override + public void doGet(@Nonnull SlingHttpServletRequest request, @Nonnull SlingHttpServletResponse response) { + log.trace("doGet"); + + List options = null; + MarketoClientConfiguration config = null; + try { + MarketoClientConfigurationManager cfgMgr = request.adaptTo(MarketoClientConfigurationManager.class); + if (cfgMgr != null) { + config = cfgMgr.getConfiguration(); + } else { + throw new RepositoryException("Unable to retrieve Marketo Client Configuration Manager"); + } + if (config == null) { + log.warn("No Marketo configuration found for resource {}", request.getRequestPathInfo().getSuffix()); + throw new RepositoryException("No Marketo configuration found for resource"); + } + + options = formCache.get(config).stream() + .sorted((MarketoField f1, MarketoField f2) -> f1.getId().compareTo(f2.getId())).map(f -> { + Map data = new HashMap<>(); + data.put("value", f.getId()); + data.put("text", f.getId()); + return new ValueMapResource(request.getResourceResolver(), new ResourceMetadata(), "nt:unstructured", + new ValueMapDecorator(data)); + }).collect(Collectors.toList()); + log.debug("Loaded {} options", options.size()); + } catch (Exception e) { + log.warn("Failed to load Marketo fields", e); + options = new ArrayList<>(); + Map data = new HashMap<>(); + data.put("value", ""); + data.put("text", "Unable to load fields from Marketo"); + options.add(new ValueMapResource(request.getResourceResolver(), new ResourceMetadata(), "nt:unstructured", + new ValueMapDecorator(data))); + } + request.setAttribute(DataSource.class.getName(), new SimpleDataSource(options.iterator())); + + } + +} diff --git a/bundle/src/main/java/com/adobe/acs/commons/marketo/impl/MarketoFormDataSource.java b/bundle/src/main/java/com/adobe/acs/commons/marketo/impl/MarketoFormDataSource.java new file mode 100644 index 0000000000..aac4cc70c9 --- /dev/null +++ b/bundle/src/main/java/com/adobe/acs/commons/marketo/impl/MarketoFormDataSource.java @@ -0,0 +1,131 @@ +/* + * #%L + * ACS AEM Commons Bundle + * %% + * Copyright (C) 2019 Adobe + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package com.adobe.acs.commons.marketo.impl; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +import javax.annotation.Nonnull; +import javax.jcr.RepositoryException; +import javax.servlet.Servlet; + +import org.apache.sling.api.SlingHttpServletRequest; +import org.apache.sling.api.SlingHttpServletResponse; +import org.apache.sling.api.resource.Resource; +import org.apache.sling.api.resource.ResourceMetadata; +import org.apache.sling.api.servlets.ServletResolverConstants; +import org.apache.sling.api.servlets.SlingSafeMethodsServlet; +import org.apache.sling.api.wrappers.ValueMapDecorator; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.adobe.acs.commons.marketo.MarketoClientConfiguration; +import com.adobe.acs.commons.marketo.MarketoClientConfigurationManager; +import com.adobe.acs.commons.marketo.client.MarketoClient; +import com.adobe.acs.commons.marketo.client.MarketoForm; +import com.adobe.granite.ui.components.ds.DataSource; +import com.adobe.granite.ui.components.ds.SimpleDataSource; +import com.adobe.granite.ui.components.ds.ValueMapResource; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; + +/** + * Used to drive the list of Form and Field ID options for the Marketo Form + * component dialog. + */ +@Component(service = Servlet.class, property = { ServletResolverConstants.SLING_SERVLET_METHODS + "=GET", + ServletResolverConstants.SLING_SERVLET_RESOURCE_TYPES + + "=acs-commons/components/content/marketo-form/form-data-source" }) +public class MarketoFormDataSource extends SlingSafeMethodsServlet { + + private static final Logger log = LoggerFactory.getLogger(MarketoFormDataSource.class); + + private static final long serialVersionUID = -4047967365420628578L; + + private transient MarketoClient client; + + private transient LoadingCache> formCache = CacheBuilder.newBuilder() + .expireAfterWrite(10, TimeUnit.MINUTES).build(new CacheLoader>() { + public List load(MarketoClientConfiguration config) throws Exception { + return client.getForms(config); + } + }); + + @Reference + public void bindMarketoClient(MarketoClient client) { + this.client = client; + } + + @Override + public void doGet(@Nonnull SlingHttpServletRequest request, @Nonnull SlingHttpServletResponse response) { + log.trace("doGet"); + + List options = null; + MarketoClientConfiguration config = null; + try { + MarketoClientConfigurationManager cfgMgr = request.adaptTo(MarketoClientConfigurationManager.class); + if (cfgMgr != null) { + config = cfgMgr.getConfiguration(); + } + if (config == null) { + log.warn("No Marketo configuration found for resource {}", request.getRequestPathInfo().getSuffix()); + throw new RepositoryException("No Marketo configuration found for resource"); + } + + int currentValue = getCurrentValue(request); + options = formCache.get(config).stream() + .sorted((MarketoForm f1, MarketoForm f2) -> f1.getName().compareTo(f2.getName())).map(f -> { + Map data = new HashMap<>(); + data.put("selected", currentValue == f.getId()); + data.put("value", f.getId()); + data.put("text", String.format("%s [%s] (%s)", f.getName(), f.getLocale(), f.getId())); + return new ValueMapResource(request.getResourceResolver(), new ResourceMetadata(), "nt:unstructured", + new ValueMapDecorator(data)); + }).collect(Collectors.toList()); + log.debug("Loaded {} options", options.size()); + } catch (Exception e) { + log.warn("Failed to load Marketo forms", e); + options = new ArrayList<>(); + Map data = new HashMap<>(); + data.put("value", ""); + data.put("text", "Unable to load forms from Marketo"); + options.add(new ValueMapResource(request.getResourceResolver(), new ResourceMetadata(), "nt:unstructured", + new ValueMapDecorator(data))); + } + request.setAttribute(DataSource.class.getName(), new SimpleDataSource(options.iterator())); + + } + + private int getCurrentValue(SlingHttpServletRequest request) { + Resource suffix = request.getRequestPathInfo().getSuffixResource(); + if (suffix != null) { + return suffix.getValueMap().get("formId", -1); + } + return -1; + } + +} diff --git a/bundle/src/main/java/com/adobe/acs/commons/marketo/impl/MarketoFormImpl.java b/bundle/src/main/java/com/adobe/acs/commons/marketo/impl/MarketoFormImpl.java new file mode 100644 index 0000000000..41fc9b5bed --- /dev/null +++ b/bundle/src/main/java/com/adobe/acs/commons/marketo/impl/MarketoFormImpl.java @@ -0,0 +1,146 @@ +/* + * #%L + * ACS AEM Commons Bundle + * %% + * Copyright (C) 2019 Adobe + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package com.adobe.acs.commons.marketo.impl; + +import java.util.List; +import java.util.stream.Collectors; + +import org.apache.commons.lang.StringEscapeUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.sling.api.SlingHttpServletRequest; +import org.apache.sling.models.annotations.DefaultInjectionStrategy; +import org.apache.sling.models.annotations.Model; +import org.apache.sling.models.annotations.Via; +import org.apache.sling.models.annotations.injectorspecific.ChildResource; +import org.apache.sling.models.annotations.injectorspecific.ValueMapValue; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.adobe.acs.commons.marketo.FormValue; +import com.adobe.acs.commons.marketo.MarketoForm; +import com.day.cq.commons.Externalizer; +import com.day.cq.wcm.api.WCMMode; + +/** + * Model for retrieving the configuration values for the Marketo form component + */ +@Model(adaptables = SlingHttpServletRequest.class, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL, adapters = { + MarketoForm.class }) +public class MarketoFormImpl implements MarketoForm { + + private static final Logger log = LoggerFactory.getLogger(MarketoFormImpl.class); + + @ValueMapValue + @Via("resource") + private String formId; + + @ChildResource + @Via("resource") + private List hidden; + + private SlingHttpServletRequest request; + + @ValueMapValue + @Via("resource") + private String script; + + @ValueMapValue + @Via("resource") + private String successUrl; + + @ChildResource + @Via("resource") + private List values; + + public MarketoFormImpl(SlingHttpServletRequest request) { + this.request = request; + } + + @Override + public String getFormId() { + return formId; + } + + @Override + public String getHidden() { + if (hidden == null || hidden.isEmpty()) { + return null; + } + String assignments = hidden.stream().map(v -> toJavaScript(v, "hidden")).collect(Collectors.joining()); + return "var hidden = {};\n" + assignments + "form.addHiddenFields(hidden);\n"; + } + + private String toJavaScript(FormValue value, String variable) { + String key = StringEscapeUtils.escapeJavaScript(value.getName()); + String val = StringEscapeUtils.escapeJavaScript(value.getValue()); + if ("static".equals(value.getSource())) { + return String.format("%s[\"%s\"]=\"%s\";%n", variable, key, val); + } else if ("contextHub".equals(value.getSource())) { + return String.format("%s[\"%s\"]=ContextHub.getItem(\"%s\");%n", variable, key, val); + } else if ("jsVariable".equals(value.getSource())) { + return String.format("%s[\"%s\"]=%s;%n", variable, key, value.getValue()); + } else { + return String.format("%s[\"%s\"]=\"%s\";%n", variable, key, + StringEscapeUtils.escapeJavaScript(request.getParameter(value.getValue()))); + } + + } + + @Override + public String getScript() { + return script; + } + + @Override + public String getSuccessUrl() { + if (StringUtils.isBlank(successUrl)) { + return null; + } + String fullUrl = successUrl; + Externalizer externalizer = request.getResourceResolver().adaptTo(Externalizer.class); + if (successUrl.startsWith("/") && externalizer != null) { + fullUrl = externalizer.relativeLink(request, successUrl); + log.debug("Externalized {} to {}", successUrl, fullUrl); + } + if (!successUrl.contains(".")) { + fullUrl += ".html"; + } + log.debug("Final URL: {}", fullUrl); + + return "form.onSuccess(function(values, followUpUrl) {\n" + "location.href = \"" + + StringEscapeUtils.escapeJavaScript(fullUrl) + "\";\n" + "return false;\n" + "});"; + + } + + @Override + public String getValues() { + if (values == null || values.isEmpty()) { + return null; + } + String assignments = values.stream().map(v -> toJavaScript(v, "values")).collect(Collectors.joining()); + return "var values = {};\n" + assignments + "form.vals(values);\n"; + } + + @Override + public boolean isEdit() { + return WCMMode.fromRequest(request) == WCMMode.EDIT; + } + +} diff --git a/bundle/src/test/java/com/adobe/acs/commons/cloudconfig/impl/CloudConfigurationListImplTest.java b/bundle/src/test/java/com/adobe/acs/commons/cloudconfig/impl/CloudConfigurationListImplTest.java new file mode 100644 index 0000000000..e7833ff343 --- /dev/null +++ b/bundle/src/test/java/com/adobe/acs/commons/cloudconfig/impl/CloudConfigurationListImplTest.java @@ -0,0 +1,88 @@ +/* + * #%L + * ACS AEM Commons Bundle + * %% + * Copyright (C) 2019 Adobe + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package com.adobe.acs.commons.cloudconfig.impl; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.io.IOException; +import java.lang.reflect.Field; +import java.util.List; + +import org.apache.sling.testing.mock.sling.ResourceResolverType; +import org.apache.sling.testing.mock.sling.servlet.MockRequestPathInfo; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import com.adobe.acs.commons.cloudconfig.CloudConfiguration; +import com.adobe.acs.commons.cloudconfig.CloudConfigurationList; + +import io.wcm.testing.mock.aem.junit.AemContext; + +public class CloudConfigurationListImplTest { + + @Rule + public final AemContext context = new AemContext(ResourceResolverType.JCR_MOCK);; + + @Before + public void init() { + context.load().json("/com/adobe/acs/commons/cloudconfig/cloudconfig.json", "/conf/test"); + } + + @SuppressWarnings("unchecked") + @Test + public void valid() + throws IOException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException { + MockRequestPathInfo requestPathInfo = (MockRequestPathInfo) context.request().getRequestPathInfo(); + requestPathInfo.setSuffix("/apps/core/wcm/templates/marketocloudconfig"); + + CloudConfigurationList list = new CloudConfigurationListImpl(context.request()); + + assertNotNull(list); + Field field = list.getClass().getDeclaredField("configs"); + field.setAccessible(true); + + assertNotNull(field.get(list)); + + CloudConfiguration config = new CloudConfigurationImpl(context.resourceResolver().getResource("/conf/test")); + ((List) field.get(list)).add(config); + + assertNotNull(list.getCloudConfigurations()); + assertEquals(1, list.getCloudConfigurations().size()); + + config = list.getCloudConfigurations().get(0); + assertNotNull(config); + assertEquals("/conf/test", config.getItemPath()); + assertEquals("/", config.getConfigPath()); + }; + + @Test + public void invalid() { + MockRequestPathInfo requestPathInfo = (MockRequestPathInfo) context.request().getRequestPathInfo(); + requestPathInfo.setSuffix(""); + + CloudConfigurationList list = new CloudConfigurationListImpl(context.request()); + + assertNotNull(list); + assertNotNull(list.getCloudConfigurations()); + assertEquals(0, list.getCloudConfigurations().size()); + } +} diff --git a/bundle/src/test/java/com/adobe/acs/commons/cloudconfig/impl/CreateCloudConfigServletTest.java b/bundle/src/test/java/com/adobe/acs/commons/cloudconfig/impl/CreateCloudConfigServletTest.java new file mode 100644 index 0000000000..6d0fbb66ea --- /dev/null +++ b/bundle/src/test/java/com/adobe/acs/commons/cloudconfig/impl/CreateCloudConfigServletTest.java @@ -0,0 +1,101 @@ +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ Copyright 2019 Adobe + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ +package com.adobe.acs.commons.cloudconfig.impl; + +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.Assert.fail; + +import java.io.IOException; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +import org.apache.sling.api.resource.ValueMap; +import org.apache.sling.caconfig.resource.ConfigurationResourceResolver; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.mockito.Mockito; + +import io.wcm.testing.mock.aem.junit.AemContext; + +public class CreateCloudConfigServletTest { + + @Rule + public final AemContext context = new AemContext(); + + @Before + public void init() { + context.load().json("/com/adobe/acs/commons/cloudconfig/cloudconfig.json", "/conf/test"); + + ConfigurationResourceResolver configrr = Mockito.mock(ConfigurationResourceResolver.class); + Mockito.when(configrr.getResourceCollection(Mockito.any(), Mockito.any(), Mockito.any())) + .thenReturn(Collections.singletonList(context.resourceResolver().getResource("/conf/test"))); + context.registerService(ConfigurationResourceResolver.class, configrr); + + } + + @Test + public void testDoPost() throws IOException { + + CreateCloudConfigServlet cccSrvlt = new CreateCloudConfigServlet(); + + Map parameterMap = new HashMap<>(); + parameterMap.put("configPath", "/conf/test2"); + parameterMap.put("title", "Test"); + parameterMap.put("name", "test"); + parameterMap.put("template", "/apps/core/wcm/templates/marketocloudconfig"); + + context.request().setParameterMap(parameterMap); + + cccSrvlt.doPost(context.request(), context.response()); + + assertNotNull(context.response().getOutputAsString()); + assertTrue(context.response().getOutputAsString().contains("Created Cloud Configuration")); + assertNotNull(context.resourceResolver().getResource("/conf/test2/settings/cloudconfigs/test")); + ValueMap properties = Optional + .ofNullable(context.resourceResolver().getResource("/conf/test2/settings/cloudconfigs/test/jcr:content")) + .map(r -> r.getValueMap()).orElse(null); + assertEquals("Test", properties.get("jcr:title", String.class)); + assertEquals("/apps/core/wcm/templates/marketocloudconfig", properties.get("cq:template", String.class)); + } + + @Test + public void testInvalid() throws IOException { + + CreateCloudConfigServlet cccSrvlt = new CreateCloudConfigServlet(); + + Map parameterMap = new HashMap<>(); + parameterMap.put("configPath", "/conf/test2"); + parameterMap.put("name", "test2"); + parameterMap.put("template", "/apps/core/wcm/templates/marketocloudconfig"); + + context.request().setParameterMap(parameterMap); + + try { + cccSrvlt.doPost(context.request(), context.response()); + fail(); + } catch (IOException e) { + assertNull(context.resourceResolver().getResource("/conf/test2/settings/cloudconfigs/test2")); + } + + } + +} diff --git a/bundle/src/test/java/com/adobe/acs/commons/marketo/client/impl/StaticResponseMarketoClient.java b/bundle/src/test/java/com/adobe/acs/commons/marketo/client/impl/StaticResponseMarketoClient.java new file mode 100644 index 0000000000..9fbcac9afb --- /dev/null +++ b/bundle/src/test/java/com/adobe/acs/commons/marketo/client/impl/StaticResponseMarketoClient.java @@ -0,0 +1,54 @@ +/* + * #%L + * ACS AEM Commons Bundle + * %% + * Copyright (C) 2019 Adobe + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package com.adobe.acs.commons.marketo.client.impl; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Iterator; + +import org.apache.commons.io.IOUtils; + +import com.drew.lang.annotations.NotNull; + +public class StaticResponseMarketoClient extends MarketoClientImpl { + + private String resourcePath; + private Iterator resourcePaths; + + public StaticResponseMarketoClient(String resourcePath) { + this.resourcePath = resourcePath; + } + + public StaticResponseMarketoClient(String[] resourcePaths) { + this.resourcePaths = Arrays.asList(resourcePaths).iterator(); + if (this.resourcePaths.hasNext()) { + resourcePath = this.resourcePaths.next(); + } + } + + protected @NotNull String getApiResponse(@NotNull String url, String bearerToken) throws IOException { + String resp = IOUtils.toString(StaticResponseMarketoClient.class.getResourceAsStream(resourcePath), StandardCharsets.UTF_8); + if (resourcePaths != null && resourcePaths.hasNext()) { + resourcePath = resourcePaths.next(); + } + return resp; + } +} diff --git a/bundle/src/test/java/com/adobe/acs/commons/marketo/client/impl/TestMarketoClient.java b/bundle/src/test/java/com/adobe/acs/commons/marketo/client/impl/TestMarketoClient.java new file mode 100644 index 0000000000..8f57d3a551 --- /dev/null +++ b/bundle/src/test/java/com/adobe/acs/commons/marketo/client/impl/TestMarketoClient.java @@ -0,0 +1,127 @@ +/* + * #%L + * ACS AEM Commons Bundle + * %% + * Copyright (C) 2019 Adobe + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package com.adobe.acs.commons.marketo.client.impl; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; + +import java.io.IOException; +import java.util.List; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import com.adobe.acs.commons.marketo.MarketoClientConfiguration; +import com.adobe.acs.commons.marketo.client.MarketoClient; +import com.adobe.acs.commons.marketo.client.MarketoField; +import com.adobe.acs.commons.marketo.client.MarketoForm; + +import io.wcm.testing.mock.aem.junit.AemContext; + +public class TestMarketoClient { + + private MarketoClientConfiguration config = new MarketoClientConfiguration() { + + @Override + public String getClientId() { + return "CLIENT"; + } + + @Override + public String getClientSecret() { + return "SECRET"; + } + + @Override + public String getEndpointHost() { + return "SERVER"; + } + + }; + + @Rule + public final AemContext context = new AemContext(); + + @Before + public void init() { + context.addModelsForPackage("com.adobe.acs.commons.marketo", "com.adobe.acs.commons.marketo.impl"); + context.load().json("/com/adobe/acs/commons/marketo/pages.json", "/content/page"); + context.load().json("/com/adobe/acs/commons/marketo/cloudconfig.json", "/etc/cloudservices/marketo/test"); + } + + @Test + public void testError() throws IOException { + MarketoClient client = new StaticResponseMarketoClient("/com/adobe/acs/commons/marketo/response-error.json"); + try { + client.getForms(config); + fail(); + } catch (IOException e) { + assertEquals("Retrieved errors in response: Access token invalid", e.getMessage()); + } + } + + @Test + public void testGetFields() throws IOException { + MarketoClient client = new StaticResponseMarketoClient(new String[] { + "/com/adobe/acs/commons/marketo/token-response.json", "/com/adobe/acs/commons/marketo/field-response.json", + "/com/adobe/acs/commons/marketo/response-noassets.json" }); + List fields = client.getFields(config); + assertNotNull(fields); + assertFalse(fields.isEmpty()); + assertEquals(1, fields.size()); + + assertEquals("Address", fields.get(0).getId()); + } + + @Test + public void testGetForms() throws IOException { + MarketoClient client = new StaticResponseMarketoClient(new String[] { + "/com/adobe/acs/commons/marketo/token-response.json", "/com/adobe/acs/commons/marketo/form-response.json", + "/com/adobe/acs/commons/marketo/response-noassets.json" }); + List forms = client.getForms(config); + assertNotNull(forms); + assertFalse(forms.isEmpty()); + assertEquals(1, forms.size()); + + assertEquals("MarketoForm [id=1, locale=en_US, name=Sample Form]", forms.get(0).toString()); + } + + @Test + public void testGetToken() throws IOException { + MarketoClient client = new StaticResponseMarketoClient("/com/adobe/acs/commons/marketo/token-response.json"); + String token = client.getApiToken(config); + assertNotNull(token); + assertEquals("TOKEN", token); + } + + @Test + public void testNotSuccess() throws IOException { + MarketoClient client = new StaticResponseMarketoClient("/com/adobe/acs/commons/marketo/response-notsuccess.json"); + try { + client.getForms(config); + fail(); + } catch (IOException e) { + // expected to occur + } + } +} diff --git a/bundle/src/test/java/com/adobe/acs/commons/marketo/impl/TestFormValueImpl.java b/bundle/src/test/java/com/adobe/acs/commons/marketo/impl/TestFormValueImpl.java new file mode 100644 index 0000000000..a690067bf8 --- /dev/null +++ b/bundle/src/test/java/com/adobe/acs/commons/marketo/impl/TestFormValueImpl.java @@ -0,0 +1,67 @@ +/* + * #%L + * ACS AEM Commons Bundle + * %% + * Copyright (C) 2019 Adobe + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package com.adobe.acs.commons.marketo.impl; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import java.io.IOException; +import java.util.Optional; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import com.adobe.acs.commons.marketo.FormValue; + +import io.wcm.testing.mock.aem.junit.AemContext; + +public class TestFormValueImpl { + + @Rule + public final AemContext context = new AemContext(); + + @Before + public void init() { + context.addModelsForPackage("com.adobe.acs.commons.marketo", "com.adobe.acs.commons.marketo.impl"); + context.load().json("/com/adobe/acs/commons/marketo/formvalue.json", "/content"); + } + + @Test + public void valid() throws IOException { + context.currentResource("/content/formvalue/jcr:content/root/valid"); + FormValue formValue = Optional.ofNullable(context.currentResource()).map(r -> r.adaptTo(FormValue.class)) + .orElse(null); + assertNotNull(formValue); + + assertEquals("Test", formValue.getName()); + assertEquals("static", formValue.getSource()); + assertEquals("Value", formValue.getValue()); + } + + @Test + public void invalid() { + context.currentResource("/content/formvalue/jcr:content/root/invalid"); + FormValue invalid = Optional.ofNullable(context.currentResource()).map(r -> r.adaptTo(FormValue.class)) + .orElse(null); + assertNull(invalid); + } +} diff --git a/bundle/src/test/java/com/adobe/acs/commons/marketo/impl/TestMarketoClientConfiguration.java b/bundle/src/test/java/com/adobe/acs/commons/marketo/impl/TestMarketoClientConfiguration.java new file mode 100644 index 0000000000..f2aa1f8d98 --- /dev/null +++ b/bundle/src/test/java/com/adobe/acs/commons/marketo/impl/TestMarketoClientConfiguration.java @@ -0,0 +1,86 @@ +/* + * #%L + * ACS AEM Commons Bundle + * %% + * Copyright (C) 2019 Adobe + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package com.adobe.acs.commons.marketo.impl; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; + +import java.util.Collections; +import java.util.Optional; + +import org.apache.sling.caconfig.resource.ConfigurationResourceResolver; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.mockito.Mockito; + +import com.adobe.acs.commons.marketo.MarketoClientConfiguration; +import com.adobe.acs.commons.marketo.MarketoClientConfigurationManager; + +import io.wcm.testing.mock.aem.junit.AemContext; + +public class TestMarketoClientConfiguration { + + @Rule + public final AemContext context = new AemContext(); + + @Before + public void init() { + context.addModelsForPackage("com.adobe.acs.commons.marketo", "com.adobe.acs.commons.marketo.impl"); + context.load().json("/com/adobe/acs/commons/marketo/pages.json", "/content/page"); + context.load().json("/com/adobe/acs/commons/marketo/cloudconfig.json", "/conf/test"); + + ConfigurationResourceResolver configrr = Mockito.mock(ConfigurationResourceResolver.class); + Mockito.when(configrr.getResourceCollection(Mockito.any(), Mockito.any(), Mockito.any())) + .thenReturn(Collections.singletonList(context.resourceResolver().getResource("/conf/test"))); + context.registerService(ConfigurationResourceResolver.class, configrr); + + } + + @Test + public void testConfigMgr() { + context.request().setResource(context.resourceResolver().getResource("/content/page")); + MarketoClientConfigurationManager mccm = context.request().adaptTo(MarketoClientConfigurationManager.class); + + assertNotNull(mccm); + assertNotNull(mccm.getConfiguration()); + } + + @Test + public void testConfig() { + MarketoClientConfiguration mcc = Optional + .ofNullable(context.resourceResolver().getResource("/conf/test/jcr:content")) + .map(r -> r.adaptTo(MarketoClientConfiguration.class)).orElse(null); + assertNotNull(mcc); + assertEquals("123", mcc.getClientId()); + assertEquals("456", mcc.getClientSecret()); + assertEquals("test.mktorest.com", mcc.getEndpointHost()); + assertEquals("123-456-789", mcc.getMunchkinId()); + assertEquals("//test.marketo.com", mcc.getServerInstance()); + assertEquals(48721, mcc.hashCode()); + + MarketoClientConfiguration mcc2 = Optional + .ofNullable(context.resourceResolver().getResource("/conf/test/jcr:content")) + .map(r -> r.adaptTo(MarketoClientConfiguration.class)).orElse(null); + assertEquals(mcc, mcc2); + assertNotEquals(mcc, null); + } +} diff --git a/bundle/src/test/java/com/adobe/acs/commons/marketo/impl/TestMarketoFieldDataSource.java b/bundle/src/test/java/com/adobe/acs/commons/marketo/impl/TestMarketoFieldDataSource.java new file mode 100644 index 0000000000..7e697a5b15 --- /dev/null +++ b/bundle/src/test/java/com/adobe/acs/commons/marketo/impl/TestMarketoFieldDataSource.java @@ -0,0 +1,98 @@ +/* + * #%L + * ACS AEM Commons Bundle + * %% + * Copyright (C) 2019 Adobe + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package com.adobe.acs.commons.marketo.impl; + +import static org.junit.Assert.assertNotNull; + +import java.io.IOException; +import java.util.Collections; + +import org.apache.sling.api.resource.Resource; +import org.apache.sling.caconfig.resource.ConfigurationResourceResolver; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.mockito.Mockito; + +import com.adobe.acs.commons.marketo.client.MarketoClient; +import com.adobe.acs.commons.marketo.client.impl.StaticResponseMarketoClient; +import com.adobe.granite.ui.components.ds.DataSource; + +import io.wcm.testing.mock.aem.junit.AemContext; + +public class TestMarketoFieldDataSource { + + @Rule + public final AemContext context = new AemContext(); + + @Before + public void init() { + context.addModelsForPackage("com.adobe.acs.commons.marketo", "com.adobe.acs.commons.marketo.impl"); + context.load().json("/com/adobe/acs/commons/marketo/pages.json", "/content/page"); + context.load().json("/com/adobe/acs/commons/marketo/cloudconfig.json", "/conf/test"); + + Resource resource = Mockito.mock(Resource.class); + Mockito.when(resource.getResourceType()).thenReturn("cq:Page"); + Mockito.when(resource.getPath()).thenReturn("/mnt/somewhere"); + Mockito.when(resource.getResourceResolver()).thenReturn(context.resourceResolver()); + context.request().setResource(resource); + context.requestPathInfo().setSuffix("/content/page"); + + } + + @Test + public void testdoGet() throws IOException { + + ConfigurationResourceResolver configrr = Mockito.mock(ConfigurationResourceResolver.class); + Mockito.when(configrr.getResourceCollection(Mockito.any(), Mockito.any(), Mockito.any())) + .thenReturn(Collections.singletonList(context.resourceResolver().getResource("/conf/test"))); + context.registerService(ConfigurationResourceResolver.class, configrr); + + MarketoFieldDataSource mktoDataSrc = new MarketoFieldDataSource(); + + MarketoClient client = new StaticResponseMarketoClient(new String[] { + "/com/adobe/acs/commons/marketo/token-response.json", "/com/adobe/acs/commons/marketo/field-response.json", + "/com/adobe/acs/commons/marketo/response-noassets.json" }); + mktoDataSrc.bindMarketoClient(client); + + mktoDataSrc.doGet(context.request(), context.response()); + + assertNotNull(context.request().getAttribute(DataSource.class.getName())); + } + + @Test + public void testInvalidResource() { + + ConfigurationResourceResolver configrr = Mockito.mock(ConfigurationResourceResolver.class); + Mockito.when(configrr.getResourceCollection(Mockito.any(), Mockito.any(), Mockito.any())) + .thenReturn(Collections.emptyList()); + context.registerService(ConfigurationResourceResolver.class, configrr); + + MarketoFieldDataSource mktoDataSrc = new MarketoFieldDataSource(); + + MarketoClient client = new StaticResponseMarketoClient(new String[] { "/marketo/token-response.json", + "/marketo/field-response.json", "/marketo/response-noassets.json" }); + mktoDataSrc.bindMarketoClient(client); + + mktoDataSrc.doGet(context.request(), context.response()); + + assertNotNull(context.request().getAttribute(DataSource.class.getName())); + } +} diff --git a/bundle/src/test/java/com/adobe/acs/commons/marketo/impl/TestMarketoFormDataSource.java b/bundle/src/test/java/com/adobe/acs/commons/marketo/impl/TestMarketoFormDataSource.java new file mode 100644 index 0000000000..1b6447a103 --- /dev/null +++ b/bundle/src/test/java/com/adobe/acs/commons/marketo/impl/TestMarketoFormDataSource.java @@ -0,0 +1,98 @@ +/* + * #%L + * ACS AEM Commons Bundle + * %% + * Copyright (C) 2019 Adobe + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package com.adobe.acs.commons.marketo.impl; + +import static org.junit.Assert.assertNotNull; + +import java.io.IOException; +import java.util.Collections; + +import org.apache.sling.api.resource.Resource; +import org.apache.sling.caconfig.resource.ConfigurationResourceResolver; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.mockito.Mockito; + +import com.adobe.acs.commons.marketo.client.MarketoClient; +import com.adobe.acs.commons.marketo.client.impl.StaticResponseMarketoClient; +import com.adobe.granite.ui.components.ds.DataSource; + +import io.wcm.testing.mock.aem.junit.AemContext; + + +public class TestMarketoFormDataSource { + + @Rule + public final AemContext context = new AemContext(); + + @Before + public void init() { + context.addModelsForPackage("com.adobe.acs.commons.marketo", "com.adobe.acs.commons.marketo.impl"); + context.load().json("/com/adobe/acs/commons/marketo/pages.json", "/content/page"); + context.load().json("/com/adobe/acs/commons/marketo/cloudconfig.json", "/conf/test"); + + Resource resource = Mockito.mock(Resource.class); + Mockito.when(resource.getResourceType()).thenReturn("cq:Page"); + Mockito.when(resource.getPath()).thenReturn("/mnt/somewhere"); + Mockito.when(resource.getResourceResolver()).thenReturn(context.resourceResolver()); + context.request().setResource(resource); + context.requestPathInfo().setSuffix("/content/page"); + + } + + @Test + public void testdoGet() throws IOException { + + ConfigurationResourceResolver configrr = Mockito.mock(ConfigurationResourceResolver.class); + Mockito.when(configrr.getResourceCollection(Mockito.any(), Mockito.any(), Mockito.any())) + .thenReturn(Collections.singletonList(context.resourceResolver().getResource("/conf/test"))); + context.registerService(ConfigurationResourceResolver.class, configrr); + + MarketoFormDataSource mktoDataSrc = new MarketoFormDataSource(); + + MarketoClient client = new StaticResponseMarketoClient(new String[] { "/com/adobe/acs/commons/marketo/token-response.json", + "/com/adobe/acs/commons/marketo/form-response.json", "/com/adobe/acs/commons/marketo/response-noassets.json" }); + mktoDataSrc.bindMarketoClient(client); + + mktoDataSrc.doGet(context.request(), context.response()); + + assertNotNull(context.request().getAttribute(DataSource.class.getName())); + } + + @Test + public void testInvalidResource() { + + ConfigurationResourceResolver configrr = Mockito.mock(ConfigurationResourceResolver.class); + Mockito.when(configrr.getResourceCollection(Mockito.any(), Mockito.any(), Mockito.any())) + .thenReturn(Collections.emptyList()); + context.registerService(ConfigurationResourceResolver.class, configrr); + + MarketoFormDataSource mktoDataSrc = new MarketoFormDataSource(); + + MarketoClient client = new StaticResponseMarketoClient(new String[] { "/marketo/token-response.json", + "/marketo/form-response.json", "/marketo/response-noassets.json" }); + mktoDataSrc.bindMarketoClient(client); + + mktoDataSrc.doGet(context.request(), context.response()); + + assertNotNull(context.request().getAttribute(DataSource.class.getName())); + } +} diff --git a/bundle/src/test/java/com/adobe/acs/commons/marketo/impl/TestMarketoFormImpl.java b/bundle/src/test/java/com/adobe/acs/commons/marketo/impl/TestMarketoFormImpl.java new file mode 100644 index 0000000000..fbef8bd27d --- /dev/null +++ b/bundle/src/test/java/com/adobe/acs/commons/marketo/impl/TestMarketoFormImpl.java @@ -0,0 +1,93 @@ +/* + * #%L + * ACS AEM Commons Bundle + * %% + * Copyright (C) 2019 Adobe + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ +package com.adobe.acs.commons.marketo.impl; + +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 java.util.Collections; + +import org.apache.sling.api.resource.Resource; +import org.apache.sling.caconfig.resource.ConfigurationResourceResolver; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.mockito.Mockito; + +import com.adobe.acs.commons.marketo.MarketoForm; + +import io.wcm.testing.mock.aem.junit.AemContext; + + +public class TestMarketoFormImpl { + + @Rule + public final AemContext context = new AemContext(); + + @Before + public void init() { + context.addModelsForPackage("com.adobe.acs.commons.marketo", "com.adobe.acs.commons.marketo.impl"); + context.load().json("/com/adobe/acs/commons/marketo/pages.json", "/content/page"); + context.load().json("/com/adobe/acs/commons/marketo/cloudconfig.json", "/conf/test"); + + ConfigurationResourceResolver configrr = Mockito.mock(ConfigurationResourceResolver.class); + Mockito.when(configrr.getResourceCollection(Mockito.any(), Mockito.any(), Mockito.any())) + .thenReturn(Collections.singletonList(context.resourceResolver().getResource("/conf/test"))); + context.registerService(ConfigurationResourceResolver.class, configrr); + } + + @Test + public void testConfig() { + Resource resource = context.resourceResolver().getResource("/content/page/about-us/jcr:content/root/marketo-form"); + context.request().setResource(resource); + MarketoForm mfc = context.request().adaptTo(MarketoForm.class); + assertNotNull(mfc); + assertNotNull(mfc.getFormId()); + assertNull(mfc.getScript()); + assertNull(mfc.getSuccessUrl()); + assertNull(mfc.getValues()); + } + + @Test + public void testAdvancedConfig() { + Resource resource = context.resourceResolver() + .getResource("/content/page/about-us/jcr:content/root/marketo-form-1"); + context.request().setResource(resource); + MarketoForm mfc = context.request().adaptTo(MarketoForm.class); + assertNotNull(mfc); + assertEquals("123", mfc.getFormId()); + assertEquals("alert('hi')", mfc.getScript()); + assertNotNull(mfc.getSuccessUrl()); + assertNotNull(mfc.getValues()); + assertNotNull(mfc.getHidden()); + assertFalse(mfc.isEdit()); + } + + @Test + public void testInvalidResource() { + Resource resource = context.resourceResolver().getResource("/content/page/about-us/jcr:content/root"); + context.request().setResource(resource); + MarketoForm mfc = context.request().adaptTo(MarketoForm.class); + assertNotNull(mfc); + assertNull(mfc.getFormId()); + } +} diff --git a/bundle/src/test/resources/com/adobe/acs/commons/cloudconfig/cloudconfig.json b/bundle/src/test/resources/com/adobe/acs/commons/cloudconfig/cloudconfig.json new file mode 100644 index 0000000000..a68e2a93be --- /dev/null +++ b/bundle/src/test/resources/com/adobe/acs/commons/cloudconfig/cloudconfig.json @@ -0,0 +1,14 @@ +{ + "jcr:primaryType": "cq:Page", + "jcr:content": { + "jcr:primaryType": "cq:PageContent", + "jcr:title": "Test Cloud Config", + "cq:template": "/apps/core/wcm/templates/marketocloudconfig", + "sling:resourceType": "page", + "endpointHost": "test.mktorest.com", + "serverInstance": "//test.marketo.com", + "munchkinId": "123-456-789", + "clientId": "123", + "clientSecret": "456" + } +} \ No newline at end of file diff --git a/bundle/src/test/resources/com/adobe/acs/commons/marketo/cloudconfig.json b/bundle/src/test/resources/com/adobe/acs/commons/marketo/cloudconfig.json new file mode 100644 index 0000000000..a68e2a93be --- /dev/null +++ b/bundle/src/test/resources/com/adobe/acs/commons/marketo/cloudconfig.json @@ -0,0 +1,14 @@ +{ + "jcr:primaryType": "cq:Page", + "jcr:content": { + "jcr:primaryType": "cq:PageContent", + "jcr:title": "Test Cloud Config", + "cq:template": "/apps/core/wcm/templates/marketocloudconfig", + "sling:resourceType": "page", + "endpointHost": "test.mktorest.com", + "serverInstance": "//test.marketo.com", + "munchkinId": "123-456-789", + "clientId": "123", + "clientSecret": "456" + } +} \ No newline at end of file diff --git a/bundle/src/test/resources/com/adobe/acs/commons/marketo/field-response.json b/bundle/src/test/resources/com/adobe/acs/commons/marketo/field-response.json new file mode 100644 index 0000000000..75887f3d29 --- /dev/null +++ b/bundle/src/test/resources/com/adobe/acs/commons/marketo/field-response.json @@ -0,0 +1,15 @@ +{ + "success": true, + "errors": [], + "requestId": "123", + "warnings": [], + "result": [ + { + "id": "Address", + "isRequired": false, + "dataType": "textarea", + "maxLength": 2000, + "visibleRows": 2 + } + ] +} \ No newline at end of file diff --git a/bundle/src/test/resources/com/adobe/acs/commons/marketo/form-response.json b/bundle/src/test/resources/com/adobe/acs/commons/marketo/form-response.json new file mode 100644 index 0000000000..48873a797a --- /dev/null +++ b/bundle/src/test/resources/com/adobe/acs/commons/marketo/form-response.json @@ -0,0 +1,43 @@ +{ + "success": true, + "errors": [], + "requestId": "123", + "warnings": [], + "result": [ + { + "id": 1, + "name": "Sample Form", + "description": "My Description", + "createdAt": "2017-08-31T20:08:43Z+0000", + "updatedAt": "2017-08-31T20:13:55Z+0000", + "url": "https://client.marketo.com/#formid", + "status": "approved", + "theme": "simple", + "language": "English", + "locale": "en_US", + "progressiveProfiling": false, + "labelPosition": "left", + "fontFamily": "Helvetica", + "fontSize": "13px", + "folder": { + "type": "Folder", + "value": 1234, + "folderName": "Sample Folder" + }, + "knownVisitor": { + "type": "form", + "template": null + }, + "thankYouList": [ + { + "followupType": "none", + "followupValue": null, + "default": true + } + ], + "buttonLocation": 1, + "buttonLabel": "Do Needful", + "waitingLabel": "Please Wait" + } + ] +} \ No newline at end of file diff --git a/bundle/src/test/resources/com/adobe/acs/commons/marketo/formvalue.json b/bundle/src/test/resources/com/adobe/acs/commons/marketo/formvalue.json new file mode 100644 index 0000000000..b55551f2a0 --- /dev/null +++ b/bundle/src/test/resources/com/adobe/acs/commons/marketo/formvalue.json @@ -0,0 +1,24 @@ +{ + "formvalue": { + "jcr:primaryType": "cq:Page", + "jcr:content": { + "jcr:primaryType": "cq:PageContent", + "jcr:title": "Form Value Test", + "sling:resourceType": "core/wcm/components/page/v2/page", + "root": { + "jcr:primaryType": "nt:unstructured", + "valid": { + "jcr:primaryType": "nt:unstructured", + "name": "Test", + "source": "static", + "value": "Value" + }, + "invalid": { + "jcr:primaryType": "nt:unstructured", + "name": "Test", + "source": "static" + } + } + } + } +} \ No newline at end of file diff --git a/bundle/src/test/resources/com/adobe/acs/commons/marketo/pages.json b/bundle/src/test/resources/com/adobe/acs/commons/marketo/pages.json new file mode 100644 index 0000000000..37763bf69d --- /dev/null +++ b/bundle/src/test/resources/com/adobe/acs/commons/marketo/pages.json @@ -0,0 +1,91 @@ +{ + "jcr:primaryType": "cq:Page", + "jcr:content": { + "jcr:primaryType": "cq:PageContent", + "jcr:title": "English", + "cq:conf": "/conf/test", + "sling:resourceType": "weretail/components/structure/page", + "root": { + "jcr:primaryType": "nt:unstructured", + "sling:resourceType": "wcm/foundation/components/responsivegrid" + } + }, + "about-us": { + "jcr:primaryType": "cq:Page", + "jcr:content": { + "jcr:primaryType": "cq:PageContent", + "jcr:title": "About Us", + "sling:resourceType": "weretail/components/structure/page", + "root": { + "jcr:primaryType": "nt:unstructured", + "sling:resourceType": "wcm/foundation/components/responsivegrid", + "marketo-form": { + "jcr:primaryType": "nt:unstructured", + "sling:resourceType": "wcm/foundation/components/responsivegrid", + "formId": "123" + }, + "marketo-form-1": { + "jcr:primaryType": "nt:unstructured", + "sling:resourceType": "wcm/foundation/components/responsivegrid", + "formId": "123", + "script": "alert('hi')", + "successUrl": "/content/anotherpage", + "values": { + "value-1": { + "jcr:primaryType": "nt:unstructured", + "name": "Name", + "source": "static", + "value": "Perficient Digital" + }, + "value-2": { + "jcr:primaryType": "nt:unstructured", + "name": "Twitter", + "source": "request", + "value": "@PRFTDigital" + } + }, + "hidden": { + "value-1": { + "jcr:primaryType": "nt:unstructured", + "name": "Name", + "source": "contextHub", + "value": "Perficient Digital" + }, + "value-2": { + "jcr:primaryType": "nt:unstructured", + "name": "Twitter", + "source": "jsVariable", + "value": "@PRFTDigital" + } + } + } + } + } + }, + "invalid-service": { + "jcr:primaryType": "cq:Page", + "jcr:content": { + "cq:conf": "/conf/fake", + "jcr:primaryType": "cq:PageContent", + "jcr:title": "About Us", + "sling:resourceType": "weretail/components/structure/page", + "root": { + "jcr:primaryType": "nt:unstructured", + "sling:resourceType": "wcm/foundation/components/responsivegrid" + } + } + }, + "no-config": { + "jcr:primaryType": "cq:Page", + "jcr:content": { + "cq:conf": "", + "jcr:primaryType": "cq:PageContent", + "jcr:title": "About Us", + "sling:resourceType": "weretail/components/structure/page", + "root": { + "jcr:primaryType": "nt:unstructured", + "sling:resourceType": "wcm/foundation/components/responsivegrid" + } + } + } +} diff --git a/bundle/src/test/resources/com/adobe/acs/commons/marketo/response-error.json b/bundle/src/test/resources/com/adobe/acs/commons/marketo/response-error.json new file mode 100644 index 0000000000..469b01d327 --- /dev/null +++ b/bundle/src/test/resources/com/adobe/acs/commons/marketo/response-error.json @@ -0,0 +1,11 @@ +{ + "requestId": "1234", + "success": false, + "warnings": [], + "errors": [ + { + "code": "601", + "message": "Access token invalid" + } + ] +} \ No newline at end of file diff --git a/bundle/src/test/resources/com/adobe/acs/commons/marketo/response-noassets.json b/bundle/src/test/resources/com/adobe/acs/commons/marketo/response-noassets.json new file mode 100644 index 0000000000..d114b1a257 --- /dev/null +++ b/bundle/src/test/resources/com/adobe/acs/commons/marketo/response-noassets.json @@ -0,0 +1,8 @@ +{ + "success": true, + "errors": [], + "requestId": "2134", + "warnings": [ + "No assets found for the given search criteria." + ] +} \ No newline at end of file diff --git a/bundle/src/test/resources/com/adobe/acs/commons/marketo/response-notsuccess.json b/bundle/src/test/resources/com/adobe/acs/commons/marketo/response-notsuccess.json new file mode 100644 index 0000000000..ee3d2ce0aa --- /dev/null +++ b/bundle/src/test/resources/com/adobe/acs/commons/marketo/response-notsuccess.json @@ -0,0 +1,6 @@ +{ + "success": false, + "errors": [], + "requestId": "123", + "warnings": [] +} \ No newline at end of file diff --git a/bundle/src/test/resources/com/adobe/acs/commons/marketo/token-response.json b/bundle/src/test/resources/com/adobe/acs/commons/marketo/token-response.json new file mode 100644 index 0000000000..854e6c733e --- /dev/null +++ b/bundle/src/test/resources/com/adobe/acs/commons/marketo/token-response.json @@ -0,0 +1,6 @@ +{ + "access_token": "TOKEN", + "token_type": "bearer", + "expires_in": 1, + "scope": "api-full-access@adobe.com" +} \ No newline at end of file diff --git a/ui.apps/src/main/content/META-INF/vault/filter.xml b/ui.apps/src/main/content/META-INF/vault/filter.xml index 7877f62abe..259eb3782a 100644 --- a/ui.apps/src/main/content/META-INF/vault/filter.xml +++ b/ui.apps/src/main/content/META-INF/vault/filter.xml @@ -13,6 +13,7 @@ + diff --git a/ui.apps/src/main/content/jcr_root/apps/acs-commons/components/content/embeddable/.content.xml b/ui.apps/src/main/content/jcr_root/apps/acs-commons/components/content/embeddable/.content.xml new file mode 100644 index 0000000000..491392d539 --- /dev/null +++ b/ui.apps/src/main/content/jcr_root/apps/acs-commons/components/content/embeddable/.content.xml @@ -0,0 +1,3 @@ + + diff --git a/ui.apps/src/main/content/jcr_root/apps/acs-commons/components/content/embeddable/marketo/.content.xml b/ui.apps/src/main/content/jcr_root/apps/acs-commons/components/content/embeddable/marketo/.content.xml new file mode 100644 index 0000000000..9b97953148 --- /dev/null +++ b/ui.apps/src/main/content/jcr_root/apps/acs-commons/components/content/embeddable/marketo/.content.xml @@ -0,0 +1,6 @@ + + diff --git a/ui.apps/src/main/content/jcr_root/apps/acs-commons/components/content/embeddable/marketo/_cq_dialog/.content.xml b/ui.apps/src/main/content/jcr_root/apps/acs-commons/components/content/embeddable/marketo/_cq_dialog/.content.xml new file mode 100644 index 0000000000..c4fbb08a9f --- /dev/null +++ b/ui.apps/src/main/content/jcr_root/apps/acs-commons/components/content/embeddable/marketo/_cq_dialog/.content.xml @@ -0,0 +1,211 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + \ No newline at end of file diff --git a/ui.apps/src/main/content/jcr_root/apps/acs-commons/components/utilities/cloudconfig/clientlib/.content.xml b/ui.apps/src/main/content/jcr_root/apps/acs-commons/components/utilities/cloudconfig/clientlib/.content.xml new file mode 100644 index 0000000000..31ca8c0fd3 --- /dev/null +++ b/ui.apps/src/main/content/jcr_root/apps/acs-commons/components/utilities/cloudconfig/clientlib/.content.xml @@ -0,0 +1,5 @@ + + diff --git a/ui.apps/src/main/content/jcr_root/apps/acs-commons/components/utilities/cloudconfig/clientlib/css.txt b/ui.apps/src/main/content/jcr_root/apps/acs-commons/components/utilities/cloudconfig/clientlib/css.txt new file mode 100644 index 0000000000..7000aaea8f --- /dev/null +++ b/ui.apps/src/main/content/jcr_root/apps/acs-commons/components/utilities/cloudconfig/clientlib/css.txt @@ -0,0 +1,17 @@ +############################################################################### +# Copyright 2019 Adobe +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +############################################################################### + +summary.css \ No newline at end of file diff --git a/ui.apps/src/main/content/jcr_root/apps/acs-commons/components/utilities/cloudconfig/clientlib/delete.js b/ui.apps/src/main/content/jcr_root/apps/acs-commons/components/utilities/cloudconfig/clientlib/delete.js new file mode 100644 index 0000000000..eebd84e6fe --- /dev/null +++ b/ui.apps/src/main/content/jcr_root/apps/acs-commons/components/utilities/cloudconfig/clientlib/delete.js @@ -0,0 +1,58 @@ +/* + * Copyright 2019 Adobe + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +(function(window, document, $, Granite) { + "use strict"; + + var ui = $(window).adaptTo("foundation-ui"); + $(window).adaptTo("foundation-registry").register("foundation.collection.action.action", { + name: "acscommons.clientlib.delete", + handler: function(name, el, config, collection, selections) { + var message = $("
"); + var intro = $("

").appendTo(message); + intro.text(Granite.I18n.get("You are going to delete the selected item")); + + ui.prompt(Granite.I18n.get("Delete"), message.html(), "notice", [{ + text: Granite.I18n.get("Cancel") + }, { + text: Granite.I18n.get("Delete"), + warning: true, + handler: function() { + doDelete(config.data.path); + } + }]); + } + }); + + function doDelete(path) { + ui.wait(); + + $.ajax({ + url: path, + type: "POST", + data: { + _charset_: "UTF-8", + ":operation": "delete" + } + }).done(function(data, textStatus, jqXHR) { + window.location.reload(); + }).fail(function(jqXHR, textStatus, errorThrown) { + var message = Granite.I18n.getVar($(jqXHR.responseText).find(".foundation-form-response-description").next().html()); + ui.alert(Granite.I18n.get("Error"), message, "error"); + }).always(function() { + ui.clearWait(); + }); + } +})(window, document, Granite.$, Granite); diff --git a/ui.apps/src/main/content/jcr_root/apps/acs-commons/components/utilities/cloudconfig/clientlib/js.txt b/ui.apps/src/main/content/jcr_root/apps/acs-commons/components/utilities/cloudconfig/clientlib/js.txt new file mode 100644 index 0000000000..ffb2c8410c --- /dev/null +++ b/ui.apps/src/main/content/jcr_root/apps/acs-commons/components/utilities/cloudconfig/clientlib/js.txt @@ -0,0 +1,17 @@ +############################################################################### +# Copyright 2019 Adobe +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +############################################################################### + +delete.js \ No newline at end of file diff --git a/ui.apps/src/main/content/jcr_root/apps/acs-commons/components/utilities/cloudconfig/clientlib/summary.css b/ui.apps/src/main/content/jcr_root/apps/acs-commons/components/utilities/cloudconfig/clientlib/summary.css new file mode 100644 index 0000000000..c9620cfc04 --- /dev/null +++ b/ui.apps/src/main/content/jcr_root/apps/acs-commons/components/utilities/cloudconfig/clientlib/summary.css @@ -0,0 +1,19 @@ +/* + * Copyright 2019 Adobe + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +.acscommons-cloudconfig-summary { + text-align: center; + padding: 1em 0; +} diff --git a/ui.apps/src/main/content/jcr_root/apps/acs-commons/components/utilities/cloudconfig/cloudconfiglist/.content.xml b/ui.apps/src/main/content/jcr_root/apps/acs-commons/components/utilities/cloudconfig/cloudconfiglist/.content.xml new file mode 100644 index 0000000000..699ab593b7 --- /dev/null +++ b/ui.apps/src/main/content/jcr_root/apps/acs-commons/components/utilities/cloudconfig/cloudconfiglist/.content.xml @@ -0,0 +1,7 @@ + + diff --git a/ui.apps/src/main/content/jcr_root/apps/acs-commons/components/utilities/cloudconfig/cloudconfiglist/cloudconfiglist.html b/ui.apps/src/main/content/jcr_root/apps/acs-commons/components/utilities/cloudconfig/cloudconfiglist/cloudconfiglist.html new file mode 100644 index 0000000000..55b5d8f4a8 --- /dev/null +++ b/ui.apps/src/main/content/jcr_root/apps/acs-commons/components/utilities/cloudconfig/cloudconfiglist/cloudconfiglist.html @@ -0,0 +1,44 @@ + + +

+

${request.requestPathInfo.suffixResource.valueMap.jcr:title}

+

${request.requestPathInfo.suffixResource.valueMap.jcr:description}

+
+
+ + + + + + + +
+

${config.title}

+
+
+

${config.configPath}

+
+
+
+ + ${'Edit Cloud Configuration' @ i18n} + ${'Delete' @ i18n} + +
+
+
+ \ No newline at end of file diff --git a/ui.apps/src/main/content/jcr_root/apps/acs-commons/components/utilities/cloudconfig/marketo/.content.xml b/ui.apps/src/main/content/jcr_root/apps/acs-commons/components/utilities/cloudconfig/marketo/.content.xml new file mode 100644 index 0000000000..d420ff58c2 --- /dev/null +++ b/ui.apps/src/main/content/jcr_root/apps/acs-commons/components/utilities/cloudconfig/marketo/.content.xml @@ -0,0 +1,7 @@ + + diff --git a/ui.apps/src/main/content/jcr_root/apps/acs-commons/components/utilities/cloudconfig/marketo/_cq_dialog/.content.xml b/ui.apps/src/main/content/jcr_root/apps/acs-commons/components/utilities/cloudconfig/marketo/_cq_dialog/.content.xml new file mode 100644 index 0000000000..c63ca2a4ec --- /dev/null +++ b/ui.apps/src/main/content/jcr_root/apps/acs-commons/components/utilities/cloudconfig/marketo/_cq_dialog/.content.xml @@ -0,0 +1,74 @@ + + + + + + + + + + </items> + </metadata> + <configuration + jcr:primaryType="nt:unstructured" + jcr:title="Configuration" + sling:resourceType="granite/ui/components/coral/foundation/form/fieldset"> + <items jcr:primaryType="nt:unstructured"> + <endpointHost + jcr:primaryType="nt:unstructured" + sling:resourceType="granite/ui/components/coral/foundation/form/textfield" + fieldLabel="REST Endpoint Host" + fieldDescription="The Marketo REST API Endpont host, found in Marketo under Admin >> Integration >> Web Services. Example: https://1234.mktorest.com" + name="./endpointHost" + required="{Boolean}true" /> + <serverInstance + jcr:primaryType="nt:unstructured" + sling:resourceType="granite/ui/components/coral/foundation/form/textfield" + fieldLabel="Marketo Server Instance" + fieldDescription="URL Used to access marketo, e.g. //app-ab3123.marketo.com" + name="./serverInstance" + required="{Boolean}true" /> + <munchkinId + jcr:primaryType="nt:unstructured" + sling:resourceType="granite/ui/components/coral/foundation/form/textfield" + fieldLabel="Munchkin Account ID" + fieldDescription="Found in Marketo under Admin >> Integration >> Munchkin" + name="./munchkinId" + required="{Boolean}true" /> + <clientId + jcr:primaryType="nt:unstructured" + sling:resourceType="granite/ui/components/coral/foundation/form/textfield" + fieldLabel="Client ID" + fieldDescription="Found in Marketo under Admin >> Integration >> LaunchPoint" + name="./clientId" + required="{Boolean}true" /> + <clientSecret + jcr:primaryType="nt:unstructured" + sling:resourceType="granite/ui/components/coral/foundation/form/password" + fieldLabel="Client Secret" + fieldDescription="Found in Marketo under Admin >> Integration >> LaunchPoint" + name="./clientSecret" + required="{Boolean}true" /> + </items> + </configuration> + </items> + </column> + </items> + </content> +</jcr:root> \ No newline at end of file diff --git a/ui.apps/src/main/content/jcr_root/apps/acs-commons/components/utilities/cloudconfig/marketo/marketo.jsp b/ui.apps/src/main/content/jcr_root/apps/acs-commons/components/utilities/cloudconfig/marketo/marketo.jsp new file mode 100644 index 0000000000..43b00f2e52 --- /dev/null +++ b/ui.apps/src/main/content/jcr_root/apps/acs-commons/components/utilities/cloudconfig/marketo/marketo.jsp @@ -0,0 +1,18 @@ +<!--/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ Copyright 2019 Adobe + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/--> +<%@ page session="false" contentType="text/html" pageEncoding="utf-8" %> +<%@include file="/libs/foundation/global.jsp" %> +<c:redirect url="/apps/acs-commons/content/cloudservice/console.html/apps/acs-commons/templates/marketocloudconfig"/> \ No newline at end of file diff --git a/ui.apps/src/main/content/jcr_root/apps/acs-commons/content/cloudservice/console/.content.xml b/ui.apps/src/main/content/jcr_root/apps/acs-commons/content/cloudservice/console/.content.xml new file mode 100644 index 0000000000..6f91938d1e --- /dev/null +++ b/ui.apps/src/main/content/jcr_root/apps/acs-commons/content/cloudservice/console/.content.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="UTF-8"?> +<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0" + jcr:primaryType="cq:Page"> + <jcr:content + jcr:mixinTypes="[sling:VanityPath]" + jcr:primaryType="nt:unstructured" + jcr:title="Cloud Service Instances" + sling:resourceType="granite/ui/components/shell/page" + consoleId="acs-commons-cloudservice-console"> + <head jcr:primaryType="nt:unstructured"> + <clientlibs + jcr:primaryType="nt:unstructured" + sling:resourceType="granite/ui/components/coral/foundation/includeclientlibs" + categories="[cq.common.wcm,acscommons.cloudconfig.clientlib]"/> + </head> + <actions + jcr:primaryType="nt:unstructured" + sling:resourceType="granite/ui/components/coral/foundation/actionbar"> + <secondary jcr:primaryType="nt:unstructured"> + <create_visible + jcr:primaryType="nt:unstructured" + sling:resourceType="granite/ui/components/coral/foundation/anchorbutton" + href="/apps/acs-commons/content/cloudservice/create.html${requestPathInfo.suffix}" + text="Create" + variant="primary"/> + </secondary> + </actions> + <content + jcr:primaryType="nt:unstructured" + sling:resourceType="granite/ui/components/coral/foundation/container"> + <items jcr:primaryType="nt:unstructured"> + <sitecollection + jcr:primaryType="nt:unstructured" + sling:resourceType="acs-commons/components/utilities/cloudconfig/cloudconfiglist"/> + </items> + </content> + <title + jcr:primaryType="nt:unstructured" + sling:resourceType="granite/ui/components/coral/foundation/text" + text="Cloud Configuration Instances"/> + </jcr:content> +</jcr:root> diff --git a/ui.apps/src/main/content/jcr_root/apps/acs-commons/content/cloudservice/create/.content.xml b/ui.apps/src/main/content/jcr_root/apps/acs-commons/content/cloudservice/create/.content.xml new file mode 100644 index 0000000000..15c45fd2c4 --- /dev/null +++ b/ui.apps/src/main/content/jcr_root/apps/acs-commons/content/cloudservice/create/.content.xml @@ -0,0 +1,161 @@ +<?xml version="1.0" encoding="UTF-8"?> +<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:granite="http://www.adobe.com/jcr/granite/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0" + jcr:primaryType="cq:Page"> + <jcr:content + jcr:primaryType="nt:unstructured" + jcr:title="Create Cloud Configuration" + sling:resourceType="granite/ui/components/coral/foundation/page"> + <head jcr:primaryType="nt:unstructured"> + <viewport + jcr:primaryType="nt:unstructured" + sling:resourceType="granite/ui/components/coral/foundation/admin/page/viewport"/> + <favicon + jcr:primaryType="nt:unstructured" + sling:resourceType="granite/ui/components/coral/foundation/page/favicon"/> + <clientlibs + jcr:primaryType="nt:unstructured" + sling:resourceType="granite/ui/components/coral/foundation/includeclientlibs" + categories="[coralui3,granite.ui.coral.foundation]"/> + </head> + <body + jcr:primaryType="nt:unstructured" + sling:resourceType="granite/ui/components/coral/foundation/page/body"> + <items jcr:primaryType="nt:unstructured"> + <form + granite:id="acs-commons-cloudservice-create" + jcr:primaryType="nt:unstructured" + sling:resourceType="granite/ui/components/coral/foundation/form" + action="/bin/acscommons/createcloudconfig" + foundationForm="{Boolean}true" + maximized="{Boolean}true" + method="post" + novalidate="{Boolean}true" + style="vertical"> + <items jcr:primaryType="nt:unstructured"> + <wizard + jcr:primaryType="nt:unstructured" + jcr:title="Create Cloud Configuration" + sling:resourceType="granite/ui/components/coral/foundation/wizard" + cancelHref="${empty header.Referer ? granite:concat("/apps/acs-commons/content/cloudservice/console.html", granite:encodeURIPath(requestPathInfo.suffix)) : header.Referer}"> + <items jcr:primaryType="nt:unstructured"> + <destinationStep + jcr:primaryType="nt:unstructured" + jcr:title="Select Configuration Root" + sling:resourceType="granite/ui/components/coral/foundation/wizard/lazycontainer" + maximized="{Boolean}true" + src="/apps/acs-commons/content/cloudservice/create/target.html/conf"> + <parentConfig jcr:primaryType="nt:unstructured"> + <next + granite:class="foundation-wizard-control" + jcr:primaryType="nt:unstructured" + sling:resourceType="granite/ui/components/coral/foundation/button" + disabled="{Boolean}true" + text="Next" + variant="primary"> + <granite:data + jcr:primaryType="nt:unstructured" + foundation-wizard-control-action="next"/> + </next> + </parentConfig> + </destinationStep> + <configureStep + jcr:primaryType="nt:unstructured" + jcr:title="Configure" + sling:resourceType="granite/ui/components/coral/foundation/container"> + <items jcr:primaryType="nt:unstructured"> + <fixedColumns + jcr:primaryType="nt:unstructured" + sling:resourceType="granite/ui/components/coral/foundation/fixedcolumns" + maximized="{Boolean}true"> + <items jcr:primaryType="nt:unstructured"> + <column + jcr:primaryType="nt:unstructured" + sling:resourceType="granite/ui/components/coral/foundation/container"> + <items jcr:primaryType="nt:unstructured"> + <configuration + jcr:primaryType="nt:unstructured" + jcr:title="New Configuration" + sling:resourceType="granite/ui/components/coral/foundation/form/fieldset"> + <items jcr:primaryType="nt:unstructured"> + <title + jcr:primaryType="nt:unstructured" + sling:resourceType="granite/ui/components/coral/foundation/form/textfield" + fieldLabel="Cloud Configuration Title" + name="title" + required="true"/> + <name + jcr:primaryType="nt:unstructured" + sling:resourceType="granite/ui/components/coral/foundation/form/textfield" + fieldLabel="Name" + name="name" + required="true"/> + <template + jcr:primaryType="nt:unstructured" + sling:resourceType="granite/ui/components/coral/foundation/form/hidden" + name="template" + value="${requestPathInfo.suffix}"/> + </items> + </configuration> + </items> + </column> + </items> + </fixedColumns> + </items> + <parentConfig jcr:primaryType="nt:unstructured"> + <next + granite:class="foundation-wizard-control" + jcr:primaryType="nt:unstructured" + sling:resourceType="granite/ui/components/coral/foundation/button" + text="Create" + type="submit" + variant="primary"> + <granite:data + jcr:primaryType="nt:unstructured" + foundation-wizard-control-action="next"/> + </next> + </parentConfig> + </configureStep> + </items> + </wizard> + </items> + <successresponse jcr:primaryType="nt:unstructured" + jcr:title="Success" + open="/libs/wcm/core/content/sites/properties.html?item={Path}" + redirect="/apps/acs-commons/content/cloudservice/console.html${requestPathInfo.suffix}" + sling:resourceType="granite/ui/components/coral/foundation/form/responses/openprompt" + text="Cloud Configuration created!"/> + </form> + </items> + </body> + </jcr:content> + <target + jcr:primaryType="nt:unstructured" + sling:resourceType="granite/ui/components/coral/foundation/form/advancedselect" + maximized="{Boolean}true" + required="{Boolean}true" + selectionMode="single" + name="configPath"> + <field + jcr:primaryType="nt:unstructured" + sling:resourceType="granite/ui/components/coral/foundation/columnview" + itemprop="item" + itemResourceType="cq/gui/components/coral/admin/page/simplecolumnitem" + layoutId="columns" + limit="{Long}40" + loadAncestors="{Boolean}true" + path="${requestPathInfo.suffix}" + previewSrc="/libs/wcm/core/content/sites/pagecolumnpreview.html{+id}" + rootPath="/conf" + selectionCount="single" + size="{Long}40" + src="/apps/acs-commons/content/cloudservice/create/target/field{.offset,limit}.html{+id}"> + <datasource + jcr:primaryType="nt:unstructured" + sling:resourceType="cq/gui/components/common/wcm/datasources/childresources" + exclude="/conf/[a-z-_]*" + limit="${empty requestPathInfo.selectors[1] ? "41" : requestPathInfo.selectors[1] + 1}" + offset="${requestPathInfo.selectors[0]}" + path="${requestPathInfo.suffix}"/> + </field> + </target> +</jcr:root> diff --git a/ui.apps/src/main/content/jcr_root/apps/acs-commons/content/cloudservice/thumb.png b/ui.apps/src/main/content/jcr_root/apps/acs-commons/content/cloudservice/thumb.png new file mode 100644 index 0000000000000000000000000000000000000000..4e6300f347511125688feade3d0bb11ed61dcf4c GIT binary patch literal 1042 zcmeAS@N?(olHy`uVBq!ia0vp^AAooZ2OE%FHD}=q1_tJvo-U3d6}R5r_4hV%WH|6} z-~aTBCP#ZZF0}Xwc~x;(bH;vqAiqRKR6UI2p7RH%7th|<@SmwHFRtq{c8+6Fh!X$D zqLAQlprOGLh#47~nb<&>g$IN=Bm@jV7^DEJA`S`S6&2{*yMO<1g$*A+KmWp;Ic-^6 zrL?AceOY`lqviMS-v%;#himM<J8|!bDcc=eQB|eoyWzj|-@5-F&Tv>%{r+qBrE0Ir zp}*x%&d;&8X6n0@V&tiJ@BKs&``6{|SF=>5KYabV)l=a?Meg?7DUbik%|3g~MWA5L zwb!Me7@upu=dkel`NY@u!PTr(C60~dIXWkMK7lM<CUcEm8=zjsegth`HVuHW<H zzfbT_pYuzKNvz-{)4tuiwZGWyy8EvGyP*V+UmY(acf<iEw*yRK8yW;RG_dMCDCW4K zwFSaXU{p>3$pfumdiI97Ovw9yi_C^x6{s*&o2P2R>I+adYY)%}h&BoJjVwUse7%I* z9;mXDy$*yegsSA0V00JyaQ3Y4iA`%ZOx&Lcv`R)ZVZUDo$Q+hASqILaKmYLU+qW6Y z|4)X1+``&xvr9?r6v$|xUYO$xZZU4Z{dTdQ!r!z;PoQI`GtNKksRL6XW&rXYtB)Y# z_19kyx9DfZ#Kv+0Ez$-$4dge3_vd&W@JmvB(80W|w*~A1xHT(TYWUPQerjDC9PfO9 zNiX%lKW$Zbpe2Buvs|d)qWZ>vueMBYV2wG|(0$KMs|grZ(C~x00b~eJNx0p#(@Q%Q z9$3`Y)Tr$5-4eCdhlTO@%g>*Ue>Plyy%i+$_WSREwPBO_Dz@LA$-&eYzW%zm**(AI z$xIv;d7E$Q-1L8_bJ~Z2@p!(`Ocn9>877|&aqqBMb~!V{L~1Gj_OR8m_cjO=yv#A1 z{o&UyDLHw0=hauarca-Kk$rZ(ZHC$G_V>T^_4UK%vI6r3B-tw@Am<H6#%4$cf@L05 hMX(%3lp^P@eGIPcn<ne?oBd<}0#8>zmvv4FO#tGth~WSL literal 0 HcmV?d00001 diff --git a/ui.apps/src/main/content/jcr_root/apps/acs-commons/templates/utilities/marketocloudconfig/.content.xml b/ui.apps/src/main/content/jcr_root/apps/acs-commons/templates/utilities/marketocloudconfig/.content.xml new file mode 100644 index 0000000000..a45f83d398 --- /dev/null +++ b/ui.apps/src/main/content/jcr_root/apps/acs-commons/templates/utilities/marketocloudconfig/.content.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8"?> +<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" + jcr:primaryType="cq:Template" + jcr:description="Marketo's powerful marketing automation software helps marketers master the art and science of digital marketing to engage customers and prospects." + jcr:title="Marketo" + allowedPaths="[/conf(/.*)?]" + ranking="{Long}100"> + <jcr:content + jcr:primaryType="cq:PageContent" + sling:resourceType="acs-commons/components/utilities/cloudconfig/marketo"/> +</jcr:root> diff --git a/ui.apps/src/main/content/jcr_root/apps/cq/core/content/nav/tools/cloudservices/.content.xml b/ui.apps/src/main/content/jcr_root/apps/cq/core/content/nav/tools/cloudservices/.content.xml new file mode 100644 index 0000000000..491392d539 --- /dev/null +++ b/ui.apps/src/main/content/jcr_root/apps/cq/core/content/nav/tools/cloudservices/.content.xml @@ -0,0 +1,3 @@ +<?xml version="1.0" encoding="UTF-8"?> +<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" + jcr:primaryType="sling:Folder"/> diff --git a/ui.apps/src/main/content/jcr_root/apps/cq/core/content/nav/tools/cloudservices/marketo/.content.xml b/ui.apps/src/main/content/jcr_root/apps/cq/core/content/nav/tools/cloudservices/marketo/.content.xml new file mode 100644 index 0000000000..de7e36ee51 --- /dev/null +++ b/ui.apps/src/main/content/jcr_root/apps/cq/core/content/nav/tools/cloudservices/marketo/.content.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" + jcr:primaryType="nt:unstructured" + href="/apps/acs-commons/content/cloudservice/console.html/apps/acs-commons/templates/utilities/marketocloudconfig" + icon="mcMarketoEngageColor" + id="marketo-cloud-configuration" + jcr:description="Marketo's powerful marketing automation software helps marketers master the art and science of digital marketing to engage customers and prospects." + jcr:title="Marketo" /> \ No newline at end of file From 75903d3efcc1e8f82580f78353063f3a87782024 Mon Sep 17 00:00:00 2001 From: Dan Klco <dan.klco@perficient.com> Date: Thu, 7 Nov 2019 21:52:01 -0500 Subject: [PATCH 2/4] Fixing code climate issues --- .../commons/marketo/client/MarketoForm.java | 2 + .../impl/CloudConfigurationListImplTest.java | 4 +- .../impl/CreateCloudConfigServletTest.java | 41 ++++++++++--------- 3 files changed, 25 insertions(+), 22 deletions(-) diff --git a/bundle/src/main/java/com/adobe/acs/commons/marketo/client/MarketoForm.java b/bundle/src/main/java/com/adobe/acs/commons/marketo/client/MarketoForm.java index c79e2e5816..bfbf07abef 100644 --- a/bundle/src/main/java/com/adobe/acs/commons/marketo/client/MarketoForm.java +++ b/bundle/src/main/java/com/adobe/acs/commons/marketo/client/MarketoForm.java @@ -36,9 +36,11 @@ public class MarketoForm { public int getId() { return id; } + public String getLocale() { return locale; } + public String getName() { return name; } diff --git a/bundle/src/test/java/com/adobe/acs/commons/cloudconfig/impl/CloudConfigurationListImplTest.java b/bundle/src/test/java/com/adobe/acs/commons/cloudconfig/impl/CloudConfigurationListImplTest.java index e7833ff343..bbfaae2058 100644 --- a/bundle/src/test/java/com/adobe/acs/commons/cloudconfig/impl/CloudConfigurationListImplTest.java +++ b/bundle/src/test/java/com/adobe/acs/commons/cloudconfig/impl/CloudConfigurationListImplTest.java @@ -40,7 +40,7 @@ public class CloudConfigurationListImplTest { @Rule - public final AemContext context = new AemContext(ResourceResolverType.JCR_MOCK);; + public final AemContext context = new AemContext(ResourceResolverType.JCR_MOCK); @Before public void init() { @@ -72,7 +72,7 @@ public void valid() assertNotNull(config); assertEquals("/conf/test", config.getItemPath()); assertEquals("/", config.getConfigPath()); - }; + } @Test public void invalid() { diff --git a/bundle/src/test/java/com/adobe/acs/commons/cloudconfig/impl/CreateCloudConfigServletTest.java b/bundle/src/test/java/com/adobe/acs/commons/cloudconfig/impl/CreateCloudConfigServletTest.java index 6d0fbb66ea..8e0b222116 100644 --- a/bundle/src/test/java/com/adobe/acs/commons/cloudconfig/impl/CreateCloudConfigServletTest.java +++ b/bundle/src/test/java/com/adobe/acs/commons/cloudconfig/impl/CreateCloudConfigServletTest.java @@ -1,18 +1,22 @@ -/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - ~ Copyright 2019 Adobe - ~ - ~ Licensed under the Apache License, Version 2.0 (the "License"); - ~ you may not use this file except in compliance with the License. - ~ You may obtain a copy of the License at - ~ - ~ http://www.apache.org/licenses/LICENSE-2.0 - ~ - ~ Unless required by applicable law or agreed to in writing, software - ~ distributed under the License is distributed on an "AS IS" BASIS, - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - ~ See the License for the specific language governing permissions and - ~ limitations under the License. - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ +/* + * #%L + * ACS AEM Commons Bundle + * %% + * Copyright (C) 2019 Adobe + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ package com.adobe.acs.commons.cloudconfig.impl; import static org.junit.Assert.assertEquals; @@ -55,8 +59,6 @@ public void init() { @Test public void testDoPost() throws IOException { - CreateCloudConfigServlet cccSrvlt = new CreateCloudConfigServlet(); - Map<String, Object> parameterMap = new HashMap<>(); parameterMap.put("configPath", "/conf/test2"); parameterMap.put("title", "Test"); @@ -64,7 +66,7 @@ public void testDoPost() throws IOException { parameterMap.put("template", "/apps/core/wcm/templates/marketocloudconfig"); context.request().setParameterMap(parameterMap); - + CreateCloudConfigServlet cccSrvlt = new CreateCloudConfigServlet(); cccSrvlt.doPost(context.request(), context.response()); assertNotNull(context.response().getOutputAsString()); @@ -80,8 +82,6 @@ public void testDoPost() throws IOException { @Test public void testInvalid() throws IOException { - CreateCloudConfigServlet cccSrvlt = new CreateCloudConfigServlet(); - Map<String, Object> parameterMap = new HashMap<>(); parameterMap.put("configPath", "/conf/test2"); parameterMap.put("name", "test2"); @@ -90,6 +90,7 @@ public void testInvalid() throws IOException { context.request().setParameterMap(parameterMap); try { + CreateCloudConfigServlet cccSrvlt = new CreateCloudConfigServlet(); cccSrvlt.doPost(context.request(), context.response()); fail(); } catch (IOException e) { From d94f561c432c6db73768e746a615c6c648b58cb6 Mon Sep 17 00:00:00 2001 From: Dan Klco <dan.klco@perficient.com> Date: Thu, 7 Nov 2019 22:36:01 -0500 Subject: [PATCH 3/4] Fixing broken tests --- .../marketo/impl/MarketoClientConfigurationManagerImpl.java | 4 ++++ .../marketo/impl/TestMarketoClientConfiguration.java | 6 ++++-- .../com/adobe/acs/commons/marketo/cloudconfig.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/bundle/src/main/java/com/adobe/acs/commons/marketo/impl/MarketoClientConfigurationManagerImpl.java b/bundle/src/main/java/com/adobe/acs/commons/marketo/impl/MarketoClientConfigurationManagerImpl.java index 2a0f42a831..4d4d815cde 100644 --- a/bundle/src/main/java/com/adobe/acs/commons/marketo/impl/MarketoClientConfigurationManagerImpl.java +++ b/bundle/src/main/java/com/adobe/acs/commons/marketo/impl/MarketoClientConfigurationManagerImpl.java @@ -61,4 +61,8 @@ public MarketoClientConfiguration getConfiguration() { }).findFirst().map(c -> c.getChild(JcrConstants.JCR_CONTENT)).map(c -> c.adaptTo(MarketoClientConfiguration.class)) .orElse(null); } + + public void setConfigRsrcRslvr(ConfigurationResourceResolver configRsrcRslvr) { + this.configRsrcRslvr = configRsrcRslvr; + } } diff --git a/bundle/src/test/java/com/adobe/acs/commons/marketo/impl/TestMarketoClientConfiguration.java b/bundle/src/test/java/com/adobe/acs/commons/marketo/impl/TestMarketoClientConfiguration.java index f2aa1f8d98..a8afd35fe1 100644 --- a/bundle/src/test/java/com/adobe/acs/commons/marketo/impl/TestMarketoClientConfiguration.java +++ b/bundle/src/test/java/com/adobe/acs/commons/marketo/impl/TestMarketoClientConfiguration.java @@ -41,6 +41,7 @@ public class TestMarketoClientConfiguration { @Rule public final AemContext context = new AemContext(); + private ConfigurationResourceResolver configrr; @Before public void init() { @@ -48,7 +49,7 @@ public void init() { context.load().json("/com/adobe/acs/commons/marketo/pages.json", "/content/page"); context.load().json("/com/adobe/acs/commons/marketo/cloudconfig.json", "/conf/test"); - ConfigurationResourceResolver configrr = Mockito.mock(ConfigurationResourceResolver.class); + configrr = Mockito.mock(ConfigurationResourceResolver.class); Mockito.when(configrr.getResourceCollection(Mockito.any(), Mockito.any(), Mockito.any())) .thenReturn(Collections.singletonList(context.resourceResolver().getResource("/conf/test"))); context.registerService(ConfigurationResourceResolver.class, configrr); @@ -58,7 +59,8 @@ public void init() { @Test public void testConfigMgr() { context.request().setResource(context.resourceResolver().getResource("/content/page")); - MarketoClientConfigurationManager mccm = context.request().adaptTo(MarketoClientConfigurationManager.class); + MarketoClientConfigurationManagerImpl mccm = new MarketoClientConfigurationManagerImpl(context.request()); + mccm.setConfigRsrcRslvr(configrr); assertNotNull(mccm); assertNotNull(mccm.getConfiguration()); diff --git a/bundle/src/test/resources/com/adobe/acs/commons/marketo/cloudconfig.json b/bundle/src/test/resources/com/adobe/acs/commons/marketo/cloudconfig.json index a68e2a93be..1f7fd99fa7 100644 --- a/bundle/src/test/resources/com/adobe/acs/commons/marketo/cloudconfig.json +++ b/bundle/src/test/resources/com/adobe/acs/commons/marketo/cloudconfig.json @@ -3,7 +3,7 @@ "jcr:content": { "jcr:primaryType": "cq:PageContent", "jcr:title": "Test Cloud Config", - "cq:template": "/apps/core/wcm/templates/marketocloudconfig", + "cq:template": "/apps/acs-commons/templates/utilities/marketocloudconfig", "sling:resourceType": "page", "endpointHost": "test.mktorest.com", "serverInstance": "//test.marketo.com", From 9e7cc33585aae24fcd539c8d0e5d57378abfe9bf Mon Sep 17 00:00:00 2001 From: Dan Klco <dan.klco@perficient.com> Date: Mon, 11 Nov 2019 12:39:58 -0500 Subject: [PATCH 4/4] Fixing Servlet attachment to be resource based for #2064 --- .../acs/commons/cloudconfig/impl/CreateCloudConfigServlet.java | 2 +- .../apps/acs-commons/content/cloudservice/console/.content.xml | 2 +- .../apps/acs-commons/content/cloudservice/create/.content.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bundle/src/main/java/com/adobe/acs/commons/cloudconfig/impl/CreateCloudConfigServlet.java b/bundle/src/main/java/com/adobe/acs/commons/cloudconfig/impl/CreateCloudConfigServlet.java index 015f783768..3ca62b5dfc 100644 --- a/bundle/src/main/java/com/adobe/acs/commons/cloudconfig/impl/CreateCloudConfigServlet.java +++ b/bundle/src/main/java/com/adobe/acs/commons/cloudconfig/impl/CreateCloudConfigServlet.java @@ -45,7 +45,7 @@ import com.day.cq.wcm.api.WCMException; @Component(service = Servlet.class, property = { "sling.servlet.methods=" + HttpConstants.METHOD_POST, - "sling.servlet.paths=/bin/acscommons/createcloudconfig" }) + "sling.servlet.resourceTypes=acs-commons/components/utilities/cloudconfig/cloudconfiglist" }) public class CreateCloudConfigServlet extends SlingAllMethodsServlet { private static final long serialVersionUID = -397622433323474345L; diff --git a/ui.apps/src/main/content/jcr_root/apps/acs-commons/content/cloudservice/console/.content.xml b/ui.apps/src/main/content/jcr_root/apps/acs-commons/content/cloudservice/console/.content.xml index 6f91938d1e..cc9bed14ce 100644 --- a/ui.apps/src/main/content/jcr_root/apps/acs-commons/content/cloudservice/console/.content.xml +++ b/ui.apps/src/main/content/jcr_root/apps/acs-commons/content/cloudservice/console/.content.xml @@ -29,7 +29,7 @@ jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/container"> <items jcr:primaryType="nt:unstructured"> - <sitecollection + <cloudconfiglist jcr:primaryType="nt:unstructured" sling:resourceType="acs-commons/components/utilities/cloudconfig/cloudconfiglist"/> </items> diff --git a/ui.apps/src/main/content/jcr_root/apps/acs-commons/content/cloudservice/create/.content.xml b/ui.apps/src/main/content/jcr_root/apps/acs-commons/content/cloudservice/create/.content.xml index 15c45fd2c4..9138ef208b 100644 --- a/ui.apps/src/main/content/jcr_root/apps/acs-commons/content/cloudservice/create/.content.xml +++ b/ui.apps/src/main/content/jcr_root/apps/acs-commons/content/cloudservice/create/.content.xml @@ -25,7 +25,7 @@ granite:id="acs-commons-cloudservice-create" jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/form" - action="/bin/acscommons/createcloudconfig" + action="/apps/acs-commons/content/cloudservice/console/jcr:content/content/items/cloudconfiglist" foundationForm="{Boolean}true" maximized="{Boolean}true" method="post"