/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.jackrabbit.oak.spi.security.authentication;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import org.apache.jackrabbit.api.security.authentication.token.TokenCredentials;
import org.apache.jackrabbit.api.security.principal.PrincipalManager;
import org.apache.jackrabbit.api.security.user.UserManager;
import org.apache.jackrabbit.oak.api.AuthInfo;
import org.apache.jackrabbit.oak.api.ContentRepository;
import org.apache.jackrabbit.oak.api.ContentSession;
import org.apache.jackrabbit.oak.api.Root;
import org.apache.jackrabbit.oak.namepath.NamePathMapper;
import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
import org.apache.jackrabbit.oak.spi.security.OpenSecurityProvider;
import org.apache.jackrabbit.oak.spi.security.SecurityProvider;
import org.apache.jackrabbit.oak.spi.security.authentication.callback.CredentialsCallback;
import org.apache.jackrabbit.oak.spi.security.authentication.callback.PrincipalProviderCallback;
import org.apache.jackrabbit.oak.spi.security.authentication.callback.RepositoryCallback;
import org.apache.jackrabbit.oak.spi.security.authentication.callback.SecurityProviderCallback;
import org.apache.jackrabbit.oak.spi.security.authentication.callback.UserManagerCallback;
import org.apache.jackrabbit.oak.spi.security.authentication.callback.WhiteboardCallback;
import org.apache.jackrabbit.oak.spi.security.principal.PrincipalConfiguration;
import org.apache.jackrabbit.oak.spi.security.principal.PrincipalImpl;
import org.apache.jackrabbit.oak.spi.security.principal.PrincipalProvider;
import org.apache.jackrabbit.oak.spi.security.principal.TestPrincipalProvider;
import org.apache.jackrabbit.oak.spi.security.user.UserConfiguration;
import org.apache.jackrabbit.oak.spi.whiteboard.DefaultWhiteboard;
import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.junit.Test;

import javax.jcr.Credentials;
import javax.jcr.GuestCredentials;
import javax.jcr.SimpleCredentials;
import javax.security.auth.DestroyFailedException;
import javax.security.auth.Destroyable;
import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.login.LoginException;
import java.io.IOException;
import java.security.Principal;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import static org.apache.jackrabbit.oak.spi.security.authentication.AbstractLoginModule.SHARED_KEY_CREDENTIALS;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.withSettings;

public class AbstractLoginModuleTest {

    private final LoginModuleMonitor monitor = mock(LoginModuleMonitor.class);

    private static AbstractLoginModule initLoginModule(@NotNull Class<?> supportedCredentials, @NotNull  Map<String, ?> sharedState) {
        AbstractLoginModule lm = new TestLoginModule(supportedCredentials);
        initialize(lm, new Subject(), null, sharedState);
        return lm;
    }

    private static AbstractLoginModule initLoginModule(@Nullable CallbackHandler cbh) {
        AbstractLoginModule lm = new TestLoginModule(TestCredentials.class);
        initialize(lm, new Subject(), cbh, Collections.emptyMap());
        return lm;
    }

    private static AbstractLoginModule initLoginModule(@NotNull CallbackHandler cbh, @NotNull LoginModuleMonitor monitor) {
        AbstractLoginModule lm = new TestLoginModule(TestCredentials.class, monitor);
        initialize(lm, new Subject(), cbh, Collections.emptyMap());
        return lm;
    }

    private static AbstractLoginModule initLoginModule(@NotNull Subject subject) {
        AbstractLoginModule lm = new TestLoginModule(TestCredentials.class, null);
        initialize(lm, subject, mock(CallbackHandler.class), Collections.emptyMap());
        return lm;
    }

    private static void initialize(@NotNull AbstractLoginModule loginModule, @NotNull Subject subject, @Nullable CallbackHandler cbh, @NotNull Map<String, ?> sharedState) {
        loginModule.initialize(subject, cbh, sharedState, null);
    }

    private static ContentRepository mockContentRepository(@Nullable ContentSession contentSession) throws Exception {
        ContentSession cs = (contentSession == null) ? mock(ContentSession.class) : contentSession;
        Root r = when(mock(Root.class).getContentSession()).thenReturn(cs).getMock();
        when(cs.getLatestRoot()).thenReturn(r);
        return when(mock(ContentRepository.class).login(null, null)).thenReturn(cs).getMock();
    }

    @Test
    public void testInitializeWithOptions() {
        AbstractLoginModule lm = new TestLoginModule(TestCredentials.class);
        Map<String, String> options = ImmutableMap.of("key", "value");
        lm.initialize(new Subject(), null, Collections.emptyMap(), options);

        assertNotSame(options, lm.options);
        assertEquals(options, lm.options);

        ConfigurationParameters options2 = ConfigurationParameters.of(options);
        lm.initialize(new Subject(), null, Collections.emptyMap(), options2);

        assertSame(options2, lm.options);
    }

