001/*
002 *  Copyright 2016 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.impl.user.directory;
017
018import java.util.Collection;
019import java.util.HashMap;
020import java.util.List;
021import java.util.Map;
022import java.util.stream.Collectors;
023
024import org.apache.avalon.framework.component.Component;
025import org.apache.commons.lang3.StringUtils;
026
027import org.ametys.core.user.User;
028import org.ametys.core.user.UserIdentity;
029import org.ametys.core.user.directory.UserDirectory;
030import org.ametys.runtime.plugin.component.AbstractLogEnabled;
031
032/**
033 * This implementation only uses predefined users 
034 */
035public class StaticUserDirectory extends AbstractLogEnabled implements UserDirectory, Component
036{
037    private static final String __PARAM_USERS = "runtime.users.static.users";
038    
039    private Map<String, User> _staticUsers;
040
041    private String _udModelId;
042
043    private Map<String, Object> _paramValues;
044
045    private String _populationId;
046
047    private String _label;
048
049    private String _id;
050
051    private boolean _grantAllCredentials = true;
052    
053    public String getId()
054    {
055        return _id;
056    }
057    
058    public String getLabel()
059    {
060        return _label;
061    }
062    
063    @Override
064    public void init(String id, String udModelId, Map<String, Object> paramValues, String label)
065    {
066        _id = id;
067        _udModelId = udModelId;
068        _staticUsers = new HashMap<>();
069        _label = label;
070        
071        _paramValues = paramValues;
072        
073        String usersAsText = (String) paramValues.get(__PARAM_USERS);
074        for (String userLine : usersAsText.split("\\n"))
075        {
076            User user = _createUser(userLine);
077            _staticUsers.put(user.getIdentity().getLogin(), user);
078        }
079    }
080    
081    @Override
082    public void setPopulationId(String populationId)
083    {
084        _populationId = populationId;
085    }
086    
087    @Override
088    public String getPopulationId()
089    {
090        return _populationId;
091    }
092    
093    @Override
094    public Map<String, Object> getParameterValues()
095    {
096        return _paramValues;
097    }
098    
099    /**
100     * Set to false to disallow any user to be authenticated by its credentials
101     * @param grantAllCredentials true if the directory should grant all call to checkCredentials
102     */
103    public void setGrantAllCredentials(boolean grantAllCredentials)
104    {
105        _grantAllCredentials  = grantAllCredentials;
106    }
107    
108    @Override
109    public String getUserDirectoryModelId()
110    {
111        return _udModelId;
112    }
113    
114    @Override
115    public Collection<User> getUsers()
116    {
117        return _staticUsers.values();
118    }
119
120    @Override
121    public List<User> getUsers(int count, int offset, Map<String, Object> parameters)
122    {
123        String pattern = StringUtils.defaultIfEmpty((String) parameters.get("pattern"), "");
124        int boundedCount = count >= 0 ? count : Integer.MAX_VALUE;
125        int boundedOffset = offset >= 0 ? offset : 0;
126        
127        List<User> result = _staticUsers.values().stream().filter(user-> _isLike(user, pattern)).collect(Collectors.toList());
128        
129        int toIndex = boundedOffset + boundedCount; 
130        toIndex = toIndex > result.size() ? result.size() : toIndex;
131        return result.subList(boundedOffset, toIndex);
132    }
133
134    @Override
135    public User getUser(String login)
136    {
137        return _staticUsers.get(login);
138    }
139
140    @Override
141    public boolean checkCredentials(String login, String password)
142    {
143        return _grantAllCredentials && _staticUsers.containsKey(login);
144    }
145    
146    @SuppressWarnings("fallthrough")
147    private User _createUser(String userLine)
148    {
149        String[] userInfo = userLine.split(":");
150        
151        String login = null;
152        String lastName = null;
153        String firstName = null;
154        String email = null;
155        
156        switch (userInfo.length)
157        {
158            case 4:
159                email = userInfo[3];
160                //fall through
161            case 3:
162                firstName = userInfo[2];
163                //fall through
164            case 2:
165                lastName = userInfo[1];
166                login = userInfo[0];
167                break;
168            case 1:
169                login = userInfo[0];
170                lastName = login;
171                break;
172            default:
173                getLogger().error("Error while reading StaticUserDirectory users, cannot create an user with the data from line {}", userLine);
174                break;
175        }
176        
177        return new User(new UserIdentity(login, _populationId), lastName, firstName, email, this);
178    }
179    
180    private boolean _isLike(User user, String pattern)
181    {
182        String modifiedPattern = StringUtils.stripAccents(pattern);
183        return StringUtils.containsIgnoreCase(StringUtils.stripAccents(user.getIdentity().getLogin()), modifiedPattern) 
184                || StringUtils.containsIgnoreCase(StringUtils.stripAccents(user.getFirstName()), modifiedPattern)
185                || StringUtils.containsIgnoreCase(StringUtils.stripAccents(user.getLastName()), modifiedPattern);
186    }
187}