/*
 * 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.security.user;

import com.google.common.collect.ImmutableSet;
import org.apache.jackrabbit.JcrConstants;
import org.apache.jackrabbit.api.security.principal.PrincipalIterator;
import org.apache.jackrabbit.api.security.principal.PrincipalManager;
import org.apache.jackrabbit.api.security.user.Group;
import org.apache.jackrabbit.api.security.user.UserManager;
import org.apache.jackrabbit.oak.api.CommitFailedException;
import org.apache.jackrabbit.oak.api.ContentSession;
import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.api.Root;
import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.api.Type;
import org.apache.jackrabbit.oak.plugins.memory.PropertyStates;
import org.apache.jackrabbit.oak.plugins.tree.TreeUtil;
import org.apache.jackrabbit.oak.security.principal.AbstractPrincipalProviderTest;
import org.apache.jackrabbit.oak.spi.security.ConfigurationBase;
import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
import org.apache.jackrabbit.oak.spi.security.authentication.SystemSubject;
import org.apache.jackrabbit.oak.spi.security.principal.EveryonePrincipal;
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.user.UserConfiguration;
import org.jetbrains.annotations.NotNull;
import org.junit.Test;

import javax.jcr.NoSuchWorkspaceException;
import javax.jcr.SimpleCredentials;
import javax.security.auth.Subject;
import javax.security.auth.login.LoginException;
import java.security.Principal;
import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

/**
 * Testing the optional caching with the {@link org.apache.jackrabbit.oak.security.user.UserPrincipalProvider}.
 */
public class UserPrincipalProviderWithCacheTest extends AbstractPrincipalProviderTest {

    private String userId;

    private ContentSession systemSession;
    private Root systemRoot;

    @Override
    public void before() throws Exception {
        super.before();

        userId = getTestUser().getID();

        systemSession = getSystemSession();
        systemRoot = systemSession.getLatestRoot();
    }

    @Override
    public void after() throws Exception {
        try {
            if (systemSession != null) {
                systemSession.close();
            }
        } finally {
            super.after();
        }
    }

    @Override
    protected ConfigurationParameters getSecurityConfigParameters() {
        return ConfigurationParameters.of(
                UserConfiguration.NAME,
                ConfigurationParameters.of(UserPrincipalProvider.PARAM_CACHE_EXPIRATION, 3600 * 1000)
        );
    }

    @NotNull
    @Override
    protected PrincipalProvider createPrincipalProvider() {
        return createPrincipalProvider(root);
    }

    private PrincipalProvider createPrincipalProvider(Root root) {
        return new UserPrincipalProvider(root, getUserConfiguration(), namePathMapper);
    }

    private ContentSession getSystemSession() throws Exception {
        if (systemSession == null) {
            systemSession = Subject.doAs(SystemSubject.INSTANCE, (PrivilegedExceptionAction<ContentSession>) () -> login(null));
        }
        return systemSession;
    }

    private void changeUserConfiguration(ConfigurationParameters params) {
        UserConfiguration userConfig = getUserConfiguration();
        ((ConfigurationBase) userConfig).setParameters(params);
    }

    private Tree getCacheTree(Root root) throws Exception {
        return getCacheTree(root, getTestUser().getPath());
    }

    private Tree getCacheTree(Root root, String authorizablePath) {
        return root.getTree(authorizablePath + '/' + CacheConstants.REP_CACHE);
    }

    private static void assertPrincipals(Set<? extends Principal> principals, Principal... expectedPrincipals) {
        assertEquals(expectedPrincipals.length, principals.size());
        for (Principal principal : expectedPrincipals) {
            assertTrue(principals.contains(principal));
        }
    }

    @Test
    public void testGetPrincipalsPopulatesCache() throws Exception {
        PrincipalProvider pp = createPrincipalProvider(systemRoot);

        Set<? extends Principal> principals = pp.getPrincipals(userId);
        assertPrincipals(principals, EveryonePrincipal.getInstance(), testGroup.getPrincipal(), getTestUser().getPrincipal());

        root.refresh();

        Tree principalCache = getCacheTree(root);
        assertTrue(principalCache.exists());
        assertEquals(CacheConstants.NT_REP_CACHE, TreeUtil.getPrimaryTypeName(principalCache));

        assertNotNull(principalCache.getProperty(CacheConstants.REP_EXPIRATION));

        PropertyState ps = principalCache.getProperty(CacheConstants.REP_GROUP_PRINCIPAL_NAMES);
        assertNotNull(ps);

        String val = ps.getValue(Type.STRING);
        assertEquals(testGroup.getPrincipal().getName(), val);
    }

