Generate reports for a users last log-in in AEM

There are cases where we need to generate reports for a users last log-in in AEM. 

I have seen many help blogs but none of them worked for me. Below given an approach which worked for me.

Approach

Utilising 'AuthenticationInfoPostProcessor' service in combination with ACS commons, its going to be easy to generate such reports. This is tested on AEM 6.5 version.

Step1: Deploy below Java code which will capture lastLogin information.
    

Java class which captures the users last login and update the user node

Note: Modify the conditions as per your project requirement. 

--Java class START ---

package yourpackage.core.services;

import java.text.SimpleDateFormat;
import java.util.Date;

import javax.jcr.Session;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.jackrabbit.api.security.user.Authorizable;
import org.apache.jackrabbit.api.security.user.UserManager;
import org.apache.sling.api.resource.LoginException;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.apache.sling.auth.core.spi.AuthenticationInfo;
import org.apache.sling.auth.core.spi.AuthenticationInfoPostProcessor;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Component(name = "UserProfileService", service = AuthenticationInfoPostProcessor.class, immediate = true)
    
public class UserProfileService implements AuthenticationInfoPostProcessor {
    
    /**
     * This class generate Last login property of any user profile
     *
     * @param authenticationinfo
     * @param servletrequest
     * @param servletresponse
     */
    
    private static final Logger LOGGER = LoggerFactory.getLogger(UserProfileService.class);
    @Reference
    private ResourceResolverFactory resourceResolverFactory;

    @Override
    public void postProcess(AuthenticationInfo info, HttpServletRequest request, HttpServletResponse response)
            throws LoginException {

    /**
         * Users last logged in will be his last active time in AEM
         * Executed only when it is a logout operation to ensure the last active time is captured
         * Ensure to update the code with relevant condition
         */
        if ((info != null && info.getAuthType() == null) || (request != null && request.getServletPath() != null
                && (*Your condition 1*))) {
            LOGGER.debug("AuthenticationInfo is null. " + "we can skip post processing this request.");
            return;
        }
        
        ResourceResolver resourceResolver = null;        
        Session session = null;
        UserManager userManager = null;
        Authorizable auth = null;

        try {
            resourceResolver = resourceResolverFactory.getResourceResolver(info);
            session = resourceResolver.adaptTo(Session.class);
            userManager = resourceResolver.adaptTo(UserManager.class);
            auth = userManager.getAuthorizable(session.getUserID());
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
                //Anonymous users need not be checked
                if (auth.getID() != null && (*Your condition 2*)) {
                    LOGGER.info("Logged in Users log in");
                    //Profile will have a new property
                    auth.setProperty("profile/lastLoggedIn", session.getValueFactory().createValue(sdf.format(new Date())));
                    session.save();
                    session.logout();
                }

        } catch (Exception exception) {
            exception.printStackTrace();
        }
    }
}

--Java class END---

 
In my case I had used below conditions.
(*Your condition 1*) - !request.getServletPath().equals("/system/sling/logout.html")
(*Your condition 2*) - !auth.getID().equals("anonymous")
  

Step 2: ACS Commons Report
Now in ACS common reports create a new report with query of type JCRSQL2



SELECT * FROM  [rep:User] as nodes WHERE  ISDESCENDANTNODE("/home/users")
AND nodes.[profile/lastLoggedIn] IS NOT NULL
AND NOT ISDESCENDANTNODE([/home/users/community])
AND NOT ISDESCENDANTNODE([/home/users/mac])
AND NOT ISDESCENDANTNODE([/home/users/rep:policy])
AND NOT ISDESCENDANTNODE([/home/users/screens])
AND NOT ISDESCENDANTNODE([/home/users/system])

And configure the report column as below.



Now you will be able to Generate the final report as shown below.





 Demo Video

Tuesday, 9 November 2021

AEM Asset Upload Size restriction - How to overcome?

By default, AEM supports Assets that are smaller than 2 GB because of a file size limit. However, you can overwrite this limit by going into CRXDE Lite and creating a node under the /apps directory detailed in URL.



Refer URL : RAW Assets Size More info: 


https://experienceleague.adobe.com/docs/experience-manager-65/assets/managing/managing-video-assets.html?lang=en#configuration-to-upload-assets-that-are-larger-than-gb


Is there any limit to upload an asset?

It can be configured to 30 GB also. AEM doesnt define a size limit.

What we need to ensure while changing the default behavior?


  • When we make this changes, ensure you take care of the time out limit on OSGi and Dispatcher idle time so that AEM keep listening the asset upload.
  • Also major point; consider the AEM's default asset processing, and hardware configurations while making this changes. 

Demo Video

How to fix traversal index issue in AEM

 Recently I got an email from my AEM Admin about the indexing issue. The email had some content as shown below.

"WARN* [qtp1832135175-163] org.apache.jackrabbit.oak.spi.query.Cursors$TraversingCursor Traversed 10,000 nodes with filter Filter(query=select * from [nt:base] where foo = 'bar', path=*, property=[foo=[bar]]); consider creating an index "

Some times while working on AEM, we may face traversal warnings. The latest AEM doesn't index the nodes by default. So to ensure our content gets indexed well within AEM, we will have to create indexing nodes and get them indexed.

Below given steps to fix index issues

  • Use the Oak index generation tool - generate index definition.
  • Add the indexing under node oak:index.
  • Trigger the re-index.

 
When we find an issue with a query(traversal warning !), we can use below tool to analyze the query.
 

Query Performance tool URL

http://[AEM URL]:[PORT]/libs/granite/operations/content/diagnosistools/queryPerformance.html

If the analysis recommends to index the nodes, we can use below Oak Index tool to generate the index definitions. 


Oak Index Definition Generator in AEM


http://oakutils.appspot.com/generate/index

 
How to validate the index operation is done?

The indexing property becomes 'false' once the indexing has been completed.

Also, in the console we can go and validate it from index diagnosis tool > index manager
http://[AEM URL]:[PORT]/libs/granite/operations/content/diagnosistools/indexManager.html

Notes:

  • We can even use Synonym file to index the synonyms in AEM.
  • We can define multiple indexes together and trigger them parallel without any issues.

Demo Video

Monday, 8 November 2021

Fix package upload issue in AEM - use CURL command for package upload

While working on AEM, some times we get package upload issue in some of the browsers . 




There could be multiple reasons for this. Now a days companies are doing stringent checks when we try to upload anything via browser. We have faced issue of package upload on AEM during the remote work situations.

Below given an alternate option to upload packages in AEM using CURL command.

CURL Command
curl -u admin:admin -F package=@"name_of_package.zip" http://localhost:4502/crx/packmgr/service/.json/?cmd=upload

Where admin:admin is the local instance user credential.


name_of_package.zip - Change the package name according to your case.

 


 Demo Video

How to raise a product issue with Adobe

To open a support ticket in Adobe, you should have the relevant product assigned as an administrator.

Login to Admin console of Adobe and select the organization from drop down as shown.




Click on support tab. Once you land on this, you can see various options like a Support summary page which gives various options for creating an adobe ticket, start a chat or get the Adobe customer care number.

You have a lot more help topics linked from this page too.

To create a support ticket , click on 'Create Case'



Next step select whether it is a user and license related or using the experience cloud product issue.



And fill in the additional details to complete the request. Once the ticket has been raised Adobe team will contact back for more clarifications.