You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by dk...@apache.org on 2021/01/25 14:49:52 UTC
[sling-org-apache-sling-app-cms] branch master updated: Forms
enhancements (#11)
This is an automated email from the ASF dual-hosted git repository.
dklco pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-app-cms.git
The following commit(s) were added to refs/heads/master by this push:
new b20cd77 Forms enhancements (#11)
b20cd77 is described below
commit b20cd7745e13c68cd3357fae7a10e3e2719979b9
Author: Dan Klco <kl...@users.noreply.github.com>
AuthorDate: Mon Jan 25 09:49:43 2021 -0500
Forms enhancements (#11)
Fixes SLING-10083 and SLING-10082
* Working on enhanced capabilities for the reference forms
* Adding support for deleting UGC and cleaning up the usage of component configurations
* Improve the handling of the error page
* Updating to add a mapping for the ugc user for the reference project
---
feature/src/main/features/cms/cms.json | 3 +-
reference/pom.xml | 20 +++
.../sling/cms/reference/forms/FormConstants.java} | 41 +++--
.../sling/cms/reference/forms/FormUtils.java} | 24 +--
.../cms/reference/forms/impl/FormHandler.java | 93 +++++++----
.../cms/reference/forms/impl/FormRequestImpl.java | 27 +++-
.../forms/impl/actions/CreateUserAction.java | 150 ++++++++++++++++++
.../actions/DeleteUserGeneratedContentAction.java | 103 ++++++++++++
.../impl/actions/RequestPasswordResetAction.java | 101 ++++++++++++
.../forms/impl/actions/ResetPasswordAction.java | 110 +++++++++++++
.../forms/impl/actions/SendEmailAction.java | 18 ++-
.../forms/impl/actions/UpdateProfileAction.java | 90 +++++------
.../actions/UpdateUserGeneratedContentAction.java | 104 +++++++++++++
.../impl/actions/UserGeneratedContentAction.java | 18 ++-
.../forms/impl/fields/SelectionHandler.java | 27 +++-
.../forms/impl/fields/TextareaHandler.java | 27 +++-
.../forms/impl/fields/TextfieldHandler.java | 26 +++-
.../providers/RequestParametersValueProvider.java | 56 +++++++
.../providers/SuffixResourceFormValueProvider.java | 63 ++++++++
.../providers/UserProfileFormValueProvider.java | 3 +-
.../main/resources/OSGI-INF/l10n/bundle.properties | 20 ++-
.../components/forms/actions/createuser.json | 5 +
.../forms/actions/createuser/createuser.jsp | 32 ++++
.../components/forms/actions/createuser/edit.json | 47 ++++++
.../components/forms/actions/deleteugc.json | 5 +
.../forms/actions/deleteugc/deleteugc.jsp | 26 ++++
.../components/forms/actions/deleteugc/edit.json | 14 ++
.../forms/actions/requestpasswordreset/edit.json | 16 ++
.../requestpasswordreset/requestpasswordreset.jsp | 26 ++++
.../components/forms/actions/resetpassword.json | 5 +
.../forms/actions/resetpassword/edit.json | 5 +
.../forms/actions/resetpassword/resetpassword.jsp | 22 +++
.../components/forms/actions/updateugc.json | 5 +
.../components/forms/actions/updateugc/edit.json | 14 ++
.../forms/actions/updateugc/updateugc.jsp | 26 ++++
.../components/forms/fields/textarea/textarea.jsp | 4 +-
.../forms/fields/textfield/textfield.jsp | 2 +-
.../apps/reference/components/forms/form/edit.json | 6 +
.../apps/reference/components/forms/login.json | 5 +
.../reference/components/forms/login/edit.json | 46 ++++++
.../reference/components/forms/login/login.jsp | 42 +++++
.../forms/providers/requestparameters.json | 6 +
.../forms/providers/requestparameters/edit.json | 21 +++
.../requestparameters/requestparameters.jsp | 26 ++++
.../components/forms/providers/suffixresource.json | 6 +
.../forms/providers/suffixresource/edit.json | 28 ++++
.../providers/suffixresource/suffixresource.jsp | 28 ++++
.../cms/reference/forms/FormActionResultTest.java | 2 -
.../cms/reference/forms/impl/FormHandlerTest.java | 55 +++++--
.../reference/forms/impl/FormRequestImplTest.java | 42 ++++-
.../forms/impl/actions/CreateUserActionTest.java | 153 ++++++++++++++++++
.../DeleteUserGeneratedContentActionTest.java | 153 ++++++++++++++++++
.../actions/RequestPasswordResetActionTest.java | 134 ++++++++++++++++
.../impl/actions/ResetPasswordActionTest.java | 168 ++++++++++++++++++++
.../forms/impl/actions/SendEmailActionTest.java | 5 +-
.../impl/actions/UpdateProfileActionTest.java | 165 ++++++++++++++++++++
.../UpdateUserGeneratedContentActionTest.java | 172 +++++++++++++++++++++
.../actions/UserGeneratedContentActionTest.java | 90 +++++++++++
...onHandlerTest.java => HoneypotHandlerTest.java} | 55 ++-----
.../forms/impl/fields/SelectionHandlerTest.java | 17 +-
.../forms/impl/fields/TextareaHandlerTest.java | 20 ++-
.../forms/impl/fields/TextfieldHandlerTest.java | 63 +++++++-
.../RequestParametersValueProviderTest.java | 76 +++++++++
.../SuffixResourceFormValueProviderTest.java | 156 +++++++++++++++++++
reference/src/test/resources/form.json | 41 ++++-
transformer/src/test/resources/thumbnail.png | Bin 21183 -> 20437 bytes
66 files changed, 2939 insertions(+), 220 deletions(-)
diff --git a/feature/src/main/features/cms/cms.json b/feature/src/main/features/cms/cms.json
index 5644ea1..6013361 100644
--- a/feature/src/main/features/cms/cms.json
+++ b/feature/src/main/features/cms/cms.json
@@ -190,7 +190,8 @@
},
"org.apache.sling.serviceusermapping.impl.ServiceUserMapperImpl.amended~sling-cms-ugc": {
"user.mapping": [
- "org.apache.sling.cms.core:sling-cms-ugc=sling-cms-ugc"
+ "org.apache.sling.cms.core:sling-cms-ugc=sling-cms-ugc",
+ "org.apache.sling.cms.reference:sling-cms-ugc=sling-cms-ugc"
]
},
"org.apache.sling.serviceusermapping.impl.ServiceUserMapperImpl.amended~sling-cms-versionmgr": {
diff --git a/reference/pom.xml b/reference/pom.xml
index 6c4b682..12e59ac 100644
--- a/reference/pom.xml
+++ b/reference/pom.xml
@@ -41,6 +41,26 @@
<groupId>biz.aQute.bnd</groupId>
<artifactId>bnd-maven-plugin</artifactId>
</plugin>
+ <plugin>
+ <groupId>org.jacoco</groupId>
+ <artifactId>jacoco-maven-plugin</artifactId>
+ <version>0.8.2</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>prepare-agent</goal>
+ </goals>
+ </execution>
+ <!-- attached to Maven test phase -->
+ <execution>
+ <id>report</id>
+ <phase>test</phase>
+ <goals>
+ <goal>report</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
</plugins>
</build>
diff --git a/reference/src/test/java/org/apache/sling/cms/reference/forms/FormActionResultTest.java b/reference/src/main/java/org/apache/sling/cms/reference/forms/FormConstants.java
similarity index 51%
copy from reference/src/test/java/org/apache/sling/cms/reference/forms/FormActionResultTest.java
copy to reference/src/main/java/org/apache/sling/cms/reference/forms/FormConstants.java
index 9ed86d7..ea556ae 100644
--- a/reference/src/test/java/org/apache/sling/cms/reference/forms/FormActionResultTest.java
+++ b/reference/src/main/java/org/apache/sling/cms/reference/forms/FormConstants.java
@@ -16,27 +16,22 @@
*/
package org.apache.sling.cms.reference.forms;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import org.apache.sling.cms.reference.forms.FormActionResult;
-import org.apache.sling.cms.reference.forms.FormException;
-import org.junit.Test;
-
-public class FormActionResultTest {
-
- @Test
- public void testSuccess() throws FormException {
- FormActionResult result = FormActionResult.success("Hello World");
- assertTrue(result.isSucceeded());
- assertEquals("Hello World", result.getMessage());
- }
-
- @Test
- public void testFailure() throws FormException {
- FormActionResult result = FormActionResult.failure("Hello World");
- assertFalse(result.isSucceeded());
- assertEquals("Hello World", result.getMessage());
- }
+public class FormConstants {
+
+ public static final String PATH_PROFILE = "profile";
+
+ public static final String PN_EMAIL = "email";
+
+ public static final String PN_SERVICE_USER = "serviceUser";
+
+ public static final String PN_ALLOWED_PROPERTIES = "allowedProperties";
+
+ public static final String PN_SUBPATH = "subpath";
+
+ public static final String SERVICE_USER = "slingcms-reference-usermanager";
+
+ public static final String PN_RESETTOKEN = "resettoken";
+ public static final String PN_RESETTIMEOUT = "resettimeout";
+
+ public static final String PN_PASSWORD = "password";
}
diff --git a/reference/src/test/java/org/apache/sling/cms/reference/forms/FormActionResultTest.java b/reference/src/main/java/org/apache/sling/cms/reference/forms/FormUtils.java
similarity index 51%
copy from reference/src/test/java/org/apache/sling/cms/reference/forms/FormActionResultTest.java
copy to reference/src/main/java/org/apache/sling/cms/reference/forms/FormUtils.java
index 9ed86d7..3e77430 100644
--- a/reference/src/test/java/org/apache/sling/cms/reference/forms/FormActionResultTest.java
+++ b/reference/src/main/java/org/apache/sling/cms/reference/forms/FormUtils.java
@@ -16,27 +16,13 @@
*/
package org.apache.sling.cms.reference.forms;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import java.util.stream.Stream;
-import org.apache.sling.cms.reference.forms.FormActionResult;
-import org.apache.sling.cms.reference.forms.FormException;
-import org.junit.Test;
+import org.apache.sling.api.resource.Resource;
-public class FormActionResultTest {
+public class FormUtils {
- @Test
- public void testSuccess() throws FormException {
- FormActionResult result = FormActionResult.success("Hello World");
- assertTrue(result.isSucceeded());
- assertEquals("Hello World", result.getMessage());
- }
-
- @Test
- public void testFailure() throws FormException {
- FormActionResult result = FormActionResult.failure("Hello World");
- assertFalse(result.isSucceeded());
- assertEquals("Hello World", result.getMessage());
+ public static final boolean handles(String[] supportedTypes, Resource resource) {
+ return Stream.of(supportedTypes).anyMatch(t -> t.equals(resource.getResourceType()));
}
}
diff --git a/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/FormHandler.java b/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/FormHandler.java
index b75ad13..66feb4f 100644
--- a/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/FormHandler.java
+++ b/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/FormHandler.java
@@ -30,12 +30,14 @@ import org.apache.jackrabbit.JcrConstants;
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.ValueMap;
import org.apache.sling.api.servlets.SlingAllMethodsServlet;
import org.apache.sling.api.wrappers.SlingHttpServletRequestWrapper;
import org.apache.sling.cms.Page;
import org.apache.sling.cms.PageManager;
import org.apache.sling.cms.ResourceTree;
import org.apache.sling.cms.reference.forms.FormAction;
+import org.apache.sling.cms.reference.forms.FormActionResult;
import org.apache.sling.cms.reference.forms.FormException;
import org.apache.sling.cms.reference.forms.FormRequest;
import org.osgi.service.component.annotations.Activate;
@@ -63,37 +65,38 @@ public class FormHandler extends SlingAllMethodsServlet {
@Override
protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response)
throws ServletException, IOException {
+ ValueMap properties = request.getResource().getValueMap();
String pagePath = Optional.ofNullable(request.getResource().adaptTo(PageManager.class))
.map(PageManager::getPage).map(Page::getPath)
.orElse(StringUtils.substringBefore(request.getResource().getPath(), "/" + JcrConstants.JCR_CONTENT));
+ String successPage = null;
+ String errorPage = pagePath;
StringSubstitutor sub = null;
try {
- if (request.getResource().getChild("actions") == null) {
- throw new FormException("No actions provided to handle this form submission");
- }
- List<Resource> actionResources = ResourceTree.stream(request.getResource().getChild("actions"))
- .map(ResourceTree::getResource).collect(Collectors.toList());
-
- FormRequest formRequest = getFormRequest(request);
+ log.debug("Extracting form request...");
+ FormRequest formRequest = request.adaptTo(FormRequest.class);
if (formRequest == null) {
log.warn("Unable to create form request");
- response.sendRedirect(request.getResourceResolver().map(request, pagePath) + ".html?error=fields");
+ response.sendRedirect(this.resolveUrl(request, errorPage, "error=init"));
return;
}
+
+ log.debug("Loading fields...");
+ boolean fieldsLoadSucceeded = ((FormRequestImpl) formRequest).initFields();
sub = new StringSubstitutor(formRequest.getFormData());
- request.getSession().setAttribute(formRequest.getSessionId(), formRequest.getFormData());
- for (Resource actionResource : actionResources) {
- log.debug("Finding action handler for: {}", actionResource);
- for (FormAction action : formActions) {
- if (action.handles(actionResource)) {
- log.debug("Invoking handler: {}", action.getClass());
- action.handleForm(actionResource, formRequest);
- break;
- }
- }
+ successPage = sub.replace(properties.get("successPage", pagePath));
+ errorPage = sub.replace(properties.get("errorPage", pagePath));
+ if (!fieldsLoadSucceeded) {
+ log.warn("Field initialization failed, check logs");
+ response.sendRedirect(this.resolveUrl(request, errorPage, "error=fields"));
+ return;
}
+ request.getSession().setAttribute(formRequest.getSessionId(), formRequest.getFormData());
+
+ log.debug("Calling actions...");
+ callActions(request, formRequest);
request.getSession().removeAttribute(formRequest.getSessionId());
} catch (FormException e) {
log.warn("Exception executing actions", e);
@@ -101,31 +104,61 @@ public class FormHandler extends SlingAllMethodsServlet {
return;
}
- String thankYouPage = sub.replace(request.getResource().getValueMap().get("successPage", pagePath));
- if (StringUtils.isNotBlank(thankYouPage)) {
- if ("forward".equals(request.getResource().getValueMap().get("successAction", String.class))) {
+ if (StringUtils.isNotBlank(successPage)) {
+ if ("forward".equals(properties.get("successAction", String.class))) {
SlingHttpServletRequestWrapper requestWrapper = new SlingHttpServletRequestWrapper(request) {
@Override
public String getMethod() {
return "GET";
}
};
-
- request.getRequestDispatcher(thankYouPage).forward(requestWrapper, response);
+ request.getRequestDispatcher(successPage).forward(requestWrapper, response);
} else {
- response.sendRedirect(resolveThankYouPage(request, thankYouPage));
+ response.sendRedirect(resolveUrl(request, successPage, "message=success"));
}
} else {
- response.sendRedirect(resolveThankYouPage(request, thankYouPage));
+ response.sendRedirect(resolveUrl(request, successPage, "message=success"));
}
}
- private String resolveThankYouPage(SlingHttpServletRequest request, String thankYouPage) {
- if (!thankYouPage.contains(".html")) {
- thankYouPage += ".html";
+ private void callActions(SlingHttpServletRequest request, FormRequest formRequest) throws FormException {
+ Resource actions = request.getResource().getChild("actions");
+ if (actions == null) {
+ throw new FormException("No actions provided to handle this form submission");
+ }
+ List<Resource> actionResources = ResourceTree.stream(actions).map(ResourceTree::getResource)
+ .collect(Collectors.toList());
+
+ for (Resource actionResource : actionResources) {
+ log.debug("Finding action handler for: {}", actionResource);
+ FormAction action = formActions.stream().filter(fa -> fa.handles(actionResource)).findFirst().orElse(null);
+ if (action != null) {
+ FormActionResult result = action.handleForm(actionResource, formRequest);
+ if (!result.isSucceeded()) {
+ throw new FormException(
+ "Failed to invoke action: " + action + " with message: " + result.getMessage());
+ } else {
+ log.debug("Successfully invoked action: {}", result.getMessage());
+ }
+ }
+ }
+ }
+
+ private String resolveUrl(SlingHttpServletRequest request, String url, String qs) {
+ if (url.contains("?")) {
+ qs = "&" + qs;
+ } else {
+ qs = "?" + qs;
+ }
+ if (url.startsWith("/")) {
+ if (!url.contains(".html")) {
+ url += ".html";
+ }
+ url += qs;
+ return request.getResourceResolver().map(request, url);
+ } else {
+ return url + qs;
}
- thankYouPage += "?message=success";
- return request.getResourceResolver().map(request, thankYouPage);
}
protected FormRequest getFormRequest(SlingHttpServletRequest request) throws FormException {
diff --git a/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/FormRequestImpl.java b/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/FormRequestImpl.java
index 396d388..2ab4b7d 100644
--- a/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/FormRequestImpl.java
+++ b/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/FormRequestImpl.java
@@ -101,19 +101,32 @@ public class FormRequestImpl implements FormRequest {
return request;
}
- public void initFields() throws FormException {
+ public boolean initFields() {
List<Resource> fields = ResourceTree.stream(getFormResource().getChild("fields")).map(ResourceTree::getResource)
.collect(Collectors.toList());
+ boolean successful = true;
for (Resource field : fields) {
- log.debug("Looking for handler for: {}", field);
- for (FieldHandler fieldHandler : fieldHandlers) {
- if (fieldHandler.handles(field)) {
- log.debug("Invoking field handler: {}", fieldHandler.getClass());
- fieldHandler.handleField(request, field, formData);
- break;
+ formData.remove(getErrorKey(field));
+ try {
+ log.debug("Looking for handler for: {}", field);
+ for (FieldHandler fieldHandler : fieldHandlers) {
+ if (fieldHandler.handles(field)) {
+ log.debug("Invoking field handler: {}", fieldHandler.getClass());
+ fieldHandler.handleField(request, field, formData);
+ break;
+ }
}
+ } catch (FormException fe) {
+ log.warn("Failed to populate field {} due to exception", field, fe);
+ successful = false;
+ formData.put(getErrorKey(field), fe.getMessage());
}
}
+ return successful;
+ }
+
+ private String getErrorKey(Resource field) {
+ return "fielderror-" + field.getValueMap().get("name", String.class);
}
@Override
diff --git a/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/actions/CreateUserAction.java b/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/actions/CreateUserAction.java
new file mode 100644
index 0000000..43bbd18
--- /dev/null
+++ b/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/actions/CreateUserAction.java
@@ -0,0 +1,150 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.sling.cms.reference.forms.impl.actions;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.text.StringSubstitutor;
+import org.apache.jackrabbit.JcrConstants;
+import org.apache.jackrabbit.api.JackrabbitSession;
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.jackrabbit.api.security.user.Group;
+import org.apache.jackrabbit.api.security.user.User;
+import org.apache.jackrabbit.api.security.user.UserManager;
+import org.apache.jackrabbit.oak.spi.security.principal.PrincipalImpl;
+import org.apache.sling.api.resource.LoginException;
+import org.apache.sling.api.resource.PersistenceException;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceResolverFactory;
+import org.apache.sling.api.resource.ResourceUtil;
+import org.apache.sling.api.resource.ValueMap;
+import org.apache.sling.cms.reference.forms.FormAction;
+import org.apache.sling.cms.reference.forms.FormActionResult;
+import org.apache.sling.cms.reference.forms.FormConstants;
+import org.apache.sling.cms.reference.forms.FormException;
+import org.apache.sling.cms.reference.forms.FormRequest;
+import org.jetbrains.annotations.NotNull;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Component(service = { FormAction.class })
+public class CreateUserAction implements FormAction {
+
+ private static final Logger log = LoggerFactory.getLogger(CreateUserAction.class);
+ public static final String RESOURCE_TYPE = "reference/components/forms/actions/createuser";
+ public static final String PROFILE_PROPERTIES = "profileProperties";
+ public static final String GROUPS = "groups";
+ public static final String PN_USERNAME = "username";
+ public static final String PN_INTERMEDIATE_PATH = "intermediatePath";
+
+ private final ResourceResolverFactory factory;
+
+ @Activate
+ public CreateUserAction(@Reference ResourceResolverFactory factory) {
+ this.factory = factory;
+ }
+
+ @Override
+ public FormActionResult handleForm(final Resource actionResource, final FormRequest request) throws FormException {
+ final StringSubstitutor sub = new StringSubstitutor(request.getFormData());
+
+ final ValueMap properties = actionResource.getValueMap();
+
+ String username = request.getFormData().get(PN_USERNAME, String.class);
+ String password = request.getFormData().get(FormConstants.PN_PASSWORD, String.class);
+
+ String intermediatePath = properties.get(PN_INTERMEDIATE_PATH, String.class);
+
+ if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
+ return FormActionResult.failure("Empty username / password");
+ }
+
+ try {
+ try (ResourceResolver adminResolver = factory.getServiceResourceResolver(
+ Collections.singletonMap(ResourceResolverFactory.SUBSERVICE, FormConstants.SERVICE_USER))) {
+ JackrabbitSession session = (JackrabbitSession) adminResolver.adaptTo(Session.class);
+ final UserManager userManager = session.getUserManager();
+
+ if (userManager.getAuthorizable(username) == null) {
+
+ log.debug("Creating user {}", username);
+ User user = userManager.createUser(username, password, new PrincipalImpl(username),
+ intermediatePath);
+
+ String[] groups = properties.get(GROUPS, new String[0]);
+ for (String g : groups) {
+ String groupName = sub.replace(g);
+ Authorizable group = userManager.getAuthorizable(groupName);
+ if (group == null || !group.isGroup()) {
+ log.error("Could not find group {}", groupName);
+ return FormActionResult.failure("Could not find group: " + groupName);
+ } else {
+ ((Group) group).addMember(user);
+ }
+
+ }
+ log.debug("Updating profile for {}", username);
+ updateProfile(adminResolver, user, properties.get(PROFILE_PROPERTIES, new String[0]),
+ request.getFormData());
+
+ log.debug("Saving changes!");
+ adminResolver.commit();
+ return FormActionResult.success("User " + username + " created successfully");
+ } else {
+ log.error("Failed to create user, {} already exists", username);
+ return FormActionResult.failure("User " + username + " already exists");
+ }
+ }
+ } catch (LoginException le) {
+ log.error("Failed to get user manager service user", le);
+ return FormActionResult.failure("Failed to get service user");
+ } catch (PersistenceException | RepositoryException e) {
+ log.error("Failed to create user " + username, e);
+ return FormActionResult.failure("Failed to create user " + username);
+ }
+ }
+
+ private void updateProfile(ResourceResolver adminResolver, User user, String @NotNull [] toset, ValueMap formData)
+ throws PersistenceException, RepositoryException {
+ if (toset.length > 0) {
+ Map<String, Object> properties = new HashMap<>();
+ Arrays.stream(toset).filter(k -> formData.keySet().contains(k))
+ .forEach(k -> properties.put(k, formData.get(k)));
+ properties.put(JcrConstants.JCR_PRIMARYTYPE, JcrConstants.NT_UNSTRUCTURED);
+ ResourceUtil.getOrCreateResource(adminResolver, user.getPath() + "/profile", properties,
+ JcrConstants.NT_UNSTRUCTURED, false);
+ }
+
+ }
+
+ @Override
+ public boolean handles(Resource actionResource) {
+ return RESOURCE_TYPE.equals(actionResource.getResourceType());
+ }
+
+}
diff --git a/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/actions/DeleteUserGeneratedContentAction.java b/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/actions/DeleteUserGeneratedContentAction.java
new file mode 100644
index 0000000..8f9f6b0
--- /dev/null
+++ b/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/actions/DeleteUserGeneratedContentAction.java
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.sling.cms.reference.forms.impl.actions;
+
+import java.util.Collections;
+
+import org.apache.commons.text.StringSubstitutor;
+import org.apache.sling.api.resource.LoginException;
+import org.apache.sling.api.resource.PersistenceException;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceResolverFactory;
+import org.apache.sling.api.resource.ValueMap;
+import org.apache.sling.cms.CMSConstants;
+import org.apache.sling.cms.reference.forms.FormAction;
+import org.apache.sling.cms.reference.forms.FormActionResult;
+import org.apache.sling.cms.reference.forms.FormException;
+import org.apache.sling.cms.reference.forms.FormRequest;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Component(service = FormAction.class, immediate = true)
+public class DeleteUserGeneratedContentAction implements FormAction {
+
+ private static final Logger log = LoggerFactory.getLogger(DeleteUserGeneratedContentAction.class);
+
+ private ResourceResolverFactory factory;
+
+ @Activate
+ public DeleteUserGeneratedContentAction(@Reference ResourceResolverFactory factory) {
+ this.factory = factory;
+ }
+
+ @Override
+ public FormActionResult handleForm(Resource actionResource, FormRequest request) throws FormException {
+ log.trace("handleForm");
+
+ ValueMap properties = actionResource.getValueMap();
+
+ try (ResourceResolver resolver = getResourceResolver()) {
+ StringSubstitutor sub = new StringSubstitutor(request.getFormData());
+
+ String path = sub.replace(properties.get("path", String.class));
+ log.debug("Deleting UGC resource at path: {}", path);
+
+ Resource resource = resolver.getResource(path);
+ if (resource == null) {
+ throw new FormException("Could not find UGC resource at path: " + path);
+ }
+ Resource ugcParent = findUgcParent(resource);
+
+ if (!request.getOriginalRequest().getResourceResolver().getUserID()
+ .equals(ugcParent.getValueMap().get("user", String.class))) {
+ throw new FormException("Cannot delete content not created by the current user");
+ }
+
+ resolver.delete(ugcParent);
+ resolver.commit();
+ log.debug("Successfully deleted user generated content");
+ return FormActionResult.success("Deleted user generated content");
+ } catch (LoginException | PersistenceException e) {
+ throw new FormException("Failed to delete user generated content", e);
+ }
+ }
+
+ private Resource findUgcParent(Resource resource) throws FormException {
+ if (CMSConstants.NT_UGC.equals(resource.getResourceType())) {
+ return resource;
+ } else if (resource.getParent() != null) {
+ return findUgcParent(resource.getParent());
+ } else {
+ throw new FormException("Failed to find UGC Parent");
+ }
+ }
+
+ private ResourceResolver getResourceResolver() throws LoginException {
+ return factory.getServiceResourceResolver(
+ Collections.singletonMap(ResourceResolverFactory.SUBSERVICE, "sling-cms-ugc"));
+ }
+
+ @Override
+ public boolean handles(Resource actionResource) {
+ return "reference/components/forms/actions/deleteugc".equals(actionResource.getResourceType());
+ }
+
+}
diff --git a/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/actions/RequestPasswordResetAction.java b/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/actions/RequestPasswordResetAction.java
new file mode 100644
index 0000000..3e95ed9
--- /dev/null
+++ b/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/actions/RequestPasswordResetAction.java
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.sling.cms.reference.forms.impl.actions;
+
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.UUID;
+
+import javax.jcr.Session;
+import javax.jcr.ValueFactory;
+
+import org.apache.jackrabbit.api.JackrabbitSession;
+import org.apache.jackrabbit.api.security.user.User;
+import org.apache.jackrabbit.api.security.user.UserManager;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceResolverFactory;
+import org.apache.sling.cms.reference.forms.FormAction;
+import org.apache.sling.cms.reference.forms.FormActionResult;
+import org.apache.sling.cms.reference.forms.FormConstants;
+import org.apache.sling.cms.reference.forms.FormException;
+import org.apache.sling.cms.reference.forms.FormRequest;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Component(service = { FormAction.class })
+public class RequestPasswordResetAction implements FormAction {
+
+ public static final String RESOURCE_TYPE = "reference/components/forms/actions/requestpasswordreset";
+ public static final String PN_RESETTOKEN = "resettoken";
+ public static final String PN_RESETTIMEOUT = "resettimeout";
+ private static final Logger log = LoggerFactory.getLogger(RequestPasswordResetAction.class);
+ private ResourceResolverFactory factory;
+
+ @Activate
+ public RequestPasswordResetAction(@Reference ResourceResolverFactory factory) {
+ this.factory = factory;
+
+ }
+
+ @Override
+ public FormActionResult handleForm(Resource actionResource, FormRequest request) throws FormException {
+ String email = request.getFormData().get(FormConstants.PN_EMAIL, String.class);
+ int resetTimeout = actionResource.getValueMap().get(PN_RESETTIMEOUT, Integer.class);
+
+ try (ResourceResolver adminResolver = factory.getServiceResourceResolver(
+ Collections.singletonMap(ResourceResolverFactory.SUBSERVICE, FormConstants.SERVICE_USER))) {
+
+ JackrabbitSession session = (JackrabbitSession) adminResolver.adaptTo(Session.class);
+ final UserManager userManager = session.getUserManager();
+
+ if (userManager.getAuthorizable(email) != null) {
+
+ User user = (User) userManager.getAuthorizable(email);
+
+ String resetToken = UUID.randomUUID().toString();
+ Calendar deadline = Calendar.getInstance();
+ deadline.add(Calendar.SECOND, resetTimeout);
+
+ ValueFactory vf = session.getValueFactory();
+
+ user.setProperty(PN_RESETTOKEN, vf.createValue(resetToken));
+ user.setProperty(PN_RESETTIMEOUT, vf.createValue(deadline));
+
+ request.getFormData().put(PN_RESETTOKEN, resetToken);
+
+ adminResolver.commit();
+
+ } else {
+ log.warn("Unable to find user {}", email);
+ return FormActionResult.failure("Unable to find user");
+ }
+ } catch (Exception e) {
+ throw new FormException("Failed to initiate password reset", e);
+ }
+ return FormActionResult.success("Reset token created");
+ }
+
+ @Override
+ public boolean handles(Resource actionResource) {
+ return RESOURCE_TYPE.equals(actionResource.getResourceType());
+ }
+
+}
\ No newline at end of file
diff --git a/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/actions/ResetPasswordAction.java b/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/actions/ResetPasswordAction.java
new file mode 100644
index 0000000..56d8d1d
--- /dev/null
+++ b/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/actions/ResetPasswordAction.java
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.sling.cms.reference.forms.impl.actions;
+
+import java.util.Calendar;
+import java.util.Collections;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.Value;
+
+import org.apache.jackrabbit.api.JackrabbitSession;
+import org.apache.jackrabbit.api.security.user.User;
+import org.apache.jackrabbit.api.security.user.UserManager;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceResolverFactory;
+import org.apache.sling.cms.reference.forms.FormAction;
+import org.apache.sling.cms.reference.forms.FormActionResult;
+import org.apache.sling.cms.reference.forms.FormConstants;
+import org.apache.sling.cms.reference.forms.FormException;
+import org.apache.sling.cms.reference.forms.FormRequest;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Component(service = { FormAction.class })
+public class ResetPasswordAction implements FormAction {
+
+ public static final String RESOURCE_TYPE = "reference/components/forms/actions/resetpassword";
+ private static final Logger log = LoggerFactory.getLogger(ResetPasswordAction.class);
+ private ResourceResolverFactory factory;
+
+ @Activate
+ public ResetPasswordAction(@Reference ResourceResolverFactory factory) {
+ this.factory = factory;
+ }
+
+ @Override
+ public FormActionResult handleForm(Resource actionResource, FormRequest request) throws FormException {
+ String email = request.getFormData().get(FormConstants.PN_EMAIL, String.class);
+ String resetToken = request.getFormData().get(FormConstants.PN_RESETTOKEN, String.class);
+ String password = request.getFormData().get("password", String.class);
+
+ try (ResourceResolver adminResolver = factory.getServiceResourceResolver(
+ Collections.singletonMap(ResourceResolverFactory.SUBSERVICE, FormConstants.SERVICE_USER))) {
+
+ JackrabbitSession session = (JackrabbitSession) adminResolver.adaptTo(Session.class);
+ final UserManager userManager = session.getUserManager();
+
+ User user = (User) userManager.getAuthorizable(email);
+
+ if (user == null) {
+ return FormActionResult.failure("No user found for " + email);
+ }
+
+ String storedToken = getValue(user.getProperty(FormConstants.PN_RESETTOKEN), String.class);
+ Calendar resetTimeout = getValue(user.getProperty(FormConstants.PN_RESETTIMEOUT), Calendar.class);
+ if (storedToken == null || !storedToken.equals(resetToken)) {
+ return FormActionResult.failure("Failed to validate token");
+ }
+ if (Calendar.getInstance().after(resetTimeout)) {
+ return FormActionResult.failure("Timeout already passed");
+ }
+ user.changePassword(password);
+
+ log.debug("Saving changes!");
+ adminResolver.commit();
+
+ return FormActionResult.success("Password reset successfully!");
+ } catch (Exception e) {
+ throw new FormException("Failed to complete password reset", e);
+ }
+ }
+
+ private <E> E getValue(Value[] property, Class<E> clazz) throws IllegalStateException, RepositoryException {
+ if (property != null && property.length > 0) {
+ Value v = property[0];
+ if (clazz.isAssignableFrom(String.class)) {
+ return clazz.cast(v.getString());
+ }
+ if (clazz.isAssignableFrom(Calendar.class)) {
+ return clazz.cast(v.getDate());
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean handles(Resource actionResource) {
+ return RESOURCE_TYPE.equals(actionResource.getResourceType());
+ }
+
+}
\ No newline at end of file
diff --git a/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/actions/SendEmailAction.java b/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/actions/SendEmailAction.java
index 630e129..3a40c11 100644
--- a/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/actions/SendEmailAction.java
+++ b/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/actions/SendEmailAction.java
@@ -28,6 +28,7 @@ import org.apache.sling.cms.reference.forms.FormException;
import org.apache.sling.cms.reference.forms.FormRequest;
import org.apache.sling.commons.messaging.mail.MailService;
import org.jetbrains.annotations.NotNull;
+import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
@@ -36,6 +37,7 @@ import org.slf4j.LoggerFactory;
@Component(service = { FormAction.class })
public class SendEmailAction implements FormAction {
+ public static final String RESOURCE_TYPE = "reference/components/forms/actions/sendemail";
public static final String FROM = "from";
private static final Logger log = LoggerFactory.getLogger(SendEmailAction.class);
@@ -43,7 +45,12 @@ public class SendEmailAction implements FormAction {
public static final String SUBJECT = "subject";
public static final String TO = "to";
- private MailService mailService;
+ private final MailService mailService;
+
+ @Activate
+ public SendEmailAction(@Reference MailService mailService) {
+ this.mailService = mailService;
+ }
@Override
public FormActionResult handleForm(final Resource actionResource, final FormRequest request) throws FormException {
@@ -71,13 +78,8 @@ public class SendEmailAction implements FormAction {
}
@Override
- public boolean handles(final Resource actionResource) {
- return "reference/components/forms/actions/sendemail".equals(actionResource.getResourceType());
- }
-
- @Reference
- public void setMailService(MailService mailService) {
- this.mailService = mailService;
+ public boolean handles(Resource actionResource) {
+ return RESOURCE_TYPE.equals(actionResource.getResourceType());
}
}
diff --git a/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/actions/UpdateProfileAction.java b/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/actions/UpdateProfileAction.java
index 53d24d9..84dea5f 100644
--- a/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/actions/UpdateProfileAction.java
+++ b/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/actions/UpdateProfileAction.java
@@ -19,6 +19,7 @@ package org.apache.sling.cms.reference.forms.impl.actions;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Map.Entry;
+import java.util.Optional;
import java.util.stream.Collectors;
import javax.jcr.RepositoryException;
@@ -34,6 +35,7 @@ import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.cms.reference.forms.FormAction;
import org.apache.sling.cms.reference.forms.FormActionResult;
+import org.apache.sling.cms.reference.forms.FormConstants;
import org.apache.sling.cms.reference.forms.FormException;
import org.apache.sling.cms.reference.forms.FormRequest;
import org.osgi.service.component.annotations.Component;
@@ -43,64 +45,66 @@ import org.slf4j.LoggerFactory;
@Component(service = FormAction.class)
public class UpdateProfileAction implements FormAction {
+ public static final String RESOURCE_TYPE = "reference/components/forms/actions/updateprofile";
+
private static final Logger log = LoggerFactory.getLogger(UpdateProfileAction.class);
@Override
public FormActionResult handleForm(Resource actionResource, FormRequest request) throws FormException {
ResourceResolver resolver = request.getOriginalRequest().getResourceResolver();
String userId = resolver.getUserID();
- JackrabbitSession session = (JackrabbitSession) resolver.adaptTo(Session.class);
-
- if (session != null) {
- try {
- final UserManager userManager = session.getUserManager();
- if (userManager.getAuthorizable(userId) != null) {
-
- User user = (User) userManager.getAuthorizable(userId);
- log.debug("Updating profile for {}", userId);
-
- String subpath = actionResource.getValueMap().get("subpath", "profile");
- ValueFactory valueFactory = session.getValueFactory();
-
- for (Entry<String, Object> e : request.getFormData().entrySet()) {
- Value value = null;
- if (e.getValue() instanceof String[]) {
- user.setProperty(subpath + "/" + e.getKey(), Arrays.stream((String[]) e.getValue())
- .map(valueFactory::createValue).collect(Collectors.toList()).toArray(new Value[0]));
- } else {
- if (e.getValue() instanceof Calendar) {
- value = valueFactory.createValue((Calendar) e.getValue());
- } else if (e.getValue() instanceof Double) {
- value = valueFactory.createValue((Double) e.getValue());
- } else if (e.getValue() instanceof Integer) {
- value = valueFactory.createValue((Double) e.getValue());
- } else {
- value = valueFactory.createValue((String) e.getValue());
- }
- user.setProperty(subpath + "/" + e.getKey(), value);
- }
- }
- log.debug("Saving changes!");
- resolver.commit();
- return FormActionResult.success("Profile Updated");
+ try {
+ JackrabbitSession session = Optional.ofNullable((JackrabbitSession) resolver.adaptTo(Session.class))
+ .orElseThrow(() -> new RepositoryException("Unable to get Jackrabbit Session"));
+
+ final UserManager userManager = session.getUserManager();
+ if (userManager.getAuthorizable(userId) == null) {
+
+ log.warn("No profile found for {}", userId);
+ return FormActionResult.failure("No profile found for " + userId);
+ }
+
+ User user = (User) userManager.getAuthorizable(userId);
+ log.debug("Updating profile for {}", userId);
+
+ String subpath = actionResource.getValueMap().get(FormConstants.PN_SUBPATH, FormConstants.PATH_PROFILE);
+ ValueFactory valueFactory = session.getValueFactory();
+
+ for (Entry<String, Object> e : request.getFormData().entrySet()) {
+ Value value = null;
+ if (e.getValue() instanceof String[]) {
+ Value[] values = Arrays.stream(((String[]) e.getValue())).map(valueFactory::createValue)
+ .collect(Collectors.toList()).toArray(new Value[0]);
+ user.setProperty(subpath + "/" + e.getKey(), values);
} else {
- log.warn("No profile found for {}", userId);
- return FormActionResult.failure("No profile found for " + userId);
+ if (e.getValue() instanceof Calendar) {
+ value = valueFactory.createValue((Calendar) e.getValue());
+ } else if (e.getValue() instanceof Double) {
+ value = valueFactory.createValue((Double) e.getValue());
+ } else if (e.getValue() instanceof Integer) {
+ value = valueFactory.createValue((Integer) e.getValue());
+ } else {
+ value = valueFactory.createValue((String) e.getValue());
+ }
+ user.setProperty(subpath + "/" + e.getKey(), value);
}
- } catch (RepositoryException | PersistenceException e) {
- log.warn("Failed to update profile for {}", userId, e);
- return FormActionResult.failure("Failed to update profile for " + userId);
}
- } else {
- log.warn("Failed to get session for {}", userId);
- return FormActionResult.failure("Failed to get session for " + userId);
+ log.debug("Saving changes!");
+ resolver.commit();
+
+ return FormActionResult.success("Profile Updated");
+
+ } catch (RepositoryException | PersistenceException e) {
+ log.warn("Failed to update profile for {}", userId, e);
+ return FormActionResult.failure("Failed to update profile for " + userId);
}
+
}
@Override
public boolean handles(Resource actionResource) {
- return "reference/components/forms/actions/updateprofile".equals(actionResource.getResourceType());
+ return RESOURCE_TYPE.equals(actionResource.getResourceType());
}
}
diff --git a/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/actions/UpdateUserGeneratedContentAction.java b/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/actions/UpdateUserGeneratedContentAction.java
new file mode 100644
index 0000000..2a94383
--- /dev/null
+++ b/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/actions/UpdateUserGeneratedContentAction.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.sling.cms.reference.forms.impl.actions;
+
+import java.util.Collections;
+import java.util.Map;
+
+import org.apache.commons.text.StringSubstitutor;
+import org.apache.sling.api.resource.LoginException;
+import org.apache.sling.api.resource.ModifiableValueMap;
+import org.apache.sling.api.resource.PersistenceException;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceResolverFactory;
+import org.apache.sling.api.resource.ValueMap;
+import org.apache.sling.cms.CMSConstants;
+import org.apache.sling.cms.reference.forms.FormAction;
+import org.apache.sling.cms.reference.forms.FormActionResult;
+import org.apache.sling.cms.reference.forms.FormException;
+import org.apache.sling.cms.reference.forms.FormRequest;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Component(service = FormAction.class, immediate = true)
+public class UpdateUserGeneratedContentAction implements FormAction {
+
+ private static final Logger log = LoggerFactory.getLogger(UpdateUserGeneratedContentAction.class);
+
+ private ResourceResolverFactory factory;
+
+ @Activate
+ public UpdateUserGeneratedContentAction(@Reference ResourceResolverFactory factory) {
+ this.factory = factory;
+ }
+
+ @Override
+ public FormActionResult handleForm(Resource actionResource, FormRequest request) throws FormException {
+ log.trace("handleForm");
+
+ ValueMap properties = actionResource.getValueMap();
+
+ try (ResourceResolver resolver = getResourceResolver()) {
+ StringSubstitutor sub = new StringSubstitutor(request.getFormData());
+
+ String path = sub.replace(properties.get("path", String.class));
+ log.debug("Updating UGC resource at path: {}", path);
+
+ Resource resource = resolver.getResource(path);
+ Resource ugcParent = findUgcParent(resource);
+
+ if (!request.getOriginalRequest().getResourceResolver().getUserID()
+ .equals(ugcParent.getValueMap().get("user", String.class))) {
+ throw new FormException("Cannot modify content not created by the current user");
+ }
+
+ ModifiableValueMap mvm = resource.adaptTo(ModifiableValueMap.class);
+ Map<String, Object> formData = request.getFormData();
+ mvm.putAll(formData);
+ resolver.commit();
+ log.debug("Successfully persisted resource");
+ return FormActionResult.success("Updated resource");
+ } catch (LoginException | PersistenceException e) {
+ throw new FormException("Failed to update resource", e);
+ }
+ }
+
+ private Resource findUgcParent(Resource resource) throws FormException {
+ if (CMSConstants.NT_UGC.equals(resource.getResourceType())) {
+ return resource;
+ } else if (resource.getParent() != null) {
+ return findUgcParent(resource.getParent());
+ } else {
+ throw new FormException("Failed to find UGC Parent");
+ }
+ }
+
+ private ResourceResolver getResourceResolver() throws LoginException {
+ return factory.getServiceResourceResolver(
+ Collections.singletonMap(ResourceResolverFactory.SUBSERVICE, "sling-cms-ugc"));
+ }
+
+ @Override
+ public boolean handles(Resource actionResource) {
+ return "reference/components/forms/actions/updateugc".equals(actionResource.getResourceType());
+ }
+
+}
diff --git a/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/actions/UserGeneratedContentAction.java b/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/actions/UserGeneratedContentAction.java
index 084d17f..fb5fa17 100644
--- a/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/actions/UserGeneratedContentAction.java
+++ b/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/actions/UserGeneratedContentAction.java
@@ -20,9 +20,10 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
+import java.util.Objects;
-import org.apache.commons.text.StringSubstitutor;
import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.apache.commons.text.StringSubstitutor;
import org.apache.jackrabbit.JcrConstants;
import org.apache.sling.api.resource.PersistenceException;
import org.apache.sling.api.resource.Resource;
@@ -38,6 +39,7 @@ import org.apache.sling.cms.usergenerated.UGCBucketConfig;
import org.apache.sling.cms.usergenerated.UserGeneratedContentService;
import org.apache.sling.cms.usergenerated.UserGeneratedContentService.APPROVE_ACTION;
import org.apache.sling.cms.usergenerated.UserGeneratedContentService.CONTENT_TYPE;
+import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
@@ -48,11 +50,15 @@ public class UserGeneratedContentAction implements FormAction {
private static final Logger log = LoggerFactory.getLogger(UserGeneratedContentAction.class);
- @Reference
- private NameFilter filter;
+ private final NameFilter filter;
- @Reference
- private UserGeneratedContentService ugcService;
+ private final UserGeneratedContentService ugcService;
+
+ @Activate
+ public UserGeneratedContentAction(@Reference NameFilter filter, @Reference UserGeneratedContentService ugcService) {
+ this.filter = filter;
+ this.ugcService = ugcService;
+ }
@Override
public FormActionResult handleForm(Resource actionResource, FormRequest request) throws FormException {
@@ -82,7 +88,7 @@ public class UserGeneratedContentAction implements FormAction {
log.warn("Invalid value: {}", v);
return null;
}
- }).forEach(v -> {
+ }).filter(Objects::nonNull).forEach(v -> {
log.debug("Adding additional property: {}", v);
contentProperties.put(v.getLeft(), v.getRight());
});
diff --git a/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/fields/SelectionHandler.java b/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/fields/SelectionHandler.java
index 955197b..8fd6e8f 100644
--- a/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/fields/SelectionHandler.java
+++ b/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/fields/SelectionHandler.java
@@ -27,18 +27,42 @@ import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.cms.reference.forms.FieldHandler;
import org.apache.sling.cms.reference.forms.FormException;
+import org.apache.sling.cms.reference.forms.FormUtils;
+import org.apache.sling.cms.reference.impl.SearchServiceImpl.Config;
+import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
+import org.osgi.service.metatype.annotations.AttributeDefinition;
+import org.osgi.service.metatype.annotations.Designate;
+import org.osgi.service.metatype.annotations.ObjectClassDefinition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Component(service = FieldHandler.class)
+@Designate(ocd = Config.class)
public class SelectionHandler implements FieldHandler {
+ public static final String DEFAULT_RESOURCE_TYPE = "reference/components/forms/fields/selection";
+
private static final Logger log = LoggerFactory.getLogger(SelectionHandler.class);
+ private final Config config;
+
+ @ObjectClassDefinition(name = "%cms.reference.selection.name", description = "%cms.reference.selection.description", localization = "OSGI-INF/l10n/bundle")
+ public @interface Config {
+
+ @AttributeDefinition(name = "%cms.reference.supportedTypes.name", description = "%cms.reference.supportedTypes.description", defaultValue = {
+ DEFAULT_RESOURCE_TYPE })
+ String[] supportedTypes() default { DEFAULT_RESOURCE_TYPE };
+ }
+
+ @Activate
+ public SelectionHandler(Config config) {
+ this.config = config;
+ }
+
@Override
public boolean handles(Resource fieldResource) {
- return "reference/components/forms/fields/selection".equals(fieldResource.getResourceType());
+ return FormUtils.handles(config.supportedTypes(), fieldResource);
}
@Override
@@ -72,6 +96,7 @@ public class SelectionHandler implements FieldHandler {
formData.put(name, value);
}
}
+
}
private String[] stripBlank(String[] parameterValues) {
diff --git a/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/fields/TextareaHandler.java b/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/fields/TextareaHandler.java
index 0b27346..13839ff 100644
--- a/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/fields/TextareaHandler.java
+++ b/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/fields/TextareaHandler.java
@@ -23,19 +23,42 @@ import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.cms.reference.forms.FieldHandler;
import org.apache.sling.cms.reference.forms.FormException;
+import org.apache.sling.cms.reference.forms.FormUtils;
+import org.apache.sling.cms.reference.forms.impl.fields.TextareaHandler.Config;
+import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
+import org.osgi.service.metatype.annotations.AttributeDefinition;
+import org.osgi.service.metatype.annotations.Designate;
+import org.osgi.service.metatype.annotations.ObjectClassDefinition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Component(service = FieldHandler.class)
+@Designate(ocd = Config.class)
public class TextareaHandler implements FieldHandler {
+ public static final String DEFAULT_RESOURCE_TYPE = "reference/components/forms/fields/textarea";
+
private static final Logger log = LoggerFactory.getLogger(TextareaHandler.class);
+ private Config config;
+
+ @ObjectClassDefinition(name = "%cms.reference.textarea.name", description = "%cms.reference.textarea.description", localization = "OSGI-INF/l10n/bundle")
+ public @interface Config {
+
+ @AttributeDefinition(name = "%cms.reference.supportedTypes.name", description = "%cms.reference.supportedTypes.description", defaultValue = {
+ DEFAULT_RESOURCE_TYPE })
+ String[] supportedTypes() default { DEFAULT_RESOURCE_TYPE };
+ }
+
+ @Activate
+ public TextareaHandler(Config config) {
+ this.config = config;
+ }
+
@Override
public boolean handles(Resource fieldResource) {
- String resourceType = fieldResource.getResourceType();
- return "reference/components/forms/fields/textarea".equals(resourceType);
+ return FormUtils.handles(config.supportedTypes(), fieldResource);
}
@Override
diff --git a/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/fields/TextfieldHandler.java b/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/fields/TextfieldHandler.java
index 7622a56..f498586 100644
--- a/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/fields/TextfieldHandler.java
+++ b/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/fields/TextfieldHandler.java
@@ -30,15 +30,22 @@ import org.apache.sling.api.request.RequestParameter;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.cms.reference.forms.FieldHandler;
import org.apache.sling.cms.reference.forms.FormException;
+import org.apache.sling.cms.reference.forms.FormUtils;
+import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
+import org.osgi.service.metatype.annotations.AttributeDefinition;
+import org.osgi.service.metatype.annotations.Designate;
+import org.osgi.service.metatype.annotations.ObjectClassDefinition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Component(service = FieldHandler.class)
+@Designate(ocd = TextfieldHandler.Config.class)
public class TextfieldHandler implements FieldHandler {
private static final Logger log = LoggerFactory.getLogger(TextfieldHandler.class);
private static final Map<String, String> typePatterns = new HashMap<>();
+ public static final String DEFAULT_RESOURCE_TYPE = "reference/components/forms/fields/textfield";
static {
typePatterns.put("date", "\\d{4}-\\d{2}-\\d{2}");
typePatterns.put("datetime-local", "\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}");
@@ -52,10 +59,24 @@ public class TextfieldHandler implements FieldHandler {
dateFormats.put("datetime-local", "yyyy-MM-ddThh:mm");
}
+ private Config config;
+
+ @ObjectClassDefinition(name = "%cms.reference.textfield.name", description = "%cms.reference.textfield.description", localization = "OSGI-INF/l10n/bundle")
+ public @interface Config {
+
+ @AttributeDefinition(name = "%cms.reference.supportedTypes.name", description = "%cms.reference.supportedTypes.description", defaultValue = {
+ DEFAULT_RESOURCE_TYPE })
+ String[] supportedTypes() default { DEFAULT_RESOURCE_TYPE };
+ }
+
+ @Activate
+ public TextfieldHandler(Config config) {
+ this.config = config;
+ }
+
@Override
public boolean handles(Resource fieldResource) {
- String resourceType = fieldResource.getResourceType();
- return "reference/components/forms/fields/textfield".equals(resourceType);
+ return FormUtils.handles(config.supportedTypes(), fieldResource);
}
@Override
@@ -89,7 +110,6 @@ public class TextfieldHandler implements FieldHandler {
formData.put(name + ".contentType", param.getContentType());
}
} else if ("date".equals(saveAs)) {
-
if (!dateFormats.containsKey(type)) {
throw new FormException("Field " + name + " is not a date type");
}
diff --git a/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/providers/RequestParametersValueProvider.java b/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/providers/RequestParametersValueProvider.java
new file mode 100644
index 0000000..ca08dee
--- /dev/null
+++ b/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/providers/RequestParametersValueProvider.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.sling.cms.reference.forms.impl.providers;
+
+import java.util.Arrays;
+import java.util.Map;
+
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.cms.reference.forms.FormValueProvider;
+import org.osgi.service.component.annotations.Component;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Component(service = FormValueProvider.class)
+public class RequestParametersValueProvider implements FormValueProvider {
+
+ private static final Logger log = LoggerFactory.getLogger(RequestParametersValueProvider.class);
+
+ @Override
+ public void loadValues(SlingHttpServletRequest request, Resource providerResource, Map<String, Object> formData) {
+ log.trace("loadFormData");
+ String[] parameters = providerResource.getValueMap().get("allowedParameters", String[].class);
+ if (parameters != null) {
+ Arrays.stream(parameters).forEach(p -> {
+ if (request.getParameter(p) != null) {
+ if (request.getParameterValues(p).length > 1) {
+ formData.put(p, request.getParameterValues(p));
+ } else {
+ formData.put(p, request.getParameter(p));
+ }
+ }
+ });
+ }
+
+ }
+
+ @Override
+ public boolean handles(Resource valueProviderResource) {
+ return "reference/components/forms/providers/requestparameters".equals(valueProviderResource.getResourceType());
+ }
+}
diff --git a/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/providers/SuffixResourceFormValueProvider.java b/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/providers/SuffixResourceFormValueProvider.java
new file mode 100644
index 0000000..15e57c6
--- /dev/null
+++ b/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/providers/SuffixResourceFormValueProvider.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.sling.cms.reference.forms.impl.providers;
+
+import java.util.Arrays;
+import java.util.Map;
+
+import org.apache.commons.text.StringSubstitutor;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ValueMap;
+import org.apache.sling.cms.reference.forms.FormConstants;
+import org.apache.sling.cms.reference.forms.FormValueProvider;
+import org.osgi.service.component.annotations.Component;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Component(service = FormValueProvider.class)
+public class SuffixResourceFormValueProvider implements FormValueProvider {
+
+ private static final Logger log = LoggerFactory.getLogger(SuffixResourceFormValueProvider.class);
+
+ @Override
+ public void loadValues(SlingHttpServletRequest request, Resource providerResource, Map<String, Object> formData) {
+ log.trace("loadValues");
+ Resource suffixResource = request.getRequestPathInfo().getSuffixResource();
+
+ ValueMap providerProperties = providerResource.getValueMap();
+ StringSubstitutor sub = new StringSubstitutor(formData);
+ String basePath = sub.replace(providerProperties.get("basePath", String.class));
+ String[] allowedProperties = providerProperties.get(FormConstants.PN_ALLOWED_PROPERTIES, String[].class);
+ if (suffixResource != null && suffixResource.getPath().startsWith(basePath)) {
+ ValueMap suffixProperties = suffixResource.getValueMap();
+ if (allowedProperties != null && allowedProperties.length > 0) {
+ Arrays.stream(allowedProperties).filter(suffixProperties::containsKey)
+ .forEach(p -> formData.put(p, suffixProperties.get(p)));
+ } else {
+ formData.putAll(suffixProperties);
+ }
+ formData.put("suffixResource", suffixResource.getPath());
+ }
+
+ }
+
+ @Override
+ public boolean handles(Resource valueProviderResource) {
+ return "reference/components/forms/providers/suffixresource".equals(valueProviderResource.getResourceType());
+ }
+}
diff --git a/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/providers/UserProfileFormValueProvider.java b/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/providers/UserProfileFormValueProvider.java
index 4219be9..323b51a 100644
--- a/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/providers/UserProfileFormValueProvider.java
+++ b/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/providers/UserProfileFormValueProvider.java
@@ -32,6 +32,7 @@ import org.apache.jackrabbit.api.security.user.UserManager;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.cms.reference.forms.FormConstants;
import org.apache.sling.cms.reference.forms.FormValueProvider;
import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
@@ -53,7 +54,7 @@ public class UserProfileFormValueProvider implements FormValueProvider {
UserManager userManager = session.getUserManager();
User user = (User) userManager.getAuthorizable(userId);
- String subpath = providerResource.getValueMap().get("subpath", "profile");
+ String subpath = providerResource.getValueMap().get(FormConstants.PN_SUBPATH, FormConstants.PATH_PROFILE);
log.debug("Loading profile data from: {}/{}", user.getPath(), subpath);
Iterator<String> keys = user.getPropertyNames(subpath);
diff --git a/reference/src/main/resources/OSGI-INF/l10n/bundle.properties b/reference/src/main/resources/OSGI-INF/l10n/bundle.properties
index 0911dc9..a4d182f 100644
--- a/reference/src/main/resources/OSGI-INF/l10n/bundle.properties
+++ b/reference/src/main/resources/OSGI-INF/l10n/bundle.properties
@@ -23,7 +23,7 @@
# the Sling SCR plugin
## Search Service Entries
-cms.reference.search.name=Apache Sling Reference Search Configuration
+cms.reference.search.name=Apache Sling CMS - Reference Search Configuration
cms.reference.search.description=Configuration for the Reference \
Search component
@@ -32,7 +32,7 @@ searchServiceUsername.description=The name of a service user to use \
to use for searching, if not specified, the current user will be used
# Send Email
-cms.reference.sendemail.name=Apache Sling Reference Send Email Form Action
+cms.reference.sendemail.name=Apache Sling CMS - Reference Send Email Form Action
cms.reference.sendemail.description=A reference form action for sending a \
simple text email
@@ -44,7 +44,6 @@ cms.reference.sendemail.smtpPort.name=SMTP Port
cms.reference.sendemail.smtpPort.description=The port upon which to connect \
to the SMTP server
-
cms.reference.sendemail.tlsEnabled.name=TLS Enabled
cms.reference.sendemail.tlsEnabled.description=Whether or not TLS security is \
enabled
@@ -55,4 +54,17 @@ to the SMTP server
cms.reference.sendemail.password.name=Password
cms.reference.sendemail.password.description=The password to use when connecting \
-to the SMTP server
\ No newline at end of file
+to the SMTP server
+
+# Form configuration titles
+cms.reference.supportedTypes.name=Supported Types
+cms.reference.supportedTypes.description=The resource types supported by this action
+
+cms.reference.selection.name=Apache Sling CMS - Reference Selection Field
+cms.reference.selection.description=Configuration for the select form field
+
+cms.reference.textarea.name=Apache Sling CMS - Reference Textarea Field
+cms.reference.selection.description=Configuration for the textarea form field
+
+cms.reference.textfield.name=pache Sling CMS - Reference Text field
+cms.reference.textfield.description=Configuration for the text field
\ No newline at end of file
diff --git a/reference/src/main/resources/jcr_root/apps/reference/components/forms/actions/createuser.json b/reference/src/main/resources/jcr_root/apps/reference/components/forms/actions/createuser.json
new file mode 100644
index 0000000..7e59253
--- /dev/null
+++ b/reference/src/main/resources/jcr_root/apps/reference/components/forms/actions/createuser.json
@@ -0,0 +1,5 @@
+{
+ "jcr:primaryType" : "sling:Component",
+ "jcr:title": "Create User",
+ "componentType": "Form Action"
+}
\ No newline at end of file
diff --git a/reference/src/main/resources/jcr_root/apps/reference/components/forms/actions/createuser/createuser.jsp b/reference/src/main/resources/jcr_root/apps/reference/components/forms/actions/createuser/createuser.jsp
new file mode 100644
index 0000000..b6c450f
--- /dev/null
+++ b/reference/src/main/resources/jcr_root/apps/reference/components/forms/actions/createuser/createuser.jsp
@@ -0,0 +1,32 @@
+<%-- /*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */ --%>
+ <%@include file="/libs/sling-cms/global.jsp"%>
+<c:if test="${cmsEditEnabled == 'true'}">
+ <h3>Create User</h3>
+ <dl>
+ <dt>Group Membership</dt>
+ <dd>${sling:encode(fn:join(properties.groups,','),'HTML')}</dd>
+ <dt>Intermediate Path</dt>
+ <dd>${sling:encode(properties.intermediatePath,'HTML')}</dd>
+ <dt>Service User</dt>
+ <dd>${sling:encode(properties.serviceUser,'HTML')}</dd>
+ <dt>Set Profile Properties</dt>
+ <dd>${sling:encode(fn:join(properties.profileProperties,','),'HTML')}</dd>
+ </dl>
+</c:if>
\ No newline at end of file
diff --git a/reference/src/main/resources/jcr_root/apps/reference/components/forms/actions/createuser/edit.json b/reference/src/main/resources/jcr_root/apps/reference/components/forms/actions/createuser/edit.json
new file mode 100644
index 0000000..3af280d
--- /dev/null
+++ b/reference/src/main/resources/jcr_root/apps/reference/components/forms/actions/createuser/edit.json
@@ -0,0 +1,47 @@
+{
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/editor/slingform",
+ "button": "Save",
+ "fields": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/general/container",
+ "groups": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/editor/fields/repeating",
+ "label": "Group Membership",
+ "name": "groups"
+ },
+ "groupsTypeHint": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/editor/fields/hidden",
+ "name": "groups@TypeHint",
+ "value": "String[]"
+ },
+ "profileProperties": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/editor/fields/repeating",
+ "label": "Profile Properties",
+ "name": "profileProperties"
+ },
+ "profilePropertiesTypeHint": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/editor/fields/hidden",
+ "name": "profileProperties@TypeHint",
+ "value": "String[]"
+ },
+ "intermediatePath": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/editor/fields/text",
+ "label": "Intermediate Path",
+ "name": "intermediatePath",
+ "required": true
+ },
+ "serviceUser": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/editor/fields/text",
+ "label": "Service User",
+ "name": "serviceUser",
+ "required": true
+ }
+ }
+}
\ No newline at end of file
diff --git a/reference/src/main/resources/jcr_root/apps/reference/components/forms/actions/deleteugc.json b/reference/src/main/resources/jcr_root/apps/reference/components/forms/actions/deleteugc.json
new file mode 100644
index 0000000..5ce7fe5
--- /dev/null
+++ b/reference/src/main/resources/jcr_root/apps/reference/components/forms/actions/deleteugc.json
@@ -0,0 +1,5 @@
+{
+ "jcr:primaryType" : "sling:Component",
+ "jcr:title": "Delete User Generated Content",
+ "componentType": "Form Action"
+}
\ No newline at end of file
diff --git a/reference/src/main/resources/jcr_root/apps/reference/components/forms/actions/deleteugc/deleteugc.jsp b/reference/src/main/resources/jcr_root/apps/reference/components/forms/actions/deleteugc/deleteugc.jsp
new file mode 100644
index 0000000..a6a6fea
--- /dev/null
+++ b/reference/src/main/resources/jcr_root/apps/reference/components/forms/actions/deleteugc/deleteugc.jsp
@@ -0,0 +1,26 @@
+<%-- /*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */ --%>
+ <%@include file="/libs/sling-cms/global.jsp"%>
+<c:if test="${cmsEditEnabled == 'true'}">
+ <h3>Delete User Generated Content</h3>
+ <dl>
+ <dt>Path</dt>
+ <dd>${sling:encode(properties.path,'HTML')}</dd>
+ </dl>
+</c:if>
\ No newline at end of file
diff --git a/reference/src/main/resources/jcr_root/apps/reference/components/forms/actions/deleteugc/edit.json b/reference/src/main/resources/jcr_root/apps/reference/components/forms/actions/deleteugc/edit.json
new file mode 100644
index 0000000..759c096
--- /dev/null
+++ b/reference/src/main/resources/jcr_root/apps/reference/components/forms/actions/deleteugc/edit.json
@@ -0,0 +1,14 @@
+{
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/editor/slingform",
+ "button": "Save",
+ "fields": {
+ "path": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/editor/fields/path",
+ "label": "Path",
+ "name": "path",
+ "required": true
+ }
+ }
+}
\ No newline at end of file
diff --git a/reference/src/main/resources/jcr_root/apps/reference/components/forms/actions/requestpasswordreset/edit.json b/reference/src/main/resources/jcr_root/apps/reference/components/forms/actions/requestpasswordreset/edit.json
new file mode 100644
index 0000000..760ab09
--- /dev/null
+++ b/reference/src/main/resources/jcr_root/apps/reference/components/forms/actions/requestpasswordreset/edit.json
@@ -0,0 +1,16 @@
+{
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/editor/slingform",
+ "button": "Save",
+ "fields": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/general/container",
+ "resettimeout": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/editor/fields/text",
+ "label": "Reset Timeout",
+ "name": "resettimeout",
+ "type": "number"
+ }
+ }
+}
\ No newline at end of file
diff --git a/reference/src/main/resources/jcr_root/apps/reference/components/forms/actions/requestpasswordreset/requestpasswordreset.jsp b/reference/src/main/resources/jcr_root/apps/reference/components/forms/actions/requestpasswordreset/requestpasswordreset.jsp
new file mode 100644
index 0000000..becd97e
--- /dev/null
+++ b/reference/src/main/resources/jcr_root/apps/reference/components/forms/actions/requestpasswordreset/requestpasswordreset.jsp
@@ -0,0 +1,26 @@
+<%-- /*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */ --%>
+ <%@include file="/libs/sling-cms/global.jsp"%>
+<c:if test="${cmsEditEnabled == 'true'}">
+ <h3>Request Password Reset</h3>
+ <dl>
+ <dt>Reset Timeout</dt>
+ <dd>${sling:encode(properties.resettimeout,'HTML')}</dd>
+ </dl>
+</c:if>
\ No newline at end of file
diff --git a/reference/src/main/resources/jcr_root/apps/reference/components/forms/actions/resetpassword.json b/reference/src/main/resources/jcr_root/apps/reference/components/forms/actions/resetpassword.json
new file mode 100644
index 0000000..0635a1b
--- /dev/null
+++ b/reference/src/main/resources/jcr_root/apps/reference/components/forms/actions/resetpassword.json
@@ -0,0 +1,5 @@
+{
+ "jcr:primaryType" : "sling:Component",
+ "jcr:title": "Reset Password",
+ "componentType": "Form Action"
+}
\ No newline at end of file
diff --git a/reference/src/main/resources/jcr_root/apps/reference/components/forms/actions/resetpassword/edit.json b/reference/src/main/resources/jcr_root/apps/reference/components/forms/actions/resetpassword/edit.json
new file mode 100644
index 0000000..4f8a34b
--- /dev/null
+++ b/reference/src/main/resources/jcr_root/apps/reference/components/forms/actions/resetpassword/edit.json
@@ -0,0 +1,5 @@
+{
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/editor/slingform",
+ "button": "No need to edit"
+}
\ No newline at end of file
diff --git a/reference/src/main/resources/jcr_root/apps/reference/components/forms/actions/resetpassword/resetpassword.jsp b/reference/src/main/resources/jcr_root/apps/reference/components/forms/actions/resetpassword/resetpassword.jsp
new file mode 100644
index 0000000..7c9b003
--- /dev/null
+++ b/reference/src/main/resources/jcr_root/apps/reference/components/forms/actions/resetpassword/resetpassword.jsp
@@ -0,0 +1,22 @@
+<%-- /*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */ --%>
+ <%@include file="/libs/sling-cms/global.jsp"%>
+<c:if test="${cmsEditEnabled == 'true'}">
+ <h3>Reset Password</h3>
+</c:if>
\ No newline at end of file
diff --git a/reference/src/main/resources/jcr_root/apps/reference/components/forms/actions/updateugc.json b/reference/src/main/resources/jcr_root/apps/reference/components/forms/actions/updateugc.json
new file mode 100644
index 0000000..e1f4e64
--- /dev/null
+++ b/reference/src/main/resources/jcr_root/apps/reference/components/forms/actions/updateugc.json
@@ -0,0 +1,5 @@
+{
+ "jcr:primaryType" : "sling:Component",
+ "jcr:title": "Update User Generated Content",
+ "componentType": "Form Action"
+}
\ No newline at end of file
diff --git a/reference/src/main/resources/jcr_root/apps/reference/components/forms/actions/updateugc/edit.json b/reference/src/main/resources/jcr_root/apps/reference/components/forms/actions/updateugc/edit.json
new file mode 100644
index 0000000..759c096
--- /dev/null
+++ b/reference/src/main/resources/jcr_root/apps/reference/components/forms/actions/updateugc/edit.json
@@ -0,0 +1,14 @@
+{
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/editor/slingform",
+ "button": "Save",
+ "fields": {
+ "path": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/editor/fields/path",
+ "label": "Path",
+ "name": "path",
+ "required": true
+ }
+ }
+}
\ No newline at end of file
diff --git a/reference/src/main/resources/jcr_root/apps/reference/components/forms/actions/updateugc/updateugc.jsp b/reference/src/main/resources/jcr_root/apps/reference/components/forms/actions/updateugc/updateugc.jsp
new file mode 100644
index 0000000..cdbf3fe
--- /dev/null
+++ b/reference/src/main/resources/jcr_root/apps/reference/components/forms/actions/updateugc/updateugc.jsp
@@ -0,0 +1,26 @@
+<%-- /*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */ --%>
+ <%@include file="/libs/sling-cms/global.jsp"%>
+<c:if test="${cmsEditEnabled == 'true'}">
+ <h3>Update User Generated Content</h3>
+ <dl>
+ <dt>Path</dt>
+ <dd>${sling:encode(properties.path,'HTML')}</dd>
+ </dl>
+</c:if>
\ No newline at end of file
diff --git a/reference/src/main/resources/jcr_root/apps/reference/components/forms/fields/textarea/textarea.jsp b/reference/src/main/resources/jcr_root/apps/reference/components/forms/fields/textarea/textarea.jsp
index e046a87..e2ca9cf 100644
--- a/reference/src/main/resources/jcr_root/apps/reference/components/forms/fields/textarea/textarea.jsp
+++ b/reference/src/main/resources/jcr_root/apps/reference/components/forms/fields/textarea/textarea.jsp
@@ -39,9 +39,9 @@
<c:set var="fieldValue" value="${properties.value}" />
</c:when>
</c:choose>
- <textarea class="${formConfig.fieldClass}" id="${properties.name}" name="${properties.name}" ${properties.required ? 'required="required"' : ''}
+ <textarea class="${sling:encode(formConfig.fieldClass,'HTML')}" id="${sling:encode(properties.name,'HTML')}" name="${sling:encode(properties.name,'HTML')}" ${properties.required ? 'required="required"' : ''}
<c:forEach var="attr" items="${properties.additionalAttributes}">
${fn:split(attr,'\\=')[0]}="${fn:split(attr,'\\=')[1]}"
</c:forEach>
- >${fieldValue}</textarea>
+ >${sling:encode(fieldValue,'HTML')}</textarea>
</div>
diff --git a/reference/src/main/resources/jcr_root/apps/reference/components/forms/fields/textfield/textfield.jsp b/reference/src/main/resources/jcr_root/apps/reference/components/forms/fields/textfield/textfield.jsp
index 09d5cfa..4adc29c 100644
--- a/reference/src/main/resources/jcr_root/apps/reference/components/forms/fields/textfield/textfield.jsp
+++ b/reference/src/main/resources/jcr_root/apps/reference/components/forms/fields/textfield/textfield.jsp
@@ -41,7 +41,7 @@
<c:set var="fieldValue" value="${properties.value}" />
</c:when>
</c:choose>
- <input type="${properties.type}" class="${formConfig.fieldClass}" id="${properties.name}" name="${properties.name}" value="${fieldValue}" ${not empty properties.pattern ? patternStr : ''} ${not empty properties.placeholder ? placeholderStr : ''} ${properties.required ? 'required="required"' : ''}
+ <input type="${sling:encode(properties.type,'HTML_ATTR')}" class="${sling:encode(formConfig.fieldClass,'HTML_ATTR')}" id="${sling:encode(properties.name,'HTML_ATTR')}" name="${sling:encode(properties.name,'HTML_ATTR')}" value="${sling:encode(fieldValue,'HTML_ATTR')}" ${not empty properties.pattern ? patternStr : ''} ${not empty properties.placeholder ? placeholderStr : ''} ${properties.required ? 'required="required"' : ''}
<c:forEach var="attr" items="${properties.additionalAttributes}">
${fn:split(attr,'\\=')[0]}="${fn:split(attr,'\\=')[1]}"
</c:forEach>
diff --git a/reference/src/main/resources/jcr_root/apps/reference/components/forms/form/edit.json b/reference/src/main/resources/jcr_root/apps/reference/components/forms/form/edit.json
index aa98ccd..422d9d3 100644
--- a/reference/src/main/resources/jcr_root/apps/reference/components/forms/form/edit.json
+++ b/reference/src/main/resources/jcr_root/apps/reference/components/forms/form/edit.json
@@ -19,6 +19,12 @@
"name": "submitText",
"required": true
},
+ "errorPage": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/editor/fields/path",
+ "label": "Error Page",
+ "name": "errorPage"
+ },
"successPage": {
"jcr:primaryType": "nt:unstructured",
"sling:resourceType": "sling-cms/components/editor/fields/path",
diff --git a/reference/src/main/resources/jcr_root/apps/reference/components/forms/login.json b/reference/src/main/resources/jcr_root/apps/reference/components/forms/login.json
new file mode 100644
index 0000000..39fbbdc
--- /dev/null
+++ b/reference/src/main/resources/jcr_root/apps/reference/components/forms/login.json
@@ -0,0 +1,5 @@
+{
+ "jcr:primaryType" : "sling:Component",
+ "jcr:title": "Login",
+ "componentType": "General"
+}
\ No newline at end of file
diff --git a/reference/src/main/resources/jcr_root/apps/reference/components/forms/login/edit.json b/reference/src/main/resources/jcr_root/apps/reference/components/forms/login/edit.json
new file mode 100644
index 0000000..1f19887
--- /dev/null
+++ b/reference/src/main/resources/jcr_root/apps/reference/components/forms/login/edit.json
@@ -0,0 +1,46 @@
+{
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/editor/slingform",
+ "button": "Save",
+ "fields": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/general/container",
+ "errorMessage": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/editor/fields/richtext",
+ "label": "Error Message",
+ "name": "errorMessage",
+ "required": true
+ },
+ "usernameLabel": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/editor/fields/text",
+ "defaultValue": "Submit",
+ "label": "Username Label",
+ "name": "usernameLabel",
+ "required": true
+ },
+ "passwordLabel": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/editor/fields/text",
+ "defaultValue": "Submit",
+ "label": "Password Label",
+ "name": "passwordLabel",
+ "required": true
+ },
+ "submitLabel": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/editor/fields/text",
+ "defaultValue": "Submit",
+ "label": "Submit Label",
+ "name": "submitLabel",
+ "required": true
+ },
+ "successPage": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/editor/fields/path",
+ "label": "Success Page",
+ "name": "successPage"
+ }
+ }
+}
\ No newline at end of file
diff --git a/reference/src/main/resources/jcr_root/apps/reference/components/forms/login/login.jsp b/reference/src/main/resources/jcr_root/apps/reference/components/forms/login/login.jsp
new file mode 100644
index 0000000..15d0957
--- /dev/null
+++ b/reference/src/main/resources/jcr_root/apps/reference/components/forms/login/login.jsp
@@ -0,0 +1,42 @@
+<%-- /*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */ --%>
+<%@include file="/libs/sling-cms/global.jsp"%>
+<sling:adaptTo adaptable="${resource}" adaptTo="org.apache.sling.cms.PageManager" var="pageManager" />
+<sling:adaptTo adaptable="${resource}" adaptTo="org.apache.sling.cms.ComponentPolicyManager" var="componentPolicyMgr" />
+<c:set var="formConfig" value="${componentPolicyMgr.componentPolicy.componentConfigs['reference/components/forms/form'].valueMap}" />
+<form class="${formConfig.formClass}" action="${pageManager.page.path}.allowpost.html/j_security_check" method="post" data-analytics-id="Login Form">
+ <c:if test="${not empty param.j_reason}">
+ <div class="${formConfig.alertClass}">
+ ${sling:encode(properties.errorMessage,'HTML')}
+ </div>
+ </c:if>
+ <div class="${formConfig.fieldGroupClass}">
+ <label for="j_username" class="label">${sling:encode(properties.usernameLabel,'HTML')} <span class="${formConfig.fieldRequiredClass}">*</span></label>
+ <input type="text" class="${formConfig.fieldClass}" required="required" name="j_username" />
+ </div>
+ <div class="${formConfig.fieldGroupClass}">
+ <label for="j_password" class="label">${sling:encode(properties.passwordLabel,'HTML')} <span class="${formConfig.fieldRequiredClass}">*</span></label>
+ <input type="password" class="${formConfig.fieldClass}" required="required" name="j_password" />
+ </div>
+ <input type="hidden" name="resource" value="${sling:encode(properties.successPage,'HTML_ATTR')}.html" />
+ <input type="hidden" name="j_validate" value="true" />
+ <div class="${formConfig.fieldGroupClass}">
+ <button class="${formConfig.submitClass}">${sling:encode(properties.submitLabel,'HTML')}</button>
+ </div>
+</form>
\ No newline at end of file
diff --git a/reference/src/main/resources/jcr_root/apps/reference/components/forms/providers/requestparameters.json b/reference/src/main/resources/jcr_root/apps/reference/components/forms/providers/requestparameters.json
new file mode 100644
index 0000000..802f8db
--- /dev/null
+++ b/reference/src/main/resources/jcr_root/apps/reference/components/forms/providers/requestparameters.json
@@ -0,0 +1,6 @@
+{
+ "jcr:primaryType" : "sling:Component",
+ "jcr:title": "Request Parameters",
+ "componentType": "Form Value Provider",
+ "reloadPage": true
+}
\ No newline at end of file
diff --git a/reference/src/main/resources/jcr_root/apps/reference/components/forms/providers/requestparameters/edit.json b/reference/src/main/resources/jcr_root/apps/reference/components/forms/providers/requestparameters/edit.json
new file mode 100644
index 0000000..1fccbaf
--- /dev/null
+++ b/reference/src/main/resources/jcr_root/apps/reference/components/forms/providers/requestparameters/edit.json
@@ -0,0 +1,21 @@
+{
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/editor/slingform",
+ "button": "Save",
+ "fields": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/general/container",
+ "subpath": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/editor/fields/repeating",
+ "label": "Allowed Parameters",
+ "name": "allowedParameters"
+ },
+ "subpathTypeHint": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/editor/fields/hidden",
+ "name": "allowedParameters@TypeHint",
+ "value": "String[]"
+ }
+ }
+}
\ No newline at end of file
diff --git a/reference/src/main/resources/jcr_root/apps/reference/components/forms/providers/requestparameters/requestparameters.jsp b/reference/src/main/resources/jcr_root/apps/reference/components/forms/providers/requestparameters/requestparameters.jsp
new file mode 100644
index 0000000..aad2f64
--- /dev/null
+++ b/reference/src/main/resources/jcr_root/apps/reference/components/forms/providers/requestparameters/requestparameters.jsp
@@ -0,0 +1,26 @@
+<%-- /*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */ --%>
+ <%@include file="/libs/sling-cms/global.jsp"%>
+<c:if test="${cmsEditEnabled == 'true'}">
+ <h3>Request Parameters</h3>
+ <dl>
+ <dt>Allowed Parameters</dt>
+ <dd>${sling:encode(fn:join(properties.allowedParameters,','),'HTML')}</dd>
+ </dl>
+</c:if>
\ No newline at end of file
diff --git a/reference/src/main/resources/jcr_root/apps/reference/components/forms/providers/suffixresource.json b/reference/src/main/resources/jcr_root/apps/reference/components/forms/providers/suffixresource.json
new file mode 100644
index 0000000..e497a9c
--- /dev/null
+++ b/reference/src/main/resources/jcr_root/apps/reference/components/forms/providers/suffixresource.json
@@ -0,0 +1,6 @@
+{
+ "jcr:primaryType" : "sling:Component",
+ "jcr:title": "Suffix Resource",
+ "componentType": "Form Value Provider",
+ "reloadPage": true
+}
\ No newline at end of file
diff --git a/reference/src/main/resources/jcr_root/apps/reference/components/forms/providers/suffixresource/edit.json b/reference/src/main/resources/jcr_root/apps/reference/components/forms/providers/suffixresource/edit.json
new file mode 100644
index 0000000..1e67bbb
--- /dev/null
+++ b/reference/src/main/resources/jcr_root/apps/reference/components/forms/providers/suffixresource/edit.json
@@ -0,0 +1,28 @@
+{
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/editor/slingform",
+ "button": "Save",
+ "fields": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/general/container",
+ "allowedProperties": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/editor/fields/repeating",
+ "label": "Allowed Properties",
+ "name": "allowedProperties"
+ },
+ "allowedPropertiesTypeHint": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/editor/fields/hidden",
+ "name": "allowedProperties@TypeHint",
+ "value": "String[]"
+ },
+ "basePath": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/editor/fields/path",
+ "label": "Base Path",
+ "name": "basePath",
+ "required": true
+ }
+ }
+}
\ No newline at end of file
diff --git a/reference/src/main/resources/jcr_root/apps/reference/components/forms/providers/suffixresource/suffixresource.jsp b/reference/src/main/resources/jcr_root/apps/reference/components/forms/providers/suffixresource/suffixresource.jsp
new file mode 100644
index 0000000..c702d5f
--- /dev/null
+++ b/reference/src/main/resources/jcr_root/apps/reference/components/forms/providers/suffixresource/suffixresource.jsp
@@ -0,0 +1,28 @@
+<%-- /*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */ --%>
+ <%@include file="/libs/sling-cms/global.jsp"%>
+<c:if test="${cmsEditEnabled == 'true'}">
+ <h3>Suffix Resource</h3>
+ <dl>
+ <dt>Allowed Properties</dt>
+ <dd>${sling:encode(fn:join(properties.allowedProperties,','),'HTML')}</dd>
+ <dt>Base Path</dt>
+ <dd>${sling:encode(properties.basePath,'HTML')}</dd>
+ </dl>
+</c:if>
\ No newline at end of file
diff --git a/reference/src/test/java/org/apache/sling/cms/reference/forms/FormActionResultTest.java b/reference/src/test/java/org/apache/sling/cms/reference/forms/FormActionResultTest.java
index 9ed86d7..9f7b5d0 100644
--- a/reference/src/test/java/org/apache/sling/cms/reference/forms/FormActionResultTest.java
+++ b/reference/src/test/java/org/apache/sling/cms/reference/forms/FormActionResultTest.java
@@ -20,8 +20,6 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
-import org.apache.sling.cms.reference.forms.FormActionResult;
-import org.apache.sling.cms.reference.forms.FormException;
import org.junit.Test;
public class FormActionResultTest {
diff --git a/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/FormHandlerTest.java b/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/FormHandlerTest.java
index 048d08d..ab0e2ab 100644
--- a/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/FormHandlerTest.java
+++ b/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/FormHandlerTest.java
@@ -17,10 +17,10 @@
package org.apache.sling.cms.reference.forms.impl;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.never;
import java.io.IOException;
+import java.lang.annotation.Annotation;
import java.util.Arrays;
import javax.servlet.ServletException;
@@ -62,20 +62,49 @@ public class FormHandlerTest {
context.currentResource(Mockito.mock(Resource.class));
formRequest = new FormRequestImpl(context.request(), null,
- Arrays.asList(new SelectionHandler(), new TextareaHandler(), new TextfieldHandler()));
+ Arrays.asList(new SelectionHandler(new SelectionHandler.Config() {
- final SendEmailAction sendEmailAction = new SendEmailAction();
- mailService = Mockito.mock(MailService.class);
- Mockito.when(mailService.getMessageBuilder()).thenReturn(new MockMessageBuilder());
- sendEmailAction.setMailService(mailService);
+ @Override
+ public Class<? extends Annotation> annotationType() {
+ return null;
+ }
+
+ @Override
+ public String[] supportedTypes() {
+ return new String[] { SelectionHandler.DEFAULT_RESOURCE_TYPE };
+ }
+
+ }), new TextareaHandler(new TextareaHandler.Config() {
+
+ @Override
+ public Class<? extends Annotation> annotationType() {
+ return null;
+ }
+
+ @Override
+ public String[] supportedTypes() {
+ return new String[] { TextareaHandler.DEFAULT_RESOURCE_TYPE };
+ }
- formHandler = new FormHandler(Arrays.asList(sendEmailAction)) {
- private static final long serialVersionUID = 1L;
+ }), new TextfieldHandler(new TextfieldHandler.Config() {
- protected FormRequest getFormRequest(final SlingHttpServletRequest request) {
- return formRequest;
- }
- };
+ @Override
+ public Class<? extends Annotation> annotationType() {
+ return null;
+ }
+
+ @Override
+ public String[] supportedTypes() {
+ return new String[] { TextfieldHandler.DEFAULT_RESOURCE_TYPE };
+ }
+
+ })));
+ context.registerAdapter(SlingHttpServletRequest.class, FormRequest.class, formRequest);
+
+ mailService = Mockito.mock(MailService.class);
+ Mockito.when(mailService.getMessageBuilder()).thenReturn(new MockMessageBuilder());
+ final SendEmailAction sendEmailAction = new SendEmailAction(mailService);
+ formHandler = new FormHandler(Arrays.asList(sendEmailAction));
}
@Test
@@ -95,7 +124,7 @@ public class FormHandlerTest {
formHandler.service(context.request(), context.response());
- assertTrue(HttpServletResponse.SC_MOVED_TEMPORARILY == context.response().getStatus());
+ assertEquals(HttpServletResponse.SC_MOVED_TEMPORARILY, context.response().getStatus());
assertEquals("/form-no-actions.html?error=actions", context.response().getHeader("Location"));
Mockito.verify(mailService, never()).sendMessage(Mockito.any());
}
diff --git a/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/FormRequestImplTest.java b/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/FormRequestImplTest.java
index 824056d..1c3285c 100644
--- a/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/FormRequestImplTest.java
+++ b/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/FormRequestImplTest.java
@@ -21,6 +21,8 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import java.io.ByteArrayInputStream;
+import java.lang.annotation.Annotation;
import java.util.Arrays;
import com.google.common.collect.ImmutableMap;
@@ -49,10 +51,46 @@ public class FormRequestImplTest {
.setParameterMap(ImmutableMap.<String, Object>builder().put("requiredtextarea", "Hello World!")
.put("singleselect", "Hello World!").put("anotherkey", "Hello World!").put("money", "123")
.put("patternfield", "123").put("double", "2.7").put("integer", "2")
- .put("datefield", "2019-02-02").build());
+ .put("file", new ByteArrayInputStream(new byte[0])).put("datefield", "2019-02-02").build());
formRequest = new FormRequestImpl(context.request(), null,
- Arrays.asList(new SelectionHandler(), new TextareaHandler(), new TextfieldHandler()));
+ Arrays.asList(new SelectionHandler(new SelectionHandler.Config() {
+
+ @Override
+ public Class<? extends Annotation> annotationType() {
+ return null;
+ }
+
+ @Override
+ public String[] supportedTypes() {
+ return new String[] { SelectionHandler.DEFAULT_RESOURCE_TYPE };
+ }
+
+ }), new TextareaHandler(new TextareaHandler.Config() {
+
+ @Override
+ public Class<? extends Annotation> annotationType() {
+ return null;
+ }
+
+ @Override
+ public String[] supportedTypes() {
+ return new String[] { TextareaHandler.DEFAULT_RESOURCE_TYPE };
+ }
+
+ }), new TextfieldHandler(new TextfieldHandler.Config() {
+
+ @Override
+ public Class<? extends Annotation> annotationType() {
+ return null;
+ }
+
+ @Override
+ public String[] supportedTypes() {
+ return new String[] { TextfieldHandler.DEFAULT_RESOURCE_TYPE };
+ }
+
+ })));
formRequest.initFields();
}
diff --git a/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/actions/CreateUserActionTest.java b/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/actions/CreateUserActionTest.java
new file mode 100644
index 0000000..bb767c5
--- /dev/null
+++ b/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/actions/CreateUserActionTest.java
@@ -0,0 +1,153 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.sling.cms.reference.forms.impl.actions;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.jcr.AccessDeniedException;
+import javax.jcr.RepositoryException;
+import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.jcr.ValueFactory;
+import javax.jcr.ValueFormatException;
+
+import org.apache.jackrabbit.api.JackrabbitSession;
+import org.apache.jackrabbit.api.security.user.Group;
+import org.apache.jackrabbit.api.security.user.User;
+import org.apache.jackrabbit.api.security.user.UserManager;
+import org.apache.jackrabbit.value.AbstractValueFactory;
+import org.apache.sling.api.resource.LoginException;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceResolverFactory;
+import org.apache.sling.cms.reference.forms.FormActionResult;
+import org.apache.sling.cms.reference.forms.FormConstants;
+import org.apache.sling.cms.reference.forms.FormException;
+import org.apache.sling.cms.reference.forms.FormRequest;
+import org.apache.sling.cms.reference.forms.impl.FormRequestImpl;
+import org.apache.sling.servlethelpers.MockSlingHttpServletRequest;
+import org.apache.sling.testing.resourceresolver.MockResource;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+public class CreateUserActionTest {
+
+ private ResourceResolverFactory factory;
+ private ResourceResolver resolver;
+ private MockResource actionResource;
+
+ @Before
+ public void init() throws FormException, LoginException, AccessDeniedException,
+ UnsupportedRepositoryOperationException, RepositoryException {
+
+ factory = Mockito.mock(ResourceResolverFactory.class);
+
+ resolver = Mockito.mock(ResourceResolver.class);
+ Mockito.when(resolver.getResource(Mockito.any())).thenReturn(Mockito.mock(Resource.class));
+
+ Mockito.when(factory.getServiceResourceResolver(Mockito.anyMap())).thenReturn(resolver);
+
+ JackrabbitSession session = Mockito.mock(JackrabbitSession.class);
+ Mockito.when(resolver.adaptTo(Mockito.any())).thenReturn(session);
+
+ ValueFactory vf = new AbstractValueFactory() {
+
+ @Override
+ protected void checkPathFormat(String pathValue) throws ValueFormatException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ protected void checkNameFormat(String nameValue) throws ValueFormatException {
+ // TODO Auto-generated method stub
+
+ }
+
+ };
+ Mockito.when(session.getValueFactory()).thenReturn(vf);
+
+ UserManager userManager = Mockito.mock(UserManager.class);
+ Mockito.when(session.getUserManager()).thenReturn(userManager);
+
+ User existingUser = Mockito.mock(User.class);
+ Mockito.when(userManager.getAuthorizable("existing@email.com")).thenReturn(existingUser);
+ Mockito.when(existingUser.getPath()).thenReturn("/home");
+
+ Group agroup = Mockito.mock(Group.class);
+ Mockito.when(agroup.isGroup()).thenReturn(true);
+ Mockito.when(userManager.getAuthorizable("group1")).thenReturn(agroup);
+
+ Map<String, Object> properties = new HashMap<>();
+ properties.put(CreateUserAction.PN_INTERMEDIATE_PATH, "app");
+ properties.put(CreateUserAction.GROUPS, new String[] { "group1" });
+ properties.put(CreateUserAction.PROFILE_PROPERTIES, new String[] { "profile", "anotherfield" });
+ actionResource = new MockResource("/content", properties, null);
+
+ Mockito.when(
+ userManager.createUser(Mockito.anyString(), Mockito.anyString(), Mockito.any(), Mockito.anyString()))
+ .thenReturn(existingUser);
+
+ }
+
+ @Test
+ public void testHandleForm() throws FormException, RepositoryException {
+
+ CreateUserAction action = new CreateUserAction(factory);
+
+ Mockito.when(resolver.getUserID()).thenReturn("valid@email.com");
+
+ FormRequest request = new FormRequestImpl(new MockSlingHttpServletRequest(resolver), null, null);
+ request.getFormData().put(CreateUserAction.PN_USERNAME, "new@email.com");
+ request.getFormData().put(FormConstants.PN_PASSWORD, "password1");
+ request.getFormData().put("profile", "value");
+ request.getFormData().put(CreateUserAction.GROUPS, new String[] { "group1" });
+
+ FormActionResult result = action.handleForm(actionResource, request);
+ assertTrue(result.isSucceeded());
+ }
+
+ @Test
+ public void testExistingUser() throws FormException, RepositoryException {
+
+ CreateUserAction action = new CreateUserAction(factory);
+
+ FormRequest request = new FormRequestImpl(new MockSlingHttpServletRequest(resolver), null, null);
+ request.getFormData().put(CreateUserAction.PN_USERNAME, "existing@email.com");
+ request.getFormData().put(FormConstants.PN_PASSWORD, "password1");
+
+ FormActionResult result = action.handleForm(actionResource, request);
+ assertFalse(result.isSucceeded());
+ }
+
+ @Test
+ public void testHandles() throws FormException {
+ CreateUserAction action = new CreateUserAction(factory);
+ Resource validResource = Mockito.mock(Resource.class);
+ Mockito.when(validResource.getResourceType()).thenReturn(CreateUserAction.RESOURCE_TYPE);
+ assertTrue(action.handles(validResource));
+
+ Resource inValidResource = Mockito.mock(Resource.class);
+ Mockito.when(inValidResource.getResourceType()).thenReturn("something/else");
+ assertFalse(action.handles(inValidResource));
+ }
+
+}
diff --git a/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/actions/DeleteUserGeneratedContentActionTest.java b/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/actions/DeleteUserGeneratedContentActionTest.java
new file mode 100644
index 0000000..b91c14a
--- /dev/null
+++ b/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/actions/DeleteUserGeneratedContentActionTest.java
@@ -0,0 +1,153 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.sling.cms.reference.forms.impl.actions;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.Collections;
+import java.util.HashMap;
+
+import org.apache.jackrabbit.JcrConstants;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.LoginException;
+import org.apache.sling.api.resource.ModifiableValueMap;
+import org.apache.sling.api.resource.PersistenceException;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceResolverFactory;
+import org.apache.sling.api.resource.ValueMap;
+import org.apache.sling.api.wrappers.ModifiableValueMapDecorator;
+import org.apache.sling.api.wrappers.ValueMapDecorator;
+import org.apache.sling.cms.CMSConstants;
+import org.apache.sling.cms.reference.forms.FormException;
+import org.apache.sling.cms.reference.forms.FormRequest;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+public class DeleteUserGeneratedContentActionTest {
+
+ @Test
+ public void testHandles() {
+
+ DeleteUserGeneratedContentAction action = new DeleteUserGeneratedContentAction(null);
+
+ Resource validResource = Mockito.mock(Resource.class);
+ Mockito.when(validResource.getResourceType()).thenReturn("reference/components/forms/actions/deleteugc");
+ assertTrue(action.handles(validResource));
+
+ Resource invalidResource = Mockito.mock(Resource.class);
+ Mockito.when(invalidResource.getResourceType())
+ .thenReturn("reference/components/forms/actions/someotheraction");
+ assertFalse(action.handles(invalidResource));
+ }
+
+ @Test
+ public void testInvalidServiceUser() throws FormException, LoginException {
+
+ LoginException le = new LoginException();
+ ResourceResolverFactory factory = Mockito.mock(ResourceResolverFactory.class);
+ Mockito.when(factory.getServiceResourceResolver(Mockito.anyMap())).thenThrow(le);
+
+ DeleteUserGeneratedContentAction action = new DeleteUserGeneratedContentAction(factory);
+
+ Resource actionResource = Mockito.mock(Resource.class);
+
+ FormRequest formRequest = Mockito.mock(FormRequest.class);
+
+ try {
+ action.handleForm(actionResource, formRequest);
+ fail();
+ } catch (FormException fe) {
+ assertEquals(le, fe.getCause());
+ }
+ }
+
+ @Test
+ public void testHandleForm() throws FormException, LoginException, PersistenceException {
+
+ ModifiableValueMap contentData = new ModifiableValueMapDecorator(new HashMap<String, Object>());
+ contentData.put(JcrConstants.JCR_PRIMARYTYPE, JcrConstants.NT_UNSTRUCTURED);
+ Resource contentResource = Mockito.mock(Resource.class);
+ Mockito.when(contentResource.getValueMap()).thenReturn(contentData);
+ Mockito.when(contentResource.adaptTo(Mockito.any())).thenReturn(contentData);
+
+ Resource ugcResource = Mockito.mock(Resource.class);
+ Mockito.when(ugcResource.getResourceType()).thenReturn(CMSConstants.NT_UGC);
+ Mockito.when(ugcResource.getValueMap())
+ .thenReturn(new ValueMapDecorator(Collections.singletonMap("user", "auser")));
+ Mockito.when(contentResource.getParent()).thenReturn(ugcResource);
+
+ ResourceResolver resolver = Mockito.mock(ResourceResolver.class);
+ Mockito.when(resolver.getUserID()).thenReturn("auser");
+ SlingHttpServletRequest request = Mockito.mock(SlingHttpServletRequest.class);
+ Mockito.when(request.getResourceResolver()).thenReturn(resolver);
+ Mockito.when(resolver.getResource("/etc/usergenerated/test")).thenReturn(contentResource);
+
+ ResourceResolverFactory factory = Mockito.mock(ResourceResolverFactory.class);
+ Mockito.when(factory.getServiceResourceResolver(Mockito.anyMap())).thenReturn(resolver);
+
+ DeleteUserGeneratedContentAction action = new DeleteUserGeneratedContentAction(factory);
+
+ ValueMap actionData = new ModifiableValueMapDecorator(new HashMap<String, Object>());
+ actionData.put("path", "/etc/usergenerated/test");
+
+ Resource actionResource = Mockito.mock(Resource.class);
+ Mockito.when(actionResource.getValueMap()).thenReturn(actionData);
+
+ FormRequest formRequest = Mockito.mock(FormRequest.class);
+ Mockito.when(formRequest.getFormData()).thenReturn(new ValueMapDecorator(Collections.emptyMap()));
+ Mockito.when(formRequest.getOriginalRequest()).thenReturn(request);
+
+ action.handleForm(actionResource, formRequest);
+
+ Mockito.verify(resolver).delete(ugcResource);
+
+ }
+
+ @Test
+ public void testNoParent() throws FormException, LoginException {
+
+ Resource contentResource = Mockito.mock(Resource.class);
+
+ ResourceResolver resolver = Mockito.mock(ResourceResolver.class);
+ Mockito.when(resolver.getResource("/etc/usergenerated/test")).thenReturn(contentResource);
+
+ ResourceResolverFactory factory = Mockito.mock(ResourceResolverFactory.class);
+ Mockito.when(factory.getServiceResourceResolver(Mockito.anyMap())).thenReturn(resolver);
+
+ DeleteUserGeneratedContentAction action = new DeleteUserGeneratedContentAction(factory);
+
+ ValueMap actionData = new ModifiableValueMapDecorator(new HashMap<String, Object>());
+ actionData.put("path", "/etc/usergenerated/test");
+
+ Resource actionResource = Mockito.mock(Resource.class);
+ Mockito.when(actionResource.getValueMap()).thenReturn(actionData);
+
+ FormRequest formRequest = Mockito.mock(FormRequest.class);
+ Mockito.when(formRequest.getFormData()).thenReturn(new ValueMapDecorator(Collections.emptyMap()));
+
+ try {
+ action.handleForm(actionResource, formRequest);
+ fail();
+ } catch (FormException fe) {
+ assertEquals("Failed to find UGC Parent", fe.getMessage());
+ }
+ }
+}
diff --git a/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/actions/RequestPasswordResetActionTest.java b/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/actions/RequestPasswordResetActionTest.java
new file mode 100644
index 0000000..cd12d85
--- /dev/null
+++ b/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/actions/RequestPasswordResetActionTest.java
@@ -0,0 +1,134 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.sling.cms.reference.forms.impl.actions;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Collections;
+
+import javax.jcr.AccessDeniedException;
+import javax.jcr.RepositoryException;
+import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.jcr.ValueFactory;
+import javax.jcr.ValueFormatException;
+
+import org.apache.jackrabbit.api.JackrabbitSession;
+import org.apache.jackrabbit.api.security.user.User;
+import org.apache.jackrabbit.api.security.user.UserManager;
+import org.apache.jackrabbit.value.AbstractValueFactory;
+import org.apache.sling.api.resource.LoginException;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceResolverFactory;
+import org.apache.sling.cms.reference.forms.FormActionResult;
+import org.apache.sling.cms.reference.forms.FormException;
+import org.apache.sling.cms.reference.forms.FormRequest;
+import org.apache.sling.cms.reference.forms.impl.FormRequestImpl;
+import org.apache.sling.servlethelpers.MockSlingHttpServletRequest;
+import org.apache.sling.testing.resourceresolver.MockResource;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+public class RequestPasswordResetActionTest {
+
+ private ResourceResolverFactory factory;
+ private ResourceResolver resolver;
+
+ @Before
+ public void init() throws FormException, LoginException, AccessDeniedException,
+ UnsupportedRepositoryOperationException, RepositoryException {
+
+ factory = Mockito.mock(ResourceResolverFactory.class);
+
+ resolver = Mockito.mock(ResourceResolver.class);
+ Mockito.when(factory.getServiceResourceResolver(Mockito.anyMap())).thenReturn(resolver);
+
+ JackrabbitSession session = Mockito.mock(JackrabbitSession.class);
+ Mockito.when(resolver.adaptTo(Mockito.any())).thenReturn(session);
+
+ ValueFactory vf = new AbstractValueFactory() {
+
+ @Override
+ protected void checkPathFormat(String pathValue) throws ValueFormatException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ protected void checkNameFormat(String nameValue) throws ValueFormatException {
+ // TODO Auto-generated method stub
+
+ }
+
+ };
+ Mockito.when(session.getValueFactory()).thenReturn(vf);
+
+ UserManager userManager = Mockito.mock(UserManager.class);
+ Mockito.when(session.getUserManager()).thenReturn(userManager);
+
+ Mockito.when(userManager.getAuthorizable("test@email.com")).thenReturn(Mockito.mock(User.class));
+
+ }
+
+ @Test
+ public void testHandleForm() throws FormException {
+
+ RequestPasswordResetAction action = new RequestPasswordResetAction(factory);
+
+ FormRequest request = new FormRequestImpl(new MockSlingHttpServletRequest(resolver), null, null);
+ request.getFormData().put("email", "test@email.com");
+
+ Resource actionResource = new MockResource("/content",
+ Collections.singletonMap(RequestPasswordResetAction.PN_RESETTIMEOUT, 2), null);
+
+ FormActionResult result = action.handleForm(actionResource, request);
+ assertTrue(result.isSucceeded());
+
+ }
+
+ @Test
+ public void testNoUser() throws FormException {
+
+ RequestPasswordResetAction action = new RequestPasswordResetAction(factory);
+
+ FormRequest request = new FormRequestImpl(new MockSlingHttpServletRequest(resolver), null, null);
+ request.getFormData().put("email", "test1@email.com");
+
+ Resource actionResource = new MockResource("/content",
+ Collections.singletonMap(RequestPasswordResetAction.PN_RESETTIMEOUT, 2), null);
+
+ FormActionResult result = action.handleForm(actionResource, request);
+ assertFalse(result.isSucceeded());
+
+ }
+
+ @Test
+ public void testHandles() throws FormException {
+
+ RequestPasswordResetAction action = new RequestPasswordResetAction(null);
+ Resource validResource = Mockito.mock(Resource.class);
+ Mockito.when(validResource.getResourceType()).thenReturn(RequestPasswordResetAction.RESOURCE_TYPE);
+ assertTrue(action.handles(validResource));
+
+ Resource inValidResource = Mockito.mock(Resource.class);
+ Mockito.when(inValidResource.getResourceType()).thenReturn("something/else");
+ assertFalse(action.handles(inValidResource));
+ }
+
+}
diff --git a/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/actions/ResetPasswordActionTest.java b/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/actions/ResetPasswordActionTest.java
new file mode 100644
index 0000000..9db49ca
--- /dev/null
+++ b/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/actions/ResetPasswordActionTest.java
@@ -0,0 +1,168 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.sling.cms.reference.forms.impl.actions;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Calendar;
+import java.util.Collections;
+
+import javax.jcr.AccessDeniedException;
+import javax.jcr.RepositoryException;
+import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.jcr.Value;
+import javax.jcr.ValueFactory;
+import javax.jcr.ValueFormatException;
+
+import org.apache.jackrabbit.api.JackrabbitSession;
+import org.apache.jackrabbit.api.security.user.User;
+import org.apache.jackrabbit.api.security.user.UserManager;
+import org.apache.jackrabbit.value.AbstractValueFactory;
+import org.apache.jackrabbit.value.DateValue;
+import org.apache.jackrabbit.value.StringValue;
+import org.apache.sling.api.resource.LoginException;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceResolverFactory;
+import org.apache.sling.cms.reference.forms.FormActionResult;
+import org.apache.sling.cms.reference.forms.FormConstants;
+import org.apache.sling.cms.reference.forms.FormException;
+import org.apache.sling.cms.reference.forms.FormRequest;
+import org.apache.sling.cms.reference.forms.impl.FormRequestImpl;
+import org.apache.sling.servlethelpers.MockSlingHttpServletRequest;
+import org.apache.sling.testing.resourceresolver.MockResource;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+public class ResetPasswordActionTest {
+
+ private ResourceResolverFactory factory;
+ private ResourceResolver resolver;
+
+ @Before
+ public void init() throws FormException, LoginException, AccessDeniedException,
+ UnsupportedRepositoryOperationException, RepositoryException {
+
+ factory = Mockito.mock(ResourceResolverFactory.class);
+
+ resolver = Mockito.mock(ResourceResolver.class);
+ Mockito.when(factory.getServiceResourceResolver(Mockito.anyMap())).thenReturn(resolver);
+
+ JackrabbitSession session = Mockito.mock(JackrabbitSession.class);
+ Mockito.when(resolver.adaptTo(Mockito.any())).thenReturn(session);
+
+ ValueFactory vf = new AbstractValueFactory() {
+
+ @Override
+ protected void checkPathFormat(String pathValue) throws ValueFormatException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ protected void checkNameFormat(String nameValue) throws ValueFormatException {
+ // TODO Auto-generated method stub
+
+ }
+
+ };
+ Mockito.when(session.getValueFactory()).thenReturn(vf);
+
+ UserManager userManager = Mockito.mock(UserManager.class);
+ Mockito.when(session.getUserManager()).thenReturn(userManager);
+
+ User validUser = Mockito.mock(User.class);
+ Mockito.when(validUser.getProperty(FormConstants.PN_RESETTOKEN))
+ .thenReturn(new Value[] { new StringValue("123") });
+ Calendar cal = Calendar.getInstance();
+ cal.add(Calendar.HOUR, 24);
+ Mockito.when(validUser.getProperty(FormConstants.PN_RESETTIMEOUT))
+ .thenReturn(new Value[] { new DateValue(cal) });
+ Mockito.when(userManager.getAuthorizable("valid@email.com")).thenReturn(validUser);
+
+ User invalidUser = Mockito.mock(User.class);
+ Mockito.when(invalidUser.getProperty(FormConstants.PN_RESETTOKEN))
+ .thenReturn(new Value[] { new StringValue("456") });
+ Mockito.when(userManager.getAuthorizable("invalid@email.com")).thenReturn(invalidUser);
+
+ User expiredUser = Mockito.mock(User.class);
+ Mockito.when(expiredUser.getProperty(FormConstants.PN_RESETTOKEN))
+ .thenReturn(new Value[] { new StringValue("456") });
+ cal = Calendar.getInstance();
+ cal.add(Calendar.HOUR, -24);
+ Mockito.when(expiredUser.getProperty(FormConstants.PN_RESETTIMEOUT))
+ .thenReturn(new Value[] { new DateValue(cal) });
+ Mockito.when(userManager.getAuthorizable("expired@email.com")).thenReturn(expiredUser);
+
+ }
+
+ @Test
+ public void testHandleForm() throws FormException {
+
+ ResetPasswordAction action = new ResetPasswordAction(factory);
+
+ FormRequest request = new FormRequestImpl(new MockSlingHttpServletRequest(resolver), null, null);
+ request.getFormData().put("email", "valid@email.com");
+ request.getFormData().put(FormConstants.PN_RESETTOKEN, "123");
+ request.getFormData().put(FormConstants.PN_PASSWORD, "password1");
+
+ Resource actionResource = new MockResource("/content",
+ Collections.singletonMap(RequestPasswordResetAction.PN_RESETTIMEOUT, 1000000), null);
+
+ FormActionResult result = action.handleForm(actionResource, request);
+ assertTrue(result.isSucceeded());
+
+ }
+
+ public FormActionResult doReset(String email) throws FormException {
+
+ ResetPasswordAction action = new ResetPasswordAction(factory);
+
+ FormRequest request = new FormRequestImpl(new MockSlingHttpServletRequest(resolver), null, null);
+ request.getFormData().put("email", email);
+
+ Resource actionResource = new MockResource("/content",
+ Collections.singletonMap(RequestPasswordResetAction.PN_RESETTIMEOUT, 2), null);
+
+ return action.handleForm(actionResource, request);
+
+ }
+
+ @Test
+ public void testInvalid() throws FormException {
+
+ assertFalse(doReset("invalid@email.com").isSucceeded());
+ assertFalse(doReset("expired@email.com").isSucceeded());
+ assertFalse(doReset("test123@email.com").isSucceeded());
+
+ }
+
+ @Test
+ public void testHandles() throws FormException {
+ ResetPasswordAction action = new ResetPasswordAction(null);
+ Resource validResource = Mockito.mock(Resource.class);
+ Mockito.when(validResource.getResourceType()).thenReturn(ResetPasswordAction.RESOURCE_TYPE);
+ assertTrue(action.handles(validResource));
+
+ Resource inValidResource = Mockito.mock(Resource.class);
+ Mockito.when(inValidResource.getResourceType()).thenReturn("something/else");
+ assertFalse(action.handles(inValidResource));
+ }
+
+}
diff --git a/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/actions/SendEmailActionTest.java b/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/actions/SendEmailActionTest.java
index eb4aaf7..66150e7 100644
--- a/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/actions/SendEmailActionTest.java
+++ b/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/actions/SendEmailActionTest.java
@@ -47,12 +47,9 @@ public class SendEmailActionTest {
context.request().setResource(context.resourceResolver().getResource("/form/jcr:content/container/form"));
resolver = context.resourceResolver();
- action = new SendEmailAction();
-
mailService = Mockito.mock(MailService.class);
Mockito.when(mailService.getMessageBuilder()).thenReturn(new MockMessageBuilder());
-
- action.setMailService(mailService);
+ action = new SendEmailAction(mailService);
}
@Test
diff --git a/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/actions/UpdateProfileActionTest.java b/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/actions/UpdateProfileActionTest.java
new file mode 100644
index 0000000..af8d167
--- /dev/null
+++ b/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/actions/UpdateProfileActionTest.java
@@ -0,0 +1,165 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.sling.cms.reference.forms.impl.actions;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Calendar;
+import java.util.Collections;
+
+import javax.jcr.AccessDeniedException;
+import javax.jcr.RepositoryException;
+import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.jcr.ValueFactory;
+import javax.jcr.ValueFormatException;
+
+import org.apache.jackrabbit.api.JackrabbitSession;
+import org.apache.jackrabbit.api.security.user.User;
+import org.apache.jackrabbit.api.security.user.UserManager;
+import org.apache.jackrabbit.value.AbstractValueFactory;
+import org.apache.sling.api.resource.LoginException;
+import org.apache.sling.api.resource.PersistenceException;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceResolverFactory;
+import org.apache.sling.cms.reference.forms.FormActionResult;
+import org.apache.sling.cms.reference.forms.FormConstants;
+import org.apache.sling.cms.reference.forms.FormException;
+import org.apache.sling.cms.reference.forms.FormRequest;
+import org.apache.sling.cms.reference.forms.impl.FormRequestImpl;
+import org.apache.sling.servlethelpers.MockSlingHttpServletRequest;
+import org.apache.sling.testing.resourceresolver.MockResource;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+public class UpdateProfileActionTest {
+
+ private ResourceResolverFactory factory;
+ private ResourceResolver resolver;
+ private User validUser;
+
+ @Before
+ public void init() throws FormException, LoginException, AccessDeniedException,
+ UnsupportedRepositoryOperationException, RepositoryException {
+
+ factory = Mockito.mock(ResourceResolverFactory.class);
+
+ resolver = Mockito.mock(ResourceResolver.class);
+
+ Mockito.when(factory.getServiceResourceResolver(Mockito.anyMap())).thenReturn(resolver);
+
+ JackrabbitSession session = Mockito.mock(JackrabbitSession.class);
+ Mockito.when(resolver.adaptTo(Mockito.any())).thenReturn(session);
+
+ ValueFactory vf = new AbstractValueFactory() {
+
+ @Override
+ protected void checkPathFormat(String pathValue) throws ValueFormatException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ protected void checkNameFormat(String nameValue) throws ValueFormatException {
+ // TODO Auto-generated method stub
+
+ }
+
+ };
+ Mockito.when(session.getValueFactory()).thenReturn(vf);
+
+ UserManager userManager = Mockito.mock(UserManager.class);
+ Mockito.when(session.getUserManager()).thenReturn(userManager);
+
+ validUser = Mockito.mock(User.class);
+ Mockito.when(userManager.getAuthorizable("valid@email.com")).thenReturn(validUser);
+
+ }
+
+ @Test
+ public void testHandleForm() throws FormException, RepositoryException {
+
+ UpdateProfileAction action = new UpdateProfileAction();
+
+ Mockito.when(resolver.getUserID()).thenReturn("valid@email.com");
+
+ FormRequest request = new FormRequestImpl(new MockSlingHttpServletRequest(resolver), null, null);
+ request.getFormData().put(FormConstants.PN_PASSWORD, "password1");
+ request.getFormData().put("dateField", Calendar.getInstance());
+ request.getFormData().put("doublefield", 2.0);
+ request.getFormData().put("intField", 2);
+ request.getFormData().put("arraufield", new String[] { "one", "two" });
+ request.getFormData().put(FormConstants.PN_PASSWORD, "password1");
+ request.getFormData().put(FormConstants.PN_PASSWORD, "password1");
+
+ Resource actionResource = new MockResource("/content",
+ Collections.singletonMap(RequestPasswordResetAction.PN_RESETTIMEOUT, 1000000), null);
+
+ FormActionResult result = action.handleForm(actionResource, request);
+ assertTrue(result.isSucceeded());
+ }
+
+ @Test
+ public void testMissingUser() throws FormException, RepositoryException {
+
+ UpdateProfileAction action = new UpdateProfileAction();
+
+ Mockito.when(resolver.getUserID()).thenReturn("invalid@email.com");
+
+ FormRequest request = new FormRequestImpl(new MockSlingHttpServletRequest(resolver), null, null);
+ request.getFormData().put(FormConstants.PN_PASSWORD, "password1");
+
+ Resource actionResource = new MockResource("/content",
+ Collections.singletonMap(RequestPasswordResetAction.PN_RESETTIMEOUT, 1000000), null);
+
+ FormActionResult result = action.handleForm(actionResource, request);
+ assertFalse(result.isSucceeded());
+ }
+
+ @Test
+ public void testError() throws FormException, RepositoryException, PersistenceException {
+
+ UpdateProfileAction action = new UpdateProfileAction();
+
+ Mockito.when(resolver.getUserID()).thenReturn("valid@email.com");
+ Mockito.doThrow(new PersistenceException("I'm a sad panda")).when(resolver).commit();
+
+ FormRequest request = new FormRequestImpl(new MockSlingHttpServletRequest(resolver), null, null);
+ request.getFormData().put(FormConstants.PN_PASSWORD, "password1");
+
+ Resource actionResource = new MockResource("/content",
+ Collections.singletonMap(RequestPasswordResetAction.PN_RESETTIMEOUT, 1000000), null);
+
+ FormActionResult result = action.handleForm(actionResource, request);
+ assertFalse(result.isSucceeded());
+ }
+
+ @Test
+ public void testHandles() throws FormException {
+ UpdateProfileAction action = new UpdateProfileAction();
+ Resource validResource = Mockito.mock(Resource.class);
+ Mockito.when(validResource.getResourceType()).thenReturn(UpdateProfileAction.RESOURCE_TYPE);
+ assertTrue(action.handles(validResource));
+
+ Resource inValidResource = Mockito.mock(Resource.class);
+ Mockito.when(inValidResource.getResourceType()).thenReturn("something/else");
+ assertFalse(action.handles(inValidResource));
+ }
+
+}
diff --git a/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/actions/UpdateUserGeneratedContentActionTest.java b/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/actions/UpdateUserGeneratedContentActionTest.java
new file mode 100644
index 0000000..e2d59fb
--- /dev/null
+++ b/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/actions/UpdateUserGeneratedContentActionTest.java
@@ -0,0 +1,172 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.sling.cms.reference.forms.impl.actions;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.Collections;
+import java.util.HashMap;
+
+import org.apache.jackrabbit.JcrConstants;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.LoginException;
+import org.apache.sling.api.resource.ModifiableValueMap;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceResolverFactory;
+import org.apache.sling.api.resource.ValueMap;
+import org.apache.sling.api.wrappers.ModifiableValueMapDecorator;
+import org.apache.sling.api.wrappers.ValueMapDecorator;
+import org.apache.sling.cms.CMSConstants;
+import org.apache.sling.cms.reference.forms.FormException;
+import org.apache.sling.cms.reference.forms.FormRequest;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+public class UpdateUserGeneratedContentActionTest {
+
+ @Test
+ public void testHandles() {
+
+ UpdateUserGeneratedContentAction ur = new UpdateUserGeneratedContentAction(null);
+
+ Resource validResource = Mockito.mock(Resource.class);
+ Mockito.when(validResource.getResourceType()).thenReturn("reference/components/forms/actions/updateugc");
+ assertTrue(ur.handles(validResource));
+
+ Resource invalidResource = Mockito.mock(Resource.class);
+ Mockito.when(invalidResource.getResourceType())
+ .thenReturn("reference/components/forms/actions/someotheraction");
+ assertFalse(ur.handles(invalidResource));
+ }
+
+ @Test
+ public void testInvalidServiceUser() throws FormException, LoginException {
+
+ LoginException le = new LoginException();
+ ResourceResolverFactory factory = Mockito.mock(ResourceResolverFactory.class);
+ Mockito.when(factory.getServiceResourceResolver(Mockito.anyMap())).thenThrow(le);
+
+ UpdateUserGeneratedContentAction ur = new UpdateUserGeneratedContentAction(factory);
+
+ ValueMap actionData = new ModifiableValueMapDecorator(new HashMap<String, Object>());
+ actionData.put("allowedProperties", new String[] { "name1", "name3", "name4" });
+ actionData.put("path", "/content/test");
+ actionData.put("serviceUser", "bob");
+
+ Resource actionResource = Mockito.mock(Resource.class);
+ Mockito.when(actionResource.getValueMap()).thenReturn(actionData);
+
+ FormRequest formRequest = Mockito.mock(FormRequest.class);
+ ValueMap formData = new ValueMapDecorator(new HashMap<>());
+ formData.put("name2", "value2");
+ formData.put("name3", "value3");
+ Mockito.when(formRequest.getFormData()).thenReturn(formData);
+
+ try {
+ ur.handleForm(actionResource, formRequest);
+ fail();
+ } catch (FormException fe) {
+ assertEquals(le, fe.getCause());
+ }
+ }
+
+ @Test
+ public void testHandleForm() throws FormException, LoginException {
+
+ ModifiableValueMap contentData = new ModifiableValueMapDecorator(new HashMap<String, Object>());
+ contentData.put(JcrConstants.JCR_PRIMARYTYPE, JcrConstants.NT_UNSTRUCTURED);
+ Resource contentResource = Mockito.mock(Resource.class);
+ Mockito.when(contentResource.getValueMap()).thenReturn(contentData);
+ Mockito.when(contentResource.adaptTo(Mockito.any())).thenReturn(contentData);
+
+ Resource ugcResource = Mockito.mock(Resource.class);
+ Mockito.when(ugcResource.getResourceType()).thenReturn(CMSConstants.NT_UGC);
+ Mockito.when(ugcResource.getValueMap())
+ .thenReturn(new ValueMapDecorator(Collections.singletonMap("user", "auser")));
+ Mockito.when(contentResource.getParent()).thenReturn(ugcResource);
+
+ ResourceResolver resolver = Mockito.mock(ResourceResolver.class);
+ Mockito.when(resolver.getUserID()).thenReturn("auser");
+ SlingHttpServletRequest request = Mockito.mock(SlingHttpServletRequest.class);
+ Mockito.when(request.getResourceResolver()).thenReturn(resolver);
+ Mockito.when(resolver.getResource("/content/test")).thenReturn(contentResource);
+
+ ResourceResolverFactory factory = Mockito.mock(ResourceResolverFactory.class);
+ Mockito.when(factory.getServiceResourceResolver(Mockito.anyMap())).thenReturn(resolver);
+
+ UpdateUserGeneratedContentAction ur = new UpdateUserGeneratedContentAction(factory);
+
+ ValueMap actionData = new ModifiableValueMapDecorator(new HashMap<String, Object>());
+ actionData.put("allowedProperties", new String[] { "name1", "name3", "name4" });
+ actionData.put("path", "/content/test");
+ actionData.put("serviceUser", "bob");
+
+ Resource actionResource = Mockito.mock(Resource.class);
+ Mockito.when(actionResource.getValueMap()).thenReturn(actionData);
+
+ FormRequest formRequest = Mockito.mock(FormRequest.class);
+ Mockito.when(formRequest.getOriginalRequest()).thenReturn(request);
+
+ ValueMap formData = new ValueMapDecorator(new HashMap<>());
+ formData.put("name2", "value2");
+ formData.put("name3", "value3");
+ Mockito.when(formRequest.getFormData()).thenReturn(formData);
+
+ ur.handleForm(actionResource, formRequest);
+
+ assertEquals(3, contentResource.getValueMap().keySet().size());
+ assertEquals("value3", contentResource.getValueMap().get("name3"));
+
+ }
+
+ @Test
+ public void testNoParent() throws FormException, LoginException {
+
+ Resource contentResource = Mockito.mock(Resource.class);
+
+ ResourceResolver resolver = Mockito.mock(ResourceResolver.class);
+ Mockito.when(resolver.getResource("/etc/usergenerated/test")).thenReturn(contentResource);
+
+ ResourceResolverFactory factory = Mockito.mock(ResourceResolverFactory.class);
+ Mockito.when(factory.getServiceResourceResolver(Mockito.anyMap())).thenReturn(resolver);
+
+ UpdateUserGeneratedContentAction ur = new UpdateUserGeneratedContentAction(factory);
+
+ ValueMap actionData = new ModifiableValueMapDecorator(new HashMap<String, Object>());
+ actionData.put("path", "/etc/usergenerated/test");
+
+ Resource actionResource = Mockito.mock(Resource.class);
+ Mockito.when(actionResource.getValueMap()).thenReturn(actionData);
+
+ FormRequest formRequest = Mockito.mock(FormRequest.class);
+ ValueMap formData = new ValueMapDecorator(new HashMap<>());
+ formData.put("name2", "value2");
+ formData.put("name3", "value3");
+ Mockito.when(formRequest.getFormData()).thenReturn(formData);
+
+ try {
+ ur.handleForm(actionResource, formRequest);
+ fail();
+ } catch (FormException fe) {
+ assertEquals("Failed to find UGC Parent", fe.getMessage());
+ }
+ }
+}
diff --git a/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/actions/UserGeneratedContentActionTest.java b/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/actions/UserGeneratedContentActionTest.java
new file mode 100644
index 0000000..065d19c
--- /dev/null
+++ b/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/actions/UserGeneratedContentActionTest.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.sling.cms.reference.forms.impl.actions;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.HashMap;
+
+import org.apache.sling.api.resource.PersistenceException;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ValueMap;
+import org.apache.sling.api.wrappers.ModifiableValueMapDecorator;
+import org.apache.sling.api.wrappers.ValueMapDecorator;
+import org.apache.sling.cms.NameFilter;
+import org.apache.sling.cms.reference.forms.FormException;
+import org.apache.sling.cms.reference.forms.FormRequest;
+import org.apache.sling.cms.usergenerated.UserGeneratedContentService;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+public class UserGeneratedContentActionTest {
+
+ @Test
+ public void testHandles() {
+
+ NameFilter filter = Mockito.mock(NameFilter.class);
+ UserGeneratedContentService ugcService = Mockito.mock(UserGeneratedContentService.class);
+
+ UserGeneratedContentAction ur = new UserGeneratedContentAction(filter, ugcService);
+
+ Resource validResource = Mockito.mock(Resource.class);
+ Mockito.when(validResource.getResourceType())
+ .thenReturn("reference/components/forms/actions/usergeneratedcontent");
+ assertTrue(ur.handles(validResource));
+
+ Resource invalidResource = Mockito.mock(Resource.class);
+ Mockito.when(invalidResource.getResourceType())
+ .thenReturn("reference/components/forms/actions/someotheraction");
+ assertFalse(ur.handles(invalidResource));
+ }
+
+ @Test
+ public void testActionResolver() throws FormException, PersistenceException {
+
+ NameFilter filter = Mockito.mock(NameFilter.class);
+ ResourceResolver resolver = Mockito.mock(ResourceResolver.class);
+
+ Resource container = Mockito.mock(Resource.class);
+ Mockito.when(container.getResourceResolver()).thenReturn(resolver);
+
+ UserGeneratedContentService ugcService = Mockito.mock(UserGeneratedContentService.class);
+ Mockito.when(ugcService.createUGCContainer(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any()))
+ .thenReturn(container);
+
+ UserGeneratedContentAction ur = new UserGeneratedContentAction(filter, ugcService);
+
+ ValueMap actionData = new ModifiableValueMapDecorator(new HashMap<String, Object>());
+ actionData.put("additionalProperties", new String[] { "name1=value1", "name3=vale2", "name4" });
+ actionData.put("path", "/content/test");
+
+ Resource actionResource = Mockito.mock(Resource.class);
+ Mockito.when(actionResource.getValueMap()).thenReturn(actionData);
+ Mockito.when(actionResource.getResourceResolver()).thenReturn(resolver);
+
+ FormRequest formRequest = Mockito.mock(FormRequest.class);
+ ValueMap formData = new ValueMapDecorator(new HashMap<>());
+ formData.put("name2", "value2");
+ formData.put("name3", "value3");
+ Mockito.when(formRequest.getFormData()).thenReturn(formData);
+ ur.handleForm(actionResource, formRequest);
+ assertTrue(true);
+
+ }
+}
diff --git a/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/fields/SelectionHandlerTest.java b/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/fields/HoneypotHandlerTest.java
similarity index 56%
copy from reference/src/test/java/org/apache/sling/cms/reference/forms/impl/fields/SelectionHandlerTest.java
copy to reference/src/test/java/org/apache/sling/cms/reference/forms/impl/fields/HoneypotHandlerTest.java
index 33baf32..260b315 100644
--- a/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/fields/SelectionHandlerTest.java
+++ b/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/fields/HoneypotHandlerTest.java
@@ -16,16 +16,14 @@
*/
package org.apache.sling.cms.reference.forms.impl.fields;
-import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
-import com.google.common.collect.ImmutableMap;
-
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.cms.reference.forms.FormException;
@@ -35,83 +33,64 @@ import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
-public class SelectionHandlerTest {
+public class HoneypotHandlerTest {
@Rule
public final SlingContext context = new SlingContext();
- private SelectionHandler handler;
+ private HoneypotHandler handler;
private ResourceResolver resolver;
@Before
public void init() {
SlingContextHelper.initContext(context);
- context.request().setResource(context.resourceResolver().getResource("/form/jcr:content/container/form"));
resolver = context.resourceResolver();
- handler = new SelectionHandler();
+ handler = new HoneypotHandler();
}
@Test
public void testHandles() {
- assertTrue(handler
- .handles(resolver.getResource("/form/jcr:content/container/form/fields/fieldset/fields/singleselect")));
-
assertFalse(handler.handles(resolver.getResource("/form/jcr:content/container/form/fields/fieldset/fields")));
assertTrue(handler
- .handles(resolver.getResource("/form/jcr:content/container/form/fields/fieldset/fields/multiselect")));
+ .handles(resolver.getResource("/form/jcr:content/container/form/fields/fieldset/fields/honeypot")));
}
@Test
- public void testSingleSelect() throws FormException {
+ public void testValid() throws FormException {
ResourceResolver resolver = context.resourceResolver();
- context.request()
- .setParameterMap(ImmutableMap.<String, Object>builder().put("singleselect", "Hello World").build());
+ context.request().setParameterMap(Collections.singletonMap("someothervalue", "something else"));
Map<String, Object> formData = new HashMap<>();
Resource fieldResource = resolver
- .getResource("/form/jcr:content/container/form/fields/fieldset/fields/singleselect");
+ .getResource("/form/jcr:content/container/form/fields/fieldset/fields/honeypot");
handler.handleField(context.request(), fieldResource, formData);
- assertEquals("Hello World", formData.get("singleselect"));
+ assertTrue(formData.isEmpty());
}
@Test
- public void testMissingSingleSelect() throws FormException {
+ public void testInValid() throws FormException {
ResourceResolver resolver = context.resourceResolver();
- context.request().getParameterMap().put("singleselect", new String[] {});
+ context.request().setParameterMap(Collections.singletonMap("honeypot", "a value"));
Map<String, Object> formData = new HashMap<>();
Resource fieldResource = resolver
- .getResource("/form/jcr:content/container/form/fields/fieldset/fields/singleselect");
+ .getResource("/form/jcr:content/container/form/fields/fieldset/fields/honeypot");
+
try {
+
handler.handleField(context.request(), fieldResource, formData);
fail();
- } catch (Exception e) {
+ } catch (FormException e) {
+ // expected
}
- assertFalse(formData.containsKey("singleselect"));
- }
- @Test
- public void testMultipleSelect() throws FormException {
- ResourceResolver resolver = context.resourceResolver();
-
- context.request().setParameterMap(ImmutableMap.<String, Object>builder().put("multiselect", "").build());
-
- Map<String, Object> formData = new HashMap<>();
- Resource fieldResource = resolver
- .getResource("/form/jcr:content/container/form/fields/fieldset/fields/multiselect");
- handler.handleField(context.request(), fieldResource, formData);
- assertFalse(formData.containsKey("multiselect"));
-
- context.request().setParameterMap(ImmutableMap.<String, Object>builder()
- .put("multiselect", new String[] { "Thing 1", "Thing 2" }).build());
- handler.handleField(context.request(), fieldResource, formData);
- assertTrue(formData.containsKey("multiselect"));
+ assertTrue(formData.isEmpty());
}
}
diff --git a/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/fields/SelectionHandlerTest.java b/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/fields/SelectionHandlerTest.java
index 33baf32..7f6eaa3 100644
--- a/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/fields/SelectionHandlerTest.java
+++ b/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/fields/SelectionHandlerTest.java
@@ -21,6 +21,7 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import java.lang.annotation.Annotation;
import java.util.HashMap;
import java.util.Map;
@@ -30,6 +31,7 @@ import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.cms.reference.forms.FormException;
import org.apache.sling.cms.reference.forms.impl.SlingContextHelper;
+import org.apache.sling.cms.reference.forms.impl.fields.SelectionHandler.Config;
import org.apache.sling.testing.mock.sling.junit.SlingContext;
import org.junit.Before;
import org.junit.Rule;
@@ -48,7 +50,20 @@ public class SelectionHandlerTest {
context.request().setResource(context.resourceResolver().getResource("/form/jcr:content/container/form"));
resolver = context.resourceResolver();
- handler = new SelectionHandler();
+ handler = new SelectionHandler(new Config() {
+
+ @Override
+ public Class<? extends Annotation> annotationType() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String[] supportedTypes() {
+ return new String[] { SelectionHandler.DEFAULT_RESOURCE_TYPE };
+ }
+
+ });
}
@Test
diff --git a/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/fields/TextareaHandlerTest.java b/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/fields/TextareaHandlerTest.java
index 3fb6f73..6b64af5 100644
--- a/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/fields/TextareaHandlerTest.java
+++ b/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/fields/TextareaHandlerTest.java
@@ -21,20 +21,22 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import java.lang.annotation.Annotation;
import java.util.HashMap;
import java.util.Map;
+import com.google.common.collect.ImmutableMap;
+
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.cms.reference.forms.FormException;
import org.apache.sling.cms.reference.forms.impl.SlingContextHelper;
+import org.apache.sling.cms.reference.forms.impl.fields.TextareaHandler.Config;
import org.apache.sling.testing.mock.sling.junit.SlingContext;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
-import com.google.common.collect.ImmutableMap;
-
public class TextareaHandlerTest {
@Rule
@@ -48,7 +50,19 @@ public class TextareaHandlerTest {
context.request().setResource(context.resourceResolver().getResource("/form/jcr:content/container/form"));
resolver = context.resourceResolver();
- handler = new TextareaHandler();
+ handler = new TextareaHandler(new Config() {
+
+ @Override
+ public Class<? extends Annotation> annotationType() {
+ return null;
+ }
+
+ @Override
+ public String[] supportedTypes() {
+ return new String[] { TextareaHandler.DEFAULT_RESOURCE_TYPE };
+ }
+
+ });
}
@Test
diff --git a/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/fields/TextfieldHandlerTest.java b/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/fields/TextfieldHandlerTest.java
index 3f1afcd..9d85b95 100644
--- a/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/fields/TextfieldHandlerTest.java
+++ b/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/fields/TextfieldHandlerTest.java
@@ -18,10 +18,14 @@ package org.apache.sling.cms.reference.forms.impl.fields;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import java.io.ByteArrayInputStream;
+import java.lang.annotation.Annotation;
import java.util.Calendar;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@@ -31,6 +35,7 @@ import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.cms.reference.forms.FormException;
import org.apache.sling.cms.reference.forms.impl.SlingContextHelper;
+import org.apache.sling.cms.reference.forms.impl.fields.TextfieldHandler.Config;
import org.apache.sling.testing.mock.sling.junit.SlingContext;
import org.junit.Before;
import org.junit.Rule;
@@ -49,7 +54,19 @@ public class TextfieldHandlerTest {
context.request().setResource(context.resourceResolver().getResource("/form/jcr:content/container/form"));
resolver = context.resourceResolver();
- handler = new TextfieldHandler();
+ handler = new TextfieldHandler(new Config() {
+
+ @Override
+ public Class<? extends Annotation> annotationType() {
+ return null;
+ }
+
+ @Override
+ public String[] supportedTypes() {
+ return new String[] { TextfieldHandler.DEFAULT_RESOURCE_TYPE };
+ }
+
+ });
}
@Test
@@ -71,12 +88,21 @@ public class TextfieldHandlerTest {
handler.handleField(context.request(), fieldResource, formData);
fail();
} catch (FormException pe) {
+ // expected
+ }
+
+ context.request()
+ .setParameterMap(ImmutableMap.<String, Object>builder().put("invaliddate", "2019-99-99").build());
+
+ Resource invalidType = resolver.getResource("/form/jcr:content/container/invalidtype");
+ try {
+ handler.handleField(context.request(), invalidType, formData);
+ fail();
+ } catch (FormException pe) {
}
Resource invalidDate = resolver.getResource("/form/jcr:content/container/invaliddate");
- context.request()
- .setParameterMap(ImmutableMap.<String, Object>builder().put("invalidate", "2019-02-12").build());
try {
handler.handleField(context.request(), invalidDate, formData);
fail();
@@ -103,9 +129,30 @@ public class TextfieldHandlerTest {
handler.handleField(context.request(), fieldResource, formData);
fail();
} catch (FormException pe) {
+ // expected
+ }
+ fieldResource = resolver
+ .getResource("/form/jcr:content/container/form/fields/fieldset/fields/unvalidateddouble");
+ try {
+ handler.handleField(context.request(), fieldResource, formData);
+ fail();
+ } catch (FormException pe) {
+ // expected
}
+ }
+
+ @Test
+ public void testFile() throws FormException {
+ ResourceResolver resolver = context.resourceResolver();
+
+ context.request().setParameterMap(Collections.singletonMap("file", new ByteArrayInputStream(new byte[0])));
+ Map<String, Object> formData = new HashMap<>();
+ Resource fieldResource = resolver.getResource("/form/jcr:content/container/form/fields/fieldset/fields/file");
+ handler.handleField(context.request(), fieldResource, formData);
+ assertNotNull(formData.get("file"));
+ assertEquals(ByteArrayInputStream.class, formData.get("file").getClass());
}
@Test
@@ -137,9 +184,17 @@ public class TextfieldHandlerTest {
handler.handleField(context.request(), fieldResource, formData);
fail();
} catch (FormException pe) {
-
+ // expected
}
+ fieldResource = resolver
+ .getResource("/form/jcr:content/container/form/fields/fieldset/fields/unvalidatedinteger");
+ try {
+ handler.handleField(context.request(), fieldResource, formData);
+ fail();
+ } catch (FormException pe) {
+
+ }
}
@Test
diff --git a/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/providers/RequestParametersValueProviderTest.java b/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/providers/RequestParametersValueProviderTest.java
new file mode 100644
index 0000000..eeb771c
--- /dev/null
+++ b/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/providers/RequestParametersValueProviderTest.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.sling.cms.reference.forms.impl.providers;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.servlethelpers.MockSlingHttpServletRequest;
+import org.apache.sling.testing.resourceresolver.MockResource;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+public class RequestParametersValueProviderTest {
+
+ @Test
+ public void testAccepts() {
+ RequestParametersValueProvider rpp = new RequestParametersValueProvider();
+
+ Resource validResource = Mockito.mock(Resource.class);
+ Mockito.when(validResource.getResourceType())
+ .thenReturn("reference/components/forms/providers/requestparameters");
+ assertTrue(rpp.handles(validResource));
+
+ Resource invalidResource = Mockito.mock(Resource.class);
+ Mockito.when(invalidResource.getResourceType())
+ .thenReturn("reference/components/forms/providers/someotherprovider");
+ assertFalse(rpp.handles(invalidResource));
+ }
+
+ @Test
+ public void testRequestParameters() {
+ RequestParametersValueProvider rpp = new RequestParametersValueProvider();
+
+ MockResource mockResource = new MockResource("/apps/rpv",
+ Collections.singletonMap("allowedParameters", new String[] { "name1", "name3", "name4" }), null);
+
+ MockSlingHttpServletRequest mockRequest = new MockSlingHttpServletRequest(null);
+ mockRequest.addRequestParameter("name1", "value1");
+ mockRequest.addRequestParameter("name2", "value2");
+ mockRequest.addRequestParameter("name4", "value1");
+ mockRequest.addRequestParameter("name4", "value2");
+
+ Map<String, Object> formData = new HashMap<>();
+ rpp.loadValues(mockRequest, mockResource, formData);
+
+ assertTrue(formData.containsKey("name1"));
+ assertEquals("value1", formData.get("name1"));
+
+ assertFalse(formData.containsKey("name2"));
+ assertFalse(formData.containsKey("name3"));
+
+ assertTrue(formData.containsKey("name1"));
+ assertTrue(Arrays.equals(new String[] { "value1", "value2" }, (String[]) formData.get("name4")));
+ }
+}
diff --git a/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/providers/SuffixResourceFormValueProviderTest.java b/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/providers/SuffixResourceFormValueProviderTest.java
new file mode 100644
index 0000000..ab61a41
--- /dev/null
+++ b/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/providers/SuffixResourceFormValueProviderTest.java
@@ -0,0 +1,156 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.sling.cms.reference.forms.impl.providers;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.request.RequestPathInfo;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.testing.resourceresolver.MockResource;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+public class SuffixResourceFormValueProviderTest {
+
+ public Resource providerResource;
+
+ @Before
+ public void init() {
+ Map<String, Object> properties = new HashMap<>();
+ properties.put("basePath", "/content/apath");
+ properties.put("allowedProperties", new String[] { "name1", "name3", "name4" });
+
+ providerResource = new MockResource("/apps/rpv", properties, null);
+
+ }
+
+ @Test
+ public void testAccepts() {
+ SuffixResourceFormValueProvider sr = new SuffixResourceFormValueProvider();
+
+ Resource validResource = Mockito.mock(Resource.class);
+ Mockito.when(validResource.getResourceType()).thenReturn("reference/components/forms/providers/suffixresource");
+ assertTrue(sr.handles(validResource));
+
+ Resource invalidResource = Mockito.mock(Resource.class);
+ Mockito.when(invalidResource.getResourceType())
+ .thenReturn("reference/components/forms/providers/someotherprovider");
+ assertFalse(sr.handles(invalidResource));
+ }
+
+ @Test
+ public void testNoSuffix() {
+ SuffixResourceFormValueProvider sr = new SuffixResourceFormValueProvider();
+
+ Map<String, Object> formData = new HashMap<>();
+
+ SlingHttpServletRequest mockRequest = Mockito.mock(SlingHttpServletRequest.class);
+ RequestPathInfo rpi = Mockito.mock(RequestPathInfo.class);
+ Mockito.when(mockRequest.getRequestPathInfo()).thenReturn(rpi);
+ sr.loadValues(mockRequest, providerResource, formData);
+
+ assertEquals(0, formData.entrySet().size());
+ Mockito.verify(rpi).getSuffixResource();
+
+ }
+
+ @Test
+ public void testValidSuffix() {
+ SuffixResourceFormValueProvider sr = new SuffixResourceFormValueProvider();
+
+ Map<String, Object> formData = new HashMap<>();
+
+ Map<String, Object> properties = new HashMap<>();
+ properties.put("name1", "value1");
+ properties.put("name2", "value2");
+
+ Resource suffixResource = new MockResource("/content/apath/apage", properties, null);
+
+ SlingHttpServletRequest mockRequest = Mockito.mock(SlingHttpServletRequest.class);
+ RequestPathInfo rpi = Mockito.mock(RequestPathInfo.class);
+ Mockito.when(rpi.getSuffixResource()).thenReturn(suffixResource);
+ Mockito.when(mockRequest.getRequestPathInfo()).thenReturn(rpi);
+ sr.loadValues(mockRequest, providerResource, formData);
+
+ assertEquals(2, formData.entrySet().size());
+ assertEquals("value1", formData.get("name1"));
+ assertEquals("/content/apath/apage", formData.get("suffixResource"));
+ Mockito.verify(rpi).getSuffixResource();
+
+ }
+
+ @Test
+ public void testAllAllowed() {
+ SuffixResourceFormValueProvider sr = new SuffixResourceFormValueProvider();
+
+ Map<String, Object> formData = new HashMap<>();
+
+ Map<String, Object> properties = new HashMap<>();
+ properties.put("name1", "value1");
+ properties.put("name2", "value2");
+
+ Map<String, Object> providerProperties = new HashMap<>();
+ providerProperties.put("basePath", "/content/apath");
+
+ Resource pr2 = new MockResource("/apps/rpv", providerProperties, null);
+
+ Resource suffixResource = new MockResource("/content/apath/apage", properties, null);
+
+ SlingHttpServletRequest mockRequest = Mockito.mock(SlingHttpServletRequest.class);
+ RequestPathInfo rpi = Mockito.mock(RequestPathInfo.class);
+ Mockito.when(rpi.getSuffixResource()).thenReturn(suffixResource);
+ Mockito.when(mockRequest.getRequestPathInfo()).thenReturn(rpi);
+ sr.loadValues(mockRequest, pr2, formData);
+
+ assertEquals(3, formData.entrySet().size());
+ assertEquals("value1", formData.get("name1"));
+ assertEquals("value2", formData.get("name2"));
+ assertEquals("/content/apath/apage", formData.get("suffixResource"));
+ Mockito.verify(rpi).getSuffixResource();
+
+ }
+
+ @Test
+ public void testInvalidSuffix() {
+ SuffixResourceFormValueProvider sr = new SuffixResourceFormValueProvider();
+
+ Map<String, Object> formData = new HashMap<>();
+
+ Map<String, Object> properties = new HashMap<>();
+ properties.put("name1", "value1");
+ properties.put("name2", "value2");
+
+ Resource suffixResource = new MockResource("/content/anotherpath", properties, null);
+
+ SlingHttpServletRequest mockRequest = Mockito.mock(SlingHttpServletRequest.class);
+ RequestPathInfo rpi = Mockito.mock(RequestPathInfo.class);
+ Mockito.when(rpi.getSuffixResource()).thenReturn(suffixResource);
+ Mockito.when(mockRequest.getRequestPathInfo()).thenReturn(rpi);
+ sr.loadValues(mockRequest, providerResource, formData);
+
+ assertEquals(0, formData.entrySet().size());
+ Mockito.verify(rpi).getSuffixResource();
+
+ }
+}
diff --git a/reference/src/test/resources/form.json b/reference/src/test/resources/form.json
index dbe3595..2021c1a 100644
--- a/reference/src/test/resources/form.json
+++ b/reference/src/test/resources/form.json
@@ -8,11 +8,18 @@
"published": true,
"container": {
"jcr:primaryType": "nt:unstructured",
+ "invalidtype": {
+ "jcr:primaryType": "nt:unstructured",
+ "required": true,
+ "name": "invalidtype",
+ "label": "Daty",
+ "saveAs": "date",
+ "sling:resourceType": "reference/components/forms/fields/textfield"
+ },
"invaliddate": {
"jcr:primaryType": "nt:unstructured",
"required": true,
- "name": "datefield",
- "type": "text",
+ "name": "invaliddate",
"label": "Daty",
"saveAs": "date",
"sling:resourceType": "reference/components/forms/fields/textfield"
@@ -101,6 +108,22 @@
"saveAs": "double",
"sling:resourceType": "reference/components/forms/fields/textfield"
},
+ "unvalidateddouble": {
+ "jcr:primaryType": "nt:unstructured",
+ "required": true,
+ "name": "double",
+ "type": "text",
+ "label": "Daty",
+ "saveAs": "double",
+ "sling:resourceType": "reference/components/forms/fields/textfield"
+ },
+ "file": {
+ "jcr:primaryType": "nt:unstructured",
+ "name": "file",
+ "type": "file",
+ "label": "File",
+ "sling:resourceType": "reference/components/forms/fields/textfield"
+ },
"integer": {
"jcr:primaryType": "nt:unstructured",
"required": true,
@@ -110,6 +133,15 @@
"saveAs": "integer",
"sling:resourceType": "reference/components/forms/fields/textfield"
},
+ "unvalidatedinteger": {
+ "jcr:primaryType": "nt:unstructured",
+ "required": true,
+ "name": "integer",
+ "type": "text",
+ "label": "Inty",
+ "saveAs": "integer",
+ "sling:resourceType": "reference/components/forms/fields/textfield"
+ },
"datefield": {
"jcr:primaryType": "nt:unstructured",
"required": true,
@@ -130,6 +162,11 @@
"multiple": false,
"sling:resourceType": "reference/components/forms/fields/selection",
"display": "select"
+ },
+ "honeypot": {
+ "jcr:primaryType": "nt:unstructured",
+ "name": "honeypot",
+ "sling:resourceType": "reference/components/forms/fields/honeypot"
}
}
}
diff --git a/transformer/src/test/resources/thumbnail.png b/transformer/src/test/resources/thumbnail.png
index 62cf067..f38c3a4 100644
Binary files a/transformer/src/test/resources/thumbnail.png and b/transformer/src/test/resources/thumbnail.png differ