    @Test
    public void testLogout() throws Exception {
        AbstractLoginModule loginModule = initLoginModule(TestCredentials.class, ImmutableMap.of());

        assertFalse(loginModule.logout());
    }

    @Test
    public void testLogoutSuccessClearsSubject() throws Exception {
        Subject subject = new Subject(false, ImmutableSet.<Principal>of(new PrincipalImpl("pName")), ImmutableSet.of(new TestCredentials()), ImmutableSet.of());
        AbstractLoginModule loginModule = initLoginModule(subject);

        assertTrue(loginModule.logout());

        assertTrue(subject.getPublicCredentials().isEmpty());
        assertTrue(subject.getPrincipals().isEmpty());
    }

    @Test
    public void testLogoutSuccessReadOnlySubject() throws Exception {
        Subject subject = new Subject(true, ImmutableSet.<Principal>of(new PrincipalImpl("pName")), ImmutableSet.of(new TestCredentials()), ImmutableSet.of());
        AbstractLoginModule loginModule = initLoginModule(subject);

        assertTrue(loginModule.logout());

        assertFalse(subject.getPublicCredentials().isEmpty());
        assertFalse(subject.getPrincipals().isEmpty());
    }

    @Test
    public void testLogoutSubjectWithoutCredentials() throws Exception {
        Subject subject = new Subject(false, ImmutableSet.<Principal>of(new PrincipalImpl("pName")), ImmutableSet.of("stringNotCredentials"), ImmutableSet.of());
        AbstractLoginModule loginModule = initLoginModule(subject);
        loginModule.logout();

        assertFalse(subject.getPublicCredentials().isEmpty());
        assertFalse(subject.getPrincipals().isEmpty());

        subject = new Subject(false, ImmutableSet.<Principal>of(new PrincipalImpl("pName")), ImmutableSet.of(), ImmutableSet.of());
        loginModule = initLoginModule(subject);
        loginModule.logout();

        assertTrue(subject.getPublicCredentials().isEmpty());
        assertFalse(subject.getPrincipals().isEmpty());
    }

    @Test
    public void testLogoutSubjectWithoutPrincipals() throws Exception {
        Subject subject = new Subject(false, ImmutableSet.of(), ImmutableSet.of(new TestCredentials()), ImmutableSet.of());
        AbstractLoginModule loginModule = initLoginModule(subject);
        loginModule.logout();

        assertFalse(subject.getPublicCredentials().isEmpty());
        assertTrue(subject.getPrincipals().isEmpty());
    }

    @Test
    public void testLogoutCPIgnored() throws LoginException {
        AbstractLoginModule loginModule = initLoginModule(new Subject());
        assertFalse(loginModule.logout(null, null));
    }

    @Test
    public void testLogoutCPSuccess() throws LoginException {
        PrincipalProvider pp = new TestPrincipalProvider("user");
        Principal p = pp.getPrincipal("user");
        assertNotNull(p);
        Principal foreignPrincipal = TestPrincipalProvider.UNKNOWN;

        String userId = TestPrincipalProvider.getIDFromPrincipal(p);
        Set<? extends Principal> principals = pp.getPrincipals(userId);
        Set<Principal> all = ImmutableSet.<Principal>builder().add(p).add(foreignPrincipal).addAll(principals).build();


        AuthInfo authInfo = new AuthInfoImpl(userId, null, all);
        Credentials foreign1 = new GuestCredentials();
        Credentials foreign2 = new TokenCredentials("token");

        Subject subject = new Subject(false,
                ImmutableSet.of(foreignPrincipal, p),
                ImmutableSet.of(authInfo, foreign1, foreign2), ImmutableSet.of());

        TestLoginModule loginModule = new TestLoginModule(SimpleCredentials.class);
        loginModule.initialize(subject, new TestCallbackHandler(pp), Collections.emptyMap(), null);

        assertTrue(loginModule.logout(ImmutableSet.of(authInfo), principals));

        Set<Object> publicCreds = subject.getPublicCredentials();
        assertFalse(publicCreds.contains(authInfo));
        assertTrue(publicCreds.contains(foreign1));
        assertTrue(publicCreds.contains(foreign2));

        assertFalse(subject.getPrincipals().contains(p));
        assertTrue(Collections.disjoint(subject.getPrincipals(), principals));
        assertTrue(subject.getPrincipals().contains(foreignPrincipal));
    }

    @Test
    public void testLogoutCPDestroyable() throws Exception {
        Credentials creds = mock(TestCredentials.class, withSettings().extraInterfaces(Destroyable.class));
        Credentials foreign1 = new GuestCredentials();
        Credentials foreign2 = new TokenCredentials("token");

        Subject subject = new Subject(true,
                ImmutableSet.<Principal>of(new PrincipalImpl("pName")),
                ImmutableSet.of(creds, foreign1, foreign2), ImmutableSet.of());

        AbstractLoginModule loginModule = initLoginModule(subject);
        assertTrue(loginModule.logout(ImmutableSet.of(creds), Collections.emptySet()));

        verify(((Destroyable) creds), times(1)).destroy();
    }

