/*
 * 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.nifi.registry.web.api;

import org.apache.commons.lang3.StringUtils;
import org.apache.nifi.registry.SecureLdapTestApiApplication;
import org.apache.nifi.registry.authorization.AccessPolicy;
import org.apache.nifi.registry.authorization.AccessPolicySummary;
import org.apache.nifi.registry.authorization.CurrentUser;
import org.apache.nifi.registry.authorization.Permissions;
import org.apache.nifi.registry.authorization.Tenant;
import org.apache.nifi.registry.bucket.Bucket;
import org.apache.nifi.registry.extension.ExtensionManager;
import org.apache.nifi.registry.properties.AESSensitivePropertyProvider;
import org.apache.nifi.registry.properties.NiFiRegistryProperties;
import org.apache.nifi.registry.properties.SensitivePropertyProvider;
import org.apache.nifi.registry.security.authorization.Authorizer;
import org.apache.nifi.registry.security.authorization.AuthorizerFactory;
import org.apache.nifi.registry.security.crypto.BootstrapFileCryptoKeyProvider;
import org.apache.nifi.registry.security.crypto.CryptoKeyProvider;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.skyscreamer.jsonassert.JSONAssert;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Profile;
import org.springframework.test.context.jdbc.Sql;
import org.springframework.test.context.junit4.SpringRunner;

import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Form;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

/**
 * Deploy the Web API Application using an embedded Jetty Server for local integration testing, with the follow characteristics:
 *
 * - A NiFiRegistryProperties has to be explicitly provided to the ApplicationContext using a profile unique to this test suite.
 * - A NiFiRegistryClientConfig has been configured to create a client capable of completing one-way TLS
 * - The database is embed H2 using volatile (in-memory) persistence
 * - Custom SQL is clearing the DB before each test method by default, unless method overrides this behavior
 */
@RunWith(SpringRunner.class)
@SpringBootTest(
        classes = SecureLdapTestApiApplication.class,
        webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
        properties = "spring.profiles.include=ITSecureLdap")
@Import(SecureITClientConfiguration.class)
@Sql(executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD, scripts = "classpath:db/clearDB.sql")
public class SecureLdapIT extends IntegrationTestBase {

    private static final String tokenLoginPath = "access/token/login";
    private static final String tokenIdentityProviderPath = "access/token/identity-provider";

    @TestConfiguration
    @Profile("ITSecureLdap")
    public static class LdapTestConfiguration {

        static AuthorizerFactory authorizerFactory;

        @Primary
        @Bean
        @DependsOn({"directoryServer"}) // Can't load LdapUserGroupProvider until the embedded LDAP server, which creates the "directoryServer" bean, is running
        public static Authorizer getAuthorizer(@Autowired NiFiRegistryProperties properties, ExtensionManager extensionManager) throws Exception {
            if (authorizerFactory == null) {
                authorizerFactory = new AuthorizerFactory(properties, extensionManager, sensitivePropertyProvider());
            }
            return authorizerFactory.getAuthorizer();
        }

        @Primary
        @Bean
        public static SensitivePropertyProvider sensitivePropertyProvider() throws Exception {
            return new AESSensitivePropertyProvider(getNiFiRegistryMasterKeyProvider().getKey());
        }

        private static CryptoKeyProvider getNiFiRegistryMasterKeyProvider() {
            return new BootstrapFileCryptoKeyProvider("src/test/resources/conf/secure-ldap/bootstrap.conf");
        }

    }

    private String adminAuthToken;
    private List<AccessPolicy> beforeTestAccessPoliciesSnapshot;

    @Before
    public void setup() {
        final String basicAuthCredentials = encodeCredentialsForBasicAuth("nifiadmin", "password");
        final String token = client
                .target(createURL(tokenIdentityProviderPath))
                .request()
                .header("Authorization", "Basic " + basicAuthCredentials)
                .post(null, String.class);
        adminAuthToken = token;

        beforeTestAccessPoliciesSnapshot = createAccessPoliciesSnapshot();
    }

    @After
    public void cleanup() {
        restoreAccessPoliciesSnapshot(beforeTestAccessPoliciesSnapshot);
    }