    @Test
    public void testGetGroupMembershipPopulatesCache() throws Exception {
        PrincipalProvider pp = createPrincipalProvider(systemRoot);

        Set<? extends Principal> principals = pp.getMembershipPrincipals(getTestUser().getPrincipal());
        assertPrincipals(principals, EveryonePrincipal.getInstance(), testGroup.getPrincipal());

        root.refresh();

        Tree principalCache = getCacheTree(root);
        assertTrue(principalCache.exists());
        assertEquals(CacheConstants.NT_REP_CACHE, TreeUtil.getPrimaryTypeName(principalCache));

        assertNotNull(principalCache.getProperty(CacheConstants.REP_EXPIRATION));

        PropertyState ps = principalCache.getProperty(CacheConstants.REP_GROUP_PRINCIPAL_NAMES);
        assertNotNull(ps);

        String val = ps.getValue(Type.STRING);
        assertEquals(testGroup.getPrincipal().getName(), val);
    }

    @Test
    public void testPrincipalManagerGetGroupMembershipPopulatesCache() throws Exception {
        PrincipalManager principalManager = getPrincipalManager(systemRoot);

        PrincipalIterator principalIterator = principalManager.getGroupMembership(getTestUser().getPrincipal());
        assertPrincipals(ImmutableSet.copyOf(principalIterator), EveryonePrincipal.getInstance(), testGroup.getPrincipal());

        root.refresh();

        Tree principalCache = getCacheTree(root);
        assertTrue(principalCache.exists());
        assertEquals(CacheConstants.NT_REP_CACHE, TreeUtil.getPrimaryTypeName(principalCache));

        assertNotNull(principalCache.getProperty(CacheConstants.REP_EXPIRATION));

        PropertyState ps = principalCache.getProperty(CacheConstants.REP_GROUP_PRINCIPAL_NAMES);
        assertNotNull(ps);

        String val = ps.getValue(Type.STRING);
        assertEquals(testGroup.getPrincipal().getName(), val);
    }

    @Test
    public void testGetPrincipalsForGroups() throws Exception {
        PrincipalProvider pp = createPrincipalProvider(systemRoot);

        Set<? extends Principal> principals = pp.getPrincipals(testGroup.getID());
        assertTrue(principals.isEmpty());

        principals = pp.getPrincipals(testGroup2.getID());
        assertTrue(principals.isEmpty());

        root.refresh();

        Tree principalCache = getCacheTree(root, testGroup.getPath());
        assertFalse(principalCache.exists());

        principalCache = getCacheTree(root, testGroup2.getPath());
        assertFalse(principalCache.exists());
    }

    @Test
    public void testGetGroupMembershipForGroups() throws Exception {
        PrincipalProvider pp = createPrincipalProvider(systemRoot);

        Set<? extends Principal> principals = pp.getMembershipPrincipals(testGroup.getPrincipal());
        assertPrincipals(principals, EveryonePrincipal.getInstance());

        principals = pp.getMembershipPrincipals(testGroup2.getPrincipal());
        assertPrincipals(principals, EveryonePrincipal.getInstance(), testGroup.getPrincipal());

        root.refresh();

        Tree principalCache = getCacheTree(root, testGroup.getPath());
        assertFalse(principalCache.exists());

        principalCache = getCacheTree(root, testGroup2.getPath());
        assertFalse(principalCache.exists());
    }

    @Test
    public void testExtractPrincipalsFromCache() throws Exception {
        // a) force the cache to be created
        PrincipalProvider pp = createPrincipalProvider(systemRoot);

        // set of principals that read from user + membership-provider.
        Set<? extends Principal> principals = pp.getPrincipals(userId);
        assertPrincipals(principals, EveryonePrincipal.getInstance(), testGroup.getPrincipal(), getTestUser().getPrincipal());

        // b) retrieve principals again (this time from the cache)
        Set<? extends Principal> principalsAgain = pp.getPrincipals(userId);

        // make sure both sets are equal
        assertEquals(principals, principalsAgain);
    }

    @Test
    public void testGroupPrincipalNameEscape() throws Exception {
        String gId = null;
        try {
            Principal groupPrincipal = new PrincipalImpl(groupId + ",,%,%%");
            Group gr = getUserManager(root).createGroup(groupPrincipal);
            gId = gr.getID();
            gr.addMember(getTestUser());
            root.commit();
            systemRoot.refresh();

            PrincipalProvider pp = createPrincipalProvider(systemRoot);
            Set<? extends Principal> principals = pp.getPrincipals(userId);
            assertTrue(principals.contains(groupPrincipal));

            principals = pp.getPrincipals(userId);
            assertTrue(principals.contains(groupPrincipal));
        } finally {
            root.refresh();
            if (gId != null) {
                getUserManager(root).getAuthorizable(gId).remove();
                root.commit();
            }
        }
    }

