/* * SonarQube * Copyright (C) 2009-2017 SonarSource SA * mailto:info AT sonarsource DOT com * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Splitter; import com.google.common.base.Strings; import com.google.common.collect.ImmutableList; import com.google.common.collect.Maps; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.regex.Pattern; import org.apache.commons.lang.StringUtils; import org.sonar.api.Properties; import org.sonar.api.Property; import org.sonar.api.PropertyType; import org.sonar.api.config.Settings; import org.sonar.api.security.LoginPasswordAuthenticator; import org.sonar.api.security.UserDetails; import org.sonar.api.utils.log.Logger; import org.sonar.api.utils.log.Loggers; @Properties({ @Property( key = FakeAuthenticator.DATA_PROPERTY, name = "Fake Users", type = PropertyType.TEXT ) }) public class FakeAuthenticator implements LoginPasswordAuthenticator { private static final Logger LOG = Loggers.get(FakeAuthenticator.class); /** * Example: * <pre> * evgeny.password=foo * evgeny.name=Evgeny Mandrikov * evgeny.email=evgeny@example.org * evgeny.groups=sonar-users * * simon.password=bar * simon.groups=sonar-users,sonar-developers * </pre> */ public static final String DATA_PROPERTY = "sonar.fakeauthenticator.users"; private final Settings settings; private Map<String, String> data; public FakeAuthenticator(Settings settings) { this.settings = settings; } public boolean authenticate(String username, String password) { // Never touch admin if (isAdmin(username)) { return true; } reloadData(); checkExistence(username); String expectedPassword = data.get(username + ".password"); if (StringUtils.equals(password, expectedPassword)) { LOG.info("user {} with password {}", username, password); return true; } else { LOG.info("user " + username + " expected password " + expectedPassword + " , but was " + password); return false; } } private void checkExistence(String username) { if (!data.containsKey(username + ".password")) { throw new IllegalArgumentException("No such user : " + username); } } public UserDetails doGetUserDetails(String username) { // Never touch admin if (isAdmin(username)) { return null; } reloadData(); checkExistence(username); UserDetails result = new UserDetails(); result.setName(Strings.nullToEmpty(data.get(username + ".name"))); result.setEmail(Strings.nullToEmpty(data.get(username + ".email"))); LOG.info("details for user {} : {}", username, result); return result; } public Collection<String> doGetGroups(String username) { // Never touch admin if (isAdmin(username)) { return null; } reloadData(); checkExistence(username); Collection<String> result = parseList(data.get(username + ".groups")); LOG.info("groups for user {} : {}", username, result); return result; } private static boolean isAdmin(String username) { return StringUtils.equals(username, "admin"); } private void reloadData() { data = parse(settings.getString(DATA_PROPERTY)); } private static final Splitter LIST_SPLITTER = Splitter.on(',').omitEmptyStrings().trimResults(); private static final Splitter LINE_SPLITTER = Splitter.on(Pattern.compile("\r?\n")).omitEmptyStrings().trimResults(); @VisibleForTesting static List<String> parseList(String data) { return ImmutableList.copyOf(LIST_SPLITTER.split(Strings.nullToEmpty(data))); } @VisibleForTesting static Map<String, String> parse(String data) { Map<String, String> result = Maps.newHashMap(); for (String entry : LINE_SPLITTER.split(Strings.nullToEmpty(data))) { Iterator<String> keyValue = Splitter.on('=').split(entry).iterator(); result.put(keyValue.next(), keyValue.next()); } return result; } public void init() { // nothing to do } }