001/* 002 * (C) Copyright 2013 Nuxeo SA (http://nuxeo.com/) and contributors. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl-2.1.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * <a href="mailto:grenard@nuxeo.com">Guillaume</a> 016 */ 017package org.nuxeo.ecm.platform.ui.select2.automation; 018 019import java.io.Serializable; 020import java.util.ArrayList; 021import java.util.List; 022import java.util.Locale; 023 024import net.sf.json.JSONArray; 025import net.sf.json.JSONObject; 026 027import org.apache.commons.lang.StringUtils; 028import org.apache.commons.logging.Log; 029import org.apache.commons.logging.LogFactory; 030import org.nuxeo.common.utils.i18n.I18NUtils; 031import org.nuxeo.ecm.automation.OperationContext; 032import org.nuxeo.ecm.automation.core.Constants; 033import org.nuxeo.ecm.automation.core.annotations.Context; 034import org.nuxeo.ecm.automation.core.annotations.Operation; 035import org.nuxeo.ecm.automation.core.annotations.OperationMethod; 036import org.nuxeo.ecm.automation.core.annotations.Param; 037import org.nuxeo.ecm.core.api.Blob; 038import org.nuxeo.ecm.core.api.Blobs; 039import org.nuxeo.ecm.core.api.DocumentModel; 040import org.nuxeo.ecm.core.api.DocumentModelList; 041import org.nuxeo.ecm.core.api.NuxeoGroup; 042import org.nuxeo.ecm.core.api.NuxeoPrincipal; 043import org.nuxeo.ecm.core.schema.SchemaManager; 044import org.nuxeo.ecm.core.schema.types.Field; 045import org.nuxeo.ecm.core.schema.types.QName; 046import org.nuxeo.ecm.core.schema.types.Schema; 047import org.nuxeo.ecm.directory.Directory; 048import org.nuxeo.ecm.directory.SizeLimitExceededException; 049import org.nuxeo.ecm.directory.api.DirectoryService; 050import org.nuxeo.ecm.platform.ui.select2.common.Select2Common; 051import org.nuxeo.ecm.platform.usermanager.UserAdapter; 052import org.nuxeo.ecm.platform.usermanager.UserManager; 053 054/** 055 * SuggestUser Operation. 056 * 057 * @since 5.7.3 058 */ 059@Operation(id = SuggestUserEntries.ID, category = Constants.CAT_SERVICES, label = "Get user/group suggestion", description = "Get the user/group list of the running instance. This is returning a blob containing a serialized JSON array..", addToStudio = false) 060public class SuggestUserEntries { 061 062 @SuppressWarnings("unused") 063 private static final Log log = LogFactory.getLog(SuggestUserEntries.class); 064 065 public static final String ID = "UserGroup.Suggestion"; 066 067 @Context 068 protected OperationContext ctx; 069 070 @Context 071 protected SchemaManager schemaManager; 072 073 @Param(name = "searchTerm", alias = "prefix", required = false) 074 protected String prefix; 075 076 @Param(name = "searchType", required = false) 077 protected String searchType; 078 079 @Param(name = "groupRestriction", required = false, description = "Enter the id of a group to suggest only user from this group.") 080 protected String groupRestriction; 081 082 /** 083 * @since 7.10 084 */ 085 @Param(name = "hideAdminGroups", required = false, description = "If set, remove all administrator groups from the suggestions") 086 protected boolean hideAdminGroups; 087 088 @Param(name = "userSuggestionMaxSearchResults", required = false) 089 protected Integer userSuggestionMaxSearchResults; 090 091 @Param(name = "firstLabelField", required = false) 092 protected String firstLabelField; 093 094 @Param(name = "secondLabelField", required = false) 095 protected String secondLabelField; 096 097 @Param(name = "thirdLabelField", required = false) 098 protected String thirdLabelField; 099 100 @Param(name = "hideFirstLabel", required = false) 101 protected boolean hideFirstLabel = false; 102 103 @Param(name = "hideSecondLabel", required = false) 104 protected boolean hideSecondLabel = false; 105 106 @Param(name = "hideThirdLabel", required = false) 107 protected boolean hideThirdLabel; 108 109 @Param(name = "displayEmailInSuggestion", required = false) 110 protected boolean displayEmailInSuggestion; 111 112 @Param(name = "hideIcon", required = false) 113 protected boolean hideIcon; 114 115 @Context 116 protected UserManager userManager; 117 118 @Context 119 protected DirectoryService directoryService; 120 121 @Param(name = "lang", required = false) 122 protected String lang; 123 124 @OperationMethod 125 public Blob run() { 126 JSONArray result = new JSONArray(); 127 boolean isGroupRestriction = !StringUtils.isBlank(groupRestriction); 128 boolean groupOnly = false; 129 boolean userOnly = isGroupRestriction; 130 131 if (!isGroupRestriction && searchType != null && !searchType.isEmpty()) { 132 if (searchType.equals(Select2Common.USER_TYPE)) { 133 userOnly = true; 134 } else if (searchType.equals(Select2Common.GROUP_TYPE)) { 135 groupOnly = true; 136 } 137 } 138 try { 139 DocumentModelList userList = null; 140 DocumentModelList groupList = null; 141 if (!groupOnly) { 142 Schema schema = schemaManager.getSchema(userManager.getUserSchemaName()); 143 userList = userManager.searchUsers(prefix); 144 Directory userDir = directoryService.getDirectory(userManager.getUserDirectoryName()); 145 for (DocumentModel user : userList) { 146 JSONObject obj = new JSONObject(); 147 for (Field field : schema.getFields()) { 148 QName fieldName = field.getName(); 149 String key = fieldName.getLocalName(); 150 Serializable value = user.getPropertyValue(fieldName.getPrefixedName()); 151 if (key.equals(userDir.getPasswordField())) { 152 continue; 153 } 154 obj.element(key, value); 155 } 156 String userId = user.getId(); 157 obj.put(Select2Common.ID, userId); 158 obj.put(Select2Common.TYPE_KEY_NAME, Select2Common.USER_TYPE); 159 obj.put(Select2Common.PREFIXED_ID_KEY_NAME, NuxeoPrincipal.PREFIX + userId); 160 Select2Common.computeUserLabel(obj, firstLabelField, secondLabelField, thirdLabelField, 161 hideFirstLabel, hideSecondLabel, hideThirdLabel, displayEmailInSuggestion, userId); 162 Select2Common.computeUserGroupIcon(obj, hideIcon); 163 if (isGroupRestriction) { 164 // We need to load all data about the user particularly 165 // its 166 // groups. 167 user = userManager.getUserModel(userId); 168 UserAdapter userAdapter = user.getAdapter(UserAdapter.class); 169 List<String> groups = userAdapter.getGroups(); 170 if (groups != null && groups.contains(groupRestriction)) { 171 result.add(obj); 172 } 173 } else { 174 result.add(obj); 175 } 176 } 177 } 178 if (!userOnly) { 179 Schema schema = schemaManager.getSchema(userManager.getGroupSchemaName()); 180 groupList = userManager.searchGroups(prefix); 181 List<String> admins = new ArrayList<>(); 182 if (hideAdminGroups) { 183 admins = userManager.getAdministratorsGroups(); 184 } 185 groupLoop: 186 for (DocumentModel group : groupList) { 187 if (hideAdminGroups) { 188 for (String adminGroupName : admins) { 189 if (adminGroupName.equals(group.getId())) { 190 break groupLoop; 191 } 192 } 193 } 194 JSONObject obj = new JSONObject(); 195 for (Field field : schema.getFields()) { 196 QName fieldName = field.getName(); 197 String key = fieldName.getLocalName(); 198 Serializable value = group.getPropertyValue(fieldName.getPrefixedName()); 199 obj.element(key, value); 200 } 201 String groupId = group.getId(); 202 obj.put(Select2Common.ID, groupId); 203 // If the group hasn't an label, let's put the groupid 204 Select2Common.computeGroupLabel(obj, groupId, userManager.getGroupLabelField(), hideFirstLabel); 205 obj.put(Select2Common.TYPE_KEY_NAME, Select2Common.GROUP_TYPE); 206 obj.put(Select2Common.PREFIXED_ID_KEY_NAME, NuxeoGroup.PREFIX + groupId); 207 Select2Common.computeUserGroupIcon(obj, hideIcon); 208 result.add(obj); 209 } 210 } 211 212 // Limit size results. 213 int userSize = userList != null ? userList.size() : 0; 214 int groupSize = groupList != null ? groupList.size() : 0; 215 int totalSize = userSize + groupSize; 216 if (userSuggestionMaxSearchResults != null && userSuggestionMaxSearchResults > 0) { 217 if (userSize > userSuggestionMaxSearchResults || groupSize > userSuggestionMaxSearchResults 218 || totalSize > userSuggestionMaxSearchResults) { 219 throw new SizeLimitExceededException(); 220 } 221 } 222 223 } catch (SizeLimitExceededException e) { 224 return searchOverflowMessage(); 225 } 226 227 return Blobs.createBlob(result.toString(), "application/json"); 228 } 229 230 /** 231 * @return searchOverflowMessage 232 * @since 5.7.3 233 */ 234 private Blob searchOverflowMessage() { 235 JSONArray result = new JSONArray(); 236 JSONObject obj = new JSONObject(); 237 obj.put(Select2Common.LABEL, 238 I18NUtils.getMessageString("messages", "label.security.searchOverFlow", new Object[0], getLocale())); 239 result.add(obj); 240 return Blobs.createBlob(result.toString(), "application/json"); 241 } 242 243 protected String getLang() { 244 if (lang == null) { 245 lang = (String) ctx.get("lang"); 246 if (lang == null) { 247 lang = Select2Common.DEFAULT_LANG; 248 } 249 } 250 return lang; 251 } 252 253 protected Locale getLocale() { 254 return new Locale(getLang()); 255 } 256 257}