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