From d9336198cba4299a3fd2f0b911c9ce06a6514009 Mon Sep 17 00:00:00 2001 From: Evgeny Mandrikov Date: Wed, 11 Jan 2012 13:45:38 +0400 Subject: SONAR-3137,SONAR-2292 Add synchronization of groups, prepare API for future enhancements --- .../sonar/api/security/ExternalGroupsProvider.java | 15 ++- .../sonar/api/security/ExternalUsersProvider.java | 15 ++- .../api/security/LoginPasswordAuthenticator.java | 15 ++- .../main/java/org/sonar/api/security/Realm.java | 60 --------- .../java/org/sonar/api/security/SecurityRealm.java | 61 +++++++++ .../java/org/sonar/api/security/UserDetails.java | 17 ++- sonar-server/src/dev/postgresql/conf/logback.xml | 28 ++-- .../java/org/sonar/server/platform/Platform.java | 4 +- .../org/sonar/server/ui/CompatibilityRealm.java | 6 +- .../java/org/sonar/server/ui/RealmFactory.java | 123 ------------------ .../org/sonar/server/ui/SecurityRealmFactory.java | 123 ++++++++++++++++++ .../main/webapp/WEB-INF/lib/need_authentication.rb | 27 +++- .../sonar/server/ui/CompatibilityRealmTest.java | 2 +- .../java/org/sonar/server/ui/RealmFactoryTest.java | 140 -------------------- .../sonar/server/ui/SecurityRealmFactoryTest.java | 141 +++++++++++++++++++++ 15 files changed, 410 insertions(+), 367 deletions(-) delete mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/security/Realm.java create mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/security/SecurityRealm.java delete mode 100644 sonar-server/src/main/java/org/sonar/server/ui/RealmFactory.java create mode 100644 sonar-server/src/main/java/org/sonar/server/ui/SecurityRealmFactory.java delete mode 100644 sonar-server/src/test/java/org/sonar/server/ui/RealmFactoryTest.java create mode 100644 sonar-server/src/test/java/org/sonar/server/ui/SecurityRealmFactoryTest.java diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/security/ExternalGroupsProvider.java b/sonar-plugin-api/src/main/java/org/sonar/api/security/ExternalGroupsProvider.java index c6f7c501f22..0410b66cc90 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/security/ExternalGroupsProvider.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/security/ExternalGroupsProvider.java @@ -19,17 +19,20 @@ */ package org.sonar.api.security; -import com.google.common.annotations.Beta; -import org.sonar.api.ServerExtension; - import java.util.Collection; /** + * Note that prefix "do" for names of methods is reserved for future enhancements, thus should not be used in subclasses. + * * @since 2.14 + * @see SecurityRealm */ -@Beta -public interface ExternalGroupsProvider extends ServerExtension { +public abstract class ExternalGroupsProvider { - Collection doGetGroups(String username); + /** + * @return list of groups associated with specified user, or null if such user doesn't exist + * @throws RuntimeException in case of unexpected error such as connection failure + */ + public abstract Collection doGetGroups(String username); } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/security/ExternalUsersProvider.java b/sonar-plugin-api/src/main/java/org/sonar/api/security/ExternalUsersProvider.java index 5e49ef8116f..00f7dfb4dac 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/security/ExternalUsersProvider.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/security/ExternalUsersProvider.java @@ -19,15 +19,18 @@ */ package org.sonar.api.security; -import com.google.common.annotations.Beta; -import org.sonar.api.ServerExtension; - /** + * Note that prefix "do" for names of methods is reserved for future enhancements, thus should not be used in subclasses. + * * @since 2.14 + * @see SecurityRealm */ -@Beta -public interface ExternalUsersProvider extends ServerExtension { +public abstract class ExternalUsersProvider { - UserDetails doGetUserDetails(String username); + /** + * @return details for specified user, or null if such user doesn't exist + * @throws RuntimeException in case of unexpected error such as connection failure + */ + public abstract UserDetails doGetUserDetails(String username); } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/security/LoginPasswordAuthenticator.java b/sonar-plugin-api/src/main/java/org/sonar/api/security/LoginPasswordAuthenticator.java index 7160746c8e5..8ca6f97864f 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/security/LoginPasswordAuthenticator.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/security/LoginPasswordAuthenticator.java @@ -23,14 +23,21 @@ import org.sonar.api.ServerExtension; /** * @since 1.12 + * @see SecurityRealm */ public interface LoginPasswordAuthenticator extends ServerExtension { /** - * Throws a runtime exception if the authenticator can not be initialized at sonar server startup, eg. if the connection to LDAP server is refused. + * @throws RuntimeException if the authenticator can not be initialized at sonar server startup, eg. if the connection to LDAP server is refused + * @deprecated in 2.14, but was left for backward compatibility - when this authenticator is not a part of {@link SecurityRealm}, otherwise has no effect and not invoked */ + @Deprecated void init(); - boolean authenticate(String login, String password); - -} \ No newline at end of file + /** + * @return true, if user was successfully authenticated with specified username and password, false otherwise + * @throws RuntimeException in case of unexpected error such as connection failure + */ + boolean authenticate(String username, String password); + +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/security/Realm.java b/sonar-plugin-api/src/main/java/org/sonar/api/security/Realm.java deleted file mode 100644 index 5ef15b9238c..00000000000 --- a/sonar-plugin-api/src/main/java/org/sonar/api/security/Realm.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Sonar, open source software quality management tool. - * Copyright (C) 2008-2012 SonarSource - * mailto:contact AT sonarsource DOT com - * - * Sonar 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. - * - * Sonar 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 Sonar; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.api.security; - -import com.google.common.annotations.Beta; -import org.sonar.api.ServerExtension; - -/** - * @since 2.14 - */ -@Beta -public abstract class Realm implements ServerExtension { - - /** - * @return unique name of this realm, e.g. "LDAP" - */ - public String getName() { - return getClass().getSimpleName(); - } - - public void init() { - } - - /** - * @return {@link LoginPasswordAuthenticator} associated with this realm, never null - */ - public abstract LoginPasswordAuthenticator getAuthenticator(); - - /** - * @return {@link ExternalUsersProvider} associated with this realm, null if not supported - */ - public ExternalUsersProvider getUsersProvider() { - return null; - } - - /** - * @return {@link ExternalGroupsProvider} associated with this realm, null if not supported - */ - public ExternalGroupsProvider getGroupsProvider() { - return null; - } - -} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/security/SecurityRealm.java b/sonar-plugin-api/src/main/java/org/sonar/api/security/SecurityRealm.java new file mode 100644 index 00000000000..f21d4d26946 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/security/SecurityRealm.java @@ -0,0 +1,61 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.api.security; + +import org.sonar.api.ServerExtension; + +/** + * @since 2.14 + */ +public abstract class SecurityRealm implements ServerExtension { + + /** + * @return unique name of this realm, e.g. "LDAP" + */ + public String getName() { + return getClass().getSimpleName(); + } + + /** + * Invoked during server startup and can be used to initialize internal state. + */ + public void init() { + } + + /** + * @return {@link LoginPasswordAuthenticator} associated with this realm, never null + */ + public abstract LoginPasswordAuthenticator getLoginPasswordAuthenticator(); + + /** + * @return {@link ExternalUsersProvider} associated with this realm, null if not supported + */ + public ExternalUsersProvider getUsersProvider() { + return null; + } + + /** + * @return {@link ExternalGroupsProvider} associated with this realm, null if not supported + */ + public ExternalGroupsProvider getGroupsProvider() { + return null; + } + +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/security/UserDetails.java b/sonar-plugin-api/src/main/java/org/sonar/api/security/UserDetails.java index e5a4db4b40f..e3519866a13 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/security/UserDetails.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/security/UserDetails.java @@ -19,18 +19,18 @@ */ package org.sonar.api.security; -import com.google.common.annotations.Beta; +import com.google.common.base.Objects; /** * This class is not intended to be subclassed by clients. * * @since 2.14 + * @see ExternalUsersProvider */ -@Beta -public class UserDetails { +public final class UserDetails { - private String name; - private String email; + private String name = ""; + private String email = ""; public UserDetails() { } @@ -51,4 +51,11 @@ public class UserDetails { return name; } + @Override + public String toString() { + return Objects.toStringHelper(this) + .add("name", name) + .add("email", email) + .toString(); + } } diff --git a/sonar-server/src/dev/postgresql/conf/logback.xml b/sonar-server/src/dev/postgresql/conf/logback.xml index 7605ec46890..3c2b26eb555 100644 --- a/sonar-server/src/dev/postgresql/conf/logback.xml +++ b/sonar-server/src/dev/postgresql/conf/logback.xml @@ -1,5 +1,4 @@ - @@ -9,34 +8,33 @@ - + - + - + - + - + - + - + - + - + - + - - + - + - + diff --git a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java index 17049e551b1..f14f10043f7 100644 --- a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java +++ b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java @@ -68,7 +68,7 @@ import org.sonar.server.rules.RulesConsole; import org.sonar.server.startup.*; import org.sonar.server.ui.CodeColorizers; import org.sonar.server.ui.JRubyI18n; -import org.sonar.server.ui.RealmFactory; +import org.sonar.server.ui.SecurityRealmFactory; import org.sonar.server.ui.Views; import javax.servlet.ServletContext; @@ -192,7 +192,7 @@ public final class Platform { servicesContainer.addComponent(DefaultRulesManager.class, false); servicesContainer.addComponent(ProfilesManager.class, false); servicesContainer.addComponent(Backup.class, false); - servicesContainer.addSingleton(RealmFactory.class); + servicesContainer.addSingleton(SecurityRealmFactory.class); servicesContainer.addSingleton(ServerLifecycleNotifier.class); servicesContainer.addSingleton(AnnotationProfileParser.class); servicesContainer.addSingleton(XMLProfileParser.class); diff --git a/sonar-server/src/main/java/org/sonar/server/ui/CompatibilityRealm.java b/sonar-server/src/main/java/org/sonar/server/ui/CompatibilityRealm.java index 45d72239373..77ef6b6140f 100644 --- a/sonar-server/src/main/java/org/sonar/server/ui/CompatibilityRealm.java +++ b/sonar-server/src/main/java/org/sonar/server/ui/CompatibilityRealm.java @@ -21,14 +21,14 @@ package org.sonar.server.ui; import org.sonar.api.CoreProperties; import org.sonar.api.security.LoginPasswordAuthenticator; -import org.sonar.api.security.Realm; +import org.sonar.api.security.SecurityRealm; /** * Provides backward compatibility for {@link CoreProperties#CORE_AUTHENTICATOR_CLASS}. * * @since 2.14 */ -class CompatibilityRealm extends Realm { +class CompatibilityRealm extends SecurityRealm { private final LoginPasswordAuthenticator authenticator; public CompatibilityRealm(LoginPasswordAuthenticator authenticator) { @@ -46,7 +46,7 @@ class CompatibilityRealm extends Realm { } @Override - public LoginPasswordAuthenticator getAuthenticator() { + public LoginPasswordAuthenticator getLoginPasswordAuthenticator() { return authenticator; } } diff --git a/sonar-server/src/main/java/org/sonar/server/ui/RealmFactory.java b/sonar-server/src/main/java/org/sonar/server/ui/RealmFactory.java deleted file mode 100644 index e3187b5929c..00000000000 --- a/sonar-server/src/main/java/org/sonar/server/ui/RealmFactory.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Sonar, open source software quality management tool. - * Copyright (C) 2008-2012 SonarSource - * mailto:contact AT sonarsource DOT com - * - * Sonar 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. - * - * Sonar 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 Sonar; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.server.ui; - -import org.apache.commons.lang.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.sonar.api.CoreProperties; -import org.sonar.api.ServerComponent; -import org.sonar.api.config.Settings; -import org.sonar.api.security.LoginPasswordAuthenticator; -import org.sonar.api.security.Realm; - -/** - * @since 2.14 - */ -public class RealmFactory implements ServerComponent { - - private static final Logger INFO = LoggerFactory.getLogger("org.sonar.INFO"); - private static final Logger LOG = LoggerFactory.getLogger(RealmFactory.class); - - private final boolean ignoreStartupFailure; - private final Realm realm; - - static final String REALM_PROPERTY = "sonar.security.realm"; - - public RealmFactory(Settings settings, Realm[] realms, LoginPasswordAuthenticator[] authenticators) { - ignoreStartupFailure = settings.getBoolean(CoreProperties.CORE_AUTHENTICATOR_IGNORE_STARTUP_FAILURE); - String realmName = settings.getString(REALM_PROPERTY); - String className = settings.getString(CoreProperties.CORE_AUTHENTICATOR_CLASS); - Realm selectedRealm = null; - if (!StringUtils.isEmpty(realmName)) { - selectedRealm = selectRealm(realms, realmName); - if (selectedRealm == null) { - LOG.error("Realm not found. Please check the property '" + REALM_PROPERTY + "' in conf/sonar.properties"); - throw new AuthenticatorNotFoundException(realmName); - } - } - if (selectedRealm == null && !StringUtils.isEmpty(className)) { - LoginPasswordAuthenticator authenticator = selectAuthenticator(authenticators, className); - if (authenticator == null) { - LOG.error("Authenticator plugin not found. Please check the property '" + CoreProperties.CORE_AUTHENTICATOR_CLASS - + "' in conf/sonar.properties"); - throw new AuthenticatorNotFoundException(className); - } - selectedRealm = new CompatibilityRealm(authenticator); - } - realm = selectedRealm; - } - - public RealmFactory(Settings settings, LoginPasswordAuthenticator[] authenticators) { - this(settings, null, authenticators); - } - - public RealmFactory(Settings settings, Realm[] realms) { - this(settings, realms, null); - } - - public RealmFactory(Settings settings) { - this(settings, null, null); - } - - public void start() { - if (realm != null) { - try { - INFO.info("Security realm: " + realm.getName()); - realm.init(); - INFO.info("Security realm started"); - } catch (RuntimeException e) { - if (ignoreStartupFailure) { - LOG.error("IGNORED - Realm fails to start: " + e.getMessage()); - } else { - LOG.error("Realm fails to start: " + e.getMessage()); - throw e; - } - } - } - } - - public Realm getRealm() { - return realm; - } - - private static Realm selectRealm(Realm[] realms, String realmName) { - if (realms != null) { - for (Realm realm : realms) { - if (StringUtils.equals(realmName, realm.getName())) { - return realm; - } - } - } - return null; - } - - private static LoginPasswordAuthenticator selectAuthenticator(LoginPasswordAuthenticator[] authenticators, String className) { - if (authenticators != null) { - for (LoginPasswordAuthenticator lpa : authenticators) { - if (lpa.getClass().getName().equals(className)) { - return lpa; - } - } - } - return null; - } - -} diff --git a/sonar-server/src/main/java/org/sonar/server/ui/SecurityRealmFactory.java b/sonar-server/src/main/java/org/sonar/server/ui/SecurityRealmFactory.java new file mode 100644 index 00000000000..2761f575399 --- /dev/null +++ b/sonar-server/src/main/java/org/sonar/server/ui/SecurityRealmFactory.java @@ -0,0 +1,123 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.server.ui; + +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.sonar.api.CoreProperties; +import org.sonar.api.ServerComponent; +import org.sonar.api.config.Settings; +import org.sonar.api.security.LoginPasswordAuthenticator; +import org.sonar.api.security.SecurityRealm; + +/** + * @since 2.14 + */ +public class SecurityRealmFactory implements ServerComponent { + + private static final Logger INFO = LoggerFactory.getLogger("org.sonar.INFO"); + private static final Logger LOG = LoggerFactory.getLogger(SecurityRealmFactory.class); + + private final boolean ignoreStartupFailure; + private final SecurityRealm realm; + + static final String REALM_PROPERTY = "sonar.security.realm"; + + public SecurityRealmFactory(Settings settings, SecurityRealm[] realms, LoginPasswordAuthenticator[] authenticators) { + ignoreStartupFailure = settings.getBoolean(CoreProperties.CORE_AUTHENTICATOR_IGNORE_STARTUP_FAILURE); + String realmName = settings.getString(REALM_PROPERTY); + String className = settings.getString(CoreProperties.CORE_AUTHENTICATOR_CLASS); + SecurityRealm selectedRealm = null; + if (!StringUtils.isEmpty(realmName)) { + selectedRealm = selectRealm(realms, realmName); + if (selectedRealm == null) { + LOG.error("Realm not found. Please check the property '" + REALM_PROPERTY + "' in conf/sonar.properties"); + throw new AuthenticatorNotFoundException(realmName); + } + } + if (selectedRealm == null && !StringUtils.isEmpty(className)) { + LoginPasswordAuthenticator authenticator = selectAuthenticator(authenticators, className); + if (authenticator == null) { + LOG.error("Authenticator plugin not found. Please check the property '" + CoreProperties.CORE_AUTHENTICATOR_CLASS + + "' in conf/sonar.properties"); + throw new AuthenticatorNotFoundException(className); + } + selectedRealm = new CompatibilityRealm(authenticator); + } + realm = selectedRealm; + } + + public SecurityRealmFactory(Settings settings, LoginPasswordAuthenticator[] authenticators) { + this(settings, null, authenticators); + } + + public SecurityRealmFactory(Settings settings, SecurityRealm[] realms) { + this(settings, realms, null); + } + + public SecurityRealmFactory(Settings settings) { + this(settings, null, null); + } + + public void start() { + if (realm != null) { + try { + INFO.info("Security realm: " + realm.getName()); + realm.init(); + INFO.info("Security realm started"); + } catch (RuntimeException e) { + if (ignoreStartupFailure) { + LOG.error("IGNORED - Realm fails to start: " + e.getMessage()); + } else { + LOG.error("Realm fails to start: " + e.getMessage()); + throw e; + } + } + } + } + + public SecurityRealm getRealm() { + return realm; + } + + private static SecurityRealm selectRealm(SecurityRealm[] realms, String realmName) { + if (realms != null) { + for (SecurityRealm realm : realms) { + if (StringUtils.equals(realmName, realm.getName())) { + return realm; + } + } + } + return null; + } + + private static LoginPasswordAuthenticator selectAuthenticator(LoginPasswordAuthenticator[] authenticators, String className) { + if (authenticators != null) { + for (LoginPasswordAuthenticator lpa : authenticators) { + if (lpa.getClass().getName().equals(className)) { + return lpa; + } + } + } + return null; + } + +} diff --git a/sonar-server/src/main/webapp/WEB-INF/lib/need_authentication.rb b/sonar-server/src/main/webapp/WEB-INF/lib/need_authentication.rb index 94e7d62223d..e7335d80369 100644 --- a/sonar-server/src/main/webapp/WEB-INF/lib/need_authentication.rb +++ b/sonar-server/src/main/webapp/WEB-INF/lib/need_authentication.rb @@ -43,8 +43,9 @@ end # class PluginRealm def initialize(java_realm) - @java_authenticator = java_realm.getAuthenticator() + @java_authenticator = java_realm.getLoginPasswordAuthenticator() @java_users_provider = java_realm.getUsersProvider() + @java_groups_provider = java_realm.getGroupsProvider() end def authenticate?(login, password) @@ -70,12 +71,34 @@ class PluginRealm else if details user.update_attributes(:name => details.getName(), :email => details.getEmail(), :password => password, :password_confirmation => password) + # Synchronize groups only when succeeded to synchronize details + synchronize_groups(user) user.save end end end end + def synchronize_groups(user) + if @java_groups_provider + begin + groups = @java_groups_provider.doGetGroups(user.login) + rescue Exception => e + Java::OrgSonarServerUi::JRubyFacade.new.logError("Error from external groups provider: #{e.message}") + else + if groups + user.groups = [] + for group_name in groups + group = Group.find_by_name(group_name) + if group + user.groups << group + end + end + end + end + end + end + def editable_password? false end @@ -89,7 +112,7 @@ class RealmFactory def self.realm if @@realm.nil? - realm_factory = Java::OrgSonarServerUi::JRubyFacade.new.getCoreComponentByClassname('org.sonar.server.ui.RealmFactory') + realm_factory = Java::OrgSonarServerUi::JRubyFacade.new.getCoreComponentByClassname('org.sonar.server.ui.SecurityRealmFactory') component = realm_factory.getRealm() @@realm = component ? PluginRealm.new(component) : DefaultRealm.new end diff --git a/sonar-server/src/test/java/org/sonar/server/ui/CompatibilityRealmTest.java b/sonar-server/src/test/java/org/sonar/server/ui/CompatibilityRealmTest.java index 84febf3eb0e..136407aeb04 100644 --- a/sonar-server/src/test/java/org/sonar/server/ui/CompatibilityRealmTest.java +++ b/sonar-server/src/test/java/org/sonar/server/ui/CompatibilityRealmTest.java @@ -35,7 +35,7 @@ public class CompatibilityRealmTest { CompatibilityRealm realm = new CompatibilityRealm(authenticator); realm.init(); verify(authenticator).init(); - assertThat(realm.getAuthenticator(), is(authenticator)); + assertThat(realm.getLoginPasswordAuthenticator(), is(authenticator)); assertThat(realm.getName(), is("CompatibilityRealm[" + authenticator.getClass().getName() + "]")); } diff --git a/sonar-server/src/test/java/org/sonar/server/ui/RealmFactoryTest.java b/sonar-server/src/test/java/org/sonar/server/ui/RealmFactoryTest.java deleted file mode 100644 index 9f27ba0ee7b..00000000000 --- a/sonar-server/src/test/java/org/sonar/server/ui/RealmFactoryTest.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Sonar, open source software quality management tool. - * Copyright (C) 2008-2012 SonarSource - * mailto:contact AT sonarsource DOT com - * - * Sonar 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. - * - * Sonar 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 Sonar; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.server.ui; - -import org.junit.Before; -import org.junit.Test; -import org.sonar.api.CoreProperties; -import org.sonar.api.config.Settings; -import org.sonar.api.security.LoginPasswordAuthenticator; -import org.sonar.api.security.Realm; - -import static org.hamcrest.Matchers.*; -import static org.junit.Assert.assertThat; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; - -public class RealmFactoryTest { - - private Settings settings; - - @Before - public void setUp() { - settings = new Settings(); - } - - /** - * Typical usage. - */ - @Test - public void shouldSelectRealmAndStart() { - Realm realm = spy(new FakeRealm()); - settings.setProperty(RealmFactory.REALM_PROPERTY, realm.getName()); - - RealmFactory factory = new RealmFactory(settings, new Realm[] {realm}); - factory.start(); - assertThat(factory.getRealm(), is(realm)); - verify(realm).init(); - } - - @Test - public void doNotFailIfNoRealms() { - RealmFactory factory = new RealmFactory(settings); - factory.start(); - assertThat(factory.getRealm(), nullValue()); - } - - @Test(expected = AuthenticatorNotFoundException.class) - public void realmNotFound() { - settings.setProperty(RealmFactory.REALM_PROPERTY, "Fake"); - - new RealmFactory(settings); - } - - @Test - public void shouldProvideCompatibilityForAuthenticator() { - settings.setProperty(CoreProperties.CORE_AUTHENTICATOR_CLASS, FakeAuthenticator.class.getName()); - LoginPasswordAuthenticator authenticator = new FakeAuthenticator(); - - RealmFactory factory = new RealmFactory(settings, new LoginPasswordAuthenticator[] {authenticator}); - Realm realm = factory.getRealm(); - assertThat(realm, instanceOf(CompatibilityRealm.class)); - } - - @Test - public void shouldTakePrecedenceOverAuthenticator() { - Realm realm = new FakeRealm(); - settings.setProperty(RealmFactory.REALM_PROPERTY, realm.getName()); - LoginPasswordAuthenticator authenticator = new FakeAuthenticator(); - settings.setProperty(CoreProperties.CORE_AUTHENTICATOR_CLASS, FakeAuthenticator.class.getName()); - - RealmFactory factory = new RealmFactory(settings, new Realm[] {realm}, new LoginPasswordAuthenticator[] {authenticator}); - assertThat(factory.getRealm(), is(realm)); - } - - @Test(expected = AuthenticatorNotFoundException.class) - public void authenticatorNotFound() { - settings.setProperty(CoreProperties.CORE_AUTHENTICATOR_CLASS, "Fake"); - - new RealmFactory(settings); - } - - @Test - public void ignoreStartupFailure() { - Realm realm = spy(new AlwaysFailsRealm()); - settings.setProperty(RealmFactory.REALM_PROPERTY, realm.getName()); - settings.setProperty(CoreProperties.CORE_AUTHENTICATOR_IGNORE_STARTUP_FAILURE, true); - - new RealmFactory(settings, new Realm[] {realm}).start(); - verify(realm).init(); - } - - @Test(expected = IllegalStateException.class) - public void shouldFail() { - Realm realm = spy(new AlwaysFailsRealm()); - settings.setProperty(RealmFactory.REALM_PROPERTY, realm.getName()); - - new RealmFactory(settings, new Realm[] {realm}).start(); - } - - private static class AlwaysFailsRealm extends FakeRealm { - @Override - public void init() { - throw new IllegalStateException(); - } - } - - private static class FakeRealm extends Realm { - @Override - public LoginPasswordAuthenticator getAuthenticator() { - return null; - } - } - - private static class FakeAuthenticator implements LoginPasswordAuthenticator { - public void init() { - } - - public boolean authenticate(String login, String password) { - return false; - } - } - -} diff --git a/sonar-server/src/test/java/org/sonar/server/ui/SecurityRealmFactoryTest.java b/sonar-server/src/test/java/org/sonar/server/ui/SecurityRealmFactoryTest.java new file mode 100644 index 00000000000..38ba8cd2662 --- /dev/null +++ b/sonar-server/src/test/java/org/sonar/server/ui/SecurityRealmFactoryTest.java @@ -0,0 +1,141 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.server.ui; + +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.CoreProperties; +import org.sonar.api.config.Settings; +import org.sonar.api.security.LoginPasswordAuthenticator; +import org.sonar.api.security.SecurityRealm; + +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; + +public class SecurityRealmFactoryTest { + + private Settings settings; + + @Before + public void setUp() { + settings = new Settings(); + } + + /** + * Typical usage. + */ + @Test + public void shouldSelectRealmAndStart() { + SecurityRealm realm = spy(new FakeRealm()); + settings.setProperty(SecurityRealmFactory.REALM_PROPERTY, realm.getName()); + + SecurityRealmFactory factory = new SecurityRealmFactory(settings, new SecurityRealm[] {realm}); + factory.start(); + assertThat(factory.getRealm(), is(realm)); + verify(realm).init(); + } + + @Test + public void doNotFailIfNoRealms() { + SecurityRealmFactory factory = new SecurityRealmFactory(settings); + factory.start(); + assertThat(factory.getRealm(), nullValue()); + } + + @Test(expected = AuthenticatorNotFoundException.class) + public void realmNotFound() { + settings.setProperty(SecurityRealmFactory.REALM_PROPERTY, "Fake"); + + new SecurityRealmFactory(settings); + } + + @Test + public void shouldProvideCompatibilityForAuthenticator() { + settings.setProperty(CoreProperties.CORE_AUTHENTICATOR_CLASS, FakeAuthenticator.class.getName()); + LoginPasswordAuthenticator authenticator = new FakeAuthenticator(); + + SecurityRealmFactory factory = new SecurityRealmFactory(settings, new LoginPasswordAuthenticator[] {authenticator}); + SecurityRealm realm = factory.getRealm(); + assertThat(realm, instanceOf(CompatibilityRealm.class)); + } + + @Test + public void shouldTakePrecedenceOverAuthenticator() { + SecurityRealm realm = new FakeRealm(); + settings.setProperty(SecurityRealmFactory.REALM_PROPERTY, realm.getName()); + LoginPasswordAuthenticator authenticator = new FakeAuthenticator(); + settings.setProperty(CoreProperties.CORE_AUTHENTICATOR_CLASS, FakeAuthenticator.class.getName()); + + SecurityRealmFactory factory = new SecurityRealmFactory(settings, new SecurityRealm[] {realm}, + new LoginPasswordAuthenticator[] {authenticator}); + assertThat(factory.getRealm(), is(realm)); + } + + @Test(expected = AuthenticatorNotFoundException.class) + public void authenticatorNotFound() { + settings.setProperty(CoreProperties.CORE_AUTHENTICATOR_CLASS, "Fake"); + + new SecurityRealmFactory(settings); + } + + @Test + public void ignoreStartupFailure() { + SecurityRealm realm = spy(new AlwaysFailsRealm()); + settings.setProperty(SecurityRealmFactory.REALM_PROPERTY, realm.getName()); + settings.setProperty(CoreProperties.CORE_AUTHENTICATOR_IGNORE_STARTUP_FAILURE, true); + + new SecurityRealmFactory(settings, new SecurityRealm[] {realm}).start(); + verify(realm).init(); + } + + @Test(expected = IllegalStateException.class) + public void shouldFail() { + SecurityRealm realm = spy(new AlwaysFailsRealm()); + settings.setProperty(SecurityRealmFactory.REALM_PROPERTY, realm.getName()); + + new SecurityRealmFactory(settings, new SecurityRealm[] {realm}).start(); + } + + private static class AlwaysFailsRealm extends FakeRealm { + @Override + public void init() { + throw new IllegalStateException(); + } + } + + private static class FakeRealm extends SecurityRealm { + @Override + public LoginPasswordAuthenticator getLoginPasswordAuthenticator() { + return null; + } + } + + private static class FakeAuthenticator implements LoginPasswordAuthenticator { + public void init() { + } + + public boolean authenticate(String login, String password) { + return false; + } + } + +} -- cgit v1.2.3