Pārlūkot izejas kodu

SONAR-3137,SONAR-2292 Complete API for external security systems

tags/2.14
Evgeny Mandrikov pirms 12 gadiem
vecāks
revīzija
a3509a17ff

+ 35
- 0
sonar-plugin-api/src/main/java/org/sonar/api/security/ExternalGroupsProvider.java Parādīt failu

@@ -0,0 +1,35 @@
/*
* Sonar, open source software quality management tool.
* Copyright (C) 2008-2011 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;

import java.util.Collection;

/**
* @since 2.14
*/
@Beta
public interface ExternalGroupsProvider extends ServerExtension {

Collection<String> doGetGroups(String username);

}

+ 2
- 3
sonar-plugin-api/src/main/java/org/sonar/api/security/ExternalUsersProvider.java Parādīt failu

@@ -19,9 +19,8 @@
*/
package org.sonar.api.security;

import org.sonar.api.ServerExtension;

import com.google.common.annotations.Beta;
import org.sonar.api.ServerExtension;

/**
* @since 2.14
@@ -29,6 +28,6 @@ import com.google.common.annotations.Beta;
@Beta
public interface ExternalUsersProvider extends ServerExtension {

UserDetails doGetUserDetails(String login);
UserDetails doGetUserDetails(String username);

}

+ 60
- 0
sonar-plugin-api/src/main/java/org/sonar/api/security/Realm.java Parādīt failu

@@ -0,0 +1,60 @@
/*
* Sonar, open source software quality management tool.
* Copyright (C) 2008-2011 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;
}

}

+ 2
- 2
sonar-server/src/main/java/org/sonar/server/platform/Platform.java Parādīt failu

@@ -67,9 +67,9 @@ import org.sonar.server.qualitymodel.DefaultModelManager;
import org.sonar.server.rules.ProfilesConsole;
import org.sonar.server.rules.RulesConsole;
import org.sonar.server.startup.*;
import org.sonar.server.ui.AuthenticatorFactory;
import org.sonar.server.ui.CodeColorizers;
import org.sonar.server.ui.JRubyI18n;
import org.sonar.server.ui.RealmFactory;
import org.sonar.server.ui.Views;

import javax.servlet.ServletContext;
@@ -193,7 +193,7 @@ public final class Platform {
servicesContainer.addComponent(DefaultRulesManager.class, false);
servicesContainer.addComponent(ProfilesManager.class, false);
servicesContainer.addComponent(Backup.class, false);
servicesContainer.addSingleton(AuthenticatorFactory.class);
servicesContainer.addSingleton(RealmFactory.class);
servicesContainer.addSingleton(ServerLifecycleNotifier.class);
servicesContainer.addSingleton(AnnotationProfileParser.class);
servicesContainer.addSingleton(XMLProfileParser.class);

+ 0
- 123
sonar-server/src/main/java/org/sonar/server/ui/AuthenticatorFactory.java Parādīt failu

@@ -1,123 +0,0 @@
/*
* Sonar, open source software quality management tool.
* Copyright (C) 2008-2011 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.ExternalUsersProvider;
import org.sonar.api.security.LoginPasswordAuthenticator;
import org.sonar.api.security.UserDetails;

public class AuthenticatorFactory implements ServerComponent {

private static final Logger LOG = LoggerFactory.getLogger(AuthenticatorFactory.class);
private static final Logger INFO = LoggerFactory.getLogger("org.sonar.INFO");

private LoginPasswordAuthenticator authenticator = null;
private String classname;
private boolean ignoreStartupFailure;
private LoginPasswordAuthenticator[] authenticators;

public AuthenticatorFactory(Settings settings, LoginPasswordAuthenticator[] authenticators) {
classname = settings.getString(CoreProperties.CORE_AUTHENTICATOR_CLASS);
ignoreStartupFailure = settings.getBoolean(CoreProperties.CORE_AUTHENTICATOR_IGNORE_STARTUP_FAILURE);
this.authenticators = authenticators;
}

/**
* This constructor is used when there aren't any authentication plugins.
*/
public AuthenticatorFactory(Settings settings) {
this(settings, null);
}