    @Test
    public void testTokenGenerationAndAccessStatus() throws Exception {

        // Note: this test intentionally does not use the token generated
        // for nifiadmin by the @Before method

        // Given: the client and server have been configured correctly for LDAP authentication
        String expectedJwtPayloadJson = "{" +
                "\"sub\":\"nobel\"," +
                "\"preferred_username\":\"nobel\"," +
                "\"iss\":\"LdapIdentityProvider\"" +
                "}";
        String expectedAccessStatusJson = "{" +
                "\"identity\":\"nobel\"," +
                "\"anonymous\":false" +
                "}";

        // When: the /access/token/login endpoint is queried
        final String basicAuthCredentials = encodeCredentialsForBasicAuth("nobel", "password");
        final Response tokenResponse = client
                .target(createURL(tokenIdentityProviderPath))
                .request()
                .header("Authorization", "Basic " + basicAuthCredentials)
                .post(null, Response.class);

        // Then: the server returns 200 OK with an access token
        assertEquals(201, tokenResponse.getStatus());
        String token = tokenResponse.readEntity(String.class);
        assertTrue(StringUtils.isNotEmpty(token));
        String[] jwtParts = token.split("\\.");
        assertEquals(3, jwtParts.length);
        String jwtPayload = new String(Base64.getDecoder().decode(jwtParts[1]), "UTF-8");
        JSONAssert.assertEquals(expectedJwtPayloadJson, jwtPayload, false);

        // When: the token is returned in the Authorization header
        final Response accessResponse = client
                .target(createURL("access"))
                .request()
                .header("Authorization", "Bearer " + token)
                .get(Response.class);

        // Then: the server acknowledges the client has access
        assertEquals(200, accessResponse.getStatus());
        String accessStatus = accessResponse.readEntity(String.class);
        JSONAssert.assertEquals(expectedAccessStatusJson, accessStatus, false);

    }

    @Test
    public void testTokenGenerationWithIdentityProvider() throws Exception {

        // Given: the client and server have been configured correctly for LDAP authentication
        String expectedJwtPayloadJson = "{" +
                "\"sub\":\"nobel\"," +
                "\"preferred_username\":\"nobel\"," +
                "\"iss\":\"LdapIdentityProvider\"," +
                "\"aud\":\"LdapIdentityProvider\"" +
                "}";
        String expectedAccessStatusJson = "{" +
                "\"identity\":\"nobel\"," +
                "\"anonymous\":false" +
                "}";

        // When: the /access/token/identity-provider endpoint is queried
        final String basicAuthCredentials = encodeCredentialsForBasicAuth("nobel", "password");
        final Response tokenResponse = client
                .target(createURL(tokenIdentityProviderPath))
                .request()
                .header("Authorization", "Basic " + basicAuthCredentials)
                .post(null, Response.class);

        // Then: the server returns 200 OK with an access token
        assertEquals(201, tokenResponse.getStatus());
        String token = tokenResponse.readEntity(String.class);
        assertTrue(StringUtils.isNotEmpty(token));
        String[] jwtParts = token.split("\\.");
        assertEquals(3, jwtParts.length);
        String jwtPayload = new String(Base64.getDecoder().decode(jwtParts[1]), "UTF-8");
        JSONAssert.assertEquals(expectedJwtPayloadJson, jwtPayload, false);

        // When: the token is returned in the Authorization header
        final Response accessResponse = client
                .target(createURL("access"))
                .request()
                .header("Authorization", "Bearer " + token)
                .get(Response.class);

        // Then: the server acknowledges the client has access
        assertEquals(200, accessResponse.getStatus());
        String accessStatus = accessResponse.readEntity(String.class);
        JSONAssert.assertEquals(expectedAccessStatusJson, accessStatus, false);

    }

    @Test
    public void testGetCurrentUserFailsForAnonymous() throws Exception {

        // Given: the client is connected to an unsecured NiFi Registry

        // When: the /access endpoint is queried with no credentials
        final Response response = client
                .target(createURL("/access"))
                .request()
                .get(Response.class);

        // Then: the server returns a 200 OK with the expected current user
        assertEquals(401, response.getStatus());

    }

