Sometimes an Alfresco Administrator might need to track active logged-in users in the system for audit purpose or for planning maintenance activities. There can be many other use-cases depending of type of usage or organization policies.
Alfresco doesn't provide this kind of feature for admins out of the box as of now. However Alfresco 5.2 version on-wards they are providing Support Tools feature which can provide various options including this particular use-case.
Support Tools is an Add-On, which is available on GitHub called alfresco-support-tools which can be installed as a module as well. It seems Alfresco 5.2 on-wards alfresco has integrated this add-on OOTB. I have not tried this add-on so not sure how it works. However the screenshots given at add-on page shows that it has good amount of features which is really useful for admins.
See here: Support Tools
Here we are going to use Alfresco's TicketComponent service to get the active user details and active ticket details.
We will create a java backed web-script which will return the basic details about the active users, total active user count, total no. of active tickets etc.
Follow the below given steps:
1- Create alfresco webscript descriptor “getActiveUsers.get.desc.xml”
<webscript> <shortname>Active Users</shortname> <description>This webscript returns the active users logged-in into Alfresco. Sample response: { activeTicketsCount: 2, activeUsers: "["admin","abhinav@gmail.com "]", activeUsersCount: 2, _comment: "Active user count may be lower than the ticket count, since a user can have more than one ticket/session. Ticket count may be higher than the active user count, since a user can have more than one ticket/session." } </description> <url>/audit/getActiveUsers</url> <format default="json"/> <authentication>admin</authentication> <family>Audit</family> </webscript> |
2- Create a freemarker template “getActiveUsers.get.json.ftl” which is used to generate the view
<#escape x as jsonUtils.encodeJSONString(x)> ${response} </#escape> |
3- Create a Java webscript class “GetActiveUsersWebscript.java”
package com.github.abhinavmishra14.audit.webscript; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.repo.security.authentication.TicketComponent; import org.json.JSONException; import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory;
import org.springframework.extensions.webscripts.DeclarativeWebScript; import org.springframework.extensions.webscripts.Status; import org.springframework.extensions.webscripts.WebScriptException; import org.springframework.extensions.webscripts.WebScriptRequest; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; /** * The Class GetActiveUsersWebscript. */ public class GetActiveUsersWebscript extends DeclarativeWebScript { /** The Constant LOGGER. */ private static final Logger LOGGER = LoggerFactory.getLogger(GetActiveUsersWebscript.class); /** The Constant ACTIVE_USERS. */ private static final String ACTIVE_USERS = "activeUsers"; /** The Constant ACTIVE_USERS_COUNT. */ private static final String ACTIVE_USERS_COUNT = "activeUsersCount"; /** The Constant ACTIVE_TICKETS_COUNT. */ private static final String ACTIVE_TICKETS_COUNT = "activeTicketsCount"; /** The Constant COMMENT_DATA. */ private static final String COMMENT_DATA = "_comment"; /** The Constant COMMENT. */ private static final String COMMENT = "getActiveUsers.comment"; /** The Constant RESPONSE. */ private static final String RESPONSE = "response"; /** The ticket component. */ private final TicketComponent ticketComponent; /** * The Constructor. * * @param ticketComponent the ticket component */ public GetActiveUsersWebscript(final TicketComponent ticketComponent) { super(); this.ticketComponent = ticketComponent; } @Override public Map<String, Object> executeImpl(final WebScriptRequest req, final Status status, final Cache cache) { final Map<String, Object> model = new ConcurrentHashMap<String, Object>(3); try { //get nonExpiredOnly users with tickets final Set<String> activeUsers = ticketComponent.getUsersWithTickets(true); final ObjectMapper objMapper = new ObjectMapper(); objMapper.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
if (activeUsers != null && !activeUsers.isEmpty()) { final JSONObject activeUsersJson = new JSONObject(); //This may be lower than the ticket count, since a user can have more than one // ticket/session activeUsersJson.put(ACTIVE_USERS, objMapper.writeValueAsString(activeUsers)); activeUsersJson.put(ACTIVE_USERS_COUNT, activeUsers.size());
//This may be higher than the user count, since a user can have more than one // ticket/session //get nonExpiredOnly ticket count activeUsersJson.put(ACTIVE_TICKETS_COUNT, ticketComponent.countTickets(true));
activeUsersJson.put(COMMENT_DATA, "Active user count may be lower than the ticket count, since a user can have more than one ticket/session. Ticket count may be higher than the active user count, since a user can have more than one ticket/session."); model.put(RESPONSE, activeUsersJson); } } catch (JsonProcessingException | JSONException excp) { LOGGER.error("Exception occurred while preparing json for active users ", excp); throw new WebScriptException( Status.STATUS_INTERNAL_SERVER_ERROR, excp.getMessage(), excp); } catch (AlfrescoRuntimeException alfErr) { LOGGER.error("Unexpected error occurred while getting active users ", alfErr); throw new WebScriptException( Status.STATUS_INTERNAL_SERVER_ERROR, alfErr.getMessage(), alfErr); } return model; } } |
4- Add the bean definition for the java webscript in spring context file.
<bean id="webscript.com.github.abhinavmishra14.audit.getActiveUsers.get" class=" com.github.abhinavmishra14.audit.webscript.GetActiveUsersWebscript" parent="webscript"> <constructor-arg ref="ticketComponent"/> </bean> |
5- Build and start the alfresco instance.
6- Access the service using URL: http://127.0.0.1:8080/alfresco/service/audit/getActiveUsers (You will be prompted for credentials, note that the user should be admin who is accessing this service)
7- It will return following type of response:
{ activeTicketsCount: 3, activeUsers: "["admin","test","test2@gmail.com "]", activeUsersCount: 3, _comment: "Active user count may be lower than the ticket count, since a user can have more than one ticket/session. Ticket count may be higher than the active user count, since a user can have more than one ticket/session." } |