    @Test(expected = LoginException.class)
    public void testLogoutCPDestroyFails() throws Exception {
        Credentials creds = mock(TestCredentials.class, withSettings().extraInterfaces(Destroyable.class));
        doThrow(new DestroyFailedException()).when((Destroyable)creds).destroy();

        Subject subject = new Subject(true, ImmutableSet.of(), ImmutableSet.of(creds), ImmutableSet.of());
        AbstractLoginModule loginModule = initLoginModule(subject);
        loginModule.logout(ImmutableSet.of(creds), null);
    }

    @Test
    public void testLogoutCPNotDestroyable() throws LoginException {
        Credentials creds = new TestCredentials();
        Subject subject = new Subject(true,
                ImmutableSet.of(),
                ImmutableSet.of(creds), ImmutableSet.of());

        TestLoginModule loginModule = (TestLoginModule) initLoginModule(subject);
        assertTrue(loginModule.logout(null, Collections.emptySet()));
    }

    @Test
    public void testLogoutCPNullParams() throws LoginException {
        Credentials creds = new TestCredentials();
        Principal unknownPrincipal = TestPrincipalProvider.UNKNOWN;
        TestPrincipalProvider pp = new TestPrincipalProvider("principal");

        Subject subject = new Subject(false, ImmutableSet.of(unknownPrincipal), ImmutableSet.of(creds), ImmutableSet.of());

        TestLoginModule loginModule = new TestLoginModule(SimpleCredentials.class);
        loginModule.initialize(subject, new TestCallbackHandler(pp), Collections.emptyMap(), null);

        assertFalse(loginModule.logout(null, null));
        // subject must not be altered by logout
        assertTrue(subject.getPublicCredentials().contains(creds));
        assertTrue(subject.getPrincipals().contains(unknownPrincipal));
    }

    @Test
    public void testLogoutCPMissingCredentials() throws LoginException {
        Credentials creds = new TestCredentials();
        Principal unknownPrincipal = TestPrincipalProvider.UNKNOWN;
        TestPrincipalProvider pp = new TestPrincipalProvider("principal");
        Principal p = pp.getPrincipal("principal");
        assertNotNull(p);

        Subject subject = new Subject(false, ImmutableSet.of(unknownPrincipal, p), ImmutableSet.of(creds), ImmutableSet.of());

        TestLoginModule loginModule = new TestLoginModule(SimpleCredentials.class);
        loginModule.initialize(subject, new TestCallbackHandler(pp), Collections.emptyMap(), null);

        assertTrue(loginModule.logout(null, ImmutableSet.of(p)));

        // only credentials/principals passed to logout must be removed
        assertTrue(subject.getPublicCredentials().contains(creds));
        assertTrue(subject.getPrincipals().contains(unknownPrincipal));
        assertFalse(subject.getPrincipals().contains(p));
    }

    @Test
    public void testLogoutCPMissingCredentialsReadOnly() throws LoginException {
        Credentials creds = new TestCredentials();
        Principal unknownPrincipal = TestPrincipalProvider.UNKNOWN;
        TestPrincipalProvider pp = new TestPrincipalProvider("principal");
        Principal p = pp.getPrincipal("principal");

        Set<? extends Principal> principals = ImmutableSet.of(unknownPrincipal, p);
        AuthInfo authInfo = new AuthInfoImpl(null, null, principals);
        Subject subject = new Subject(true, principals, ImmutableSet.of(creds, authInfo), ImmutableSet.of());

        TestLoginModule loginModule = new TestLoginModule(SimpleCredentials.class);
        loginModule.initialize(subject, new TestCallbackHandler(pp), Collections.emptyMap(), null);

        assertTrue(loginModule.logout(ImmutableSet.of(creds, authInfo), Collections.singleton(p)));
        // read-only subject must not be altered by logout
        assertTrue(subject.getPublicCredentials().contains(creds));
        assertTrue(subject.getPrincipals().contains(unknownPrincipal));
        assertTrue(subject.getPrincipals().contains(p));
    }

    @Test
    public void testLogoutCPMissingPrincipals() throws LoginException {
        Credentials creds = new TestCredentials();
        Principal preExisting = new PrincipalImpl("pName");

        Subject subject = new Subject(false, ImmutableSet.of(preExisting), ImmutableSet.of(creds), ImmutableSet.of());
        TestLoginModule loginModule = (TestLoginModule) initLoginModule(subject);
        assertTrue(loginModule.logout(ImmutableSet.of(creds), null));

        assertFalse(subject.getPublicCredentials().contains(creds));
        assertTrue(subject.getPrincipals().contains(preExisting));
    }

    @Test
    public void testAbort() throws LoginException {
        AbstractLoginModule loginModule = initLoginModule(TestCredentials.class, ImmutableMap.of());

        assertTrue(loginModule.abort());
    }

