/*
* (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());
}
}