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/15 15:07:29 UTC
[sling-org-apache-sling-app-cms] 01/01: Working on enhanced
capabilities for the reference forms
This is an automated email from the ASF dual-hosted git repository.
dklco pushed a commit to branch forms-enhancements
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-app-cms.git
commit c6e02d9be734f5f2433f6e69e85b885333d5836d
Author: Dan Klco <dk...@apache.org>
AuthorDate: Fri Jan 15 10:07:11 2021 -0500
Working on enhanced capabilities for the reference forms
---
reference/pom.xml | 20 +++
.../sling/cms/reference/forms/FormConstants.java | 37 +++++
.../sling/cms/reference/forms/FormUtils.java | 28 ++++
.../cms/reference/forms/impl/FormHandler.java | 15 +-
.../forms/impl/actions/CreateUserAction.java | 163 +++++++++++++++++++
.../impl/actions/RequestPasswordResetAction.java | 115 ++++++++++++++
.../forms/impl/actions/ResetPasswordAction.java | 126 +++++++++++++++
.../forms/impl/actions/SendEmailAction.java | 31 +++-
.../forms/impl/actions/UpdateProfileAction.java | 83 +++++-----
.../forms/impl/actions/UpdateResourceAction.java | 113 +++++++++++++
.../providers/RequestParametersValueProvider.java | 56 +++++++
.../providers/SuffixResourceFormValueProvider.java | 63 ++++++++
.../providers/UserProfileFormValueProvider.java | 3 +-
.../main/resources/OSGI-INF/l10n/bundle.properties | 24 ++-
.../components/forms/actions/createuser.json | 5 +
.../forms/actions/createuser/createuser.jsp | 32 ++++
.../components/forms/actions/createuser/edit.json | 47 ++++++
.../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/updateresource.json | 5 +
.../forms/actions/updateresource/edit.json | 32 ++++
.../actions/updateresource/updateresource.jsp | 30 ++++
.../components/forms/fields/textarea/textarea.jsp | 4 +-
.../forms/fields/textfield/textfield.jsp | 2 +-
.../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/impl/FormHandlerTest.java | 15 +-
.../reference/forms/impl/FormRequestImplTest.java | 3 +-
.../actions/RequestPasswordResetActionTest.java | 146 +++++++++++++++++
.../impl/actions/ResetPasswordActionTest.java | 175 +++++++++++++++++++++
.../forms/impl/actions/SendEmailActionTest.java | 18 ++-
.../impl/actions/UpdateResourceActionTest.java | 162 +++++++++++++++++++
.../forms/impl/fields/HoneypotHandlerTest.java | 99 ++++++++++++
.../forms/impl/fields/TextfieldHandlerTest.java | 47 +++++-
.../RequestParametersValueProviderTest.java | 76 +++++++++
.../SuffixResourceFormValueProviderTest.java | 156 ++++++++++++++++++
reference/src/test/resources/form.json | 42 ++++-
47 files changed, 2183 insertions(+), 72 deletions(-)
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/main/java/org/apache/sling/cms/reference/forms/FormConstants.java b/reference/src/main/java/org/apache/sling/cms/reference/forms/FormConstants.java
new file mode 100644
index 0000000..182dcc9
--- /dev/null
+++ b/reference/src/main/java/org/apache/sling/cms/reference/forms/FormConstants.java
@@ -0,0 +1,37 @@
+/*
+ * 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;
+
+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 = "passwordw";
+}
diff --git a/reference/src/main/java/org/apache/sling/cms/reference/forms/FormUtils.java b/reference/src/main/java/org/apache/sling/cms/reference/forms/FormUtils.java
new file mode 100644
index 0000000..3e77430
--- /dev/null
+++ b/reference/src/main/java/org/apache/sling/cms/reference/forms/FormUtils.java
@@ -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.
+ */
+package org.apache.sling.cms.reference.forms;
+
+import java.util.stream.Stream;
+
+import org.apache.sling.api.resource.Resource;
+
+public class FormUtils {
+
+ 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..0b8de5b 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
@@ -36,6 +36,7 @@ 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;
@@ -86,11 +87,15 @@ public class FormHandler extends SlingAllMethodsServlet {
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;
+ 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());
}
}
}
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..83cfc4d
--- /dev/null
+++ b/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/actions/CreateUserAction.java
@@ -0,0 +1,163 @@
+/*
+ * 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.apache.sling.cms.reference.forms.FormUtils;
+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.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 = { FormAction.class })
+@Designate(ocd = CreateUserAction.Config.class)
+public class CreateUserAction implements FormAction {
+
+ private static final Logger log = LoggerFactory.getLogger(CreateUserAction.class);
+ public static final String DEFAULT_RESOURCE_TYPE = "reference/components/forms/actions/createuser";
+ public static final String PROFILE_PROPERTIES = "profileProperties";
+ public static final String GROUPS = "groups";
+
+ private final ResourceResolverFactory factory;
+ private final Config config;
+
+ @Activate
+ public CreateUserAction(@Reference ResourceResolverFactory factory, Config config) {
+ this.factory = factory;
+ this.config = config;
+ }
+
+ @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("username", String.class);
+ String password = request.getFormData().get(FormConstants.PN_PASSWORD, String.class);
+
+ String intermediatePath = properties.get("intermediatePath", 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(new PrincipalImpl(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(new PrincipalImpl(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 FormUtils.handles(config.supportedTypes(), actionResource);
+ }
+
+ @ObjectClassDefinition(name = "%cms.reference.createuser.name", description = "%cms.reference.createuser.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 };
+ }
+
+}
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..9ab6da6
--- /dev/null
+++ b/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/actions/RequestPasswordResetAction.java
@@ -0,0 +1,115 @@
+/*
+ * 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 java.util.stream.Stream;
+
+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.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 = { FormAction.class })
+@Designate(ocd = RequestPasswordResetAction.Config.class)
+public class RequestPasswordResetAction implements FormAction {
+
+ public static final String DEFAULT_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;
+ private Config config;
+
+ @Activate
+ public RequestPasswordResetAction(@Reference ResourceResolverFactory factory, Config config) {
+ this.factory = factory;
+ this.config = config;
+ }
+
+ @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 Stream.of(config.supportedTypes()).anyMatch(t -> t.equals(actionResource.getResourceType()));
+ }
+
+ @ObjectClassDefinition(name = "%cms.reference.requestpasswordreset.name", description = "%cms.reference.requestpasswordreset.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 };
+ }
+
+}
\ 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..da70b34
--- /dev/null
+++ b/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/actions/ResetPasswordAction.java
@@ -0,0 +1,126 @@
+/*
+ * 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.stream.Stream;
+
+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.apache.sling.cms.reference.forms.FormUtils;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+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 = { FormAction.class })
+@Designate(ocd = ResetPasswordAction.Config.class)
+public class ResetPasswordAction implements FormAction {
+
+ public static final String DEFAULT_RESOURCE_TYPE = "reference/components/forms/actions/resetpassword";
+ private static final Logger log = LoggerFactory.getLogger(ResetPasswordAction.class);
+ private ResourceResolverFactory factory;
+ private Config config;
+
+ @Activate
+ public ResetPasswordAction(@Reference ResourceResolverFactory factory, Config config) {
+ this.factory = factory;
+ this.config = config;
+ }
+
+ @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 FormUtils.handles(config.supportedTypes(), actionResource);
+ }
+
+ @ObjectClassDefinition(name = "%cms.reference.resetpassword.name", description = "%cms.reference.resetpassword.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 };
+ }
+
+}
\ 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..cc20283 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
@@ -16,6 +16,8 @@
*/
package org.apache.sling.cms.reference.forms.impl.actions;
+import java.util.stream.Stream;
+
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
@@ -28,14 +30,20 @@ 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.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 = { FormAction.class })
+@Designate(ocd = SendEmailAction.Config.class)
public class SendEmailAction implements FormAction {
+ public static final String DEFAULT_RESOURCE_TYPE = "reference/components/forms/actions/sendemail";
public static final String FROM = "from";
private static final Logger log = LoggerFactory.getLogger(SendEmailAction.class);
@@ -43,7 +51,14 @@ public class SendEmailAction implements FormAction {
public static final String SUBJECT = "subject";
public static final String TO = "to";
- private MailService mailService;
+ private final MailService mailService;
+ private Config config;
+
+ @Activate
+ public SendEmailAction(@Reference MailService mailService, Config config) {
+ this.mailService = mailService;
+ this.config = config;
+ }
@Override
public FormActionResult handleForm(final Resource actionResource, final FormRequest request) throws FormException {
@@ -71,13 +86,15 @@ public class SendEmailAction implements FormAction {
}
@Override
- public boolean handles(final Resource actionResource) {
- return "reference/components/forms/actions/sendemail".equals(actionResource.getResourceType());
+ public boolean handles(Resource actionResource) {
+ return Stream.of(config.supportedTypes()).anyMatch(t -> t.equals(actionResource.getResourceType()));
}
- @Reference
- public void setMailService(MailService mailService) {
- this.mailService = mailService;
- }
+ @ObjectClassDefinition(name = "%cms.reference.sendemail.name", description = "%cms.reference.sendemail.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 };
+ }
}
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..4aba5cc 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
@@ -34,6 +34,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;
@@ -51,51 +52,53 @@ public class UpdateProfileAction implements FormAction {
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();
+ if (session == null) {
+ log.warn("Failed to get session for {}", userId);
+ return FormActionResult.failure("Failed to get session for " + userId);
+ }
+ try {
+ 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);
- return FormActionResult.success("Profile Updated");
+ 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((Double) 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
diff --git a/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/actions/UpdateResourceAction.java b/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/actions/UpdateResourceAction.java
new file mode 100644
index 0000000..b6b4203
--- /dev/null
+++ b/reference/src/main/java/org/apache/sling/cms/reference/forms/impl/actions/UpdateResourceAction.java
@@ -0,0 +1,113 @@
+/*
+ * 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.Map;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.text.StringSubstitutor;
+import org.apache.jackrabbit.JcrConstants;
+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.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.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 UpdateResourceAction implements FormAction {
+
+ private static final Logger log = LoggerFactory.getLogger(UpdateResourceAction.class);
+
+ private ResourceResolverFactory factory;
+
+ @Activate
+ public UpdateResourceAction(@Reference ResourceResolverFactory factory) {
+ this.factory = factory;
+ }
+
+ @Override
+ public FormActionResult handleForm(Resource actionResource, FormRequest request) throws FormException {
+ log.trace("handleForm");
+
+ ValueMap properties = actionResource.getValueMap();
+
+ String[] allowedProperties = properties.get(FormConstants.PN_ALLOWED_PROPERTIES, String[].class);
+ ResourceResolver resolver = null;
+ try {
+ resolver = getResourceResolver(actionResource);
+ StringSubstitutor sub = new StringSubstitutor(request.getFormData());
+
+ String path = sub.replace(properties.get("path", String.class));
+ log.debug("Upserting resource at path: {}", path);
+ Resource resource = ResourceUtil.getOrCreateResource(resolver, path,
+ Collections.singletonMap(JcrConstants.JCR_PRIMARYTYPE, JcrConstants.NT_UNSTRUCTURED),
+ JcrConstants.NT_UNSTRUCTURED, false);
+
+ ModifiableValueMap mvm = resource.adaptTo(ModifiableValueMap.class);
+ Map<String, Object> formData = request.getFormData();
+ if (allowedProperties != null && allowedProperties.length > 0) {
+ Arrays.stream(allowedProperties).filter(formData::containsKey).forEach(p -> {
+ log.debug("Setting property {}", p);
+ mvm.put(p, formData.get(p));
+ });
+ } else {
+ 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);
+ } finally {
+ if (StringUtils.isNotBlank(properties.get(FormConstants.PN_SERVICE_USER, String.class)) && resolver != null) {
+ resolver.close();
+ }
+ }
+ }
+
+ private ResourceResolver getResourceResolver(Resource actionResource) throws LoginException {
+ String serviceUser = actionResource.getValueMap().get(FormConstants.PN_SERVICE_USER, String.class);
+ if (StringUtils.isNotBlank(serviceUser)) {
+ return factory.getServiceResourceResolver(
+ Collections.singletonMap(ResourceResolverFactory.SUBSERVICE, serviceUser));
+ } else {
+ return actionResource.getResourceResolver();
+ }
+
+ }
+
+ @Override
+ public boolean handles(Resource actionResource) {
+ return "reference/components/forms/actions/updateresource".equals(actionResource.getResourceType());
+ }
+
+}
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..5b263ae 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,21 @@ 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.createuser.name=Apache Sling CMS - Reference Create User
+cms.reference.createuser.description=Form action for creating a user
+
+cms.reference.requestpasswordreset.name=Apache Sling CMS - Reference Password Reset Request
+cms.reference.requestpasswordreset.description=Form action for initiating a password \
+reset request
+
+cms.reference.resetpassword.name=Apache Sling CMS - Reference Password Reset
+cms.reference.requestpasswordreset.description=Form action for resetting a user password
+
+cms.reference.sendemail.name=Apache Sling CMS - Reference Send Email
+cms.reference.requestpasswordreset.description=Form action for sending an email
\ 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/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/updateresource.json b/reference/src/main/resources/jcr_root/apps/reference/components/forms/actions/updateresource.json
new file mode 100644
index 0000000..2ec03ee
--- /dev/null
+++ b/reference/src/main/resources/jcr_root/apps/reference/components/forms/actions/updateresource.json
@@ -0,0 +1,5 @@
+{
+ "jcr:primaryType" : "sling:Component",
+ "jcr:title": "Update Resource",
+ "componentType": "Form Action"
+}
\ No newline at end of file
diff --git a/reference/src/main/resources/jcr_root/apps/reference/components/forms/actions/updateresource/edit.json b/reference/src/main/resources/jcr_root/apps/reference/components/forms/actions/updateresource/edit.json
new file mode 100644
index 0000000..a67511b
--- /dev/null
+++ b/reference/src/main/resources/jcr_root/apps/reference/components/forms/actions/updateresource/edit.json
@@ -0,0 +1,32 @@
+{
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/editor/slingform",
+ "button": "Save",
+ "fields": {
+ "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[]"
+ },
+ "path": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/editor/fields/path",
+ "label": "Path",
+ "name": "path",
+ "required": true
+ },
+ "serviceUser": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "sling-cms/components/editor/fields/text",
+ "label": "Service User",
+ "name": "serviceUser"
+ }
+ }
+}
\ No newline at end of file
diff --git a/reference/src/main/resources/jcr_root/apps/reference/components/forms/actions/updateresource/updateresource.jsp b/reference/src/main/resources/jcr_root/apps/reference/components/forms/actions/updateresource/updateresource.jsp
new file mode 100644
index 0000000..3389be7
--- /dev/null
+++ b/reference/src/main/resources/jcr_root/apps/reference/components/forms/actions/updateresource/updateresource.jsp
@@ -0,0 +1,30 @@
+<%-- /*
+ * 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 Resource</h3>
+ <dl>
+ <dt>Allowed Properties</dt>
+ <dd>${sling:encode(fn:join(properties.allowedProperties,','),'HTML')}</dd>
+ <dt>Path</dt>
+ <dd>${sling:encode(properties.path,'HTML')}</dd>
+ <dt>Service User</dt>
+ <dd>${sling:encode(properties.serviceUser,'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/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/impl/FormHandlerTest.java b/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/FormHandlerTest.java
index 048d08d..f8b80ce 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
@@ -21,6 +21,7 @@ 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;
@@ -64,11 +65,21 @@ public class FormHandlerTest {
formRequest = new FormRequestImpl(context.request(), null,
Arrays.asList(new SelectionHandler(), new TextareaHandler(), new TextfieldHandler()));
- final SendEmailAction sendEmailAction = new SendEmailAction();
mailService = Mockito.mock(MailService.class);
Mockito.when(mailService.getMessageBuilder()).thenReturn(new MockMessageBuilder());
- sendEmailAction.setMailService(mailService);
+ final SendEmailAction sendEmailAction = new SendEmailAction(mailService, new SendEmailAction.Config() {
+ @Override
+ public Class<? extends Annotation> annotationType() {
+ return null;
+ }
+
+ @Override
+ public String[] supportedTypes() {
+ return new String[] { SendEmailAction.DEFAULT_RESOURCE_TYPE };
+ }
+
+ });
formHandler = new FormHandler(Arrays.asList(sendEmailAction)) {
private static final long serialVersionUID = 1L;
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..e90933f 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,7 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import java.io.ByteArrayInputStream;
import java.util.Arrays;
import com.google.common.collect.ImmutableMap;
@@ -49,7 +50,7 @@ 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()));
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..78ee756
--- /dev/null
+++ b/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/actions/RequestPasswordResetActionTest.java
@@ -0,0 +1,146 @@
+/*
+ * 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.lang.annotation.Annotation;
+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.cms.reference.forms.impl.actions.RequestPasswordResetAction.Config;
+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(Mockito.eq("test@email.com"))).thenReturn(Mockito.mock(User.class));
+
+ }
+
+ @Test
+ public void testHandleForm() throws FormException {
+
+ RequestPasswordResetAction action = new RequestPasswordResetAction(factory, null);
+
+ 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, null);
+
+ 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 {
+ Config config = new Config() {
+ @Override
+ public Class<? extends Annotation> annotationType() {
+ return null;
+ }
+
+ @Override
+ public String[] supportedTypes() {
+ return new String[] { RequestPasswordResetAction.DEFAULT_RESOURCE_TYPE };
+ }
+ };
+ RequestPasswordResetAction action = new RequestPasswordResetAction(null, config);
+ Resource validResource = Mockito.mock(Resource.class);
+ Mockito.when(validResource.getResourceType()).thenReturn(RequestPasswordResetAction.DEFAULT_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..3f86f86
--- /dev/null
+++ b/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/actions/ResetPasswordActionTest.java
@@ -0,0 +1,175 @@
+/*
+ * 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.lang.annotation.Annotation;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+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.cms.reference.forms.impl.actions.RequestPasswordResetAction.Config;
+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(Mockito.eq("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(Mockito.eq("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(Mockito.eq("expired@email.com"))).thenReturn(expiredUser);
+
+ }
+
+ @Test
+ public void testHandleForm() throws FormException {
+
+ RequestPasswordResetAction action = new RequestPasswordResetAction(factory, null);
+
+ FormRequest request = new FormRequestImpl(new MockSlingHttpServletRequest(resolver), null, null);
+ request.getFormData().put("email", "test@email.com");
+ request.getFormData().put(FormConstants.PN_RESETTOKEN, "123");
+ request.getFormData().put(FormConstants.PN_PASSWORD, "password1");
+
+ Resource actionResource = new MockResource("/content", Collections.emptyMap(), null);
+
+ FormActionResult result = action.handleForm(actionResource, request);
+ assertTrue(result.isSucceeded());
+
+ }
+
+ @Test
+ public void testNoUser() throws FormException {
+
+ ResetPasswordAction action = new ResetPasswordAction(factory, null);
+
+ 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 {
+ Config config = new Config() {
+ @Override
+ public Class<? extends Annotation> annotationType() {
+ return null;
+ }
+
+ @Override
+ public String[] supportedTypes() {
+ return new String[] { RequestPasswordResetAction.DEFAULT_RESOURCE_TYPE };
+ }
+ };
+ RequestPasswordResetAction action = new RequestPasswordResetAction(null, config);
+ Resource validResource = Mockito.mock(Resource.class);
+ Mockito.when(validResource.getResourceType()).thenReturn(RequestPasswordResetAction.DEFAULT_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..815dd5e 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
@@ -19,6 +19,8 @@ package org.apache.sling.cms.reference.forms.impl.actions;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import java.lang.annotation.Annotation;
+
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.cms.reference.forms.FormActionResult;
import org.apache.sling.cms.reference.forms.FormException;
@@ -47,12 +49,20 @@ 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, new SendEmailAction.Config() {
+
+ @Override
+ public Class<? extends Annotation> annotationType() {
+ return null;
+ }
+
+ @Override
+ public String[] supportedTypes() {
+ return new String[] { SendEmailAction.DEFAULT_RESOURCE_TYPE };
+ }
+ });
}
@Test
diff --git a/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/actions/UpdateResourceActionTest.java b/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/actions/UpdateResourceActionTest.java
new file mode 100644
index 0000000..49315cb
--- /dev/null
+++ b/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/actions/UpdateResourceActionTest.java
@@ -0,0 +1,162 @@
+/*
+ * 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.HashMap;
+
+import org.apache.jackrabbit.JcrConstants;
+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.reference.forms.FormException;
+import org.apache.sling.cms.reference.forms.FormRequest;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+public class UpdateResourceActionTest {
+
+ @Test
+ public void testHandles() {
+
+ UpdateResourceAction ur = new UpdateResourceAction(null);
+
+ Resource validResource = Mockito.mock(Resource.class);
+ Mockito.when(validResource.getResourceType()).thenReturn("reference/components/forms/actions/updateresource");
+ 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 {
+
+ UpdateResourceAction ur = new UpdateResourceAction(null);
+
+ 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);
+
+ ResourceResolver resolver = Mockito.mock(ResourceResolver.class);
+ Mockito.when(resolver.getResource(Mockito.eq("/content/test"))).thenReturn(contentResource);
+
+ ValueMap actionData = new ModifiableValueMapDecorator(new HashMap<String, Object>());
+ actionData.put("allowedProperties", new String[] { "name1", "name3", "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);
+
+ assertEquals(2, contentResource.getValueMap().keySet().size());
+ assertEquals("value3", contentResource.getValueMap().get("name3"));
+ assertFalse(contentResource.getValueMap().containsKey("name2"));
+
+ }
+
+ @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);
+
+ UpdateResourceAction ur = new UpdateResourceAction(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 testServiceUser() 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);
+
+ ResourceResolver resolver = Mockito.mock(ResourceResolver.class);
+ Mockito.when(resolver.getResource(Mockito.eq("/content/test"))).thenReturn(contentResource);
+
+ ResourceResolverFactory factory = Mockito.mock(ResourceResolverFactory.class);
+ Mockito.when(factory.getServiceResourceResolver(Mockito.anyMap())).thenReturn(resolver);
+
+ UpdateResourceAction ur = new UpdateResourceAction(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);
+
+ ur.handleForm(actionResource, formRequest);
+
+ assertEquals(2, contentResource.getValueMap().keySet().size());
+ assertEquals("value3", contentResource.getValueMap().get("name3"));
+ assertFalse(contentResource.getValueMap().containsKey("name2"));
+
+ }
+}
diff --git a/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/fields/HoneypotHandlerTest.java b/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/fields/HoneypotHandlerTest.java
new file mode 100644
index 0000000..7deb692
--- /dev/null
+++ b/reference/src/test/java/org/apache/sling/cms/reference/forms/impl/fields/HoneypotHandlerTest.java
@@ -0,0 +1,99 @@
+/*
+ * 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.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;
+import org.apache.sling.cms.reference.forms.impl.SlingContextHelper;
+import org.apache.sling.testing.mock.sling.junit.SlingContext;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+public class HoneypotHandlerTest {
+
+ @Rule
+ public final SlingContext context = new SlingContext();
+ private HoneypotHandler handler;
+ private ResourceResolver resolver;
+
+ @Before
+ public void init() {
+ SlingContextHelper.initContext(context);
+
+ resolver = context.resourceResolver();
+ handler = new HoneypotHandler();
+ }
+
+ @Test
+ public void testHandles() {
+
+ 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/honeypot")));
+ }
+
+ @Test
+ public void testValid() throws FormException {
+ ResourceResolver resolver = context.resourceResolver();
+
+ 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/honeypot");
+
+ handler.handleField(context.request(), fieldResource, formData);
+
+ assertTrue(formData.isEmpty());
+ }
+
+ @Test
+ public void testInValid() throws FormException {
+ ResourceResolver resolver = context.resourceResolver();
+
+ 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/honeypot");
+
+ try {
+
+ handler.handleField(context.request(), fieldResource, formData);
+ fail();
+ } catch (FormException e) {
+ // expected
+ }
+
+ assertTrue(formData.isEmpty());
+ }
+
+}
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..855127f 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,13 @@ 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.util.Calendar;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@@ -71,12 +74,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 +115,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 +170,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..1d558c8 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,23 @@
"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",
+ "required": true,
+ "name": "file",
+ "type": "file",
+ "label": "File",
+ "sling:resourceType": "reference/components/forms/fields/textfield"
+ },
"integer": {
"jcr:primaryType": "nt:unstructured",
"required": true,
@@ -110,6 +134,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 +163,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"
}
}
}