    @Test
    public void testAbortWithFailedSystemLogout() throws Exception {
        ContentRepository cr = mockContentRepository(null);
        AbstractLoginModule loginModule = initLoginModule(new TestCallbackHandler(cr, null));

        // trigger creation of system-session
        loginModule.getRoot();
        assertTrue(loginModule.abort());
    }

    @Test
    public void testClearStateWithSessionCloseFailing() throws Exception {
        ContentSession cs = mock(ContentSession.class);
        ContentRepository cr = mockContentRepository(cs);
        doThrow(IOException.class).when(cs).close();

        CallbackHandler cbh = new TestCallbackHandler(cr, mock(SecurityProvider.class));

        AbstractLoginModule loginModule = initLoginModule(cbh, monitor);
        loginModule.getRoot();
        loginModule.clearState();
        verify(monitor).loginError();
        verifyNoMoreInteractions(monitor);
        verify(cs, times(1)).close();
    }

    @Test
    public void testCloseSystemSession() throws Exception {
        ContentSession cs = mock(ContentSession.class);
        ContentRepository cr = mockContentRepository(cs);

        CallbackHandler cbh = new TestCallbackHandler(cr, mock(SecurityProvider.class));

        AbstractLoginModule loginModule = initLoginModule(cbh);
        loginModule.getRoot();
        loginModule.closeSystemSession();
        verify(cs, times(1)).close();
    }

    @Test
    public void testGetSharedLoginName() {
        Map<String, String> sharedState = new HashMap<>();

        sharedState.put(AbstractLoginModule.SHARED_KEY_LOGIN_NAME, "test");
        AbstractLoginModule lm = initLoginModule(TestCredentials.class, sharedState);
        assertEquals("test", lm.getSharedLoginName());

        sharedState.clear();
        lm = initLoginModule(TestCredentials.class, sharedState);
        assertNull(lm.getSharedLoginName());
    }

    @Test
    public void testGetSharedCredentials() {
        Map<String, Object> sharedState = new HashMap<>();

        sharedState.put(SHARED_KEY_CREDENTIALS, new TestCredentials());
        AbstractLoginModule lm = initLoginModule(TestCredentials.class, sharedState);
        assertTrue(lm.getSharedCredentials() instanceof TestCredentials);

        sharedState.put(SHARED_KEY_CREDENTIALS, new SimpleCredentials("test", "test".toCharArray()));
        lm = initLoginModule(TestCredentials.class, sharedState);
        assertTrue(lm.getSharedCredentials() instanceof SimpleCredentials);

        lm = initLoginModule(SimpleCredentials.class, sharedState);
        assertTrue(lm.getSharedCredentials() instanceof SimpleCredentials);

        sharedState.put(SHARED_KEY_CREDENTIALS, "no credentials object");
        lm = initLoginModule(TestCredentials.class, sharedState);
        assertNull(lm.getSharedCredentials());

        sharedState.clear();
        lm = initLoginModule(TestCredentials.class, sharedState);
        assertNull(lm.getSharedCredentials());
    }

    @Test
    public void testGetCredentialsFromSharedState() {
        Map<String, Credentials> sharedState = new HashMap<>();
        sharedState.put(SHARED_KEY_CREDENTIALS, new TestCredentials());

        AbstractLoginModule lm = initLoginModule(TestCredentials.class, sharedState);
        assertTrue(lm.getCredentials() instanceof TestCredentials);

        SimpleCredentials sc = new SimpleCredentials("test", "test".toCharArray());
        sharedState.put(SHARED_KEY_CREDENTIALS, sc);
        lm = initLoginModule(TestCredentials.class, sharedState);
        assertNull(lm.getCredentials());

        sharedState.put(SHARED_KEY_CREDENTIALS, sc);
        lm = initLoginModule(SimpleCredentials.class, sharedState);
        assertTrue(lm.getCredentials() instanceof SimpleCredentials);

        sharedState.clear();
        lm = initLoginModule(TestCredentials.class, sharedState);
        assertNull(lm.getCredentials());
    }

    @Test
    public void testGetCredentialsFromSubject() {
        Subject subject = new Subject();
        subject.getPublicCredentials().add(new TestCredentials());

        AbstractLoginModule lm = new TestLoginModule(TestCredentials.class);
        lm.initialize(subject, null, ImmutableMap.of(), null);

        assertTrue(lm.getCredentials() instanceof TestCredentials);
    }

    @Test
    public void testGetCredentialsFromSubjectWrongClass() {
        Subject subject = new Subject();
        subject.getPublicCredentials().add(new SimpleCredentials("userid", new char[0]));

        AbstractLoginModule lm = new TestLoginModule(TestCredentials.class);
        lm.initialize(subject, null, Collections.emptyMap(), null);

        assertNull(lm.getCredentials());
    }

    @Test
    public void testGetCredentialsFromCallbackHandler() {
        CallbackHandler cbh = callbacks -> {
            for (Callback cb : callbacks) {
                if (cb instanceof CredentialsCallback) {
                    ((CredentialsCallback) cb).setCredentials(new TestCredentials());
                }
            }
        };

        AbstractLoginModule lm = initLoginModule(cbh);
        assertTrue(lm.getCredentials() instanceof TestCredentials);

        lm = new TestLoginModule(SimpleCredentials.class);
        lm.initialize(new Subject(), cbh, Collections.emptyMap(), null);
        assertNull(lm.getCredentials());
    }

