/*
 * 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.syncope.fit.core;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import static org.junit.jupiter.api.Assumptions.assumeTrue;

import java.security.AccessControlException;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import javax.ws.rs.ForbiddenException;
import javax.ws.rs.core.GenericType;
import javax.ws.rs.core.Response;
import org.apache.commons.lang3.tuple.Triple;
import org.apache.syncope.client.lib.AnonymousAuthenticationHandler;
import org.apache.syncope.client.lib.BasicAuthenticationHandler;
import org.apache.syncope.client.lib.SyncopeClient;
import org.apache.syncope.common.lib.SyncopeClientException;
import org.apache.syncope.common.lib.SyncopeConstants;
import org.apache.syncope.common.lib.request.AnyObjectCR;
import org.apache.syncope.common.lib.request.GroupCR;
import org.apache.syncope.common.lib.request.MembershipUR;
import org.apache.syncope.common.lib.request.ResourceDR;
import org.apache.syncope.common.lib.request.PasswordPatch;
import org.apache.syncope.common.lib.request.StatusR;
import org.apache.syncope.common.lib.request.StringPatchItem;
import org.apache.syncope.common.lib.request.StringReplacePatchItem;
import org.apache.syncope.common.lib.request.UserCR;
import org.apache.syncope.common.lib.request.UserUR;
import org.apache.syncope.common.lib.to.AnyTO;
import org.apache.syncope.common.lib.to.AnyTypeClassTO;
import org.apache.syncope.common.lib.to.AnyTypeTO;
import org.apache.syncope.common.lib.to.GroupTO;
import org.apache.syncope.common.lib.to.MembershipTO;
import org.apache.syncope.common.lib.to.PagedResult;
import org.apache.syncope.common.lib.to.PlainSchemaTO;
import org.apache.syncope.common.lib.to.ProvisioningResult;
import org.apache.syncope.common.lib.to.RoleTO;
import org.apache.syncope.common.lib.to.UserTO;
import org.apache.syncope.common.lib.to.UserRequestForm;
import org.apache.syncope.common.lib.types.AnyTypeKind;
import org.apache.syncope.common.lib.types.AttrSchemaType;
import org.apache.syncope.common.lib.types.CipherAlgorithm;
import org.apache.syncope.common.lib.types.ClientExceptionType;
import org.apache.syncope.common.lib.types.PatchOperation;
import org.apache.syncope.common.lib.types.ResourceDeassociationAction;
import org.apache.syncope.common.lib.types.SchemaType;
import org.apache.syncope.common.lib.types.IdRepoEntitlement;
import org.apache.syncope.common.lib.types.StatusRType;
import org.apache.syncope.common.rest.api.RESTHeaders;
import org.apache.syncope.common.rest.api.beans.AnyQuery;
import org.apache.syncope.common.rest.api.beans.UserRequestQuery;
import org.apache.syncope.common.rest.api.service.AnyObjectService;
import org.apache.syncope.common.rest.api.service.SchemaService;
import org.apache.syncope.common.rest.api.service.UserService;
import org.apache.syncope.core.spring.security.Encryptor;
import org.apache.syncope.fit.AbstractITCase;
import org.apache.syncope.fit.ElasticsearchDetector;
import org.apache.syncope.fit.FlowableDetector;
import org.junit.jupiter.api.Test;
import org.springframework.jdbc.core.JdbcTemplate;

public class AuthenticationITCase extends AbstractITCase {

    private static int getFailedLogins(final UserService userService, final String userKey) {
        UserTO readUserTO = userService.read(userKey);
        assertNotNull(readUserTO);
        assertNotNull(readUserTO.getFailedLogins());
        return readUserTO.getFailedLogins();
    }

    @Test
    public void readEntitlements() {
        // 1. as not authenticated (not allowed)
        try {
            clientFactory.create().self();
            fail("This should not happen");
        } catch (AccessControlException e) {
            assertNotNull(e);
        }

        // 2. as anonymous
        Triple<Map<String, Set<String>>, List<String>, UserTO> self = clientFactory.create(
                new AnonymousAuthenticationHandler(ANONYMOUS_UNAME, ANONYMOUS_KEY)).self();
        assertEquals(1, self.getLeft().size());
        assertTrue(self.getLeft().keySet().contains(IdRepoEntitlement.ANONYMOUS));
        assertEquals(List.of(), self.getMiddle());
        assertEquals(ANONYMOUS_UNAME, self.getRight().getUsername());

        // 3. as admin
        self = adminClient.self();
        assertEquals(adminClient.platform().getEntitlements().size(), self.getLeft().size());
        assertFalse(self.getLeft().keySet().contains(IdRepoEntitlement.ANONYMOUS));
        assertEquals(List.of(), self.getMiddle());
        assertEquals(ADMIN_UNAME, self.getRight().getUsername());

        // 4. as user
        self = clientFactory.create("bellini", ADMIN_PWD).self();
        assertFalse(self.getLeft().isEmpty());
        assertFalse(self.getLeft().keySet().contains(IdRepoEntitlement.ANONYMOUS));
        assertEquals(List.of(), self.getMiddle());
        assertEquals("bellini", self.getRight().getUsername());
    }

    @Test
    public void userSchemaAuthorization() {
        String schemaName = "authTestSchema" + getUUIDString();

        // 1. create a schema (as admin)
        PlainSchemaTO schemaTO = new PlainSchemaTO();
        schemaTO.setKey(schemaName);
        schemaTO.setMandatoryCondition("false");
        schemaTO.setType(AttrSchemaType.String);

        PlainSchemaTO newPlainSchemaTO = createSchema(SchemaType.PLAIN, schemaTO);
        assertEquals(schemaTO, newPlainSchemaTO);

        // 2. create an user with the role created above (as admin)
        UserCR userCR = UserITCase.getUniqueSample("auth@test.org");
        UserTO userTO = createUser(userCR).getEntity();
        assertNotNull(userTO);

        // 3. read the schema created above (as admin) - success
        schemaTO = schemaService.read(SchemaType.PLAIN, schemaName);
        assertNotNull(schemaTO);

        // 4. read the schema created above (as user) - success
        SchemaService schemaService2 = clientFactory.create(userTO.getUsername(), "password123").
                getService(SchemaService.class);
        schemaTO = schemaService2.read(SchemaType.PLAIN, schemaName);
        assertNotNull(schemaTO);

        // 5. update the schema create above (as user) - failure
        try {
            schemaService2.update(SchemaType.PLAIN, schemaTO);
            fail("Schema update as user should not work");
        } catch (ForbiddenException e) {
            assertNotNull(e);
        }

        assertEquals(0, getFailedLogins(userService, userTO.getKey()));
    }

    @Test
    public void userRead() {
        UserCR userCR = UserITCase.getUniqueSample("testuserread@test.org");
        userCR.getRoles().add("User manager");

        UserTO userTO = createUser(userCR).getEntity();
        assertNotNull(userTO);

        UserService userService2 = clientFactory.create(userTO.getUsername(), "password123").
                getService(UserService.class);

        UserTO readUserTO = userService2.read("1417acbe-cbf6-4277-9372-e75e04f97000");
        assertNotNull(readUserTO);

        UserService userService3 = clientFactory.create("puccini", ADMIN_PWD).getService(UserService.class);

        try {
            userService3.read("b3cbc78d-32e6-4bd4-92e0-bbe07566a2ee");
            fail("This should not happen");
        } catch (SyncopeClientException e) {
            assertNotNull(e);
            assertEquals(ClientExceptionType.DelegatedAdministration, e.getType());
        }
    }

    @Test
    public void userSearch() {
        UserCR userCR = UserITCase.getUniqueSample("testusersearch@test.org");
        userCR.getRoles().add("User reviewer");

        UserTO userTO = createUser(userCR).getEntity();
        assertNotNull(userTO);

        // 1. user assigned to role 1, with search entitlement on realms /odd and /even: won't find anything with 
        // root realm
        UserService userService2 = clientFactory.create(userTO.getUsername(), "password123").
                getService(UserService.class);

        if (ElasticsearchDetector.isElasticSearchEnabled(adminClient.platform())) {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException ex) {
                // ignore
            }
        }

        PagedResult<UserTO> matchingUsers = userService2.search(new AnyQuery.Builder().
                realm(SyncopeConstants.ROOT_REALM).
                fiql(SyncopeClient.getUserSearchConditionBuilder().isNotNull("key").query()).build());
        assertNotNull(matchingUsers);
        assertFalse(matchingUsers.getResult().isEmpty());
        Set<String> matchingUserKeys = matchingUsers.getResult().stream().
                map(AnyTO::getKey).collect(Collectors.toSet());
        assertTrue(matchingUserKeys.contains("1417acbe-cbf6-4277-9372-e75e04f97000"));
        assertFalse(matchingUserKeys.contains("74cd8ece-715a-44a4-a736-e17b46c4e7e6"));
        assertFalse(matchingUserKeys.contains("823074dc-d280-436d-a7dd-07399fae48ec"));

        // 2. user assigned to role 4, with search entitlement on realm /even/two
        UserService userService3 = clientFactory.create("puccini", ADMIN_PWD).getService(UserService.class);

        matchingUsers = userService3.search(new AnyQuery.Builder().realm("/even/two").
                fiql(SyncopeClient.getUserSearchConditionBuilder().isNotNull("loginDate").query()).build());
        assertNotNull(matchingUsers);
        assertTrue(matchingUsers.getResult().stream().allMatch(matching -> "/even/two".equals(matching.getRealm())));
    }

    @Test
    public void delegatedUserCRUD() {
        String roleKey = null;
        String delegatedAdminKey = null;
        try {
            // 1. create role for full user administration, under realm /even/two
            RoleTO role = new RoleTO();
            role.setKey("Delegated user admin");
            role.getEntitlements().add(IdRepoEntitlement.USER_CREATE);
            role.getEntitlements().add(IdRepoEntitlement.USER_UPDATE);
            role.getEntitlements().add(IdRepoEntitlement.USER_DELETE);
            role.getEntitlements().add(IdRepoEntitlement.USER_SEARCH);
            role.getEntitlements().add(IdRepoEntitlement.USER_READ);
            role.getRealms().add("/even/two");

            roleKey = roleService.create(role).getHeaderString(RESTHeaders.RESOURCE_KEY);
            assertNotNull(roleKey);

            // 2. as admin, create delegated admin user, and assign the role just created
            UserCR delegatedAdminCR = UserITCase.getUniqueSample("admin@syncope.apache.org");
            delegatedAdminCR.getRoles().add(roleKey);
            UserTO delegatedAdmin = createUser(delegatedAdminCR).getEntity();
            delegatedAdminKey = delegatedAdmin.getKey();

            // 3. instantiate a delegate user service client, for further operations
            UserService delegatedUserService =
                    clientFactory.create(delegatedAdmin.getUsername(), "password123").getService(UserService.class);

            // 4. as delegated, create user under realm / -> fail
            UserCR userCR = UserITCase.getUniqueSample("delegated@syncope.apache.org");
            try {
                delegatedUserService.create(userCR);
                fail("This should not happen");
            } catch (SyncopeClientException e) {
                assertEquals(ClientExceptionType.DelegatedAdministration, e.getType());
            }

            // 5. set realm to /even/two -> succeed
            userCR.setRealm("/even/two");

            Response response = delegatedUserService.create(userCR);
            assertEquals(Response.Status.CREATED.getStatusCode(), response.getStatus());

            UserTO user = response.readEntity(new GenericType<ProvisioningResult<UserTO>>() {
            }).getEntity();
            assertEquals("surname", user.getPlainAttr("surname").get().getValues().get(0));

            // 5. as delegated, update user attempting to move under realm / -> fail
            UserUR userUR = new UserUR();
            userUR.setKey(user.getKey());
            userUR.setRealm(new StringReplacePatchItem.Builder().value("/odd").build());
            userUR.getPlainAttrs().add(attrAddReplacePatch("surname", "surname2"));

            try {
                delegatedUserService.update(userUR);
                fail("This should not happen");
            } catch (SyncopeClientException e) {
                assertEquals(ClientExceptionType.DelegatedAdministration, e.getType());
            }

            // 6. revert realm change -> succeed
            userUR.setRealm(null);

            response = delegatedUserService.update(userUR);
            assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());

            user = response.readEntity(new GenericType<ProvisioningResult<UserTO>>() {
            }).getEntity();
            assertEquals("surname2", user.getPlainAttr("surname").get().getValues().get(0));

            // 7. as delegated, delete user
            delegatedUserService.delete(user.getKey());

            try {
                userService.read(user.getKey());
                fail("This should not happen");
            } catch (SyncopeClientException e) {
                assertEquals(ClientExceptionType.NotFound, e.getType());
            }
        } finally {
            if (roleKey != null) {
                roleService.delete(roleKey);
            }
            if (delegatedAdminKey != null) {
                userService.delete(delegatedAdminKey);
            }
        }
    }

    @Test
    public void checkFailedLogins() {
        UserCR userCR = UserITCase.getUniqueSample("checkFailedLogin@syncope.apache.org");
        userCR.getRoles().add("User manager");

        UserTO userTO = createUser(userCR).getEntity();
        assertNotNull(userTO);
        String userKey = userTO.getKey();

        UserService userService2 = clientFactory.create(userTO.getUsername(), "password123").
                getService(UserService.class);
        assertEquals(0, getFailedLogins(userService2, userKey));

        // authentications failed ...
        try {
            clientFactory.create(userTO.getUsername(), "wrongpwd1");
            fail("This should not happen");
        } catch (AccessControlException e) {
            assertNotNull(e);
        }
        try {
            clientFactory.create(userTO.getUsername(), "wrongpwd1");
            fail("This should not happen");
        } catch (AccessControlException e) {
            assertNotNull(e);
        }
        assertEquals(2, getFailedLogins(userService, userKey));

        UserService userService4 = clientFactory.create(userTO.getUsername(), "password123").
                getService(UserService.class);
        assertEquals(0, getFailedLogins(userService4, userKey));
    }

    @Test
    public void checkUserSuspension() {
        UserCR userCR = UserITCase.getUniqueSample("checkSuspension@syncope.apache.org");
        userCR.setRealm("/odd");
        userCR.getRoles().add("User manager");

        UserTO userTO = createUser(userCR).getEntity();
        String userKey = userTO.getKey();
        assertNotNull(userTO);

        assertEquals(0, getFailedLogins(userService, userKey));

        // authentications failed ...
        try {
            clientFactory.create(userTO.getUsername(), "wrongpwd1");
            fail("This should not happen");
        } catch (AccessControlException e) {
            assertNotNull(e);
        }
        try {
            clientFactory.create(userTO.getUsername(), "wrongpwd1");
            fail("This should not happen");
        } catch (AccessControlException e) {
            assertNotNull(e);
        }
        try {
            clientFactory.create(userTO.getUsername(), "wrongpwd1");
            fail("This should not happen");
        } catch (AccessControlException e) {
            assertNotNull(e);
        }

        assertEquals(3, getFailedLogins(userService, userKey));

        // last authentication before suspension
        try {
            clientFactory.create(userTO.getUsername(), "wrongpwd1");
            fail("This should not happen");
        } catch (AccessControlException e) {
            assertNotNull(e);
        }

        userTO = userService.read(userTO.getKey());
        assertNotNull(userTO);
        assertNotNull(userTO.getFailedLogins());
        assertEquals(3, userTO.getFailedLogins().intValue());
        assertEquals("suspended", userTO.getStatus());

        // Access with correct credentials should fail as user is suspended
        try {
            clientFactory.create(userTO.getUsername(), "password123");
            fail("This should not happen");
        } catch (AccessControlException e) {
            assertNotNull(e);
        }

        StatusR reactivate = new StatusR.Builder().key(userTO.getKey()).
                type(StatusRType.REACTIVATE).build();
        userTO = userService.status(reactivate).readEntity(new GenericType<ProvisioningResult<UserTO>>() {
        }).getEntity();
        assertNotNull(userTO);
        assertEquals("active", userTO.getStatus());

        SyncopeClient goodPwdClient = clientFactory.create(userTO.getUsername(), "password123");
        assertEquals(0, goodPwdClient.self().getRight().getFailedLogins().intValue());
    }

    @Test
    public void anyTypeEntitlement() {
        String anyTypeKey = "FOLDER " + getUUIDString();

        // 1. no entitlement exists (yet) for the any type to be created
        assertFalse(adminClient.platform().getEntitlements().stream().
                anyMatch(entitlement -> entitlement.contains(anyTypeKey)));

        // 2. create plain schema, any type class and any type
        PlainSchemaTO path = new PlainSchemaTO();
        path.setKey("path" + getUUIDString());
        path.setType(AttrSchemaType.String);
        path = createSchema(SchemaType.PLAIN, path);

        AnyTypeClassTO anyTypeClass = new AnyTypeClassTO();
        anyTypeClass.setKey("folder" + getUUIDString());
        anyTypeClass.getPlainSchemas().add(path.getKey());
        anyTypeClassService.create(anyTypeClass);

        AnyTypeTO anyTypeTO = new AnyTypeTO();
        anyTypeTO.setKey(anyTypeKey);
        anyTypeTO.setKind(AnyTypeKind.ANY_OBJECT);
        anyTypeTO.getClasses().add(anyTypeClass.getKey());
        anyTypeService.create(anyTypeTO);

        // 2. now entitlement exists for the any type just created
        assertTrue(adminClient.platform().getEntitlements().stream().
                anyMatch(entitlement -> entitlement.contains(anyTypeKey)));

        // 3. attempt to create an instance of the type above: fail because no entitlement was assigned
        AnyObjectCR folder = new AnyObjectCR();
        folder.setName("home");
        folder.setRealm(SyncopeConstants.ROOT_REALM);
        folder.setType(anyTypeKey);
        folder.getPlainAttrs().add(attr(path.getKey(), "/home"));

        SyncopeClient belliniClient = clientFactory.create("bellini", ADMIN_PWD);
        try {
            belliniClient.getService(AnyObjectService.class).create(folder);
            fail("This should not happen");
        } catch (SyncopeClientException e) {
            assertEquals(ClientExceptionType.DelegatedAdministration, e.getType());
        }

        // 4. give create entitlement for the any type just created
        RoleTO role = new RoleTO();
        role.setKey("role" + getUUIDString());
        role.getRealms().add(SyncopeConstants.ROOT_REALM);
        role.getEntitlements().add(anyTypeKey + "_READ");
        role.getEntitlements().add(anyTypeKey + "_CREATE");
        role = createRole(role);

        UserTO bellini = userService.read("bellini");
        UserUR req = new UserUR();
        req.setKey(bellini.getKey());
        req.getRoles().add(new StringPatchItem.Builder().
                operation(PatchOperation.ADD_REPLACE).value(role.getKey()).build());
        bellini = updateUser(req).getEntity();
        assertTrue(bellini.getRoles().contains(role.getKey()));

        // 5. now the instance of the type above can be created successfully
        belliniClient.logout();
        belliniClient.login(new BasicAuthenticationHandler("bellini", ADMIN_PWD));
        belliniClient.getService(AnyObjectService.class).create(folder);
    }

    @Test
    public void asGroupOwner() {
        // 0. prepare
        UserTO owner = createUser(UserITCase.getUniqueSample("owner@syncope.org")).getEntity();
        assertNotNull(owner);

        GroupCR groupCR = GroupITCase.getSample("forgroupownership");
        groupCR.setUserOwner(owner.getKey());
        GroupTO group = createGroup(groupCR).getEntity();
        assertNotNull(group);
        assertEquals(owner.getKey(), group.getUserOwner());

        UserCR memberCR = UserITCase.getUniqueSample("forgroupownership@syncope.org");
        memberCR.getMemberships().add(new MembershipTO.Builder(group.getKey()).build());
        memberCR.getMemberships().add(new MembershipTO.Builder("37d15e4c-cdc1-460b-a591-8505c8133806").build());
        UserTO member = createUser(memberCR).getEntity();
        assertEquals(2, member.getMemberships().size());
        String memberKey = member.getKey();

        if (ElasticsearchDetector.isElasticSearchEnabled(adminClient.platform())) {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException ex) {
                // ignore
            }
        }

        PagedResult<UserTO> matching = userService.search(
                new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
                        fiql(SyncopeClient.getUserSearchConditionBuilder().inGroups(group.getKey()).query()).
                        page(1).size(1000).build());
        int fullMatchSize = matching.getResult().size();
        assertTrue(matching.getResult().stream().anyMatch(user -> memberKey.equals(user.getKey())));

        UserService groupOwnerService = clientFactory.create(owner.getUsername(), "password123").
                getService(UserService.class);

        // 1. search
        matching = groupOwnerService.search(
                new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
                        fiql(SyncopeClient.getUserSearchConditionBuilder().isNotNull("key").query()).
                        page(1).size(1000).build());
        assertEquals(fullMatchSize, matching.getResult().size());
        assertTrue(matching.getResult().stream().anyMatch(user -> memberKey.equals(user.getKey())));

        // 2. update and read
        UserUR memberUR = new UserUR();
        memberUR.setKey(memberKey);
        memberUR.setUsername(new StringReplacePatchItem.Builder().value("new" + getUUIDString()).build());

        Response response = groupOwnerService.update(memberUR);
        assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());

        member = groupOwnerService.read(memberKey);
        assertEquals(memberUR.getUsername().getValue(), member.getUsername());
        assertEquals(2, member.getMemberships().size());

        // 3. update with membership removal -> fail
        memberUR.setUsername(null);
        memberUR.getMemberships().add(new MembershipUR.Builder(group.getKey()).
                operation(PatchOperation.DELETE).build());
        try {
            groupOwnerService.update(memberUR);
            fail();
        } catch (SyncopeClientException e) {
            assertEquals(ClientExceptionType.DelegatedAdministration, e.getType());
        }

        // 4. update non-member -> fail
        UserTO nonmember = createUser(UserITCase.getUniqueSample("nonmember@syncope.org")).getEntity();
        UserUR nonmemberUR = new UserUR();
        nonmemberUR.setKey(nonmember.getKey());
        nonmemberUR.setUsername(new StringReplacePatchItem.Builder().value("new" + getUUIDString()).build());
        try {
            groupOwnerService.update(nonmemberUR);
            fail();
        } catch (SyncopeClientException e) {
            assertEquals(ClientExceptionType.DelegatedAdministration, e.getType());
        }

        // 5. update user under /even
        memberCR = UserITCase.getUniqueSample("forgroupownership2@syncope.org");
        memberCR.setRealm("/even");
        memberCR.getMemberships().add(new MembershipTO.Builder(group.getKey()).build());
        member = createUser(memberCR).getEntity();

        memberUR = new UserUR();
        memberUR.setKey(member.getKey());
        memberUR.setUsername(new StringReplacePatchItem.Builder().value("new" + getUUIDString()).build());
        response = groupOwnerService.update(memberUR);
        assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());

        // 6 delete
        groupOwnerService.delete(memberKey);
        try {
            userService.read(memberKey);
            fail();
        } catch (SyncopeClientException e) {
            assertEquals(ClientExceptionType.NotFound, e.getType());
        }
    }

    @Test
    public void issueSYNCOPE434() {
        assumeTrue(FlowableDetector.isFlowableEnabledForUserWorkflow(adminClient.platform()));

        // 1. create user with group 'groupForWorkflowApproval' 
        // (users with group groupForWorkflowApproval are defined in workflow as subject to approval)
        UserCR userCR = UserITCase.getUniqueSample("createWithReject@syncope.apache.org");
        userCR.getMemberships().add(new MembershipTO.Builder("0cbcabd2-4410-4b6b-8f05-a052b451d18f").build());

        UserTO userTO = createUser(userCR).getEntity();
        assertNotNull(userTO);
        assertEquals("createApproval", userTO.getStatus());

        // 2. try to authenticate: fail
        try {
            clientFactory.create(userTO.getUsername(), "password123").self();
            fail("This should not happen");
        } catch (AccessControlException e) {
            assertNotNull(e);
        }

        // 3. approve user
        UserRequestForm form = userRequestService.listForms(
                new UserRequestQuery.Builder().user(userTO.getKey()).build()).getResult().get(0);
        form = userRequestService.claimForm(form.getTaskId());
        form.getProperty("approveCreate").get().setValue(Boolean.TRUE.toString());
        userTO = userRequestService.submitForm(form).readEntity(new GenericType<ProvisioningResult<UserTO>>() {
        }).getEntity();
        assertNotNull(userTO);
        assertEquals("active", userTO.getStatus());

        // 4. try to authenticate again: success
        Triple<Map<String, Set<String>>, List<String>, UserTO> self =
                clientFactory.create(userTO.getUsername(), "password123").self();
        assertNotNull(self);
        assertNotNull(self.getLeft());
        assertEquals(List.of(), self.getMiddle());
        assertNotNull(self.getRight());
    }

    @Test
    public void issueSYNCOPE164() throws Exception {
        // 1. create user with db resource
        UserCR userCR = UserITCase.getUniqueSample("syncope164@syncope.apache.org");
        userCR.setRealm("/even/two");
        userCR.setPassword("password123");
        userCR.getResources().add(RESOURCE_NAME_TESTDB);
        UserTO user = createUser(userCR).getEntity();
        assertNotNull(user);

        // 2. unlink the resource from the created user
        ResourceDR resourceDR = new ResourceDR.Builder().key(user.getKey()).
                action(ResourceDeassociationAction.UNLINK).resource(RESOURCE_NAME_TESTDB).build();
        assertNotNull(parseBatchResponse(userService.deassociate(resourceDR)));

        // 3. change password on Syncope
        UserUR userUR = new UserUR();
        userUR.setKey(user.getKey());
        userUR.setPassword(new PasswordPatch.Builder().value("password234").build());
        user = updateUser(userUR).getEntity();
        assertNotNull(user);

        // 4. check that the db resource has still the initial password value
        JdbcTemplate jdbcTemplate = new JdbcTemplate(testDataSource);
        String value = queryForObject(jdbcTemplate, MAX_WAIT_SECONDS,
                "SELECT PASSWORD FROM test WHERE ID=?", String.class, user.getUsername());
        assertEquals(Encryptor.getInstance().encode("password123", CipherAlgorithm.SHA1), value.toUpperCase());

        // 5. successfully authenticate with old (on db resource) and new (on internal storage) password values
        Triple<Map<String, Set<String>>, List<String>, UserTO> self =
                clientFactory.create(user.getUsername(), "password123").self();
        assertNotNull(self);
        self = clientFactory.create(user.getUsername(), "password234").self();
        assertNotNull(self);
    }

    @Test
    public void issueSYNCOPE706() {
        String username = getUUIDString();
        try {
            userService.read(username);
            fail("This should not happen");
        } catch (SyncopeClientException e) {
            assertEquals(ClientExceptionType.NotFound, e.getType());
        }

        try {
            clientFactory.create(username, "anypassword").self();
            fail("This should not happen");
        } catch (AccessControlException e) {
            assertNotNull(e.getMessage());
        }
    }
}