    @Test
    public void testGetCurrentUser() throws Exception {

        // Given: the client is connected to an unsecured NiFi Registry
        String expectedJson = "{" +
                "\"identity\":\"nifiadmin\"," +
                "\"anonymous\":false," +
                "\"resourcePermissions\":{" +
                "\"anyTopLevelResource\":{\"canRead\":true,\"canWrite\":true,\"canDelete\":true}," +
                "\"buckets\":{\"canRead\":true,\"canWrite\":true,\"canDelete\":true}," +
                "\"tenants\":{\"canRead\":true,\"canWrite\":true,\"canDelete\":true}," +
                "\"policies\":{\"canRead\":true,\"canWrite\":true,\"canDelete\":true}," +
                "\"proxy\":{\"canRead\":true,\"canWrite\":true,\"canDelete\":true}}" +
                "}";

        // When: the /access endpoint is queried using a JWT for the nifiadmin LDAP user
        final Response response = client
                .target(createURL("/access"))
                .request()
                .header("Authorization", "Bearer " + adminAuthToken)
                .get(Response.class);

        // Then: the server returns a 200 OK with the expected current user
        assertEquals(200, response.getStatus());
        String actualJson = response.readEntity(String.class);
        JSONAssert.assertEquals(expectedJson, actualJson, false);

    }

    @Test
    public void testUsers() throws Exception {

        // Given: the client and server have been configured correctly for LDAP authentication
        String expectedJson = "[" +
                "{\"identity\":\"nifiadmin\",\"userGroups\":[],\"configurable\":false," +
                    "\"resourcePermissions\":{" +
                    "\"anyTopLevelResource\":{\"canRead\":true,\"canWrite\":true,\"canDelete\":true}," +
                    "\"buckets\":{\"canRead\":true,\"canWrite\":true,\"canDelete\":true}," +
                    "\"tenants\":{\"canRead\":true,\"canWrite\":true,\"canDelete\":true}," +
                    "\"policies\":{\"canRead\":true,\"canWrite\":true,\"canDelete\":true}," +
                    "\"proxy\":{\"canRead\":true,\"canWrite\":true,\"canDelete\":true}}}," +
                "{\"identity\":\"euler\",\"userGroups\":[{\"identity\":\"mathematicians\"}],\"accessPolicies\":[],\"configurable\":false}," +
                "{\"identity\":\"euclid\",\"userGroups\":[{\"identity\":\"mathematicians\"}],\"accessPolicies\":[],\"configurable\":false}," +
                "{\"identity\":\"boyle\",\"userGroups\":[{\"identity\":\"chemists\"}],\"accessPolicies\":[],\"configurable\":false}," +
                "{\"identity\":\"newton\",\"userGroups\":[{\"identity\":\"scientists\"}],\"accessPolicies\":[],\"configurable\":false}," +
                "{\"identity\":\"riemann\",\"userGroups\":[{\"identity\":\"mathematicians\"}],\"accessPolicies\":[],\"configurable\":false}," +
                "{\"identity\":\"gauss\",\"userGroups\":[{\"identity\":\"mathematicians\"}],\"accessPolicies\":[],\"configurable\":false}," +
                "{\"identity\":\"galileo\",\"userGroups\":[{\"identity\":\"scientists\"},{\"identity\":\"italians\"}],\"accessPolicies\":[],\"configurable\":false}," +
                "{\"identity\":\"nobel\",\"userGroups\":[{\"identity\":\"chemists\"}],\"accessPolicies\":[],\"configurable\":false}," +
                "{\"identity\":\"pasteur\",\"userGroups\":[{\"identity\":\"chemists\"}],\"accessPolicies\":[],\"configurable\":false}," +
                "{\"identity\":\"tesla\",\"userGroups\":[{\"identity\":\"scientists\"}],\"accessPolicies\":[],\"configurable\":false}," +
                "{\"identity\":\"nogroup\",\"userGroups\":[],\"accessPolicies\":[],\"configurable\":false}," +
                "{\"identity\":\"einstein\",\"userGroups\":[{\"identity\":\"scientists\"}],\"accessPolicies\":[],\"configurable\":false}," +
                "{\"identity\":\"curie\",\"userGroups\":[{\"identity\":\"chemists\"}],\"accessPolicies\":[],\"configurable\":false}]";

        // When: the /tenants/users endpoint is queried
        final String usersJson = client
                .target(createURL("tenants/users"))
                .request()
                .header("Authorization", "Bearer " + adminAuthToken)
                .get(String.class);

        // Then: the server returns a list of all users (see test-ldap-data.ldif)
        JSONAssert.assertEquals(expectedJson, usersJson, false);
    }

