/** * Licensed to Apereo under one or more contributor license agreements. See the NOTICE file * distributed with this work for additional information regarding copyright ownership. Apereo * licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use * this file except in compliance with the License. You may obtain a copy of the License at the * following location: * * <p>http://www.apache.org/licenses/LICENSE-2.0 * * <p>Unless required by applicable law or agreed to in writing, software distributed under the * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the License for the specific language governing permissions and * limitations under the License. */ package org.apereo.portal.portlets.googleanalytics; import com.fasterxml.jackson.databind.JsonNode; import java.io.IOException; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import javax.portlet.PortletPreferences; import javax.portlet.RenderRequest; import javax.servlet.http.HttpServletRequest; import org.apereo.portal.EntityIdentifier; import org.apereo.portal.groups.IEntityGroup; import org.apereo.portal.groups.IGroupMember; import org.apereo.portal.portlets.PortletPreferencesJsonDao; import org.apereo.portal.security.IPerson; import org.apereo.portal.security.IPersonManager; import org.apereo.portal.services.GroupService; import org.apereo.portal.url.IPortalRequestUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.portlet.bind.annotation.RenderMapping; @Controller @RequestMapping("VIEW") public class GoogleAnalyticsController { protected final Logger logger = LoggerFactory.getLogger(getClass()); private PortletPreferencesJsonDao portletPreferencesJsonDao; @Autowired private IPortalRequestUtils portalRequestUtils; @Autowired private IPersonManager personManager; @Autowired public void setPortletPreferencesJsonDao(PortletPreferencesJsonDao portletPreferencesJsonDao) { this.portletPreferencesJsonDao = portletPreferencesJsonDao; } @RenderMapping public String renderAnalyticsHeader(RenderRequest request, ModelMap model) throws IOException { // For which user account are we logging portal activity? final HttpServletRequest req = portalRequestUtils.getCurrentPortalRequest(); final IPerson person = personManager.getPerson(req); final String username = person.getUserName(); final IGroupMember groupMember = GroupService.getGroupMember(username, IPerson.class); final Map<String, Boolean> isMemberCache = new HashMap<>(); final PortletPreferences preferences = request.getPreferences(); final JsonNode config = this.portletPreferencesJsonDao.getJsonNode( preferences, GoogleAnalyticsConfigController.CONFIG_PREF_NAME); final JsonNode propertyConfig = config.get("defaultConfig"); this.filterAnalyticsGroups(groupMember, propertyConfig, isMemberCache); final JsonNode hosts = config.get("hosts"); if (hosts != null) { for (final Iterator<JsonNode> hostsItr = hosts.elements(); hostsItr.hasNext(); ) { final JsonNode institution = hostsItr.next(); this.filterAnalyticsGroups(groupMember, institution, isMemberCache); } } model.put("data", config); if (propertyConfig == null || propertyConfig.get("propertyId") == null) { return "jsp/GoogleAnalytics/noop"; } else { return "jsp/GoogleAnalytics/init"; } } /** Remove groups from the AnalyticsConfig that the current user is not a member of */ private void filterAnalyticsGroups( IGroupMember groupMember, JsonNode config, Map<String, Boolean> isMemberCache) { if (config == null) { return; } final JsonNode dimensionGroups = config.get("dimensionGroups"); if (dimensionGroups == null) { return; } for (final Iterator<JsonNode> groupItr = dimensionGroups.elements(); groupItr.hasNext(); ) { final JsonNode group = groupItr.next(); final JsonNode valueNode = group.get("value"); if (valueNode == null) { continue; } final String groupName = valueNode.asText(); Boolean isMember = isMemberCache.get(groupName); if (isMember == null) { isMember = isMember(groupMember, groupName); isMemberCache.put(groupName, isMember); } if (!isMember) { groupItr.remove(); } } } /** Check if the user is a member of the specified group name */ private boolean isMember(IGroupMember groupMember, String groupName) { try { IEntityGroup group = GroupService.findGroup(groupName); if (group != null) { return groupMember.isDeepMemberOf(group); } final EntityIdentifier[] results = GroupService.searchForGroups(groupName, GroupService.IS, IPerson.class); if (results == null || results.length == 0) { this.logger.warn( "No portal group found for '{}' no users will be placed in that group for analytics", groupName); return false; } if (results.length > 1) { this.logger.warn( "{} groups were found for groupName '{}'. The first result will be used.", results.length, groupName); } group = (IEntityGroup) GroupService.getGroupMember(results[0]); return groupMember.isDeepMemberOf(group); } catch (Exception e) { this.logger.warn( "Failed to determine if {} is a member of {}, returning false", groupMember, groupName, e); return false; } } }