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