    @Test
    public void testUserGroups() throws Exception {

        // Given: the client and server have been configured correctly for LDAP authentication
        String expectedJson = "[" +
                "{" +
                    "\"identity\":\"chemists\"," +
                    "\"users\":[{\"identity\":\"pasteur\"},{\"identity\":\"boyle\"},{\"identity\":\"curie\"},{\"identity\":\"nobel\"}]," +
                    "\"accessPolicies\":[]," +
                    "\"configurable\":false" +
                "}," +
                "{" +
                    "\"identity\":\"mathematicians\"," +
                    "\"users\":[{\"identity\":\"gauss\"},{\"identity\":\"euclid\"},{\"identity\":\"riemann\"},{\"identity\":\"euler\"}]," +
                    "\"accessPolicies\":[]," +
                    "\"configurable\":false" +
                "}," +
                "{" +
                    "\"identity\":\"scientists\"," +
                    "\"users\":[{\"identity\":\"einstein\"},{\"identity\":\"tesla\"},{\"identity\":\"newton\"},{\"identity\":\"galileo\"}]," +
                    "\"accessPolicies\":[]," +
                    "\"configurable\":false" +
                "}," +
                "{" +
                    "\"identity\":\"italians\"," +
                    "\"users\":[{\"identity\":\"galileo\"}]," +
                    "\"accessPolicies\":[]," +
                    "\"configurable\":false" +
                "}]";

        // When: the /tenants/users endpoint is queried
        final String groupsJson = client
                .target(createURL("tenants/user-groups"))
                .request()
                .header("Authorization", "Bearer " + adminAuthToken)
                .get(String.class);

        // Then: the server returns a list of all users (see test-ldap-data.ldif)
        JSONAssert.assertEquals(expectedJson, groupsJson, false);
    }

    @Test
    public void testCreateTenantFails() throws Exception {

        // Given: the server has been configured with the LdapUserGroupProvider, which is non-configurable,
        //   and: the client wants to create a tenant
        Tenant tenant = new Tenant();
        tenant.setIdentity("new_tenant");

        // When: the POST /tenants/users endpoint is accessed
        final Response createUserResponse = client
                .target(createURL("tenants/users"))
                .request()
                .header("Authorization", "Bearer " + adminAuthToken)
                .post(Entity.entity(tenant, MediaType.APPLICATION_JSON_TYPE), Response.class);

        // Then: an error is returned
        assertEquals(409, createUserResponse.getStatus());

        // When: the POST /tenants/users endpoint is accessed
        final Response createUserGroupResponse = client
                .target(createURL("tenants/user-groups"))
                .request()
                .header("Authorization", "Bearer " + adminAuthToken)
                .post(Entity.entity(tenant, MediaType.APPLICATION_JSON_TYPE), Response.class);

        // Then: an error is returned because the UserGroupProvider is non-configurable
        assertEquals(409, createUserGroupResponse.getStatus());
    }