    @Test
    public void testMembershipChange() throws Exception {
        PrincipalProvider pp = createPrincipalProvider(systemRoot);

        // set of principals that read from user + membership-provider.
        Set<? extends Principal> principals = pp.getPrincipals(userId);

        // change group membership with a different root
        UserManager uMgr = getUserManager(root);
        Group gr = uMgr.getAuthorizable(groupId, Group.class);
        assertTrue(gr.removeMember(uMgr.getAuthorizable(userId)));
        root.commit();
        systemRoot.refresh();

        // system-principal provider must still see the principals from the cache (not the changed onces)
        Set<? extends Principal> principalsAgain = pp.getPrincipals(userId);
        assertEquals(principals, principalsAgain);

        // disable the cache again
        changeUserConfiguration(ConfigurationParameters.EMPTY);
        pp = createPrincipalProvider(systemRoot);

        // now group principals must no longer be retrieved from the cache
        assertPrincipals(pp.getPrincipals(userId), EveryonePrincipal.getInstance(), getTestUser().getPrincipal());
    }

    @Test
    public void testCacheUpdate() throws Exception {
        PrincipalProvider pp = createPrincipalProvider(systemRoot);

        // set of principals that read from user + membership-provider -> cache being filled
        Set<? extends Principal> principals = pp.getPrincipals(userId);
        assertTrue(getCacheTree(systemRoot).exists());

        // change the group membership of the test user
        UserManager uMgr = getUserConfiguration().getUserManager(systemRoot, namePathMapper);
        Group gr = uMgr.getAuthorizable(groupId, Group.class);
        assertTrue(gr.removeMember(uMgr.getAuthorizable(userId)));
        systemRoot.commit();

        // force cache expiration by manually setting the expiration time
        Tree cache = getCacheTree(systemRoot);
        cache.setProperty(CacheConstants.REP_EXPIRATION, 2);
        systemRoot.commit(CacheValidatorProvider.asCommitAttributes());

        // retrieve principals again to have cache updated
        pp = createPrincipalProvider(systemRoot);
        Set<? extends Principal> principalsAgain = pp.getPrincipals(userId);
        assertNotEquals(principals, principalsAgain);
        assertPrincipals(principalsAgain, EveryonePrincipal.getInstance(), getTestUser().getPrincipal());

        // verify that the cache has really been updated
        cache = getCacheTree(systemRoot);
        assertNotSame(2, TreeUtil.getLong(cache, CacheConstants.REP_EXPIRATION, 2));
        assertEquals("", TreeUtil.getString(cache, CacheConstants.REP_GROUP_PRINCIPAL_NAMES));

        // check that an cached empty membership set doesn't break the retrieval (OAK-8306)
        principalsAgain = pp.getPrincipals(userId);
        assertNotEquals(principals, principalsAgain);
        assertPrincipals(principalsAgain, EveryonePrincipal.getInstance(), getTestUser().getPrincipal());
    }

    @Test
    public void testMissingExpiration() throws Exception {
        PrincipalProvider pp = createPrincipalProvider(systemRoot);

        // set of principals that read from user + membership-provider -> cache being filled
        Set<? extends Principal> principals = pp.getPrincipals(userId);
        assertTrue(getCacheTree(systemRoot).exists());

        // manually remove rep:expiration property to verify this doesn't cause NPE
        Tree cache = getCacheTree(systemRoot);
        cache.removeProperty(CacheConstants.REP_EXPIRATION);
        systemRoot.commit(CacheValidatorProvider.asCommitAttributes());

        assertFalse(getCacheTree(systemRoot).hasProperty(CacheConstants.REP_EXPIRATION));

        // retrieve principals again: the cache must be treated as expired and
        // not causing NPE although the property is missing
        pp = createPrincipalProvider(systemRoot);
        Set<? extends Principal> principalsAgain = pp.getPrincipals(userId);
        assertEquals(principals, principalsAgain);

        // verify that the cache has really been updated
        cache = getCacheTree(systemRoot);
        assertTrue(cache.hasProperty(CacheConstants.REP_EXPIRATION));
    }

    @Test
    public void testOnlySystemCreatesCache() throws Exception {
        Set<? extends Principal> principals = principalProvider.getPrincipals(getTestUser().getID());
        assertPrincipals(principals, EveryonePrincipal.getInstance(), testGroup.getPrincipal(), getTestUser().getPrincipal());

        root.refresh();
        Tree userTree = root.getTree(getTestUser().getPath());

        assertFalse(userTree.hasChild(CacheConstants.REP_CACHE));
    }

