001/*
002 * (C) Copyright 2006-2018 Nuxeo(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 *     Thomas Roger
018 */
019package org.nuxeo.ecm.automation.core.operations.users;
020
021import static org.nuxeo.ecm.platform.usermanager.UserConfig.COMPANY_COLUMN;
022import static org.nuxeo.ecm.platform.usermanager.UserConfig.EMAIL_COLUMN;
023import static org.nuxeo.ecm.platform.usermanager.UserConfig.FIRSTNAME_COLUMN;
024import static org.nuxeo.ecm.platform.usermanager.UserConfig.LASTNAME_COLUMN;
025import static org.nuxeo.ecm.platform.usermanager.UserConfig.SCHEMA_NAME;
026import static org.nuxeo.ecm.platform.usermanager.UserConfig.TENANT_ID_COLUMN;
027import static org.nuxeo.ecm.platform.usermanager.UserConfig.USERNAME_COLUMN;
028
029import java.io.IOException;
030import java.io.Serializable;
031import java.util.ArrayList;
032import java.util.Arrays;
033import java.util.Collections;
034import java.util.HashMap;
035import java.util.HashSet;
036import java.util.LinkedHashMap;
037import java.util.List;
038import java.util.Map;
039import java.util.Set;
040
041import org.apache.commons.lang3.StringUtils;
042import org.nuxeo.ecm.automation.core.Constants;
043import org.nuxeo.ecm.automation.core.annotations.Context;
044import org.nuxeo.ecm.automation.core.annotations.Operation;
045import org.nuxeo.ecm.automation.core.annotations.OperationMethod;
046import org.nuxeo.ecm.automation.core.annotations.Param;
047import org.nuxeo.ecm.core.api.Blob;
048import org.nuxeo.ecm.core.api.Blobs;
049import org.nuxeo.ecm.core.api.DocumentModel;
050import org.nuxeo.ecm.core.api.DocumentModelList;
051import org.nuxeo.ecm.platform.usermanager.UserManager;
052
053/**
054 * @since 5.6
055 */
056@Operation(id = QueryUsers.ID, //
057        category = Constants.CAT_USERS_GROUPS, //
058        aliases = { "Services.QueryUsers" }, //
059        label = "Query users", //
060        description = "Query users on a combination of their username, firstName and lastName fields, or on any of them (pattern).")
061public class QueryUsers {
062
063    public static final String ID = "User.Query";
064
065    public static final Set<String> FULLTEXT_FIELDS = new HashSet<>(
066            Arrays.asList(USERNAME_COLUMN, FIRSTNAME_COLUMN, LASTNAME_COLUMN));
067
068    public static final String JSON_USERNAME = USERNAME_COLUMN;
069
070    public static final String JSON_FIRSTNAME = FIRSTNAME_COLUMN;
071
072    public static final String JSON_LASTNAME = LASTNAME_COLUMN;
073
074    public static final String JSON_EMAIL = EMAIL_COLUMN;
075
076    public static final String JSON_COMPANY = COMPANY_COLUMN;
077
078    public static final String JSON_TENANT_ID = TENANT_ID_COLUMN;
079
080    @Context
081    protected UserManager userManager;
082
083    @Param(name = "username", required = false)
084    protected String username;
085
086    @Param(name = "firstName", required = false)
087    protected String firstName;
088
089    @Param(name = "lastName", required = false)
090    protected String lastName;
091
092    @Param(name = "pattern", required = false)
093    protected String pattern;
094
095    @Param(name = "tenantId", required = false)
096    protected String tenantId;
097
098    @OperationMethod
099    public Blob run() throws IOException {
100        List<DocumentModel> users;
101        if (StringUtils.isBlank(pattern)) {
102            Map<String, Serializable> filter = new HashMap<>();
103            if (StringUtils.isNotBlank(username)) {
104                filter.put(USERNAME_COLUMN, username);
105            }
106            if (StringUtils.isNotBlank(firstName)) {
107                filter.put(FIRSTNAME_COLUMN, firstName);
108            }
109            if (StringUtils.isNotBlank(lastName)) {
110                filter.put(LASTNAME_COLUMN, lastName);
111            }
112            if (StringUtils.isNotBlank(tenantId)) {
113                filter.put(TENANT_ID_COLUMN, tenantId);
114            }
115            users = userManager.searchUsers(filter, FULLTEXT_FIELDS);
116        } else {
117            users = new ArrayList<>();
118            Set<String> userIds = new HashSet<>();
119            for (String field : FULLTEXT_FIELDS) {
120                Map<String, Serializable> filter = new HashMap<>();
121                filter.put(field, pattern);
122                if (StringUtils.isNotBlank(tenantId)) {
123                    filter.put(TENANT_ID_COLUMN, tenantId);
124                }
125                DocumentModelList userDocs = userManager.searchUsers(filter, Collections.singleton(field));
126                for (DocumentModel userDoc : userDocs) {
127                    if (userIds.add(userDoc.getId())) { // avoid duplicates
128                        users.add(userDoc);
129                    }
130                }
131            }
132        }
133        return buildResponse(users);
134    }
135
136    protected Blob buildResponse(List<DocumentModel> users) throws IOException {
137        List<Map<String, Object>> array = new ArrayList<>();
138        for (DocumentModel user : users) {
139            Map<String, Object> o = new LinkedHashMap<>();
140            putIfNotNull(o, JSON_USERNAME, user.getProperty(SCHEMA_NAME, USERNAME_COLUMN));
141            putIfNotNull(o, JSON_FIRSTNAME, user.getProperty(SCHEMA_NAME, FIRSTNAME_COLUMN));
142            putIfNotNull(o, JSON_LASTNAME, user.getProperty(SCHEMA_NAME, LASTNAME_COLUMN));
143            putIfNotNull(o, JSON_EMAIL, user.getProperty(SCHEMA_NAME, EMAIL_COLUMN));
144            putIfNotNull(o, JSON_COMPANY, user.getProperty(SCHEMA_NAME, COMPANY_COLUMN));
145            putIfNotNull(o, JSON_TENANT_ID, user.getProperty(SCHEMA_NAME, TENANT_ID_COLUMN));
146            array.add(o);
147        }
148        return Blobs.createJSONBlobFromValue(Collections.singletonMap("users", array));
149    }
150
151    protected void putIfNotNull(Map<String, Object> map, String key, Object value) {
152        if (value != null) {
153            map.put(key, value);
154        }
155    }
156
157}