001/* 002 * Copyright 2017 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.cms.rights.solrchecking; 017 018import java.util.ArrayList; 019import java.util.Collection; 020import java.util.Collections; 021import java.util.HashMap; 022import java.util.LinkedHashMap; 023import java.util.List; 024import java.util.Map; 025import java.util.Set; 026import java.util.stream.Collectors; 027 028import org.apache.avalon.framework.activity.Initializable; 029import org.apache.avalon.framework.parameters.Parameters; 030import org.apache.avalon.framework.service.ServiceException; 031import org.apache.avalon.framework.service.ServiceManager; 032import org.apache.cocoon.acting.ServiceableAction; 033import org.apache.cocoon.environment.ObjectModelHelper; 034import org.apache.cocoon.environment.Redirector; 035import org.apache.cocoon.environment.Request; 036import org.apache.cocoon.environment.SourceResolver; 037import org.apache.commons.lang3.StringUtils; 038import org.slf4j.Logger; 039 040import org.ametys.core.cocoon.JSonReader; 041import org.ametys.core.group.GroupIdentity; 042import org.ametys.core.right.AllowedUsers; 043import org.ametys.core.user.UserIdentity; 044import org.ametys.core.util.AvalonLoggerAdapter; 045import org.ametys.plugins.repository.AmetysObject; 046import org.ametys.plugins.repository.AmetysObjectResolver; 047import org.ametys.plugins.repository.AmetysRepositoryException; 048import org.ametys.plugins.repository.provider.RequestAttributeWorkspaceSelector; 049import org.ametys.runtime.config.Config; 050 051/** 052 * Action called to know allowed users for each {@link AmetysObject} in a list. 053 */ 054public class AllowedUsersByObjectAction extends ServiceableAction implements Initializable 055{ 056 /** The Ametys object resolver */ 057 protected AmetysObjectResolver _resolver; 058 059 /** The helper for read access */ 060 protected ReadAccessHelper _readAccessHelper; 061 062 private Logger _logger; 063 064 @Override 065 public void service(ServiceManager smanager) throws ServiceException 066 { 067 super.service(smanager); 068 _resolver = (AmetysObjectResolver) smanager.lookup(AmetysObjectResolver.ROLE); 069 _readAccessHelper = (ReadAccessHelper) smanager.lookup(ReadAccessHelper.ROLE); 070 } 071 072 @Override 073 public void initialize() throws Exception 074 { 075 // will be called after #enableLogging, so getLogger() will not return null 076 _logger = new AvalonLoggerAdapter(getLogger()); 077 } 078 079 @Override 080 public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters parameters) throws Exception 081 { 082 Request request = ObjectModelHelper.getRequest(objectModel); 083 084 Map<String, Object> result = new HashMap<>(); 085 request.setAttribute(JSonReader.OBJECT_TO_READ, result); 086 087 String coreName = parameters.getParameter("coreName"); 088 String objectIdsAsString = request.getParameter("ids"); 089 090 Map<String, Map<String, Object>> responseMap = new LinkedHashMap<>(); 091 result.put("response", responseMap); 092 List<String> unresolvedIds = new ArrayList<>(); 093 result.put("unresolvedIds", unresolvedIds); 094 095 096 // Retrieve the current workspace. 097 String currentWsp = RequestAttributeWorkspaceSelector.getForcedWorkspace(request); 098 099 try 100 { 101 // Force the workspace. 102 String solrCorePrefix = Config.getInstance().getValue("cms.solr.core.prefix"); 103 if (coreName.startsWith(solrCorePrefix)) 104 { 105 String workspaceName = coreName.substring(solrCorePrefix.length()); 106 RequestAttributeWorkspaceSelector.setForcedWorkspace(request, workspaceName); 107 _act(objectIdsAsString, responseMap, unresolvedIds); 108 } 109 else 110 { 111 throw new IllegalArgumentException("The core name '" + coreName + "' does not start with the prefix '" + solrCorePrefix + "'"); 112 } 113 } 114 finally 115 { 116 // Restore context 117 RequestAttributeWorkspaceSelector.setForcedWorkspace(request, currentWsp); 118 } 119 120 return EMPTY_MAP; 121 } 122 123 private void _act(String objectIdsAsString, Map<String, Map<String, Object>> responseMap, List<String> unresolvedIds) 124 { 125 if (objectIdsAsString == null) 126 { 127 throw new IllegalArgumentException("{} was called with no parameter 'ids'. It is very likely that this request has exceeded the Tomcat maximum POST size. "); 128 } 129 String[] objectIds = StringUtils.split(objectIdsAsString, ','); 130 _logger.info("Start retrieving allowed users for {} ametys object id(s)", objectIds.length); 131 for (String objectId : objectIds) 132 { 133 AmetysObject ametysObject; 134 try 135 { 136 ametysObject = _resolver.resolveById(objectId); 137 } 138 catch (AmetysRepositoryException e) 139 { 140 unresolvedIds.add(objectId); 141 _logger.info("The object with id '{}' cannot be retrieved.", objectId, e); 142 continue; 143 } 144 145 try 146 { 147 AllowedUsers allowedUsersObj = _readAccessHelper.allowedUsers(ametysObject); 148 149 Boolean anonymous = allowedUsersObj.isAnonymousAllowed(); 150 Boolean anyConnected = allowedUsersObj.isAnyConnectedUserAllowed(); 151 Set<GroupIdentity> allowedGroups = allowedUsersObj.getAllowedGroups(); 152 Set<GroupIdentity> deniedGroups = allowedUsersObj.getDeniedGroups(); 153 154 List<String> allowedGroupsStr = _groupsAsStrings(allowedGroups); 155 List<String> deniedGroupsStr = _groupsAsStrings(deniedGroups); 156 List<String> allowedUsers = _usersAsStrings(allowedUsersObj.getAllowedUsers()); 157 List<String> deniedUsers = _usersAsStrings(allowedUsersObj.getDeniedUsers()); 158 159 Map<String, Object> unresolvedAllowedUsers = new LinkedHashMap<>(); 160 unresolvedAllowedUsers.put("anonymous", anonymous); 161 unresolvedAllowedUsers.put("anyConnected", anyConnected); 162 unresolvedAllowedUsers.put("allowedGroups", allowedGroupsStr); 163 unresolvedAllowedUsers.put("deniedGroups", deniedGroupsStr); 164 unresolvedAllowedUsers.put("allowedUsers", allowedUsers); 165 unresolvedAllowedUsers.put("deniedUsers", deniedUsers); 166 responseMap.put(objectId, unresolvedAllowedUsers); 167 } 168 catch (Exception e) 169 { 170 unresolvedIds.add(objectId); 171 _logger.error("An unexpected exception occured when trying to get read access of object with id '{}'.", objectId, e); 172 } 173 } 174 175 _logger.info("End retrieving allowed users for {} ametys objects ids. {} id(s) could not be resolved.", objectIds.length, unresolvedIds.size()); 176 } 177 178 private List<String> _groupsAsStrings(Collection<GroupIdentity> groups) 179 { 180 if (groups == null) 181 { 182 return Collections.EMPTY_LIST; 183 } 184 185 return groups.stream() 186 .map(GroupIdentity::groupIdentityToString) 187 .collect(Collectors.toList()); 188 } 189 190 private List<String> _usersAsStrings(Collection<UserIdentity> users) 191 { 192 if (users == null) 193 { 194 return Collections.EMPTY_LIST; 195 } 196 197 return users.stream() 198 .map(UserIdentity::userIdentityToString) 199 .collect(Collectors.toList()); 200 } 201}