    @Test
    public void testGetCredentialsIOException() {
        AbstractLoginModule lm = initLoginModule(new ThrowingCallbackHandler(true), monitor);
        assertNull(lm.getCredentials());
        verify(monitor, times(1)).loginError();
        verifyNoMoreInteractions(monitor);
    }

    @Test
    public void testGetCredentialsUnsupportedCallbackException() {
        AbstractLoginModule lm = initLoginModule(new ThrowingCallbackHandler(false), monitor);
        assertNull(lm.getCredentials());
        verify(monitor, times(1)).loginError();
        verifyNoMoreInteractions(monitor);
    }

    @Test
    public void testGetCredentialsCallbackReturnsNull() {
        CallbackHandler cbh = callbacks -> {
            for (Callback cb : callbacks) {
                if (cb instanceof CredentialsCallback) {
                    ((CredentialsCallback) cb).setCredentials(null);
                }
            }
        };
        AbstractLoginModule lm = initLoginModule(cbh);
        assertNull(lm.getCredentials());
    }

    @Test
    public void testGetSharedPreAuthLoginEmptySharedState() {
        AbstractLoginModule loginModule = initLoginModule(TestCredentials.class, ImmutableMap.of());
        assertNull(loginModule.getSharedPreAuthLogin());
    }

    @Test
    public void testGetSharedPreAuthLogin() {
        Map<String, PreAuthenticatedLogin> sharedState = new HashMap<>();
        AbstractLoginModule loginModule = initLoginModule(TestCredentials.class, sharedState);

        PreAuthenticatedLogin preAuthenticatedLogin = new PreAuthenticatedLogin("userId");
        sharedState.put(AbstractLoginModule.SHARED_KEY_PRE_AUTH_LOGIN, preAuthenticatedLogin);

        assertSame(preAuthenticatedLogin, loginModule.getSharedPreAuthLogin());
    }

    @Test
    public void testGetSharedPreAuthLoginWrongEntry() {
        Map<String, String> sharedState = new HashMap<>();
        AbstractLoginModule loginModule = initLoginModule(TestCredentials.class, sharedState);

        sharedState.put(AbstractLoginModule.SHARED_KEY_PRE_AUTH_LOGIN, "wrongType");

        assertNull(loginModule.getSharedPreAuthLogin());
    }

    @Test
    public void testIncompleteRepositoryCallback() {
        AbstractLoginModule loginModule = initLoginModule(new TestCallbackHandler());

        assertNull(loginModule.getSecurityProvider());
        assertNull(loginModule.getRoot());
    }

    @Test
    public void testGetRoot() throws Exception {
        AbstractLoginModule loginModule = initLoginModule(new TestCallbackHandler(mockContentRepository(null), null));

        Root root = loginModule.getRoot();
        assertNotNull(root);
        // root is stored as field -> second access returns the same object
        assertSame(root, loginModule.getRoot());
    }

    @Test
    public void testGetRootIOException() {
        AbstractLoginModule lm = initLoginModule(new ThrowingCallbackHandler(true), monitor);
        assertNull(lm.getRoot());
        verify(monitor).loginError();
        verifyNoMoreInteractions(monitor);
    }

    @Test
    public void testGetRootUnsupportedCallbackException() {
        AbstractLoginModule lm = initLoginModule(new ThrowingCallbackHandler(false), monitor);
        assertNull(lm.getRoot());
        verify(monitor).loginError();
        verifyNoMoreInteractions(monitor);
    }

    @Test
    public void testGetRootMissingCallbackHandler() {
        AbstractLoginModule loginModule = initLoginModule((CallbackHandler) null);
        assertNull(loginModule.getRoot());
    }

    @Test
    public void testGetSecurityProvider() {
        AbstractLoginModule loginModule = initLoginModule(new TestCallbackHandler(null, new OpenSecurityProvider()));

        SecurityProvider securityProvider = loginModule.getSecurityProvider();
        assertNotNull(securityProvider);
        // securityProvider is stored as field -> second access returns the same object
        assertSame(securityProvider, loginModule.getSecurityProvider());
    }

    @Test
    public void testGetSecurityProviderIOException() {
        AbstractLoginModule loginModule = initLoginModule(new ThrowingCallbackHandler(true));

        assertNull(loginModule.getSecurityProvider());
    }

    @Test
    public void testGetSecurityProviderUnsupportedCallbackException() {
        AbstractLoginModule loginModule = initLoginModule(new ThrowingCallbackHandler(false));

        assertNull(loginModule.getRoot());
    }

    @Test
    public void testGetSecurityProviderMissingCallbackHandler() {
        AbstractLoginModule loginModule = initLoginModule((CallbackHandler) null);
        assertNull(loginModule.getSecurityProvider());
    }

