CCM NG: LoginManagerTest. Note: LoginManager does not work yet, Test class and LoginManager etc still need some work
git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@3527 8810af33-2d31-482b-a856-94f89814c4dfpull/2/head
parent
c9b854a723
commit
5282e63ebd
|
|
@ -26,6 +26,8 @@ import com.arsdigita.util.parameter.SpecificClassParameter;
|
||||||
import com.arsdigita.util.parameter.StringArrayParameter;
|
import com.arsdigita.util.parameter.StringArrayParameter;
|
||||||
import com.arsdigita.util.parameter.StringParameter;
|
import com.arsdigita.util.parameter.StringParameter;
|
||||||
|
|
||||||
|
import org.libreccm.core.authentication.LocalLoginModule;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|
@ -79,7 +81,8 @@ public class SecurityConfig extends AbstractConfig {
|
||||||
private final Parameter m_loginConfig = new StringArrayParameter(
|
private final Parameter m_loginConfig = new StringArrayParameter(
|
||||||
"waf.login_config", Parameter.REQUIRED,
|
"waf.login_config", Parameter.REQUIRED,
|
||||||
new String[]{
|
new String[]{
|
||||||
"Register:com.arsdigita.kernel.security.LocalLoginModule:requisite",});
|
String.format("Register:%s:requisite",
|
||||||
|
LocalLoginModule.class.getName())});
|
||||||
|
|
||||||
private final Parameter m_adminEmail = new StringParameter(
|
private final Parameter m_adminEmail = new StringParameter(
|
||||||
"waf.admin.contact_email", Parameter.OPTIONAL, null);
|
"waf.admin.contact_email", Parameter.OPTIONAL, null);
|
||||||
|
|
@ -101,13 +104,13 @@ public class SecurityConfig extends AbstractConfig {
|
||||||
*/
|
*/
|
||||||
private final Parameter m_hashAlgorithm = new StringParameter(
|
private final Parameter m_hashAlgorithm = new StringParameter(
|
||||||
"waf.security.hash_algorithm", Parameter.REQUIRED, "SHA-512");
|
"waf.security.hash_algorithm", Parameter.REQUIRED, "SHA-512");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default length of the salt for new passwords.
|
* Default length of the salt for new passwords.
|
||||||
*/
|
*/
|
||||||
private final Parameter m_saltLength = new IntegerParameter(
|
private final Parameter m_saltLength = new IntegerParameter(
|
||||||
"waf.security.salt_length", Parameter.REQUIRED, 256);
|
"waf.security.salt_length", Parameter.REQUIRED, 256);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an empty SecurityConfig object
|
* Constructs an empty SecurityConfig object
|
||||||
*/
|
*/
|
||||||
|
|
@ -123,7 +126,7 @@ public class SecurityConfig extends AbstractConfig {
|
||||||
register(m_autoRegistrationOn);
|
register(m_autoRegistrationOn);
|
||||||
register(m_userBanOn);
|
register(m_userBanOn);
|
||||||
register(m_enableQuestion);
|
register(m_enableQuestion);
|
||||||
|
|
||||||
register(m_hashAlgorithm);
|
register(m_hashAlgorithm);
|
||||||
register(m_saltLength);
|
register(m_saltLength);
|
||||||
|
|
||||||
|
|
@ -185,7 +188,7 @@ public class SecurityConfig extends AbstractConfig {
|
||||||
|
|
||||||
public String getAdminContactEmail() {
|
public String getAdminContactEmail() {
|
||||||
String email = (String) get(m_adminEmail);
|
String email = (String) get(m_adminEmail);
|
||||||
|
|
||||||
// Return empty string instead of looking up into the database. If no
|
// Return empty string instead of looking up into the database. If no
|
||||||
// email if configured for the admin we consider that as a configuration
|
// email if configured for the admin we consider that as a configuration
|
||||||
// issue.
|
// issue.
|
||||||
|
|
@ -223,7 +226,6 @@ public class SecurityConfig extends AbstractConfig {
|
||||||
// }
|
// }
|
||||||
// return s_systemAdministratorEmailAddress;
|
// return s_systemAdministratorEmailAddress;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
public final boolean isAutoRegistrationOn() {
|
public final boolean isAutoRegistrationOn() {
|
||||||
return ((Boolean) get(m_autoRegistrationOn)).booleanValue();
|
return ((Boolean) get(m_autoRegistrationOn)).booleanValue();
|
||||||
}
|
}
|
||||||
|
|
@ -231,9 +233,9 @@ public class SecurityConfig extends AbstractConfig {
|
||||||
public String getHashAlgorithm() {
|
public String getHashAlgorithm() {
|
||||||
return (String) get(m_hashAlgorithm);
|
return (String) get(m_hashAlgorithm);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getSaltLength() {
|
public Integer getSaltLength() {
|
||||||
return (Integer) get(m_saltLength);
|
return (Integer) get(m_saltLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2003-2004 Red Hat Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This library 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 2.1 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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 library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.arsdigita.runtime;
|
||||||
|
|
||||||
|
import com.arsdigita.util.Assert;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subject to change.
|
||||||
|
*
|
||||||
|
* An error to indicate invalid configurations.
|
||||||
|
*
|
||||||
|
* Usage: throw new ConfigError( "message" );
|
||||||
|
*
|
||||||
|
* @author Justin Ross <jross@redhat.com>
|
||||||
|
*/
|
||||||
|
public class ConfigError extends Error {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 5224480607138738741L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new configuration error with the content
|
||||||
|
* <code>message</code>.
|
||||||
|
*
|
||||||
|
* @param message A <code>String</code> describing what's wrong; it cannot
|
||||||
|
* be null
|
||||||
|
*/
|
||||||
|
public ConfigError(final String message) {
|
||||||
|
super(message);
|
||||||
|
|
||||||
|
Assert.exists(message, String.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new configuration error with a default message.
|
||||||
|
*/
|
||||||
|
public ConfigError() {
|
||||||
|
super("Configuration is invalid");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -18,197 +18,42 @@
|
||||||
*/
|
*/
|
||||||
package org.libreccm.core.authentication;
|
package org.libreccm.core.authentication;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import com.arsdigita.kernel.security.SecurityConfig;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.security.auth.login.AppConfigurationEntry;
|
import javax.security.auth.login.AppConfigurationEntry;
|
||||||
import javax.security.auth.login.Configuration;
|
import javax.security.auth.login.Configuration;
|
||||||
|
import javax.security.auth.spi.LoginModule;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses a string array/list of strings to create an configuration for JAAS.
|
* Configuration for JAAS containing all active {@link LoginModule}
|
||||||
|
* implementations.
|
||||||
*
|
*
|
||||||
* This class is based on the {@code com.arsdigita.kernel.security.LoginConfig}
|
* The active modules are stored in the {@link SecurityConfig} as an array
|
||||||
* class. The code itself has been heavily refactored using features like
|
* of strings. The original {@code com.arsdigita.kernel.security.LoginConfig}
|
||||||
* Generics and other things added to the Java language and the Java Standard
|
* class parsed this string array in its constructor. For LibreCCM 7 the code
|
||||||
* Library in the last ten years since the original class was written.
|
* has been split up. The logic for parsing the configuration is now provided
|
||||||
|
* by the {@link LoginConfigBuilder} class. This allowed us the greatly
|
||||||
|
* simplify this class. Also now we don't have a constructor which throws
|
||||||
|
* Exceptions.
|
||||||
*
|
*
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
*/
|
*/
|
||||||
public class LoginConfig extends Configuration {
|
public class LoginConfig extends Configuration {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maps application names to {@code AppConfigurationEntry[]}.
|
* The configuration entries.
|
||||||
*
|
|
||||||
* ToDo: To create a configuration this class parses strings. Of course the
|
|
||||||
* parsing may fails. In this case the constructor throws an exception.
|
|
||||||
* Throwing exceptions from a constructor is considered a bad practise
|
|
||||||
* because this may leaves a party created object. Instead the better option
|
|
||||||
* would be a factory method or a builder.
|
|
||||||
*/
|
*/
|
||||||
private final Map<String, AppConfigurationEntry[]> appConfigs = new HashMap<>();
|
private final Map<String, AppConfigurationEntry[]> appConfigs;
|
||||||
|
|
||||||
private LoginConfig() {
|
private LoginConfig() {
|
||||||
//Nothing.
|
this.appConfigs = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
LoginConfig(final Map<String, AppConfigurationEntry[]> appConfigs) {
|
||||||
* Creates a new login configuration from a list of string. {@code Request}
|
this.appConfigs = appConfigs;
|
||||||
* and {@code Register} are mandatory contexts, WAF refuses to start if they
|
|
||||||
* are not configured. Each login context can span multiple modules.
|
|
||||||
*
|
|
||||||
* The input list comprises of strings adhering to the following format:
|
|
||||||
*
|
|
||||||
* <pre>
|
|
||||||
* context:moduleName:controlFlag[:option1[:option2[:...]]]
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* <dl>
|
|
||||||
*
|
|
||||||
* <dt>context</dt>
|
|
||||||
* <dd>String</dd>
|
|
||||||
*
|
|
||||||
* <dt>moduleName</dt>
|
|
||||||
* <dd>String</dd>
|
|
||||||
*
|
|
||||||
* <dt>controlFlag</dt>
|
|
||||||
* <dd>"required"</dd>
|
|
||||||
* <dd>"requisite"</dd>
|
|
||||||
* <dd>"sufficient"</dd>
|
|
||||||
* <dd>"optional"</dd>
|
|
||||||
*
|
|
||||||
* <dt>option</dt>
|
|
||||||
* <dd>"key=value"</dd>
|
|
||||||
* </dl>
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* Example:</p>
|
|
||||||
*
|
|
||||||
* <pre>
|
|
||||||
* Request:com.arsdigita.kernel.security.CredentialLoginModule:requisite:debug=true
|
|
||||||
* Register:com.arsdigita.kernel.security.LocalLoginModule:requisite
|
|
||||||
* Register:com.arsdigita.kernel.security.UserIDLoginModule:requisite
|
|
||||||
* Register:com.arsdigita.kernel.security.CredentialLoginModule:optional
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* @param config The configuration in string format.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public LoginConfig(final List<String> config) {
|
|
||||||
final Map<String, List<String>> contextConfigs = new HashMap<>();
|
|
||||||
|
|
||||||
for (String tuple : config) {
|
|
||||||
final int pos = tuple.indexOf(':');
|
|
||||||
final String context = tuple.substring(0, pos);
|
|
||||||
final String moduleConfig = tuple.substring(pos + 1);
|
|
||||||
final List<String> contextConfig = retrieveContextConfig(
|
|
||||||
context, contextConfigs);
|
|
||||||
|
|
||||||
contextConfig.add(moduleConfig);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (final Map.Entry<String, List<String>> entry : contextConfigs.
|
|
||||||
entrySet()) {
|
|
||||||
addAppConfig(entry.getKey(), entry.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<String> retrieveContextConfig(
|
|
||||||
final String context, final Map<String, List<String>> contextConfigs) {
|
|
||||||
List<String> contextConfig = contextConfigs.get(context);
|
|
||||||
|
|
||||||
if (contextConfig == null) {
|
|
||||||
contextConfig = new ArrayList<>();
|
|
||||||
contextConfigs.put(context, contextConfig);
|
|
||||||
}
|
|
||||||
|
|
||||||
return contextConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addAppConfig(final String name, final List<String> entries) {
|
|
||||||
final AppConfigurationEntry[] configEntries
|
|
||||||
= new AppConfigurationEntry[entries.size()];
|
|
||||||
for (int i = 0; i < entries.size(); i++) {
|
|
||||||
final List<String> entry = Arrays.asList(entries.get(i).split(":"));
|
|
||||||
configEntries[i] = loadAppConfigEntry(entry);
|
|
||||||
|
|
||||||
}
|
|
||||||
appConfigs.put(name, configEntries);
|
|
||||||
}
|
|
||||||
|
|
||||||
private AppConfigurationEntry loadAppConfigEntry(final List<String> entry) {
|
|
||||||
if (entry.size() < 2) {
|
|
||||||
throw new LoginConfigMalformedException("LoginConfig is malformed.");
|
|
||||||
}
|
|
||||||
|
|
||||||
final String name = entry.get(0);
|
|
||||||
final AppConfigurationEntry.LoginModuleControlFlag flag = parseFlag(
|
|
||||||
entry.get(1));
|
|
||||||
final Map<String, String> options = new HashMap<>();
|
|
||||||
|
|
||||||
if (entry.size() > 2) {
|
|
||||||
for (int i = 2; i < entry.size(); i++) {
|
|
||||||
addOption(entry.get(i), options);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new AppConfigurationEntry(name, flag, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
private AppConfigurationEntry.LoginModuleControlFlag parseFlag(
|
|
||||||
final String flagStr) {
|
|
||||||
switch (flagStr) {
|
|
||||||
case "REQUISITE":
|
|
||||||
return AppConfigurationEntry.LoginModuleControlFlag.REQUISITE;
|
|
||||||
|
|
||||||
case "REQUIRED":
|
|
||||||
return AppConfigurationEntry.LoginModuleControlFlag.REQUIRED;
|
|
||||||
|
|
||||||
case "SUFFICIENT":
|
|
||||||
return AppConfigurationEntry.LoginModuleControlFlag.SUFFICIENT;
|
|
||||||
|
|
||||||
case "OPTIONAL":
|
|
||||||
return AppConfigurationEntry.LoginModuleControlFlag.OPTIONAL;
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new LoginConfigMalformedException(String.format(
|
|
||||||
"Unknown flag \"%s\". Valid flags are: REQUISITE, "
|
|
||||||
+ "REQUIRED, SUFFICIENT, OPTIONAL",
|
|
||||||
flagStr));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addOption(final String option,
|
|
||||||
final Map<String, String> options) {
|
|
||||||
final int index = option.indexOf('=');
|
|
||||||
if (index == -1) {
|
|
||||||
throw new LoginConfigMalformedException(String.format(
|
|
||||||
"The option string \"%s\" is malformed.", option));
|
|
||||||
}
|
|
||||||
|
|
||||||
final String key = option.substring(0, index);
|
|
||||||
final String value = option.substring(index + 1);
|
|
||||||
options.put(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void foo(final LoginConfig config) {
|
|
||||||
if (config.appConfigs.get("foo") != null) {
|
|
||||||
config.appConfigs.remove("foo");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convenient constructor taking an arrays of strings containing the
|
|
||||||
* configuration. Internally this constructor converts the array to a list
|
|
||||||
* and calls {@link #LoginConfig(java.util.List)}.
|
|
||||||
*
|
|
||||||
* @param config The configuration in string form.
|
|
||||||
*
|
|
||||||
* @see #LoginConfig(java.util.List)
|
|
||||||
*/
|
|
||||||
public LoginConfig(final String[] config) {
|
|
||||||
this(Arrays.asList(config));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,308 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015 LibreCCM Foundation.
|
||||||
|
*
|
||||||
|
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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 library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.libreccm.core.authentication;
|
||||||
|
|
||||||
|
import com.arsdigita.kernel.security.SecurityConfig;
|
||||||
|
import com.arsdigita.runtime.ConfigError;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.security.auth.login.AppConfigurationEntry;
|
||||||
|
import javax.security.auth.spi.LoginModule;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a {@link LoginConfig} instance from an array or an list of strings.
|
||||||
|
*
|
||||||
|
* The process of creating a {@link LoginConfig} instance from the string values
|
||||||
|
* like those stored in the {@link SecurityConfig} is a complex process.
|
||||||
|
* Originally the constructor of the
|
||||||
|
* {@code com.arsdigita.kernel.security.LoginConfig} class has done all this
|
||||||
|
* work. Some parts were outsourced to private methods.
|
||||||
|
*
|
||||||
|
* The problem with this approach is that several of this method may throw an
|
||||||
|
* exception/error. But throwing exceptions from a constructor is considered a
|
||||||
|
* bad practise. Also the private support methods made the original
|
||||||
|
* {@code LoginConfig} class quite big and complex. Therefore the code has been
|
||||||
|
* split up. The construction process is now done by this class which creates
|
||||||
|
* {@code LoginConfig} from a provided list or array of strings. The strings
|
||||||
|
* must be in the correct format:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* context:moduleName:controlFlag[:option1[:option2[:...]]]
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* <dl>
|
||||||
|
* <dt>{@code context}</dt>
|
||||||
|
* <dd>String</dd>
|
||||||
|
*
|
||||||
|
* <dt>{@code moduleName}</dt>
|
||||||
|
* <dd>Fully qualified class name of a {@link LoginModule}.</dd>
|
||||||
|
*
|
||||||
|
* <dt>{@code controlFlag}</dt>
|
||||||
|
* <dd>
|
||||||
|
* One of the following flags:
|
||||||
|
* <ul>
|
||||||
|
* <li>{@code required}</li>
|
||||||
|
* <li>{@code requisite}</li>
|
||||||
|
* <li>{@code sufficient}</li>
|
||||||
|
* <li>{@code optional}</li>
|
||||||
|
* </ul>
|
||||||
|
* </dd>
|
||||||
|
*
|
||||||
|
* <dt>option</dt>
|
||||||
|
* <dd>Options for the module in the following format: {@code key=value}</dd>
|
||||||
|
* </dl>
|
||||||
|
*
|
||||||
|
* Examples:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* Request:com.arsdigita.kernel.security.CredentialLoginModule:requisite:debug=true
|
||||||
|
* Register:com.arsdigita.kernel.security.LocalLoginModule:requisite
|
||||||
|
* Register:com.arsdigita.kernel.security.UserIDLoginModule:requisite
|
||||||
|
* Register:com.arsdigita.kernel.security.CredentialLoginModule:optional
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* The build a {@link LoginConfig} first construct an instance of this class and
|
||||||
|
* pass the string array containing the configuration. For example:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* final LoginConfigBuilder loginConfigBuilder =
|
||||||
|
* new LoginConfigBuilder(SecurityConfig.getInstance().getLoginConfig());
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* Then call the {@link #build()} method which does all the work:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* final LoginConfig loginConfig = loginConfigBuilder.build();
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
|
*/
|
||||||
|
public class LoginConfigBuilder {
|
||||||
|
|
||||||
|
private final transient String[] config;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@code LoginConfigBuilder} for the provided configuration.
|
||||||
|
*
|
||||||
|
* @param config The configuration for which an {@link LoginConfig} should
|
||||||
|
* be created, as array of strings as provided by
|
||||||
|
* {@link SecurityConfig#getLoginConfig()}.
|
||||||
|
*/
|
||||||
|
public LoginConfigBuilder(final String[] config) {
|
||||||
|
this.config = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a {@link LoginConfig} from {@link #config}.
|
||||||
|
*
|
||||||
|
* If one entry of the {@link #config} is malformed a {@link ConfigError}
|
||||||
|
* will be thrown.
|
||||||
|
*
|
||||||
|
* @return A {@link LoginConfig} object.
|
||||||
|
*/
|
||||||
|
public LoginConfig build() {
|
||||||
|
//Temporary storage for the data extracted from the config string array.
|
||||||
|
final Map<String, List<String>> contextConfigs = new HashMap<>();
|
||||||
|
|
||||||
|
//Parse the tuples in the config string array.
|
||||||
|
for (final String tuple : config) {
|
||||||
|
//Find the index of the first ':'.
|
||||||
|
final int index = tuple.indexOf(':');
|
||||||
|
//Extract context and module config parts from the tuple.
|
||||||
|
final String context = tuple.substring(0, index);
|
||||||
|
final String moduleConfig = tuple.substring(index + 1);
|
||||||
|
|
||||||
|
//Put them in the list for the context.
|
||||||
|
final List<String> contextConfig = retrieveContextConfig(
|
||||||
|
context, contextConfigs);
|
||||||
|
contextConfig.add(moduleConfig);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//Create the map of AppConfigurationEntry objects.
|
||||||
|
final Map<String, AppConfigurationEntry[]> appConfigs = new HashMap<>();
|
||||||
|
for (final Map.Entry<String, List<String>> entry : contextConfigs
|
||||||
|
.entrySet()) {
|
||||||
|
//Add the config entry. The helper method called creates the
|
||||||
|
//AppConfigurationEntry object from the string value.
|
||||||
|
addAppConfig(appConfigs, entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
//Create the LoginConfig object with the Map of AppConfigurationEntries.
|
||||||
|
return new LoginConfig(appConfigs);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method for retrieving a list for specific context from the context
|
||||||
|
* maps. Used by {@link #build()}. If the map has no entry with the provided
|
||||||
|
* name a new list is created a put into the list.
|
||||||
|
*
|
||||||
|
* @param context The name of the context, used as key in the
|
||||||
|
* provided map.
|
||||||
|
* @param contextConfigs The map of context configs.
|
||||||
|
*
|
||||||
|
* @return The context configs list for the provided context.
|
||||||
|
*/
|
||||||
|
private List<String> retrieveContextConfig(
|
||||||
|
final String context, final Map<String, List<String>> contextConfigs) {
|
||||||
|
List<String> contextConfig = contextConfigs.get(context);
|
||||||
|
|
||||||
|
if (contextConfig == null) {
|
||||||
|
contextConfig = new ArrayList<>();
|
||||||
|
contextConfigs.put(context, contextConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
return contextConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method for creating an {@link AppConfigurationEntry} object from a
|
||||||
|
* string.
|
||||||
|
*
|
||||||
|
* @param appConfigs The map of {@link AppConfigurationEntry} objects in
|
||||||
|
* which the created entry will be stored.
|
||||||
|
* @param name The name of the context for which the
|
||||||
|
* {@link AppConfigurationEntry} is created.
|
||||||
|
* @param entries The list of configuration entries to parse.
|
||||||
|
*/
|
||||||
|
private void addAppConfig(
|
||||||
|
final Map<String, AppConfigurationEntry[]> appConfigs,
|
||||||
|
final String name,
|
||||||
|
final List<String> entries) {
|
||||||
|
|
||||||
|
//Map containing the parsed entries
|
||||||
|
final AppConfigurationEntry[] configEntries
|
||||||
|
= new AppConfigurationEntry[entries
|
||||||
|
.size()];
|
||||||
|
|
||||||
|
//Parse all entries. We use a "traditional" for loop here because we
|
||||||
|
//need the position in the array.
|
||||||
|
for (int i = 0; i < entries.size(); i++) {
|
||||||
|
//Load the current configuration entry.
|
||||||
|
configEntries[i] = loadAppConfigEntry(entries.get(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
//Put the parsed entires into the map
|
||||||
|
appConfigs.put(name, configEntries);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method for parsing a single configuration entry. The
|
||||||
|
*
|
||||||
|
* tokens entry
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private AppConfigurationEntry loadAppConfigEntry(final String entry) {
|
||||||
|
//Split the string tokens. The tokens are limited by the ':' character.
|
||||||
|
final String[] tokens = entry.split(":");
|
||||||
|
|
||||||
|
//If there less then two tokens the entry is malformed and we throw an
|
||||||
|
//ConfigError.
|
||||||
|
if (tokens.length < 2) {
|
||||||
|
final StringBuilder builder = new StringBuilder();
|
||||||
|
for (final String str : tokens) {
|
||||||
|
builder.append(str);
|
||||||
|
}
|
||||||
|
throw new ConfigError(String.format(
|
||||||
|
"Malformed SecurityConfig entry: %s", builder.toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
//Extract the name of the configured module (the first token)
|
||||||
|
final String name = tokens[0];
|
||||||
|
//Extract the flat (second token)
|
||||||
|
final AppConfigurationEntry.LoginModuleControlFlag flag = parseFlag(
|
||||||
|
tokens[1]);
|
||||||
|
|
||||||
|
//Extract the provided options if any
|
||||||
|
final Map<String, String> options = new HashMap<>();
|
||||||
|
if (tokens.length > 2) {
|
||||||
|
for (int i = 2; i < tokens.length; i++) {
|
||||||
|
//The the option to the map of options.
|
||||||
|
addOption(tokens[i], options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Create an AppConfguration using the extracted data.
|
||||||
|
return new AppConfigurationEntry(name, flag, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method to convert a string to a
|
||||||
|
* {@link AppConfigurationEntry.LoginModuleControlFlag}. If the provided
|
||||||
|
* string is not a valid flag a {@link ConfigError} is thrown.
|
||||||
|
*
|
||||||
|
* @param flag The string to convert.
|
||||||
|
*
|
||||||
|
* @return {@link AppConfigurationEntry.LoginModuleControlFlag} instance.
|
||||||
|
*/
|
||||||
|
private AppConfigurationEntry.LoginModuleControlFlag parseFlag(
|
||||||
|
final String flag) {
|
||||||
|
switch (flag.toUpperCase()) {
|
||||||
|
case "REQUISITE":
|
||||||
|
return AppConfigurationEntry.LoginModuleControlFlag.REQUISITE;
|
||||||
|
|
||||||
|
case "REQUIRED":
|
||||||
|
return AppConfigurationEntry.LoginModuleControlFlag.REQUIRED;
|
||||||
|
|
||||||
|
case "SUFFICIENT":
|
||||||
|
return AppConfigurationEntry.LoginModuleControlFlag.SUFFICIENT;
|
||||||
|
|
||||||
|
case "OPTIONAL":
|
||||||
|
return AppConfigurationEntry.LoginModuleControlFlag.OPTIONAL;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new ConfigError(String.format(
|
||||||
|
"Unknown flag \"%s\". Valid flags are: REQUISITE, "
|
||||||
|
+ "REQUIRED, SUFFICIENT, OPTIONAL",
|
||||||
|
flag));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method for extracting the key and value parts from an module
|
||||||
|
* option string. If the option string is malformed an {@link ConfigError}
|
||||||
|
* is thrown.
|
||||||
|
*
|
||||||
|
* @param option The option string to parse.
|
||||||
|
* @param options The map of options to which the parsed option we be added.
|
||||||
|
*/
|
||||||
|
private void addOption(final String option,
|
||||||
|
final Map<String, String> options) {
|
||||||
|
//Find the index of the '=' character.
|
||||||
|
final int index = option.indexOf('=');
|
||||||
|
//If there is no '=' in the string the option string is invalid
|
||||||
|
if (index == -1) {
|
||||||
|
throw new ConfigError(String.format(
|
||||||
|
"The option string \"%s\" is malformed.", option));
|
||||||
|
}
|
||||||
|
|
||||||
|
//Extract key and value an put them into the options map.
|
||||||
|
final String key = option.substring(0, index);
|
||||||
|
final String value = option.substring(index + 1);
|
||||||
|
options.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,45 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2015 LibreCCM Foundation.
|
|
||||||
*
|
|
||||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library 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 library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package org.libreccm.core.authentication;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
|
||||||
*/
|
|
||||||
public class LoginConfigMalformedException extends RuntimeException {
|
|
||||||
private static final long serialVersionUID = 8573796343232732323L;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new instance of <code>NewException</code> without detail
|
|
||||||
* message.
|
|
||||||
*/
|
|
||||||
public LoginConfigMalformedException() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs an instance of <code>NewException</code> with the specified
|
|
||||||
* detail message.
|
|
||||||
*
|
|
||||||
* @param msg the detail message.
|
|
||||||
*/
|
|
||||||
public LoginConfigMalformedException(final String msg) {
|
|
||||||
super(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -53,13 +53,13 @@ public class LoginManager {
|
||||||
/**
|
/**
|
||||||
* Name of the register login context.
|
* Name of the register login context.
|
||||||
*/
|
*/
|
||||||
private static final String REGISTER_LOGIN_CONTEXT = "RegisterLoginContext";
|
private static final String REGISTER_LOGIN_CONTEXT = "Register";
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private transient CcmSessionContext sessionContext;
|
private transient CcmSessionContext sessionContext;
|
||||||
|
|
||||||
@Inject
|
// @Inject
|
||||||
private transient UserRepository userRepository;
|
// private transient UserRepository userRepository;
|
||||||
|
|
||||||
public void login(final String username, final String password)
|
public void login(final String username, final String password)
|
||||||
throws LoginException {
|
throws LoginException {
|
||||||
|
|
|
||||||
|
|
@ -103,6 +103,7 @@ public class SecurityConfigTest {
|
||||||
.getPackage())
|
.getPackage())
|
||||||
.addPackage(org.libreccm.tests.categories.IntegrationTest.class
|
.addPackage(org.libreccm.tests.categories.IntegrationTest.class
|
||||||
.getPackage())
|
.getPackage())
|
||||||
|
.addPackage(org.libreccm.core.authentication.LocalLoginModule.class.getPackage())
|
||||||
.addAsLibraries(libs)
|
.addAsLibraries(libs)
|
||||||
.addAsResource(
|
.addAsResource(
|
||||||
"configtests/com/arsdigita/kernel/security/SecurityConfigTest/ccm-core.config",
|
"configtests/com/arsdigita/kernel/security/SecurityConfigTest/ccm-core.config",
|
||||||
|
|
|
||||||
|
|
@ -112,7 +112,7 @@ public class UserManagerTest {
|
||||||
|
|
||||||
return ShrinkWrap
|
return ShrinkWrap
|
||||||
.create(WebArchive.class,
|
.create(WebArchive.class,
|
||||||
"LibreCCM-org.libreccm.core.UserRepositoryTest.war")
|
"LibreCCM-org.libreccm.core.UserManagerTest.war")
|
||||||
.addPackage(User.class.getPackage())
|
.addPackage(User.class.getPackage())
|
||||||
.addPackage(org.libreccm.web.Application.class.getPackage())
|
.addPackage(org.libreccm.web.Application.class.getPackage())
|
||||||
.addPackage(org.libreccm.categorization.Category.class.
|
.addPackage(org.libreccm.categorization.Category.class.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,252 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015 LibreCCM Foundation.
|
||||||
|
*
|
||||||
|
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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 library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.libreccm.core.authentication;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.*;
|
||||||
|
|
||||||
|
import org.jboss.arquillian.container.test.api.Deployment;
|
||||||
|
import org.jboss.arquillian.junit.Arquillian;
|
||||||
|
import org.jboss.arquillian.junit.InSequence;
|
||||||
|
import org.jboss.arquillian.persistence.PersistenceTest;
|
||||||
|
import org.jboss.arquillian.persistence.UsingDataSet;
|
||||||
|
import org.jboss.arquillian.transaction.api.annotation.TransactionMode;
|
||||||
|
import org.jboss.arquillian.transaction.api.annotation.Transactional;
|
||||||
|
import org.jboss.shrinkwrap.api.ShrinkWrap;
|
||||||
|
import org.jboss.shrinkwrap.api.asset.EmptyAsset;
|
||||||
|
import org.jboss.shrinkwrap.api.spec.WebArchive;
|
||||||
|
import org.jboss.shrinkwrap.resolver.api.maven.Maven;
|
||||||
|
import org.jboss.shrinkwrap.resolver.api.maven.PomEquippedResolveStage;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.AfterClass;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.experimental.categories.Category;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.libreccm.core.CcmObject;
|
||||||
|
import org.libreccm.core.CcmSessionContext;
|
||||||
|
import org.libreccm.core.EmailAddress;
|
||||||
|
import org.libreccm.tests.categories.IntegrationTest;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.security.auth.login.Configuration;
|
||||||
|
import javax.security.auth.login.LoginException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
|
*/
|
||||||
|
@Category(IntegrationTest.class)
|
||||||
|
@RunWith(Arquillian.class)
|
||||||
|
@PersistenceTest
|
||||||
|
@Transactional(TransactionMode.COMMIT)
|
||||||
|
public class LoginManagerTest {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private transient LoginManager loginManager;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private transient CcmSessionContext ccmSessionContext;
|
||||||
|
|
||||||
|
public LoginManagerTest() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void setUpClass() {
|
||||||
|
final String[] config = new String[]{
|
||||||
|
String.format("Register:%s:requisite",
|
||||||
|
LocalLoginModule.class.getName())};
|
||||||
|
final LoginConfigBuilder loginConfigBuilder = new LoginConfigBuilder(
|
||||||
|
config);
|
||||||
|
Configuration.setConfiguration(loginConfigBuilder.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void tearDownClass() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deployment
|
||||||
|
public static WebArchive createDeployment() {
|
||||||
|
final PomEquippedResolveStage pom = Maven
|
||||||
|
.resolver()
|
||||||
|
.loadPomFromFile("pom.xml");
|
||||||
|
final PomEquippedResolveStage dependencies = pom
|
||||||
|
.importCompileAndRuntimeDependencies();
|
||||||
|
final File[] libs = dependencies.resolve().withTransitivity().asFile();
|
||||||
|
|
||||||
|
for (File lib : libs) {
|
||||||
|
System.err.printf("Adding file '%s' to test archive...%n",
|
||||||
|
lib.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
return ShrinkWrap
|
||||||
|
.create(WebArchive.class,
|
||||||
|
"LibreCCM-org.libreccm.core.authentication.LoginManagerTest.war")
|
||||||
|
.addPackage(CcmObject.class.getPackage())
|
||||||
|
.addPackage(org.libreccm.web.Application.class.getPackage())
|
||||||
|
.addPackage(org.libreccm.categorization.Category.class.
|
||||||
|
getPackage())
|
||||||
|
.addPackage(org.libreccm.l10n.LocalizedString.class.getPackage()).
|
||||||
|
addPackage(org.libreccm.jpa.EntityManagerProducer.class
|
||||||
|
.getPackage())
|
||||||
|
.addPackage(org.libreccm.jpa.utils.MimeTypeConverter.class
|
||||||
|
.getPackage())
|
||||||
|
.addPackage(org.libreccm.testutils.EqualsVerifier.class.
|
||||||
|
getPackage())
|
||||||
|
.addPackage(org.libreccm.core.authentication.LoginManager.class
|
||||||
|
.getPackage())
|
||||||
|
.addPackage(com.arsdigita.kernel.KernelConfig.class.getPackage())
|
||||||
|
.addPackage(com.arsdigita.runtime.AbstractConfig.class.getPackage())
|
||||||
|
.addPackage(com.arsdigita.util.parameter.AbstractParameter.class
|
||||||
|
.getPackage())
|
||||||
|
.addPackage(com.arsdigita.util.UncheckedWrapperException.class
|
||||||
|
.getPackage())
|
||||||
|
.addPackage(org.libreccm.tests.categories.IntegrationTest.class
|
||||||
|
.getPackage())
|
||||||
|
.addPackage(com.arsdigita.web.CCMApplicationContextListener.class
|
||||||
|
.getPackage())
|
||||||
|
.addAsLibraries(libs)
|
||||||
|
.addAsResource("test-persistence.xml",
|
||||||
|
"META-INF/persistence.xml")
|
||||||
|
.addAsResource(
|
||||||
|
"configtests/com/arsdigita/kernel/KernelConfigTest/ccm-core.config",
|
||||||
|
"ccm-core.config")
|
||||||
|
.addAsWebInfResource(
|
||||||
|
"configtests/com/arsdigita/kernel/KernelConfigTest/registry.properties",
|
||||||
|
"conf/registry/registry.properties")
|
||||||
|
.addAsWebInfResource(
|
||||||
|
"configtests/com/arsdigita/kernel/KernelConfigTest/kernel.properties",
|
||||||
|
"conf/registry/ccm-core/kernel.properties")
|
||||||
|
.addAsResource(
|
||||||
|
"com/arsdigita/kernel/KernelConfig_parameter.properties",
|
||||||
|
"com/arsdigita/kernel/KernelConfig_parameter.properties")
|
||||||
|
.addAsWebInfResource("test-web.xml", "WEB-INF/web.xml")
|
||||||
|
.addAsWebInfResource(EmptyAsset.INSTANCE, "WEB-INF/beans.xml");
|
||||||
|
}
|
||||||
|
|
||||||
|
@InSequence(1)
|
||||||
|
public void isLoginManagerInjected() {
|
||||||
|
assertThat(loginManager, is(not(nullValue())));
|
||||||
|
}
|
||||||
|
|
||||||
|
@InSequence(2)
|
||||||
|
public void isCcmSessionContextInjected() {
|
||||||
|
assertThat(ccmSessionContext, is(not(nullValue())));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@UsingDataSet(
|
||||||
|
"datasets/org/libreccm/core/authentication/LoginManagerTest/data.json")
|
||||||
|
@InSequence(10)
|
||||||
|
public void loginValidCredentials() throws LoginException {
|
||||||
|
loginManager.login("jdoe@example.com", "correct-pw");
|
||||||
|
|
||||||
|
assertThat(ccmSessionContext.getCurrentParty(), is(not(nullValue())));
|
||||||
|
final EmailAddress emailAddress = new EmailAddress();
|
||||||
|
emailAddress.setAddress("jdoe@example.org");
|
||||||
|
emailAddress.setBouncing(false);
|
||||||
|
emailAddress.setVerified(true);
|
||||||
|
assertThat(ccmSessionContext.getCurrentParty().getEmailAddresses(),
|
||||||
|
contains(equalTo(emailAddress)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@UsingDataSet(
|
||||||
|
"datasets/org/libreccm/core/authentication/LoginManagerTest/data.json")
|
||||||
|
@InSequence(20)
|
||||||
|
public void loginWrongCredentials() throws LoginException {
|
||||||
|
try {
|
||||||
|
loginManager.login("jdoe@example.com", "wrong-pw");
|
||||||
|
} catch (LoginException ex) {
|
||||||
|
assertThat(ccmSessionContext.getCurrentParty(), is(nullValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
fail("No login exception was thrown.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@UsingDataSet(
|
||||||
|
"datasets/org/libreccm/core/authentication/LoginManagerTest/data.json")
|
||||||
|
@InSequence(30)
|
||||||
|
public void loginEmptyPassword() {
|
||||||
|
try {
|
||||||
|
loginManager.login("jdoe@example.com", "");
|
||||||
|
} catch (LoginException ex) {
|
||||||
|
assertThat(ccmSessionContext.getCurrentParty(), is(nullValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
fail("No login exception was thrown.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@UsingDataSet(
|
||||||
|
"datasets/org/libreccm/core/authentication/LoginManagerTest/data.json")
|
||||||
|
@InSequence(40)
|
||||||
|
public void loginEmptyUserName() {
|
||||||
|
try {
|
||||||
|
loginManager.login("", "correct-pw");
|
||||||
|
} catch (LoginException ex) {
|
||||||
|
assertThat(ccmSessionContext.getCurrentParty(), is(nullValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
fail("No login exception was thrown.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@UsingDataSet(
|
||||||
|
"datasets/org/libreccm/core/authentication/LoginManagerTest/data.json")
|
||||||
|
@InSequence(50)
|
||||||
|
public void loginNullPassword() {
|
||||||
|
try {
|
||||||
|
loginManager.login("jdoe@example.com", null);
|
||||||
|
} catch (LoginException ex) {
|
||||||
|
assertThat(ccmSessionContext.getCurrentParty(), is(nullValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
fail("No login exception was thrown.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@UsingDataSet(
|
||||||
|
"datasets/org/libreccm/core/authentication/LoginManagerTest/data.json")
|
||||||
|
@InSequence(60)
|
||||||
|
public void loginNullUsername() {
|
||||||
|
try {
|
||||||
|
loginManager.login(null, "correct-pw");
|
||||||
|
} catch (LoginException ex) {
|
||||||
|
assertThat(ccmSessionContext.getCurrentParty(), is(nullValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
fail("No login exception was thrown.");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
{
|
||||||
|
"subjects":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"subject_id": -10
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"subject_email_addresses":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"subject_id": -10,
|
||||||
|
"email_address": "jdoe@example.com",
|
||||||
|
"bouncing": false,
|
||||||
|
"verified": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"ccm_users":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"banned": false,
|
||||||
|
"hash_algorithm": "SHA-512",
|
||||||
|
"family_name": "Doe",
|
||||||
|
"given_name": "John",
|
||||||
|
"password": "abc8f796612f5c5b5d0c89cf86ea3b8d1c7d15f9c06851f85708013b0248b2e6d9b315b48f586168fe6cc29296e5a9090a5aab14a85b3ffd0633ca8ccc587a09",
|
||||||
|
"salt": "fiagaifa",
|
||||||
|
"screen_name": "jdoe",
|
||||||
|
"subject_id": -10
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue