/* * (C) Copyright 2013 Nuxeo SA (http://nuxeo.com/) and others. * * Licensed 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 * * http://www.apache.org/licenses/LICENSE-2.0 * * 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. * * Contributors: * <a href="mailto:grenard@nuxeo.com">Guillaume</a> */ package org.nuxeo.ecm.automation.core.operations.users; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.Locale; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.nuxeo.common.utils.i18n.I18NUtils; import org.nuxeo.ecm.automation.OperationContext; import org.nuxeo.ecm.automation.core.Constants; import org.nuxeo.ecm.automation.core.annotations.Context; import org.nuxeo.ecm.automation.core.annotations.Operation; import org.nuxeo.ecm.automation.core.annotations.OperationMethod; import org.nuxeo.ecm.automation.core.annotations.Param; import org.nuxeo.ecm.automation.features.SuggestConstants; import org.nuxeo.ecm.core.api.Blob; import org.nuxeo.ecm.core.api.Blobs; import org.nuxeo.ecm.core.api.DocumentModel; import org.nuxeo.ecm.core.api.DocumentModelList; import org.nuxeo.ecm.core.api.NuxeoGroup; import org.nuxeo.ecm.core.api.NuxeoPrincipal; import org.nuxeo.ecm.core.schema.SchemaManager; import org.nuxeo.ecm.core.schema.types.Field; import org.nuxeo.ecm.core.schema.types.QName; import org.nuxeo.ecm.core.schema.types.Schema; import org.nuxeo.ecm.directory.Directory; import org.nuxeo.ecm.directory.SizeLimitExceededException; import org.nuxeo.ecm.directory.api.DirectoryService; import org.nuxeo.ecm.platform.usermanager.UserAdapter; import org.nuxeo.ecm.platform.usermanager.UserManager; import net.sf.json.JSONArray; import net.sf.json.JSONObject; /** * SuggestUser Operation. * * @since 5.7.3 */ @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) public class SuggestUserEntries { @SuppressWarnings("unused") private static final Log log = LogFactory.getLog(SuggestUserEntries.class); public static final String ID = "UserGroup.Suggestion"; public static final String POWERUSERS = "powerusers"; @Context protected OperationContext ctx; @Context protected SchemaManager schemaManager; @Param(name = "searchTerm", alias = "prefix", required = false) protected String prefix; @Param(name = "searchType", required = false) protected String searchType; @Param(name = "groupRestriction", required = false, description = "Enter the id of a group to suggest only user from this group.") protected String groupRestriction; /** * @since 7.10 */ @Param(name = "hideAdminGroups", required = false, description = "If set, remove all administrator groups from the suggestions") protected boolean hideAdminGroups; /** * @since 8.3 */ @Param(name = "hidePowerUsersGroup", required = false, description = "If set, remove power users group from the suggestions") protected boolean hidePowerUsersGroup; @Param(name = "userSuggestionMaxSearchResults", required = false) protected Integer userSuggestionMaxSearchResults; @Param(name = "firstLabelField", required = false) protected String firstLabelField; @Param(name = "secondLabelField", required = false) protected String secondLabelField; @Param(name = "thirdLabelField", required = false) protected String thirdLabelField; @Param(name = "hideFirstLabel", required = false) protected boolean hideFirstLabel = false; @Param(name = "hideSecondLabel", required = false) protected boolean hideSecondLabel = false; @Param(name = "hideThirdLabel", required = false) protected boolean hideThirdLabel; @Param(name = "displayEmailInSuggestion", required = false) protected boolean displayEmailInSuggestion; @Param(name = "hideIcon", required = false) protected boolean hideIcon; @Context protected UserManager userManager; @Context protected DirectoryService directoryService; @Param(name = "lang", required = false) protected String lang; @OperationMethod public Blob run() { JSONArray result = new JSONArray(); boolean isGroupRestriction = !StringUtils.isBlank(groupRestriction); boolean groupOnly = false; boolean userOnly = isGroupRestriction; if (!isGroupRestriction && searchType != null && !searchType.isEmpty()) { if (searchType.equals(SuggestConstants.USER_TYPE)) { userOnly = true; } else if (searchType.equals(SuggestConstants.GROUP_TYPE)) { groupOnly = true; } } try { DocumentModelList userList = null; DocumentModelList groupList = null; if (!groupOnly) { Schema schema = schemaManager.getSchema(userManager.getUserSchemaName()); userList = userManager.searchUsers(prefix); Directory userDir = directoryService.getDirectory(userManager.getUserDirectoryName()); for (DocumentModel user : userList) { JSONObject obj = new JSONObject(); for (Field field : schema.getFields()) { QName fieldName = field.getName(); String key = fieldName.getLocalName(); Serializable value = user.getPropertyValue(fieldName.getPrefixedName()); if (key.equals(userDir.getPasswordField())) { continue; } obj.element(key, value); } String userId = user.getId(); obj.put(SuggestConstants.ID, userId); obj.put(SuggestConstants.TYPE_KEY_NAME, SuggestConstants.USER_TYPE); obj.put(SuggestConstants.PREFIXED_ID_KEY_NAME, NuxeoPrincipal.PREFIX + userId); SuggestConstants.computeUserLabel(obj, firstLabelField, secondLabelField, thirdLabelField, hideFirstLabel, hideSecondLabel, hideThirdLabel, displayEmailInSuggestion, userId); SuggestConstants.computeUserGroupIcon(obj, hideIcon); if (isGroupRestriction) { // We need to load all data about the user particularly // its // groups. user = userManager.getUserModel(userId); UserAdapter userAdapter = user.getAdapter(UserAdapter.class); List<String> groups = userAdapter.getGroups(); if (groups != null && groups.contains(groupRestriction)) { result.add(obj); } } else { result.add(obj); } } } if (!userOnly) { Schema schema = schemaManager.getSchema(userManager.getGroupSchemaName()); groupList = userManager.searchGroups(prefix); List<String> admins = new ArrayList<>(); if (hideAdminGroups) { admins = userManager.getAdministratorsGroups(); } groupLoop: for (DocumentModel group : groupList) { if (hideAdminGroups) { for (String adminGroupName : admins) { if (adminGroupName.equals(group.getId())) { break groupLoop; } } } if (hidePowerUsersGroup) { if (POWERUSERS.equals(group.getId())) { break groupLoop; } } JSONObject obj = new JSONObject(); for (Field field : schema.getFields()) { QName fieldName = field.getName(); String key = fieldName.getLocalName(); Serializable value = group.getPropertyValue(fieldName.getPrefixedName()); obj.element(key, value); } String groupId = group.getId(); obj.put(SuggestConstants.ID, groupId); // If the group hasn't an label, let's put the groupid SuggestConstants.computeGroupLabel(obj, groupId, userManager.getGroupLabelField(), hideFirstLabel); obj.put(SuggestConstants.TYPE_KEY_NAME, SuggestConstants.GROUP_TYPE); obj.put(SuggestConstants.PREFIXED_ID_KEY_NAME, NuxeoGroup.PREFIX + groupId); SuggestConstants.computeUserGroupIcon(obj, hideIcon); result.add(obj); } } // Limit size results. int userSize = userList != null ? userList.size() : 0; int groupSize = groupList != null ? groupList.size() : 0; int totalSize = userSize + groupSize; if (userSuggestionMaxSearchResults != null && userSuggestionMaxSearchResults > 0) { if (userSize > userSuggestionMaxSearchResults || groupSize > userSuggestionMaxSearchResults || totalSize > userSuggestionMaxSearchResults) { throw new SizeLimitExceededException(); } } } catch (SizeLimitExceededException e) { return searchOverflowMessage(); } return Blobs.createBlob(result.toString(), "application/json"); } /** * @return searchOverflowMessage * @since 5.7.3 */ private Blob searchOverflowMessage() { JSONArray result = new JSONArray(); JSONObject obj = new JSONObject(); obj.put(SuggestConstants.LABEL, I18NUtils.getMessageString("messages", "label.security.searchOverFlow", new Object[0], getLocale())); result.add(obj); return Blobs.createBlob(result.toString(), "application/json"); } protected String getLang() { if (lang == null) { lang = (String) ctx.get("lang"); if (lang == null) { lang = SuggestConstants.DEFAULT_LANG; } } return lang; } protected Locale getLocale() { return new Locale(getLang()); } }