    @Test
    public void testGetWhiteboardFromCallback() {
        AbstractLoginModule loginModule = initLoginModule(new TestCallbackHandler(new DefaultWhiteboard()));

        Whiteboard wb = loginModule.getWhiteboard();
        assertNotNull(wb);
        // whiteboard is stored as field -> second access returns the same object
        assertSame(wb, loginModule.getWhiteboard());

    }

    @Test
    public void testGetWhiteboardFromIncompleteCallback() {
        AbstractLoginModule loginModule = initLoginModule(new TestCallbackHandler());

        assertNull(loginModule.getWhiteboard());
    }

    @Test
    public void testGetWhiteboardIOException() {
        AbstractLoginModule loginModule = initLoginModule(new ThrowingCallbackHandler(true));

        assertNull(loginModule.getWhiteboard());
    }

    @Test
    public void testGetWhiteboardUnsupportedCallbackException() {
        AbstractLoginModule loginModule = initLoginModule(new ThrowingCallbackHandler(false));

        assertNull(loginModule.getWhiteboard());
    }

    @Test
    public void testGetWhiteBoardMissingCallbackHandler() {
        AbstractLoginModule loginModule = initLoginModule((CallbackHandler) null);
        assertNull(loginModule.getWhiteboard());
    }

    @Test
    public void testGetUserManagerFromCallback() {
        AbstractLoginModule loginModule = initLoginModule(new TestCallbackHandler(mock(UserManager.class)));

        UserManager userManager = loginModule.getUserManager();
        assertNotNull(userManager);
        // usermanager is stored as field -> second access returns the same object
        assertSame(userManager, loginModule.getUserManager());
    }

    @Test
    public void testGetUserManagerFromIncompleteCallback() {
        AbstractLoginModule loginModule = initLoginModule(new TestCallbackHandler());

        assertNull(loginModule.getUserManager());
    }

    @Test
    public void testGetUserManagerIOException() {
        AbstractLoginModule loginModule = initLoginModule(new ThrowingCallbackHandler(true));

        assertNull(loginModule.getUserManager());
    }

    @Test
    public void testGetUserManagerUnsupportedCallbackException() {
        AbstractLoginModule loginModule = initLoginModule(new ThrowingCallbackHandler(false));

        assertNull(loginModule.getUserManager());
    }

    @Test
    public void testGetUserManagerWithRepositoryCallbackHandler() throws Exception {
        Root r = mock(Root.class);
        ContentSession cs = when(mock(ContentSession.class).getLatestRoot()).thenReturn(r).getMock();
        ContentRepository cp = when(mock(ContentRepository.class).login(null, null)).thenReturn(cs).getMock();
        UserManager um = mock(UserManager.class);
        UserConfiguration uc = when(mock(UserConfiguration.class).getUserManager(r, NamePathMapper.DEFAULT)).thenReturn(um).getMock();
        SecurityProvider sp = when(mock(SecurityProvider.class).getConfiguration(UserConfiguration.class)).thenReturn(uc).getMock();

        CallbackHandler cbh = new TestCallbackHandler(cp, sp);
        AbstractLoginModule loginModule = initLoginModule(cbh);
        assertEquals(um, loginModule.getUserManager());
    }

    @Test
    public void testGetUserManagerMissingCallbackHandler() {
        AbstractLoginModule loginModule = initLoginModule((CallbackHandler) null);
        assertNull(loginModule.getUserManager());
    }

    @Test
    public void testGetUserManagerMissingRoot() throws Exception {
        ContentRepository cp = when(mock(ContentRepository.class).login(null, null)).thenReturn(mock(ContentSession.class)).getMock();

        CallbackHandler cbh = new TestCallbackHandler(cp, mock(SecurityProvider.class));
        AbstractLoginModule loginModule = initLoginModule(cbh);
        assertNull(loginModule.getUserManager());
    }

    @Test
    public void testGetUserManagerMissingSecurityProvider() throws Exception {
        ContentSession cs = when(mock(ContentSession.class).getLatestRoot()).thenReturn(mock(Root.class)).getMock();
        ContentRepository cp = when(mock(ContentRepository.class).login(null, null)).thenReturn(cs).getMock();

        CallbackHandler cbh = new TestCallbackHandler(cp, null);
        AbstractLoginModule loginModule = initLoginModule(cbh);
        assertNull(loginModule.getUserManager());
    }

    @Test
    public void testGetPrincipalProviderFromCallback() {
        AbstractLoginModule loginModule = initLoginModule(new TestCallbackHandler(new TestPrincipalProvider()));

        assertNotNull(loginModule.getPrincipalProvider());

        PrincipalProvider principalProvider = loginModule.getPrincipalProvider();
        assertNotNull(principalProvider);
        // principalProvider is stored as field -> second access returns the same object
        assertSame(principalProvider, loginModule.getPrincipalProvider());
    }

