001/*
002 *  Copyright 2015 Anyware Services
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 */
016package org.ametys.plugins.core.user;
017
018import java.util.ArrayList;
019import java.util.HashMap;
020import java.util.HashSet;
021import java.util.List;
022import java.util.Map;
023import java.util.Set;
024
025import org.apache.avalon.framework.parameters.Parameters;
026import org.apache.avalon.framework.service.ServiceException;
027import org.apache.avalon.framework.service.ServiceManager;
028import org.apache.avalon.framework.service.Serviceable;
029import org.apache.avalon.framework.thread.ThreadSafe;
030import org.apache.cocoon.acting.AbstractAction;
031import org.apache.cocoon.environment.ObjectModelHelper;
032import org.apache.cocoon.environment.Redirector;
033import org.apache.cocoon.environment.Request;
034import org.apache.cocoon.environment.SourceResolver;
035import org.apache.commons.lang3.StringUtils;
036
037import org.ametys.core.cocoon.JSonReader;
038import org.ametys.core.user.CurrentUserProvider;
039import org.ametys.core.user.User;
040import org.ametys.core.user.UserIdentity;
041import org.ametys.core.user.UserManager;
042import org.ametys.runtime.authentication.AccessDeniedException;
043
044/**
045 * Get users.
046 */
047public class UserSearchAction extends AbstractAction implements ThreadSafe, Serviceable
048{
049    private static final int _DEFAULT_COUNT_VALUE = 100;
050    private static final int _DEFAULT_OFFSET_VALUE = 0;
051    
052    private UserManager _userManager;
053    private UserHelper _userHelper;
054    private CurrentUserProvider _userProvider;
055    
056    @Override
057    public void service(ServiceManager manager) throws ServiceException
058    {
059        _userManager = (UserManager) manager.lookup(UserManager.ROLE);
060        _userHelper = (UserHelper) manager.lookup(UserHelper.ROLE);
061        _userProvider = (CurrentUserProvider) manager.lookup(CurrentUserProvider.ROLE);
062    }
063    
064    @Override
065    public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters parameters) throws Exception
066    {
067        @SuppressWarnings("unchecked")
068        Map<String, Object> jsParameters = (Map<String, Object>) objectModel.get(ObjectModelHelper.PARENT_CONTEXT);
069        
070        List<Map<String, Object>> users = new ArrayList<>();
071        
072        if (_userProvider.getUser() == null)
073        {
074            throw new AccessDeniedException("Anonymous user tried to access to users list");
075        }
076        
077        @SuppressWarnings("unchecked")
078        List<String> contexts = (List<String>) jsParameters.get("contexts");
079        
080        boolean userPopulationOnly = Boolean.TRUE.equals(jsParameters.get("userPopulationOnly")); // Filter on current user's population only
081        
082        if (userPopulationOnly || contexts == null)
083        {
084            // search over the given population
085            String userPopulationId = userPopulationOnly ? _userProvider.getUser().getPopulationId() : (String) jsParameters.get("userPopulationId");
086            String userDirectoryId = null;
087            if (jsParameters.get("userDirectoryId") != null)
088            {
089                userDirectoryId = (String) jsParameters.get("userDirectoryId");
090                userDirectoryId = "-".equals(userDirectoryId) ? null : userDirectoryId;
091            }
092            
093            _searchUsersByPopulation(users, jsParameters, source, parameters, userPopulationId, userDirectoryId);
094        }
095        else
096        {
097            // search over the populations of the given context
098            _searchUsersByContext(users, jsParameters, source, parameters, new HashSet<>(contexts));
099        }
100        
101        Map<String, Object> result = new HashMap<>();
102        result.put("users", users);
103
104        Request request = ObjectModelHelper.getRequest(objectModel);
105        request.setAttribute(JSonReader.OBJECT_TO_READ, result);
106
107        return EMPTY_MAP;
108    }
109    
110    /**
111     * Get the search parameters
112     * @param source The search pattern
113     * @return the search parameters
114     */
115    protected Map<String, Object> _getSearchParameters(String source)
116    {
117        Map<String, Object> params = new HashMap<>();
118        params.put("pattern", source);
119        return params;
120    }
121    
122    private void _searchUsersByContext(List<Map<String, Object>> users, Map<String, Object> jsParameters, String source, Parameters parameters, Set<String> contexts)
123    {
124        if (jsParameters.get("login") != null)
125        {
126            @SuppressWarnings("unchecked")
127            List<String> logins = (List<String>) jsParameters.get("login");
128            for (String login : logins)
129            {
130                users.add(_userHelper.user2json(_userManager.getUserByContext(contexts, login, true), true));
131            }
132        }
133        else if (jsParameters.get("value") != null)
134        {
135            String[] values = ((String) jsParameters.get("value")).split(",");
136            for (String value : values)
137            {
138                String login = StringUtils.substringBeforeLast(value, "#");
139                String populationId = StringUtils.substringAfterLast(value, "#");
140                users.add(_userHelper.user2json(new UserIdentity(login, populationId), true));
141            }
142        }
143        else
144        {
145            int count = parameters.getParameterAsInteger("limit", _DEFAULT_COUNT_VALUE);
146            if (count == -1)
147            {
148                count = Integer.MAX_VALUE;
149            }
150            int offset = parameters.getParameterAsInteger("start", _DEFAULT_OFFSET_VALUE);
151            
152            List<User> usersByContext = _userManager.getUsersByContext(contexts, count, offset, _getSearchParameters(source), true);
153            users.addAll(_userHelper.users2json(usersByContext, true));
154        }
155    }
156    
157    private void _searchUsersByPopulation(List<Map<String, Object>> users, Map<String, Object> jsParameters, String source, Parameters parameters, String userPopulationId, String userDirectoryId)
158    {
159        if (jsParameters.get("login") != null && userDirectoryId != null)
160        {
161            @SuppressWarnings("unchecked")
162            List<String> logins = (List<String>) jsParameters.get("login");
163            for (String login : logins)
164            {
165                users.add(_userHelper.user2json(_userManager.getUserByDirectory(userPopulationId, userDirectoryId, login), true));
166            }
167        }
168        else if (jsParameters.get("login") != null)
169        {
170            // userDirectoryId = null => take account of all the user directories
171            @SuppressWarnings("unchecked")
172            List<String> logins = (List<String>) jsParameters.get("login");
173            for (String login : logins)
174            {
175                users.add(_userHelper.user2json(_userManager.getUser(userPopulationId, login), true));
176            }
177        }
178        else if (userDirectoryId != null)
179        {
180            int count = parameters.getParameterAsInteger("limit", _DEFAULT_COUNT_VALUE);
181            if (count == -1)
182            {
183                count = Integer.MAX_VALUE;
184            }
185            int offset = parameters.getParameterAsInteger("start", _DEFAULT_OFFSET_VALUE);
186            
187            users.addAll(_userHelper.users2json(_userManager.getUsersByDirectory(userPopulationId, userDirectoryId, count, offset, _getSearchParameters(source)), true));
188        }
189        else
190        {
191            // userDirectoryId = null => take account of all the user directories
192            int count = parameters.getParameterAsInteger("limit", _DEFAULT_COUNT_VALUE);
193            if (count == -1)
194            {
195                count = Integer.MAX_VALUE;
196            }
197            int offset = parameters.getParameterAsInteger("start", _DEFAULT_OFFSET_VALUE);
198            
199            users.addAll(_userHelper.users2json(_userManager.getUsers(userPopulationId, count, offset, _getSearchParameters(source)), true));
200        }
201    }
202}