    @Test
    public void testOnlySystemReadsFromCache() throws Exception {
        String userId = getTestUser().getID();

        PrincipalProvider systemPP = createPrincipalProvider(systemRoot);
        Set<? extends Principal> principals = systemPP.getPrincipals(userId);
        assertPrincipals(principals, EveryonePrincipal.getInstance(), testGroup.getPrincipal(), getTestUser().getPrincipal());

        root.refresh();
        assertPrincipals(principalProvider.getPrincipals(userId), EveryonePrincipal.getInstance(), testGroup.getPrincipal(), getTestUser().getPrincipal());

        testGroup.removeMember(getTestUser());
        root.commit();

        assertPrincipals(principalProvider.getPrincipals(userId), EveryonePrincipal.getInstance(), getTestUser().getPrincipal());
        assertPrincipals(systemPP.getPrincipals(userId), EveryonePrincipal.getInstance(), testGroup.getPrincipal(), getTestUser().getPrincipal());
    }

    @Test
    public void testInvalidExpiry() throws Exception {
        long[] noCache = new long[] {0, -1, Long.MIN_VALUE};
        for (long exp : noCache) {

            changeUserConfiguration(ConfigurationParameters.of(UserPrincipalProvider.PARAM_CACHE_EXPIRATION, exp));

            PrincipalProvider pp = createPrincipalProvider(systemRoot);
            pp.getPrincipals(userId);

            root.refresh();
            Tree userTree = root.getTree(getTestUser().getPath());
            assertFalse(userTree.hasChild(CacheConstants.REP_CACHE));
        }
    }

    @Test
    public void testLongOverflow() throws Exception {
        long[] maxCache = new long[] {Long.MAX_VALUE, Long.MAX_VALUE-1, Long.MAX_VALUE-10000};

        Root systemRoot = getSystemSession().getLatestRoot();
        for (long exp : maxCache) {
            changeUserConfiguration(ConfigurationParameters.of(UserPrincipalProvider.PARAM_CACHE_EXPIRATION, exp));

            PrincipalProvider pp = createPrincipalProvider(systemRoot);
            pp.getPrincipals(userId);

            Tree userTree = systemRoot.getTree(getTestUser().getPath());

            Tree cache = userTree.getChild(CacheConstants.REP_CACHE);
            assertTrue(cache.exists());

            PropertyState propertyState = cache.getProperty(CacheConstants.REP_EXPIRATION);
            assertNotNull(propertyState);
            assertEquals(Long.MAX_VALUE, propertyState.getValue(Type.LONG).longValue());

            cache.remove();
            systemRoot.commit();
        }
    }

    @Test
    public void testChangeCache() throws Exception {
        PrincipalProvider pp = createPrincipalProvider(systemRoot);
        pp.getPrincipals(userId);

        root.refresh();

        List<PropertyState> props = new ArrayList<>();
        props.add(PropertyStates.createProperty(CacheConstants.REP_EXPIRATION, 25));
        props.add(PropertyStates.createProperty(CacheConstants.REP_GROUP_PRINCIPAL_NAMES, EveryonePrincipal.NAME));
        props.add(PropertyStates.createProperty(JcrConstants.JCR_PRIMARYTYPE, JcrConstants.NT_UNSTRUCTURED));
        props.add(PropertyStates.createProperty("residualProp", "anyvalue"));

        // changing cache with (normally) sufficiently privileged session and with system-session must not succeed
        for (Root r : new Root[] {root, systemRoot}) {
            for (PropertyState ps : props) {
                try {
                    Tree cache = getCacheTree(r);
                    cache.setProperty(ps);
                    r.commit();
                    fail("Attempt to modify the cache tree must fail.");
                } catch (CommitFailedException e) {
                    // success
                } finally {
                    r.refresh();
                }
            }
        }
    }

    @Test
    public void testRemoveCache() throws Exception {
        PrincipalProvider pp = createPrincipalProvider(systemRoot);
        pp.getPrincipals(userId);

        // removing cache with sufficiently privileged session must succeed
        root.refresh();
        Tree cache = getCacheTree(root);
        cache.remove();
        root.commit();
    }

    @Test
    public void testConcurrentLoginWithCacheRemoval() throws Exception {
        changeUserConfiguration(ConfigurationParameters.of(UserPrincipalProvider.PARAM_CACHE_EXPIRATION, 1));

        final List<Exception> exceptions = new ArrayList<>();
        List<Thread> threads = new ArrayList<>();
        for (int i = 0; i < 100; i++) {
            threads.add(new Thread(() -> {
                try {
                    login(new SimpleCredentials(userId, userId.toCharArray())).close();
                } catch (Exception e) {
                    exceptions.add(e);
                }
            }));
        }
        for (Thread t : threads) {
            t.start();
        }
        for (Thread t : threads) {
            t.join();
        }
        for (Exception e : exceptions) {
            e.printStackTrace();
        }
        if (!exceptions.isEmpty()) {
            fail();
        }
    }
}