    @Test
    public void testGetPrincipalProviderFromIncompleteCallback() {
        AbstractLoginModule loginModule = initLoginModule(new TestCallbackHandler());

        assertNull(loginModule.getPrincipalProvider());
    }

    @Test
    public void testGetPrincipalProviderIOException() {
        AbstractLoginModule loginModule = initLoginModule(new ThrowingCallbackHandler(true));

        assertNull(loginModule.getPrincipalProvider());
    }

    @Test
    public void testGetPrincipalProviderUnsupportedCallbackException() {
        AbstractLoginModule loginModule = initLoginModule(new ThrowingCallbackHandler(false));

        assertNull(loginModule.getPrincipalProvider());
    }

    @Test
    public void testGetPrincipalProviderWithRepositoryCallbackHandler() throws Exception {
        Root r = mock(Root.class);
        ContentSession cs = when(mock(ContentSession.class).getLatestRoot()).thenReturn(r).getMock();
        ContentRepository cp = when(mock(ContentRepository.class).login(null, null)).thenReturn(cs).getMock();
        PrincipalProvider pp = mock(PrincipalProvider.class);
        PrincipalConfiguration pc = when(mock(PrincipalConfiguration.class).getPrincipalProvider(r, NamePathMapper.DEFAULT)).thenReturn(pp).getMock();
        SecurityProvider sp = when(mock(SecurityProvider.class).getConfiguration(PrincipalConfiguration.class)).thenReturn(pc).getMock();

        CallbackHandler cbh = new TestCallbackHandler(cp, sp);
        AbstractLoginModule loginModule = initLoginModule(cbh);
        assertEquals(pp, loginModule.getPrincipalProvider());
    }

    @Test
    public void testGetPrincipalProviderMissingCallbackHandler() {
        AbstractLoginModule loginModule = initLoginModule((CallbackHandler) null);
        assertNull(loginModule.getPrincipalProvider());
    }

    @Test
    public void testGetPrincipalProviderMissingRoot() throws Exception {
        ContentRepository cp = when(mock(ContentRepository.class).login(null, null)).thenReturn(mock(ContentSession.class)).getMock();

        CallbackHandler cbh = new TestCallbackHandler(cp, mock(SecurityProvider.class));
        AbstractLoginModule loginModule = initLoginModule(cbh);
        assertNull(loginModule.getPrincipalProvider());
    }

    @Test
    public void testGetPrincipalProviderMissingSecurityProvider() throws Exception {
        ContentSession cs = when(mock(ContentSession.class).getLatestRoot()).thenReturn(mock(Root.class)).getMock();
        ContentRepository cp = when(mock(ContentRepository.class).login(null, null)).thenReturn(cs).getMock();

        CallbackHandler cbh = new TestCallbackHandler(cp, null);
        AbstractLoginModule loginModule = initLoginModule(cbh);
        assertNull(loginModule.getPrincipalProvider());
    }

    @Test
    public void testGetPrincipals() {
        PrincipalProvider principalProvider = new TestPrincipalProvider();

        AbstractLoginModule loginModule = initLoginModule(new TestCallbackHandler(principalProvider));

        Principal principal = principalProvider.findPrincipals(PrincipalManager.SEARCH_TYPE_NOT_GROUP).next();
        String userId = TestPrincipalProvider.getIDFromPrincipal(principal);
        Set<? extends Principal> principals = loginModule.getPrincipals(userId);

        assertFalse(principals.isEmpty());
        assertEquals(principalProvider.getPrincipals(userId), principals);
    }


    @Test
    public void testGetPrincipalsMissingProvider() {
        AbstractLoginModule loginModule = initLoginModule(new TestCallbackHandler());

        Set<? extends Principal> principals = loginModule.getPrincipals("userId");
        assertTrue(principals.isEmpty());
    }

    @Test
    public void testGetPrincipalsFromPrincipal() {
        PrincipalProvider principalProvider = new TestPrincipalProvider();

        AbstractLoginModule loginModule = initLoginModule(new TestCallbackHandler(principalProvider));

        Principal principal = principalProvider.findPrincipals(PrincipalManager.SEARCH_TYPE_NOT_GROUP).next();
        Set<Principal> expected = new HashSet<>();
        expected.add(principal);
        expected.addAll(principalProvider.getMembershipPrincipals(principal));

        Set<? extends Principal> principals = loginModule.getPrincipals(principal);

        assertFalse(principals.isEmpty());
        assertEquals(expected, principals);
    }

    @Test
    public void testGetPrincipalsFromPrincipalMissingProvider() {
        AbstractLoginModule loginModule = initLoginModule(new TestCallbackHandler());

        Set<? extends Principal> principals = loginModule.getPrincipals(new PrincipalImpl("principalName"));
        assertTrue(principals.isEmpty());
    }

    @Test
    public void testSetAuthInfo() {
        Subject subject = new Subject();
        AuthInfo authInfo = new AuthInfoImpl("userid", null, null);

        AbstractLoginModule.setAuthInfo(authInfo, subject);
        Set<AuthInfo> fromSubject = subject.getPublicCredentials(AuthInfo.class);
        assertEquals(1, fromSubject.size());
        assertSame(authInfo, fromSubject.iterator().next());
    }