    @Test
    public void testAccessPolicyCreation() throws Exception {

        // Given: the server has been configured with an initial admin "nifiadmin" and a user with no accessPolicies "nobel"
        String nobelId = getTenantIdentifierByIdentity("nobel");
        String chemistsId = getTenantIdentifierByIdentity("chemists"); // a group containing user "nobel"

        final String basicAuthCredentials = encodeCredentialsForBasicAuth("nobel", "password");
        final String nobelAuthToken = client
                .target(createURL(tokenIdentityProviderPath))
                .request()
                .header("Authorization", "Basic " + basicAuthCredentials)
                .post(null, String.class);

        // When: user nobel re-checks top-level permissions
        final CurrentUser currentUser = client
                .target(createURL("/access"))
                .request()
                .header("Authorization", "Bearer " + nobelAuthToken)
                .get(CurrentUser.class);

        // Then: 200 OK is returned indicating user has access to no top-level resources
        assertEquals(new Permissions(), currentUser.getResourcePermissions().getBuckets());
        assertEquals(new Permissions(), currentUser.getResourcePermissions().getTenants());
        assertEquals(new Permissions(), currentUser.getResourcePermissions().getPolicies());
        assertEquals(new Permissions(), currentUser.getResourcePermissions().getProxy());

        // When: nifiadmin creates a bucket
        final Bucket bucket = new Bucket();
        bucket.setName("Integration Test Bucket");
        bucket.setDescription("A bucket created by an integration test.");
        Response adminCreatesBucketResponse = client
                .target(createURL("buckets"))
                .request()
                .header("Authorization", "Bearer " + adminAuthToken)
                .post(Entity.entity(bucket, MediaType.APPLICATION_JSON), Response.class);

        // Then: the server returns a 200 OK
        assertEquals(200, adminCreatesBucketResponse.getStatus());
        Bucket createdBucket = adminCreatesBucketResponse.readEntity(Bucket.class);


        // When: user nobel initial queries /buckets
        final Bucket[] buckets1 = client
                .target(createURL("buckets"))
                .request()
                .header("Authorization", "Bearer " + nobelAuthToken)
                .get(Bucket[].class);

        // Then: an empty list is returned (nobel has no read access yet)
        assertNotNull(buckets1);
        assertEquals(0, buckets1.length);


        // When: nifiadmin grants read access on createdBucket to 'chemists' a group containing nobel
        AccessPolicy readPolicy = new AccessPolicy();
        readPolicy.setResource("/buckets/" + createdBucket.getIdentifier());
        readPolicy.setAction("read");
        readPolicy.addUserGroups(Arrays.asList(new Tenant(chemistsId, "chemists")));
        Response adminGrantsReadAccessResponse = client
                .target(createURL("policies"))
                .request()
                .header("Authorization", "Bearer " + adminAuthToken)
                .post(Entity.entity(readPolicy, MediaType.APPLICATION_JSON), Response.class);

        // Then: the server returns a 201 Created
        assertEquals(201, adminGrantsReadAccessResponse.getStatus());


        // When: nifiadmin tries to list all buckets
        final Bucket[] adminBuckets = client
                .target(createURL("buckets"))
                .request()
                .header("Authorization", "Bearer " + adminAuthToken)
                .get(Bucket[].class);

        // Then: the full list is returned (verifies that per-bucket access policies are additive to base /buckets policy)
        assertNotNull(adminBuckets);
        assertEquals(1, adminBuckets.length);
        assertEquals(createdBucket.getIdentifier(), adminBuckets[0].getIdentifier());
        assertEquals(new Permissions().withCanRead(true).withCanWrite(true).withCanDelete(true), adminBuckets[0].getPermissions());


        // When: user nobel re-queries /buckets
        final Bucket[] buckets2 = client
                .target(createURL("buckets"))
                .request()
                .header("Authorization", "Bearer " + nobelAuthToken)
                .get(Bucket[].class);

        // Then: the created bucket is now present
        assertNotNull(buckets2);
        assertEquals(1, buckets2.length);
        assertEquals(createdBucket.getIdentifier(), buckets2[0].getIdentifier());
        assertEquals(new Permissions().withCanRead(true), buckets2[0].getPermissions());


        // When: nifiadmin grants write access on createdBucket to user 'nobel'
        AccessPolicy writePolicy = new AccessPolicy();
        writePolicy.setResource("/buckets/" + createdBucket.getIdentifier());
        writePolicy.setAction("write");
        writePolicy.addUsers(Arrays.asList(new Tenant(nobelId, "nobel")));
        Response adminGrantsWriteAccessResponse = client
                .target(createURL("policies"))
                .request()
                .header("Authorization", "Bearer " + adminAuthToken)
                .post(Entity.entity(writePolicy, MediaType.APPLICATION_JSON), Response.class);

        // Then: the server returns a 201 Created
        assertEquals(201, adminGrantsWriteAccessResponse.getStatus());


        // When: user nobel re-queries /buckets
        final Bucket[] buckets3 = client
                .target(createURL("buckets"))
                .request()
                .header("Authorization", "Bearer " + nobelAuthToken)
                .get(Bucket[].class);

        // Then: the authorizedActions are updated
        assertNotNull(buckets3);
        assertEquals(1, buckets3.length);
        assertEquals(createdBucket.getIdentifier(), buckets3[0].getIdentifier());
        assertEquals(new Permissions().withCanRead(true).withCanWrite(true), buckets3[0].getPermissions());

    }

