/* * Copyright (C) 2005-2013 Alfresco Software Limited. * * This file is part of Alfresco * * Alfresco is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Alfresco is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Alfresco. If not, see . */ package org.alfresco.repo.activities; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.model.ContentModel; import org.alfresco.query.PagingRequest; import org.alfresco.query.PagingResults; import org.alfresco.repo.activities.feed.cleanup.FeedCleaner; import org.alfresco.repo.domain.activities.ActivityFeedDAO; import org.alfresco.repo.domain.activities.ActivityFeedEntity; import org.alfresco.repo.domain.activities.FeedControlDAO; import org.alfresco.repo.domain.activities.FeedControlEntity; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.permissions.AccessDeniedException; import org.alfresco.repo.tenant.TenantService; import org.alfresco.service.cmr.activities.ActivityPostService; import org.alfresco.service.cmr.activities.ActivityService; import org.alfresco.service.cmr.activities.FeedControl; import org.alfresco.service.cmr.repository.AssociationRef; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.security.AuthorityService; import org.alfresco.service.cmr.security.NoSuchPersonException; import org.alfresco.service.cmr.security.PersonService; import org.alfresco.service.cmr.site.SiteInfo; import org.alfresco.service.cmr.site.SiteService; import org.alfresco.service.namespace.QName; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.json.JSONObject; import org.json.JSONException; import org.springframework.beans.factory.InitializingBean; import org.springframework.extensions.surf.util.ParameterCheck; /** * Activity Service Implementation * * @author janv */ public class ActivityServiceImpl implements ActivityService, InitializingBean { private static final Log logger = LogFactory.getLog(ActivityServiceImpl.class); private ActivityFeedDAO feedDAO; private FeedControlDAO feedControlDAO; private FeedCleaner feedCleaner; private AuthorityService authorityService; private TenantService tenantService; private SiteService siteService; private ActivityPostService activityPostService; private PersonService personService; private NodeService nodeService; private int maxFeedItems = 100; private boolean userNamesAreCaseSensitive = false; public void setMaxFeedItems(int maxFeedItems) { this.maxFeedItems = maxFeedItems; } public void setUserNamesAreCaseSensitive(boolean userNamesAreCaseSensitive) { this.userNamesAreCaseSensitive = userNamesAreCaseSensitive; } public void setFeedDAO(ActivityFeedDAO feedDAO) { this.feedDAO = feedDAO; } public void setFeedControlDAO(FeedControlDAO feedControlDAO) { this.feedControlDAO = feedControlDAO; } public void setFeedCleaner(FeedCleaner feedCleaner) { this.feedCleaner = feedCleaner; } public void setAuthorityService(AuthorityService authorityService) { this.authorityService = authorityService; } public void setTenantService(TenantService tenantService) { this.tenantService = tenantService; } public void setSiteService(SiteService siteService) { this.siteService = siteService; } public void setActivityPostService(ActivityPostService activityPostService) { this.activityPostService = activityPostService; } public void setPersonService(PersonService personService) { this.personService = personService; } public void setNodeService(NodeService nodeService) { this.nodeService = nodeService; } /*(non-Javadoc) * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() */ public void afterPropertiesSet() throws Exception { int feedCleanerMaxFeedItems = feedCleaner.getMaxFeedSize(); if (maxFeedItems > feedCleanerMaxFeedItems) { logger.warn("Cannot retrieve more items than feed cleaner max items (overriding "+maxFeedItems+" to "+feedCleanerMaxFeedItems+")"); maxFeedItems = feedCleanerMaxFeedItems; } } /* (non-Javadoc) * @see org.alfresco.service.cmr.activities.ActivityService#postActivity(java.lang.String, java.lang.String, java.lang.String, java.lang.String) */ public void postActivity(String activityType, String siteId, String appTool, String activityData) { // delegate activityPostService.postActivity(activityType, siteId, appTool, activityData); } /* (non-Javadoc) * @see org.alfresco.service.cmr.activities.ActivityService#postActivity(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String) */ public void postActivity(String activityType, String siteId, String appTool, String activityData, String userId) { // delegate activityPostService.postActivity(activityType, siteId, appTool, activityData, userId); } /* (non-Javadoc) * @see org.alfresco.service.cmr.activities.ActivityService#postActivity(java.lang.String, java.lang.String, java.lang.String, org.alfresco.service.cmr.repository.NodeRef) */ public void postActivity(String activityType, String siteId, String appTool, NodeRef nodeRef) { // delegate activityPostService.postActivity(activityType, siteId, appTool, nodeRef); } /* (non-Javadoc) * @see org.alfresco.service.cmr.activities.ActivityService#postActivity(java.lang.String, java.lang.String, java.lang.String, org.alfresco.service.cmr.repository.NodeRef, java.lang.String) */ public void postActivity(String activityType, String siteId, String appTool, NodeRef nodeRef, String name) { // delegate activityPostService.postActivity(activityType, siteId, appTool, nodeRef, name); } /* (non-Javadoc) * @see org.alfresco.service.cmr.activities.ActivityService#postActivity(java.lang.String, java.lang.String, java.lang.String, org.alfresco.service.cmr.repository.NodeRef, java.lang.String, org.alfresco.service.namespace.QName, org.alfresco.service.cmr.repository.NodeRef) */ public void postActivity(String activityType, String siteId, String appTool, NodeRef nodeRef, String name, QName typeQName, NodeRef parentNodeRef) { // delegate activityPostService.postActivity(activityType, siteId, appTool, nodeRef, name, typeQName, parentNodeRef); } /* (non-Javadoc) * @see org.alfresco.service.cmr.activities.ActivityService#getUserFeedEntries(java.lang.String, java.lang.String, java.lang.String) */ public List getUserFeedEntries(String feedUserId, String siteId) { return getUserFeedEntries(feedUserId, siteId, false, false, null, null); } /* (non-Javadoc) * @see org.alfresco.service.cmr.activities.ActivityService#getUserFeedEntries(java.lang.String, java.lang.String, java.lang.String, boolean, boolean) */ public List getUserFeedEntries(String feedUserId, String siteId, boolean excludeThisUser, boolean excludeOtherUsers) { return getUserFeedEntries(feedUserId, siteId, excludeThisUser, excludeOtherUsers, null, null); } /* (non-Javadoc) * @see org.alfresco.service.cmr.activities.ActivityService#getUserFeedEntries(java.lang.String, java.lang.String, java.lang.String, boolean, boolean, java.util.Set, java.util.Set) */ public List getUserFeedEntries(String feedUserId, String siteId, boolean excludeThisUser, boolean excludeOtherUsers, Set userFilter, Set actvityFilter) { List activityFeedEntries = new ArrayList(); try { List activityFeeds = getUserFeedEntries(feedUserId, siteId, excludeThisUser, excludeOtherUsers, userFilter, actvityFilter, -1); if (activityFeeds != null) { for (ActivityFeedEntity activityFeed : activityFeeds) { activityFeedEntries.add(activityFeed.getJSONString()); } } } catch (JSONException je) { AlfrescoRuntimeException are = new AlfrescoRuntimeException("Unable to get user feed entries: " + je.getMessage()); logger.error(are); throw are; } return activityFeedEntries; } /* (non-Javadoc) * @see org.alfresco.service.cmr.activities.ActivityService#getPagedUserFeedEntries(java.lang.String, java.lang.String, java.lang.String, boolean, boolean, java.util.Set, java.util.Set) */ public PagingResults getPagedUserFeedEntries(String feedUserId, String siteId, boolean excludeThisUser, boolean excludeOtherUsers, long minFeedId, PagingRequest pagingRequest) { try { // NOTE: siteId is optional ParameterCheck.mandatoryString("feedUserId", feedUserId); if(!userNamesAreCaseSensitive) { feedUserId = feedUserId.toLowerCase(); } String currentUser = getCurrentUser(); if (! ((currentUser == null) || (authorityService.isAdminAuthority(currentUser)) || (currentUser.equals(feedUserId)) || (AuthenticationUtil.getSystemUserName().equals(this.tenantService.getBaseNameUser(currentUser))))) { throw new AccessDeniedException("Unable to get user feed entries for '" + feedUserId + "' - currently logged in as '" + currentUser +"'"); } if (siteId != null) { siteId = tenantService.getName(siteId); } String networkId = tenantService.getCurrentUserDomain(); PagingResults activityFeedEntries = feedDAO.selectPagedUserFeedEntries(feedUserId, networkId, siteId, excludeThisUser, excludeOtherUsers, minFeedId, pagingRequest); return activityFeedEntries; } catch (SQLException se) { AlfrescoRuntimeException are = new AlfrescoRuntimeException("Unable to get user feed entries: " + se.getMessage()); logger.error(are); throw are; } } /** * Attempts to find the avatar {@link NodeRef} for the user in supplied {@link ActivityFeedEntity}. As this is aimed * at setting the {@link NodeRef} from a client-side point of view there are a couple of activity types where * the user is taken from the activity summary rather than from the poster (e.g. when a user role is changed). * A cache should be passed in from which to retrieve previously fetched {@link NodeRef}s for efficiency. * * @param activityFeed * @param userIdToAvatarNodeRefCache * @return */ protected NodeRef getUserAvatarNodeRef(ActivityFeedEntity activityFeed, Map userIdToAvatarNodeRefCache) { NodeRef avatarNodeRef = null; String postUserId = null; if (activityFeed.getActivityType().equals("org.alfresco.site.user-role-changed")) { try { JSONObject j = new JSONObject(activityFeed.getActivitySummary()); postUserId = j.get("memberUserName").toString(); } catch (JSONException e) { // Ignore any exceptions. This is only an attempt to prevent 304 revalidation so // the consequences of an exception are not significant, we will simply allow // the avatar to be looked up by username. } } else { postUserId = activityFeed.getPostUserId(); } if (postUserId == null) { // No action required. We're simply going to allow the feed data to be returned without // an avatarNodeRef being set. The end result will be that the avatar is requested via // user name and this will result in a 304 revalidation request. This should theoretically // be a rare occurrence. } else if (userIdToAvatarNodeRefCache.containsKey(postUserId)) { // If we've previously cached the users avatar, or if we've determine that the user doesn't // have an avatar then use the cached data. avatarNodeRef = userIdToAvatarNodeRefCache.get(postUserId); } else { try { NodeRef postPerson = this.personService.getPerson(postUserId); List assocRefs = this.nodeService.getTargetAssocs(postPerson, ContentModel.ASSOC_AVATAR); if (!assocRefs.isEmpty()) { // Get the avatar for the user id, set it in the activity feed and update the cache avatarNodeRef = assocRefs.get(0).getTargetRef(); } } catch (NoSuchPersonException e) { if (logger.isDebugEnabled()) { logger.warn("getUserFeedEntries: person no longer exists: "+postUserId); } } // Update the cache (setting null if there is no avatar for the user)... userIdToAvatarNodeRefCache.put(postUserId, avatarNodeRef); } return avatarNodeRef; } public List getUserFeedEntries(String feedUserId, String siteId, boolean excludeThisUser, boolean excludeOtherUsers, long minFeedId) { return getUserFeedEntries(feedUserId, siteId, excludeThisUser, excludeOtherUsers, null, null, minFeedId); } public List getUserFeedEntries(String feedUserId, String siteId, boolean excludeThisUser, boolean excludeOtherUsers, Set userFilter, Set actvityFilter, long minFeedId) { // NOTE: siteId is optional ParameterCheck.mandatoryString("feedUserId", feedUserId); if (! userNamesAreCaseSensitive) { feedUserId = feedUserId.toLowerCase(); } String currentUser = getCurrentUser(); if (! ((currentUser == null) || (authorityService.isAdminAuthority(currentUser)) || (currentUser.equals(feedUserId)) || (AuthenticationUtil.getSystemUserName().equals(this.tenantService.getBaseNameUser(currentUser))))) { throw new AccessDeniedException("Unable to get user feed entries for '" + feedUserId + "' - currently logged in as '" + currentUser +"'"); } List result = new ArrayList(); // avoid DB calls if filters are empty if(actvityFilter != null && actvityFilter.isEmpty()) { return result; } if(userFilter != null && userFilter.isEmpty()) { return result; } try { if (siteId != null) { siteId = tenantService.getName(siteId); } List activityFeeds = feedDAO.selectUserFeedEntries(feedUserId, siteId, excludeThisUser, excludeOtherUsers, minFeedId, maxFeedItems); // Create a local cache just for this method to map IDs of users to their avatar NodeRef. This // is local to the method because we only want to cache per request - there is not point in keeping // an instance cache because the data will become stale if a user changes their avatar. Map userIdToAvatarNodeRefCache = new HashMap(); String currentTenantDomain = tenantService.getCurrentUserDomain(); if (logger.isDebugEnabled()) { logger.debug("Selected feed entries for user : '" + feedUserId + "',\n for site : '" + siteId + "',\n excluding this user : '" + excludeThisUser + "',\n excluding other users : '" + excludeOtherUsers + "',\n with min feed id : '" + minFeedId + "',\n with max feed items : '" + maxFeedItems); } for (ActivityFeedEntity activityFeed : activityFeeds) { if (actvityFilter != null && !actvityFilter.contains(activityFeed.getActivityType())) { if (logger.isTraceEnabled()) { logger.trace("Filtering " + activityFeed.toString() + " \n by the activity filter."); } continue; } if (userFilter != null && !userFilter.contains(activityFeed.getPostUserId())) { if (logger.isTraceEnabled()) { logger.trace("Filtering " + activityFeed.toString() + " \n by the user filter."); } continue; } String siteNetwork = activityFeed.getSiteNetwork(); if (siteId == null) { // note: pending requirements for THOR-224, for now assume all activities are within context of site and filter by current tenant if (siteNetwork != null && !currentTenantDomain.equals(tenantService.getDomain(siteNetwork))) { continue; } } // In order to prevent unnecessary 304 revalidations on user avatars in the activity stream the // activity posting user avatars will be retrieved and added to the activity feed. This will enable // avatars to be requested using the unique nodeRef which can be safely cached by the browser and // improve performance... NodeRef avatarNodeRef = null; String postUserId = activityFeed.getPostUserId(); if (userIdToAvatarNodeRefCache.containsKey(postUserId)) { // If we've previously cached the users avatar, or if we've determine that the user doesn't // have an avatar then use the cached data. avatarNodeRef = userIdToAvatarNodeRefCache.get(postUserId); } else { try { NodeRef postPerson = this.personService.getPerson(postUserId); List assocRefs = this.nodeService.getTargetAssocs(postPerson, ContentModel.ASSOC_AVATAR); if (!assocRefs.isEmpty()) { // Get the avatar for the user id, set it in the activity feed and update the cache avatarNodeRef = assocRefs.get(0).getTargetRef(); } } catch (NoSuchPersonException e) { if (logger.isDebugEnabled()) { logger.warn("getUserFeedEntries: person no longer exists: "+postUserId); } } // Update the cache (setting null if there is no avatar for the user)... userIdToAvatarNodeRefCache.put(postUserId, avatarNodeRef); } activityFeed.setPostUserAvatarNodeRef(avatarNodeRef); activityFeed.setSiteNetwork(tenantService.getBaseName(siteNetwork)); result.add(activityFeed); if (logger.isTraceEnabled()) { logger.trace("Selected user feed entry: " + activityFeed.toString()); } } } catch (SQLException se) { AlfrescoRuntimeException are = new AlfrescoRuntimeException("Unable to get user feed entries: " + se.getMessage()); logger.error(are); throw are; } return result; } /* (non-Javadoc) * @see org.alfresco.service.cmr.activities.ActivityService#getSiteFeedEntries(java.lang.String, java.lang.String) */ public List getSiteFeedEntries(String siteId) { ParameterCheck.mandatoryString("siteId", siteId); List activityFeedEntries = new ArrayList(); // Create a local cache just for this method to map IDs of users to their avatar NodeRef. This // is local to the method because we only want to cache per request - there is not point in keeping // an instance cache because the data will become stale if a user changes their avatar. Map userIdToAvatarNodeRefCache = new HashMap(); try { if (siteService != null) { SiteInfo siteInfo = siteService.getSite(siteId); if (siteInfo == null) { throw new AccessDeniedException("No such site: " + siteId); } } siteId = tenantService.getName(siteId); List activityFeeds = feedDAO.selectSiteFeedEntries(siteId, maxFeedItems); if (logger.isDebugEnabled()) { logger.debug("Selected feed entries for site : '" + siteId + "'"); } for (ActivityFeedEntity activityFeed : activityFeeds) { activityFeed.setSiteNetwork(tenantService.getBaseName(activityFeed.getSiteNetwork())); // In order to prevent unnecessary 304 revalidations on user avatars in the activity stream the // activity posting user avatars will be retrieved and added to the activity feed. This will enable // avatars to be requested using the unique nodeRef which can be safely cached by the browser and // improve performance... NodeRef avatarNodeRef = null; String postUserId = activityFeed.getPostUserId(); if (userIdToAvatarNodeRefCache.containsKey(postUserId)) { // If we've previously cached the users avatar, or if we've determine that the user doesn't // have an avatar then use the cached data. avatarNodeRef = userIdToAvatarNodeRefCache.get(postUserId); } else { try { NodeRef postPerson = this.personService.getPerson(postUserId); List assocRefs = this.nodeService.getTargetAssocs(postPerson, ContentModel.ASSOC_AVATAR); if (!assocRefs.isEmpty()) { // Get the avatar for the user id, set it in the activity feed and update the cache avatarNodeRef = assocRefs.get(0).getTargetRef(); } } catch (NoSuchPersonException e) { if (logger.isDebugEnabled()) { logger.warn("getUserFeedEntries: person no longer exists: "+postUserId); } } // Update the cache (setting null if there is no avatar for the user)... userIdToAvatarNodeRefCache.put(postUserId, avatarNodeRef); } activityFeed.setPostUserAvatarNodeRef(avatarNodeRef); activityFeedEntries.add(activityFeed.getJSONString()); if (logger.isTraceEnabled()) { logger.trace("Selected site feed entry: " + activityFeed.toString()); } } } catch (SQLException se) { AlfrescoRuntimeException are = new AlfrescoRuntimeException("Unable to get site feed entries: " + se.getMessage()); logger.error(are); throw are; } catch (JSONException je) { AlfrescoRuntimeException are = new AlfrescoRuntimeException("Unable to get site feed entries: " + je.getMessage()); logger.error(are); throw are; } return activityFeedEntries; } /* (non-Javadoc) * @see org.alfresco.service.cmr.activities.ActivityService#getMaxFeedItems() */ public int getMaxFeedItems() { return this.maxFeedItems; } /* (non-Javadoc) * @see org.alfresco.service.cmr.activities.ActivityService#setFeedControl(org.alfresco.service.cmr.activities.FeedControl) */ public void setFeedControl(FeedControl feedControl) { ParameterCheck.mandatory("feedControl", feedControl); String userId = getCurrentUser(); if (userId == null) { throw new AlfrescoRuntimeException("Current user " + userId + " is not permitted to set feed control"); } try { if (! existsFeedControl(feedControl)) { if (logger.isDebugEnabled()) { logger.debug("Inserting feed control for siteId: " + feedControl.getSiteId() + ",\n appToolId : " + feedControl.getAppToolId() + ",\n for user : " + userId); } //MNT-9104 If username contains uppercase letters the action of joining a site will not be displayed in "My activities" if (! userNamesAreCaseSensitive) { userId = userId.toLowerCase(); } feedControlDAO.insertFeedControl(new FeedControlEntity(userId, feedControl)); } } catch (SQLException e) { AlfrescoRuntimeException are = new AlfrescoRuntimeException("Failed to set feed control: " + e, e); logger.error(are); throw are; } } /* (non-Javadoc) * @see org.alfresco.service.cmr.activities.ActivityService#getFeedControls() */ public List getFeedControls() { String userId = getCurrentUser(); return getFeedControlsImpl(userId); } /* (non-Javadoc) * @see org.alfresco.service.cmr.activities.ActivityService#getFeedControls(java.lang.String) */ public List getFeedControls(String userId) { ParameterCheck.mandatoryString("userId", userId); if (! userNamesAreCaseSensitive) { userId = userId.toLowerCase(); } String currentUser = getCurrentUser(); if ((currentUser == null) || (! ((authorityService.isAdminAuthority(currentUser)) || (currentUser.equals(userId)) || (AuthenticationUtil.getSystemUserName().equals(this.tenantService.getBaseNameUser(currentUser)))))) { throw new AlfrescoRuntimeException("Current user " + currentUser + " is not permitted to get feed controls for " + userId); } return getFeedControlsImpl(userId); } private List getFeedControlsImpl(String userId) { ParameterCheck.mandatoryString("userId", userId); if (!userNamesAreCaseSensitive) { userId = userId.toLowerCase(); } try { List feedControlDaos = feedControlDAO.selectFeedControls(userId); if (logger.isDebugEnabled()) { logger.debug("Selecting feed controls for userId: " + userId); } List feedControls = new ArrayList(feedControlDaos.size()); for (FeedControlEntity feedControlDao : feedControlDaos) { FeedControl feedCtrl = feedControlDao.getFeedControl(); feedControls.add(feedCtrl); if (logger.isDebugEnabled()) { logger.debug("Found feed control for userId: " + userId + ",\n appToolId : " + feedCtrl.getAppToolId() + ",\n siteId: " + feedCtrl.getSiteId()); } } return feedControls; } catch (SQLException e) { AlfrescoRuntimeException are = new AlfrescoRuntimeException("Failed to get feed controls: " + e, e); logger.error(are); throw are; } } /* (non-Javadoc) * @see org.alfresco.service.cmr.activities.ActivityService#deleteFeedControl(org.alfresco.service.cmr.activities.FeedControl) */ public void unsetFeedControl(FeedControl feedControl) { ParameterCheck.mandatory("feedControl", feedControl); String userId = getCurrentUser(); if (userId == null) { throw new AlfrescoRuntimeException("Current user " + userId + " is not permitted to unset feed control"); } try { if (logger.isDebugEnabled()) { logger.debug("Deleting feed control for siteId: " + feedControl.getSiteId() + ",\n appToolId : " + feedControl.getAppToolId() + ",\n for user : " + userId); } // MNT-9104 If username contains uppercase letters the action of joining a site will not be displayed in "My activities" if (!userNamesAreCaseSensitive) { userId = userId.toLowerCase(); } feedControlDAO.deleteFeedControl(new FeedControlEntity(userId, feedControl)); } catch (SQLException e) { AlfrescoRuntimeException are = new AlfrescoRuntimeException("Failed to unset feed control: " + e, e); logger.error(are); throw are; } } /* (non-Javadoc) * @see org.alfresco.service.cmr.activities.ActivityService#existsFeedControl(java.lang.String, org.alfresco.service.cmr.activities.FeedControl) */ public boolean existsFeedControl(FeedControl feedControl) { ParameterCheck.mandatory("feedControl", feedControl); String userId = getCurrentUser(); try { if (logger.isDebugEnabled()) { logger.debug("Selecting feed control for siteId: " + feedControl.getSiteId() + ",\n appToolId : " + feedControl.getAppToolId() + ",\n for user : " + userId); } // MNT-9104 If username contains uppercase letters the action of joining a site will not be displayed in "My activities" if (!userNamesAreCaseSensitive) { userId = userId.toLowerCase(); } long id = feedControlDAO.selectFeedControl(new FeedControlEntity(userId, feedControl)); boolean exists = (id != -1); if (logger.isDebugEnabled()) { if(exists) { logger.debug("The entry exists."); } else { logger.debug("The entry doesn't exist."); } } return exists; } catch (SQLException e) { AlfrescoRuntimeException are = new AlfrescoRuntimeException("Failed to query feed control: " + e, e); logger.error(are); throw are; } } private String getCurrentUser() { String userId = AuthenticationUtil.getFullyAuthenticatedUser(); if ((userId != null) && (! userNamesAreCaseSensitive) && (! AuthenticationUtil.getSystemUserName().equals(this.tenantService.getBaseNameUser(userId)))) { // user names are not case-sensitive userId = userId.toLowerCase(); } return userId; } /* private FeedControl getTenantFeedControl(FeedControl feedControl) { // TODO return null; } private FeedControl getBaseFeedControl(FeedControl feedControl) { // TODO return null; } */ }