    @Test
    public void testSetAuthInfoPreExisting() {
        Subject subject = new Subject();
        subject.getPublicCredentials().add(new AuthInfoImpl(null, null, null));

        AuthInfo authInfo = new AuthInfoImpl("userid", null, null);

        AbstractLoginModule.setAuthInfo(authInfo, subject);
        Set<AuthInfo> fromSubject = subject.getPublicCredentials(AuthInfo.class);
        assertEquals(1, fromSubject.size());
        assertSame(authInfo, fromSubject.iterator().next());
    }

    @Test
    public void testOnError() {
        CallbackHandler cbh = callbacks -> {
            for (Callback cb : callbacks) {
                if (cb instanceof RepositoryCallback) {
                    ((RepositoryCallback) cb).setLoginModuleMonitor(monitor);
                }
            }
        };

        AbstractLoginModule lm = initLoginModule(cbh);
        assertSame(monitor, lm.getLoginModuleMonitor());
        lm.onError();
        verify(monitor).loginError();
        verifyNoMoreInteractions(monitor);
    }

    @Test
    public void testLoginModuleMonitorMissingCallback() {
        AbstractLoginModule lm = initLoginModule((CallbackHandler) null);
        assertSame(LoginModuleMonitor.NOOP, lm.getLoginModuleMonitor());
        lm.onError();
        verifyNoInteractions(monitor);
    }

    @Test
    public void testErrorOnGetLoginModuleMonitor() {
        AbstractLoginModule lm = initLoginModule(new ThrowingCallbackHandler(true));

        assertSame(LoginModuleMonitor.NOOP, lm.getLoginModuleMonitor());
        lm.onError();
        verifyNoInteractions(monitor);
    }

    //--------------------------------------------------------------------------

    private static class TestCredentials implements Credentials {}

    private static final class TestLoginModule extends AbstractLoginModule {

        private final Class<?> supportedCredentialsClass;
        private final LoginModuleMonitor mon;

        private TestLoginModule(@NotNull Class<?> supportedCredentialsClass) {
            this(supportedCredentialsClass, null);
        }

        private TestLoginModule(@NotNull Class<?> supportedCredentialsClass, @Nullable LoginModuleMonitor mon) {
            this.supportedCredentialsClass = supportedCredentialsClass;
            this.mon = mon;
        }

        @NotNull
        @Override
        protected Set<Class> getSupportedCredentials() {
            return Collections.singleton(supportedCredentialsClass);
        }

        @Override
        public boolean login() {
            throw new UnsupportedOperationException();
        }

        @Override
        public boolean commit() {
            throw new UnsupportedOperationException();
        }

        @Override
        protected @NotNull LoginModuleMonitor getLoginModuleMonitor() {
            if (mon != null) {
                return mon;
            } else {
                return super.getLoginModuleMonitor();
            }
        }
    }

    private static final class TestCallbackHandler implements CallbackHandler {

        private Whiteboard whiteboard = null;
        private UserManager userManager = null;
        private PrincipalProvider principalProvider = null;
        private ContentRepository contentRepository = null;
        private SecurityProvider securityProvider = null;

        private TestCallbackHandler() {
        }

        private TestCallbackHandler(@NotNull Whiteboard whiteboard) {
            this.whiteboard = whiteboard;
        }

        private TestCallbackHandler(@NotNull UserManager userManager) {
            this.userManager = userManager;
        }

        private TestCallbackHandler(@NotNull PrincipalProvider principalProvider) {
            this.principalProvider = principalProvider;
        }

        private TestCallbackHandler(@Nullable ContentRepository contentRepository, @Nullable SecurityProvider securityProvider) {
            this.contentRepository = contentRepository;
            this.securityProvider = securityProvider;
        }

        @Override
        public void handle(Callback[] callbacks) throws UnsupportedCallbackException {
            for (Callback cb : callbacks) {
                if (cb instanceof WhiteboardCallback) {
                    ((WhiteboardCallback) cb).setWhiteboard(whiteboard);
                } else if (cb instanceof PrincipalProviderCallback) {
                    ((PrincipalProviderCallback) cb).setPrincipalProvider(principalProvider);
                } else if (cb instanceof UserManagerCallback) {
                    ((UserManagerCallback) cb).setUserManager(userManager);
                } else if (cb instanceof SecurityProviderCallback) {
                    ((SecurityProviderCallback) cb).setSecurityProvider(securityProvider);
                } else if (cb instanceof RepositoryCallback) {
                    RepositoryCallback rcb = (RepositoryCallback) cb;
                    rcb.setContentRepository(contentRepository);
                    rcb.setSecurityProvider(securityProvider);
                    rcb.setLoginModuleMonitor(LoginModuleMonitor.NOOP);
                } else {
                    throw new UnsupportedCallbackException(cb);
                }
            }
        }
    }
}