/**
* Start the authenticator selected in sonar configuration. If no authentication plugin is selected, then
* the default authentication mechanism is used and null is returned.
*
* @throws AuthenticatorNotFoundException if authenticator can not be found
* @throws RuntimeException if authenticator can not be started
*/
public void start() {
// check authentication plugin at startup
if (StringUtils.isEmpty(classname)) {
// use sonar internal authenticator
return;
}

authenticator = searchAuthenticator();
if (authenticator == null) {
LOG.error("Authentication plugin not found. Please check the property '" + CoreProperties.CORE_AUTHENTICATOR_CLASS + "' in conf/sonar.properties");
throw new AuthenticatorNotFoundException(classname);
}

try {
INFO.info("Authentication plugin: class " + classname);
authenticator.init();
INFO.info("Authentication plugin started");

} catch (RuntimeException e) {
if (ignoreStartupFailure) {
LOG.error("IGNORED - Authentication plugin fails to start: " + e.getMessage());
} else {
LOG.error("Authentication plugin fails to start: " + e.getMessage());
throw e;
}
}
}

public LoginPasswordAuthenticator getAuthenticator() {
return authenticator;
}

public ExternalUsersProvider getUsersProvider() {
if (authenticator != null) {
if (authenticator instanceof ExternalUsersProvider) {
return (ExternalUsersProvider) authenticator;
}
return new DefaultUsersProvider();
}
return null;
}

private static class DefaultUsersProvider implements ExternalUsersProvider {
public UserDetails doGetUserDetails(String login) {
UserDetails result = new UserDetails();
result.setName(login);
result.setEmail("");
return result;
}
}

private LoginPasswordAuthenticator searchAuthenticator() {
if (authenticators != null) {
for (LoginPasswordAuthenticator lpa : authenticators) {
if (lpa.getClass().getName().equals(classname)) {
return lpa;
}
}
}
return null;
}
}

+ 4
- 0
sonar-server/src/main/java/org/sonar/server/ui/AuthenticatorNotFoundException.java Parādīt failu

@@ -19,6 +19,10 @@
*/
package org.sonar.server.ui;

