Search code examples
javaalfrescomulti-tenant

Get people in all tenants


I try to count the people in all tenants using a Java web script. This web script shall be invoked as the admin user of the default tenant and collect people statistics for each tenant.

I struggle to get the people for a tenant. The methods countPeople() and getAllPeople() of org.alfresco.service.cmr.security.PersonService always give me only the people in the default tenant, even though I wrap this call in AuthenticationUtil.runAs(...).

import org.alfresco.repo.security.authentication.AuthenticationContext;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.tenant.MultiTAdminServiceImpl;
import org.alfresco.repo.tenant.Tenant;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.security.PersonService;

// ...

protected Map<String, Object> executeImpl(WebScriptRequest req, Status status) {
    final Map<String, Object> model = new HashMap<>();
    final Map<String, Map<String, Long>> tenantNameToTenantData = new HashMap<>();
    if (tenantAdminService != null) {
        for (final Tenant tenant : tenantAdminService.getAllTenants()) {
            final String tenantDomain = tenant.getTenantDomain();
            final String systemUserName = authenticationContext.getSystemUserName(tenantDomain);

            final Map<String, Long> tenantData = AuthenticationUtil.runAs(() -> {
                final Map<String, Long> td = new HashMap<>();
                final long userCount = (long) personService.countPeople();
                td.put("userCount", userCount);

                long totalUsage = 0L;
                for (NodeRef personNodeRef : personService.getAllPeople()) {
                    totalUsage += (long) serviceRegistry.getNodeService().getProperty(personNodeRef, ContentModel.PROP_SIZE_CURRENT);
                }
                totalUsage = totalUsage / (1_024L * 1_024L);
                td.put("totalUsage", totalUsage);
                return td;
            }, systemUserName);

            tenantNameToTenantData.put(tenantDomain, tenantData);
        }
    }
    model.put("tenants", tenantNameToTenantData);
    return model;
}

The call to authenticationContext.getSystemUserName(tenantDomain) returns the correct names (System@tenant1, ...).

How can I get the people for each tenant without having to explicitly authenticate as the tenant admin?


Solution

  • Thanks to Gragravarr for the hint to use TenantUtil.runAsTenant. This is how it works:

    final TenantUtil.TenantRunAsWork<Map<String, Long>> runAsWork = () -> {
        final Map<String, String> td = new HashMap<>();
        td.put("userCount", (long) personService.countPeople());
    
        long totalUsage = 0L;
        for (NodeRef personNodeRef : personService.getAllPeople()) {
            totalUsage += (long) serviceRegistry.getNodeService().getProperty(personNodeRef, ContentModel.PROP_SIZE_CURRENT);
        }
        totalUsage = totalUsage / (1_024L * 1_024L);
        td.put("totalUsage", totalUsage);
    
        return td;
    };
    final Map<String, Long> tenantData =
        TenantUtil.runAsTenant(runAsWork, tenantDomain);