    /** A helper method to lookup identifiers for tenant identities using the REST API
     *
     * @param tenantIdentity - the identity to lookup
     * @return A string containing the identifier of the tenant, or null if the tenant identity is not found.
     */
    private String getTenantIdentifierByIdentity(String tenantIdentity) {

        final Tenant[] users = client
                .target(createURL("tenants/users"))
                .request()
                .header("Authorization", "Bearer " + adminAuthToken)
                .get(Tenant[].class);

        final Tenant[] groups = client
                .target(createURL("tenants/user-groups"))
                .request()
                .header("Authorization", "Bearer " + adminAuthToken)
                .get(Tenant[].class);

        final Tenant matchedTenant = Stream.concat(Arrays.stream(users), Arrays.stream(groups))
                .filter(tenant -> tenant.getIdentity().equalsIgnoreCase(tenantIdentity))
                .findFirst()
                .orElse(null);

        return matchedTenant != null ? matchedTenant.getIdentifier() : null;
    }

    /** A helper method to lookup access policies
     *
     * @return A string containing the identifier of the policy, or null if the policy identity is not found.
     */
    private AccessPolicy getPolicyByResourceAction(String action, String resource) {

        final AccessPolicySummary[] policies = client
                .target(createURL("policies"))
                .request()
                .header("Authorization", "Bearer " + adminAuthToken)
                .get(AccessPolicySummary[].class);

        final AccessPolicySummary matchedPolicy = Arrays.stream(policies)
                .filter(p -> p.getAction().equalsIgnoreCase(action) && p.getResource().equalsIgnoreCase(resource))
                .findFirst()
                .orElse(null);

        if (matchedPolicy == null) {
            return null;
        }

        String policyId = matchedPolicy.getIdentifier();

        final AccessPolicy policy = client
                .target(createURL("policies/" + policyId))
                .request()
                .header("Authorization", "Bearer " + adminAuthToken)
                .get(AccessPolicy.class);

        return policy;
    }

    private List<AccessPolicy> createAccessPoliciesSnapshot() {

        final AccessPolicySummary[] policySummaries = client
                .target(createURL("policies"))
                .request()
                .header("Authorization", "Bearer " + adminAuthToken)
                .get(AccessPolicySummary[].class);

        final List<AccessPolicy> policies = new ArrayList<>(policySummaries.length);
        for (AccessPolicySummary s : policySummaries) {
            AccessPolicy policy = client
                    .target(createURL("policies/" + s.getIdentifier()))
                    .request()
                    .header("Authorization", "Bearer " + adminAuthToken)
                    .get(AccessPolicy.class);
            policies.add(policy);
        }

        return policies;
    }

    private void restoreAccessPoliciesSnapshot(List<AccessPolicy> accessPoliciesSnapshot) {

        List<AccessPolicy> currentAccessPolicies = createAccessPoliciesSnapshot();

        Set<String> policiesToRestore = accessPoliciesSnapshot.stream()
                .map(AccessPolicy::getIdentifier)
                .collect(Collectors.toSet());

        Set<String> policiesToDelete = currentAccessPolicies.stream()
                .filter(p -> !policiesToRestore.contains(p.getIdentifier()))
                .map(AccessPolicy::getIdentifier)
                .collect(Collectors.toSet());

        for (AccessPolicy originalPolicy : accessPoliciesSnapshot) {

            Response getCurrentPolicy = client
                    .target(createURL("policies/" + originalPolicy.getIdentifier()))
                    .request()
                    .header("Authorization", "Bearer " + adminAuthToken)
                    .get(Response.class);

            if (getCurrentPolicy.getStatus() == 200) {
                // update policy to match original
                client.target(createURL("policies/" + originalPolicy.getIdentifier()))
                        .request()
                        .header("Authorization", "Bearer " + adminAuthToken)
                        .put(Entity.entity(originalPolicy, MediaType.APPLICATION_JSON));
            } else {
                // post the original policy
                client.target(createURL("policies"))
                        .request()
                        .header("Authorization", "Bearer " + adminAuthToken)
                        .post(Entity.entity(originalPolicy, MediaType.APPLICATION_JSON));
            }

        }

        for (String id : policiesToDelete) {
            try {
                client.target(createURL("policies/" + id))
                        .request()
                        .header("Authorization", "Bearer " + adminAuthToken)
                        .delete();
            } catch (Exception e) {
                // do nothing
            }
        }

    }

    private static Form encodeCredentialsForURLFormParams(String username, String password) {
        return new Form()
                .param("username", username)
                .param("password", password);
    }

    private static String encodeCredentialsForBasicAuth(String username, String password) {
        final String credentials = username + ":" + password;
        final String base64credentials =  new String(Base64.getEncoder().encode(credentials.getBytes(Charset.forName("UTF-8"))));
        return base64credentials;
    }
}