/**
* @deprecated in 2.14 and should be removed
*/
@Deprecated
public class AuthenticatorNotFoundException extends RuntimeException {

public AuthenticatorNotFoundException(String classname) {

+ 52
- 0
sonar-server/src/main/java/org/sonar/server/ui/CompatibilityRealm.java Parādīt failu

@@ -0,0 +1,52 @@
/*
* Sonar, open source software quality management tool.
* Copyright (C) 2008-2011 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.sonar.api.CoreProperties;
import org.sonar.api.security.LoginPasswordAuthenticator;
import org.sonar.api.security.Realm;

/**
* Provides backward compatibility for {@link CoreProperties#CORE_AUTHENTICATOR_CLASS}.
*
* @since 2.14
*/
class CompatibilityRealm extends Realm {
private final LoginPasswordAuthenticator authenticator;

public CompatibilityRealm(LoginPasswordAuthenticator authenticator) {
this.authenticator = authenticator;
}

@Override
public void init() {
authenticator.init();
}

@Override
public String getName() {
return "CompatibilityRealm[" + authenticator.getClass().getName() + "]";
}

@Override
public LoginPasswordAuthenticator getAuthenticator() {
return authenticator;
}
}

+ 121
- 0
sonar-server/src/main/java/org/sonar/server/ui/RealmFactory.java Parādīt failu

@@ -0,0 +1,121 @@
/*
* Sonar, open source software quality management tool.
* Copyright (C) 2008-2011 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() {
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;
}

}

+ 44
- 61
sonar-server/src/main/webapp/WEB-INF/lib/need_authentication.rb Parādīt failu

@@ -21,81 +21,70 @@
#
# Use Sonar database (table USERS) to authenticate users.
#
class DefaultAuthenticator
class DefaultRealm
def authenticate?(login, password)
return false if login.blank? || password.blank?
user=User.find_by_login(login)
user = User.find_by_login(login)
user && user.authenticated?(password)
end

def editable_password?
true
end
end


#
# Use an external system to authenticate users, for example LDAP. See the Java extension point org.sonar.api.security.LoginPasswordAuthenticator.
#
class PluginAuthenticator
def initialize(java_authenticator)
@java_authenticator=java_authenticator
end

def authenticate?(login, password)
login.present? && password.present? && @java_authenticator.authenticate(login, password)
def synchronize(user, password)
# nothing to do
end

def editable_password?
false
true
end
end

#
# Since 2.14
# Experimental
#
# Use an external system to authenticate users with fallback to Sonar database.
# Use an external security system with fallback to Sonar database.
# See the Java extension point org.sonar.api.security.Realm
#
class FallbackAuthenticator
def initialize(java_authenticator)
@java_authenticator = java_authenticator
class PluginRealm
def initialize(java_realm)
@java_authenticator = java_realm.getAuthenticator()
@java_users_provider = java_realm.getUsersProvider()
end

def authenticate?(login, password)
return false if login.blank? || password.blank?
# TODO handle exceptions
if @java_authenticator.authenticate(login, password)
return true
end
# Fallback to password in Sonar Database
# Fallback to password from Sonar Database
user = User.find_by_login(login)
return user && user.authenticated?(password)
end

def synchronize(user, password)
if @java_users_provider
# TODO handle exceptions
details = @java_users_provider.doGetUserDetails(user.login)
user.update_attributes(:name => details.getName(), :email => details.getEmail(), :password => password, :password_confirmation => password)
user.save
end
end

def editable_password?
true
false
end
end

#
# Load the authentication system to use. The server must be restarted when configuration is changed.
# Load the realm to use. The server must be restarted when configuration is changed.
#
class AuthenticatorFactory
@@authenticator = nil
@@users_provider = nil

def self.authenticator
if @@authenticator.nil?
authenticator_factory=Java::OrgSonarServerUi::JRubyFacade.new.getCoreComponentByClassname('org.sonar.server.ui.AuthenticatorFactory')
component=authenticator_factory.getAuthenticator()
@@authenticator=(component ? FallbackAuthenticator.new(component) : DefaultAuthenticator.new)
@@users_provider = (component ? authenticator_factory.getUsersProvider() : nil)
class RealmFactory
@@realm = nil

def self.realm
if @@realm.nil?
realm_factory = Java::OrgSonarServerUi::JRubyFacade.new.getCoreComponentByClassname('org.sonar.server.ui.RealmFactory')
component = realm_factory.getRealm()
@@realm = component ? PluginRealm.new(component) : DefaultRealm.new
end
@@authenticator
end

def self.users_provider
@@users_provider
@@realm
end
end

@@ -131,44 +120,38 @@ module NeedAuthentication
user = User.find_by_login(login)
if user
# User exists
return nil if !AuthenticatorFactory.authenticator.authenticate?(login, password)
return nil if !RealmFactory.realm.authenticate?(login, password)
# Password correct

users_provider = AuthenticatorFactory.users_provider
if users_provider
# Sync details
details = AuthenticatorFactory.users_provider.doGetUserDetails(login)
user.update_attributes(:name => details.getName(), :email => details.getEmail(), :password => password, :password_confirmation => password)
# TODO log if unable to save?
user.save
end
# Synchronize details
RealmFactory.realm.synchronize(user, password)
else
# User not found
return nil if !AuthenticatorFactory.authenticator.authenticate?(login, password)
return nil if !RealmFactory.realm.authenticate?(login, password)
# Password correct

# Automatically create a user in the sonar db if authentication has been successfully done
create_user = java_facade.getSettings().getBoolean('sonar.authenticator.createUsers')
users_provider = AuthenticatorFactory.users_provider
if create_user && users_provider
details = users_provider.doGetUserDetails(login)
user = User.new(:login => login, :name => details.getName(), :email => details.getEmail(), :password => password, :password_confirmation => password)
if create_user
user = User.new(:login => login, :name => login, :email => '', :password => password, :password_confirmation => password)
default_group_name = java_facade.getSettings().getString('sonar.defaultGroup')
default_group=Group.find_by_name(default_group_name)
default_group = Group.find_by_name(default_group_name)
if default_group
user.groups<<default_group
user.save
else
logger.error("The default user group does not exist: #{default_group_name}. Please check the parameter 'Default user group' in general settings.")
end

# Synchronize details
RealmFactory.realm.synchronize(user, password)
end
end

return user
end

def editable_password?
AuthenticatorFactory.authenticator.editable_password?
RealmFactory.realm.editable_password?
end
end
end

+ 0
- 113
sonar-server/src/test/java/org/sonar/server/ui/AuthenticatorFactoryTest.java Parādīt failu

@@ -1,113 +0,0 @@
/*
* Sonar, open source software quality management tool.
* Copyright (C) 2008-2011 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.Test;
import org.sonar.api.CoreProperties;
import org.sonar.api.config.Settings;
import org.sonar.api.security.LoginPasswordAuthenticator;

import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.core.IsNull.nullValue;
import static org.junit.Assert.assertThat;

public class AuthenticatorFactoryTest {

@Test
public void doNotFailIfNoAuthenticationPlugins() {
AuthenticatorFactory factory = new AuthenticatorFactory(new Settings());
assertThat(factory.getAuthenticator(), nullValue());
factory.start();
}

@Test
public void startSelectedAuthenticator() {
Settings settings = new Settings();
settings.setProperty(CoreProperties.CORE_AUTHENTICATOR_CLASS, FakeAuthenticator.class.getName());

LoginPasswordAuthenticator authenticator = new FakeAuthenticator();
AuthenticatorFactory factory = new AuthenticatorFactory(settings, new LoginPasswordAuthenticator[]{authenticator});
factory.start();
assertThat(factory.getAuthenticator(), is(authenticator));
}

@Test(expected = ConnectionException.class)
public void authenticatorDoesNotStart() {
Settings settings = new Settings();
settings.setProperty(CoreProperties.CORE_AUTHENTICATOR_CLASS, FailAuthenticator.class.getName());

AuthenticatorFactory factory = new AuthenticatorFactory(settings, new LoginPasswordAuthenticator[]{new FakeAuthenticator(), new FailAuthenticator()});
factory.start();
factory.getAuthenticator();
}

@Test(expected = AuthenticatorNotFoundException.class)
public void authenticatorNotFound() {
Settings settings = new Settings();
settings.setProperty(CoreProperties.CORE_AUTHENTICATOR_CLASS, "foo");

AuthenticatorFactory factory = new AuthenticatorFactory(settings, new LoginPasswordAuthenticator[]{new FakeAuthenticator(), new FailAuthenticator()});
factory.start();
factory.getAuthenticator();
}

@Test(expected = AuthenticatorNotFoundException.class)
public void noAuthenticators() {
Settings settings = new Settings();
settings.setProperty(CoreProperties.CORE_AUTHENTICATOR_CLASS, "foo");

AuthenticatorFactory factory = new AuthenticatorFactory(settings, null);
factory.start();
}

@Test
public void ignoreStartupFailure() {
Settings settings = new Settings();
settings.setProperty(CoreProperties.CORE_AUTHENTICATOR_CLASS, FailAuthenticator.class.getName());
settings.setProperty(CoreProperties.CORE_AUTHENTICATOR_IGNORE_STARTUP_FAILURE, Boolean.TRUE);

AuthenticatorFactory factory = new AuthenticatorFactory(settings, new LoginPasswordAuthenticator[]{new FakeAuthenticator(), new FailAuthenticator()});
factory.start();
assertThat(factory.getAuthenticator(), not(nullValue()));
}

static class FakeAuthenticator implements LoginPasswordAuthenticator {
public void init() {
}

public boolean authenticate(String login, String password) {
return false;
}
}

static class ConnectionException extends RuntimeException {
}

static class FailAuthenticator implements LoginPasswordAuthenticator {
public void init() {
throw new ConnectionException();
}

public boolean authenticate(String login, String password) {
return false;
}
}
}

+ 42
- 0
sonar-server/src/test/java/org/sonar/server/ui/CompatibilityRealmTest.java Parādīt failu

@@ -0,0 +1,42 @@
/*
* Sonar, open source software quality management tool.
* Copyright (C) 2008-2011 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.Test;
import org.sonar.api.security.LoginPasswordAuthenticator;

import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;

public class CompatibilityRealmTest {

@Test
public void shouldDelegate() {
LoginPasswordAuthenticator authenticator = mock(LoginPasswordAuthenticator.class);
CompatibilityRealm realm = new CompatibilityRealm(authenticator);
realm.init();
verify(authenticator).init();
assertThat(realm.getAuthenticator(), is(authenticator));
assertThat(realm.getName(), is("CompatibilityRealm[" + authenticator.getClass().getName() + "]"));
}

}

+ 139
- 0
sonar-server/src/test/java/org/sonar/server/ui/RealmFactoryTest.java Parādīt failu

@@ -0,0 +1,139 @@
/*
* Sonar, open source software quality management tool.
* Copyright (C) 2008-2011 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);
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;
}
}

}

Notiek ielāde…
Atcelt
Saglabāt