Thursday 12 October 2017

AEM Page Redirect - Sling Model


We usually come across page redirection in AEM , its a common practice to include the redirection logic in the base page component of a site. Providing the code sample required for redirection.

Sling Model for handling page redirection in AEM :

import java.io.IOException;

import javax.annotation.PostConstruct;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpStatus;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.models.annotations.Default;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.injectorspecific.ScriptVariable;
import org.apache.sling.models.annotations.injectorspecific.SlingObject;
import org.apache.sling.models.annotations.injectorspecific.ValueMapValue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.adobe.acs.commons.util.ModeUtil;
import com.day.cq.wcm.api.Page;
import com.google.common.net.HttpHeaders;

@Model(adaptables = SlingHttpServletRequest.class)
public class RedirectPageModel {

private static final Logger LOG = LoggerFactory.getLogger(RedirectPageModel.class);

@SlingObject
private SlingHttpServletResponse response;
@SlingObject
private ResourceResolver resourceResolver;
@ScriptVariable
private Page currentPage;
@ValueMapValue(name = "redirectStatus")
@Default(longValues = HttpStatus.SC_MOVED_PERMANENTLY)
private Long slingRedirectStatus;
@ValueMapValue
private String redirectTarget;

@PostConstruct
private void activate() throws IOException {
if (!ModeUtil.isPublish()) {
return;
}
String redirectUrl = getRedirectTarget();
if (StringUtils.isNotBlank(redirectUrl)) {
final int redirectStatus = slingRedirectStatus.intValue();
LOG.trace("Redirecting ({}) to {}", redirectStatus, redirectUrl);
if(redirectStatus==HttpStatus.SC_MOVED_TEMPORARILY){
response.sendRedirect(redirectUrl);
}else {
response.setHeader(HttpHeaders.LOCATION, redirectUrl);
response.setStatus(redirectStatus);
}
}

}

public boolean isRedirectConfigured(){
return StringUtils.isBlank(getRedirectTarget());
}

/**
* Get the "redirectTarget" property from the page content. Check to see its
* not pointing to same page. If its external, return it as is. If its
* internal, remove the html extension and use the resource resolver to map
* it.
*
* @return target path/url
*/
public final String getRedirectTarget() {
if (StringUtils.startsWithIgnoreCase(redirectTarget, "http")) {
return redirectTarget;
}
if (StringUtils.equals(redirectTarget, currentPage.getPath())) {
LOG.warn("{} is trying to redirect to self", currentPage.getPath());
return null;
}
return resourceResolver.map(redirectTarget) + ".html";
}
}

redirection.html file to be included in component html :

<sly data-sly-use.redirectModel="${'com.crazy.cms.slingmodels.RedirectPageModel'}"/>

<h1 data-sly-test="${redirectModel.isRedirectConfigured}" class="cq-redirect-notice">
    This page redirects to <a href="${redirectModel.redirectTarget}">here</a>
</h1>



Wednesday 11 October 2017

AEM System/Service User - Ensure Service User of ACS Commons

In the latest AEM version usage of admin resource resolver is deprecated. We have to use the system/service user to access the data. 

You can manually create System user using aem crx explorer console and create a service mapping to access it in your application. But the process of creating system user and setting up the required permissions should be replicated across all the AEM instances, which is a additional burden and error prone. To overcome this ACS commons has provided a beautiful service (Ensure Service User )which can create the System user and set the permissions automatically based on OSGi configuration. 

The Ensure Service User facilitates defining service users and their ACLs in OSGi configurations, and will intelligently ensure they exist on the target AEM instances.

Below is the example configuration 

















Principal Name : The service user name ,can be just the principal name, a relative path, or the absolute path where the user should be stored in the JCR. Service users will ONLY exist under /home/users/system. If a system user exists with the same principal name at a different location then a new user will not be created, pricncipalName cannot be same.


Operation : add OR remove
  • add ensures the existence of the service user and ACLs
  • remove ensures that the service user and any ACLs are removed
Ensure Immediately : Options: true OR false
When set to true, the user creation and permissions update  are performed whenever this bundle is loaded.

ACE's :  List of ACE definitions(permissions) to be set for the service user

                 Format: type=allow;privileges=jcr:read,rep:write;path=/content/myapp
    • type:(Required) allow OR deny
    • privileges: (Required) comma delimited list of valid JCR privileges
    • path: (Required) absolute content path which the ACE will be applied
More details can be found at ACS Commons Documention