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.lang.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        if (contexts != null)
081        {
082            // search over the populations of the given context
083            _searchUsersByContext(users, jsParameters, source, parameters, new HashSet<>(contexts));
084        }
085        else
086        {
087            // search over the given population
088            String userPopulationId = (String) jsParameters.get("userPopulationId");
089            String userDirectoryId = null;
090            if (jsParameters.get("userDirectoryId") != null)
091            {
092                userDirectoryId = (String) jsParameters.get("userDirectoryId");
093                userDirectoryId = "-".equals(userDirectoryId) ? null : userDirectoryId;
094            }
095            _searchUsersByPopulation(users, jsParameters, source, parameters, userPopulationId, userDirectoryId);
096        }
097        
098        Map<String, Object> result = new HashMap<>();
099        result.put("users", users);
100
101        Request request = ObjectModelHelper.getRequest(objectModel);
102        request.setAttribute(JSonReader.OBJECT_TO_READ, result);
103
104        return EMPTY_MAP;
105    }
106    
107    /**
108     * Get the search parameters
109     * @param source The search pattern
110     * @return the search parameters
111     */
112    protected Map<String, Object> _getSearchParameters(String source)
113    {
114        Map<String, Object> params = new HashMap<>();
115        params.put("pattern", source);
116        return params;
117    }
118    
119    private void _searchUsersByContext(List<Map<String, Object>> users, Map<String, Object> jsParameters, String source, Parameters parameters, Set<String> contexts)
120    {
121        if (jsParameters.get("login") != null)
122        {
123            @SuppressWarnings("unchecked")
124            List<String> logins = (List<String>) jsParameters.get("login");
125            for (String login : logins)
126            {
127                users.add(_userHelper.user2json(_userManager.getUserByContext(contexts, login, true), true));
128            }
129        }
130        else if (jsParameters.get("value") != null)
131        {
132            String[] values = ((String) jsParameters.get("value")).split(",");
133            for (String value : values)
134            {
135                String login = StringUtils.substringBeforeLast(value, "#");
136                String populationId = StringUtils.substringAfterLast(value, "#");
137                users.add(_userHelper.user2json(new UserIdentity(login, populationId), true));
138            }
139        }
140        else
141        {
142            int count = parameters.getParameterAsInteger("limit", _DEFAULT_COUNT_VALUE);
143            if (count == -1)
144            {
145                count = Integer.MAX_VALUE;
146            }
147            int offset = parameters.getParameterAsInteger("start", _DEFAULT_OFFSET_VALUE);
148            
149            List<User> usersByContext = _userManager.getUsersByContext(contexts, count, offset, _getSearchParameters(source), true);
150            users.addAll(_userHelper.users2json(usersByContext, true));
151        }
152    }
153    
154    private void _searchUsersByPopulation(List<Map<String, Object>> users, Map<String, Object> jsParameters, String source, Parameters parameters, String userPopulationId, String userDirectoryId)
155    {
156        if (jsParameters.get("login") != null && userDirectoryId != null)
157        {
158            @SuppressWarnings("unchecked")
159            List<String> logins = (List<String>) jsParameters.get("login");
160            for (String login : logins)
161            {
162                users.add(_userHelper.user2json(_userManager.getUserByDirectory(userPopulationId, userDirectoryId, login), true));
163            }
164        }
165        else if (jsParameters.get("login") != null)
166        {
167            // userDirectoryId = null => take account of all the user directories
168            @SuppressWarnings("unchecked")
169            List<String> logins = (List<String>) jsParameters.get("login");
170            for (String login : logins)
171            {
172                users.add(_userHelper.user2json(_userManager.getUser(userPopulationId, login), true));
173            }
174        }
175        else if (userDirectoryId != null)
176        {
177            int count = parameters.getParameterAsInteger("limit", _DEFAULT_COUNT_VALUE);
178            if (count == -1)
179            {
180                count = Integer.MAX_VALUE;
181            }
182            int offset = parameters.getParameterAsInteger("start", _DEFAULT_OFFSET_VALUE);
183            
184            users.addAll(_userHelper.users2json(_userManager.getUsersByDirectory(userPopulationId, userDirectoryId, count, offset, _getSearchParameters(source)), true));
185        }
186        else
187        {
188            // userDirectoryId = null => take account of all the user directories
189            int count = parameters.getParameterAsInteger("limit", _DEFAULT_COUNT_VALUE);
190            if (count == -1)
191            {
192                count = Integer.MAX_VALUE;
193            }
194            int offset = parameters.getParameterAsInteger("start", _DEFAULT_OFFSET_VALUE);
195            
196            users.addAll(_userHelper.users2json(_userManager.getUsers(userPopulationId, count, offset, _getSearchParameters(source)), true));
197        }
198    }
199}