/*
 * 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.awaitility.Awaitility.await;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import static org.junit.jupiter.api.Assumptions.assumeFalse;

import java.io.IOException;
import java.security.AccessControlException;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.ws.rs.ForbiddenException;
import javax.ws.rs.core.GenericType;
import javax.ws.rs.core.Response;
import org.apache.commons.lang3.SerializationUtils;
import org.apache.syncope.client.lib.AnonymousAuthenticationHandler;
import org.apache.syncope.client.lib.SyncopeClient;
import org.apache.syncope.common.lib.AnyOperations;
import org.apache.syncope.common.lib.Attr;
import org.apache.syncope.common.lib.EntityTOUtils;
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.AnyObjectUR;
import org.apache.syncope.common.lib.request.AttrPatch;
import org.apache.syncope.common.lib.request.GroupCR;
import org.apache.syncope.common.lib.request.GroupUR;
import org.apache.syncope.common.lib.request.ResourceAR;
import org.apache.syncope.common.lib.request.ResourceDR;
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.to.AnyObjectTO;
import org.apache.syncope.common.lib.to.AnyTypeClassTO;
import org.apache.syncope.common.lib.to.AnyTypeTO;
import org.apache.syncope.common.lib.to.ConnInstanceTO;
import org.apache.syncope.common.lib.to.ConnObjectTO;
import org.apache.syncope.common.lib.to.DerSchemaTO;
import org.apache.syncope.common.lib.to.ExecTO;
import org.apache.syncope.common.lib.to.GroupTO;
import org.apache.syncope.common.lib.to.ItemTO;
import org.apache.syncope.common.lib.to.MappingTO;
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.PropagationStatus;
import org.apache.syncope.common.lib.to.ProvisionTO;
import org.apache.syncope.common.lib.to.ProvisioningResult;
import org.apache.syncope.common.lib.to.ResourceTO;
import org.apache.syncope.common.lib.to.TypeExtensionTO;
import org.apache.syncope.common.lib.to.UserTO;
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.ConnectorCapability;
import org.apache.syncope.common.lib.types.ExecStatus;
import org.apache.syncope.common.lib.types.MappingPurpose;
import org.apache.syncope.common.lib.types.PatchOperation;
import org.apache.syncope.common.lib.types.ProvisionAction;
import org.apache.syncope.common.lib.types.ResourceAssociationAction;
import org.apache.syncope.common.lib.types.ResourceDeassociationAction;
import org.apache.syncope.common.lib.types.SchemaType;
import org.apache.syncope.common.lib.types.TaskType;
import org.apache.syncope.common.rest.api.beans.AnyQuery;
import org.apache.syncope.common.rest.api.service.GroupService;
import org.apache.syncope.common.rest.api.service.SyncopeService;
import org.apache.syncope.core.provisioning.java.job.TaskJob;
import org.apache.syncope.core.spring.security.Encryptor;
import org.apache.syncope.fit.AbstractITCase;
import org.apache.syncope.fit.ElasticsearchDetector;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

public class GroupITCase extends AbstractITCase {

    public static GroupCR getBasicSample(final String name) {
        return new GroupCR.Builder(SyncopeConstants.ROOT_REALM, name + getUUIDString()).build();
    }

    public static GroupCR getSample(final String name) {
        GroupCR groupCR = getBasicSample(name);

        groupCR.getPlainAttrs().add(attr("icon", "anIcon"));

        groupCR.getResources().add(RESOURCE_NAME_LDAP);
        return groupCR;
    }

    @Test
    public void create() {
        GroupCR groupCR = getSample("lastGroup");
        groupCR.getVirAttrs().add(attr("rvirtualdata", "rvirtualvalue"));
        groupCR.setGroupOwner("f779c0d4-633b-4be5-8f57-32eb478a3ca5");

        GroupTO groupTO = createGroup(groupCR).getEntity();
        assertNotNull(groupTO);

        assertNotNull(groupTO.getVirAttr("rvirtualdata").get().getValues());
        assertFalse(groupTO.getVirAttr("rvirtualdata").get().getValues().isEmpty());
        assertEquals("rvirtualvalue", groupTO.getVirAttr("rvirtualdata").get().getValues().get(0));

        assertTrue(groupTO.getResources().contains(RESOURCE_NAME_LDAP));

        ConnObjectTO connObjectTO =
                RESOURCE_SERVICE.readConnObject(RESOURCE_NAME_LDAP, AnyTypeKind.GROUP.name(), groupTO.getKey());
        assertNotNull(connObjectTO);
        assertNotNull(connObjectTO.getAttr("owner"));

        // SYNCOPE-515: remove ownership
        GroupUR groupUR = new GroupUR();
        groupUR.setKey(groupTO.getKey());
        groupUR.setGroupOwner(new StringReplacePatchItem());

        assertNull(updateGroup(groupUR).getEntity().getGroupOwner());
    }

    @Test
    public void createWithInternationalCharacters() {
        GroupCR groupCR = getSample("räksmörgås");

        GroupTO groupTO = createGroup(groupCR).getEntity();
        assertNotNull(groupTO);
    }

    @Test
    public void delete() {
        try {
            GROUP_SERVICE.delete(UUID.randomUUID().toString());
        } catch (SyncopeClientException e) {
            assertEquals(Response.Status.NOT_FOUND, e.getType().getResponseStatus());
        }

        GroupCR groupCR = new GroupCR();
        groupCR.setName("toBeDeleted" + getUUIDString());
        groupCR.setRealm("/even");

        groupCR.getResources().add(RESOURCE_NAME_LDAP);

        GroupTO groupTO = createGroup(groupCR).getEntity();
        assertNotNull(groupTO);

        GroupTO deletedGroup = deleteGroup(groupTO.getKey()).getEntity();
        assertNotNull(deletedGroup);

        try {
            GROUP_SERVICE.read(deletedGroup.getKey());
        } catch (SyncopeClientException e) {
            assertEquals(Response.Status.NOT_FOUND, e.getType().getResponseStatus());
        }
    }

    @Test
    public void list() {
        PagedResult<GroupTO> groupTOs =
                GROUP_SERVICE.search(new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).build());
        assertNotNull(groupTOs);
        assertTrue(groupTOs.getResult().size() >= 8);
        groupTOs.getResult().forEach(Assertions::assertNotNull);
    }

    @Test
    public void read() {
        GroupTO groupTO = GROUP_SERVICE.read("37d15e4c-cdc1-460b-a591-8505c8133806");

        assertNotNull(groupTO);
        assertNotNull(groupTO.getPlainAttrs());
        assertFalse(groupTO.getPlainAttrs().isEmpty());
        assertEquals(2, groupTO.getStaticUserMembershipCount());
    }

    @Test
    public void selfRead() {
        UserTO userTO = USER_SERVICE.read("1417acbe-cbf6-4277-9372-e75e04f97000");
        assertNotNull(userTO);

        assertTrue(userTO.getMembership("37d15e4c-cdc1-460b-a591-8505c8133806").isPresent());
        assertFalse(userTO.getMembership("29f96485-729e-4d31-88a1-6fc60e4677f3").isPresent());

        GroupService groupService2 = CLIENT_FACTORY.create("rossini", ADMIN_PWD).getService(GroupService.class);

        try {
            groupService2.read("29f96485-729e-4d31-88a1-6fc60e4677f3");
            fail("This should not happen");
        } catch (SyncopeClientException e) {
            assertEquals(ClientExceptionType.DelegatedAdministration, e.getType());
        }

        List<GroupTO> groups = groupService2.own();
        assertNotNull(groups);
        assertTrue(groups.stream().anyMatch(group -> "37d15e4c-cdc1-460b-a591-8505c8133806".equals(group.getKey())));
    }

    @Test
    public void update() {
        GroupCR groupCR = getSample("latestGroup" + getUUIDString());
        GroupTO groupTO = createGroup(groupCR).getEntity();

        assertEquals(1, groupTO.getPlainAttrs().size());

        GroupUR groupUR = new GroupUR();
        groupUR.setKey(groupTO.getKey());
        String modName = "finalGroup" + getUUIDString();
        groupUR.setName(new StringReplacePatchItem.Builder().value(modName).build());
        groupUR.getPlainAttrs().add(attrAddReplacePatch("show", "FALSE"));

        groupTO = updateGroup(groupUR).getEntity();

        assertEquals(modName, groupTO.getName());
        assertEquals(2, groupTO.getPlainAttrs().size());

        groupTO.getPlainAttr("show").get().getValues().clear();

        groupUR = new GroupUR.Builder(groupTO.getKey()).
                plainAttr(new AttrPatch.Builder(new Attr.Builder("show").build()).
                        operation(PatchOperation.DELETE).build()).build();

        groupTO = updateGroup(groupUR).getEntity();

        assertFalse(groupTO.getPlainAttr("show").isPresent());
    }

    @Test
    public void patch() {
        GroupCR createReq = getBasicSample("patch");
        createReq.setUDynMembershipCond(
                "(($groups==ebf97068-aa4b-4a85-9f01-680e8c4cf227;$resources!=ws-target-resource-1);aLong==1)");
        createReq.getADynMembershipConds().put(
                PRINTER,
                "(($groups==ece66293-8f31-4a84-8e8d-23da36e70846;cool==ss);$resources==ws-target-resource-2);"
                + "$type==PRINTER");

        GroupTO created = createGroup(createReq).getEntity();

        created.getPlainAttrs().add(new Attr.Builder("icon").build());
        created.getPlainAttrs().add(new Attr.Builder("show").build());
        created.getPlainAttrs().add(new Attr.Builder("rderived_sx").value("sx").build());
        created.getPlainAttrs().add(new Attr.Builder("rderived_dx").value("dx").build());
        created.getPlainAttrs().add(new Attr.Builder("title").value("mr").build());

        GroupTO original = GROUP_SERVICE.read(created.getKey());

        GroupUR groupUR = AnyOperations.diff(created, original, true);
        GroupTO updated = updateGroup(groupUR).getEntity();

        Map<String, Attr> attrs = EntityTOUtils.buildAttrMap(updated.getPlainAttrs());
        assertFalse(attrs.containsKey("icon"));
        assertFalse(attrs.containsKey("show"));
        assertEquals(List.of("sx"), attrs.get("rderived_sx").getValues());
        assertEquals(List.of("dx"), attrs.get("rderived_dx").getValues());
        assertEquals(List.of("mr"), attrs.get("title").getValues());
    }

    @Test
    public void updateAsGroupOwner() {
        // 1. read group as admin
        GroupTO groupTO = GROUP_SERVICE.read("ebf97068-aa4b-4a85-9f01-680e8c4cf227");

        // issue SYNCOPE-15
        assertNotNull(groupTO.getCreationDate());
        assertNotNull(groupTO.getLastChangeDate());
        assertEquals("admin", groupTO.getCreator());
        assertEquals("admin", groupTO.getLastModifier());

        // 2. prepare update
        GroupUR groupUR = new GroupUR();
        groupUR.setKey(groupTO.getKey());
        groupUR.setName(new StringReplacePatchItem.Builder().value("Director").build());

        // 3. try to update as verdi, not owner of group 6 - fail
        GroupService groupService2 = CLIENT_FACTORY.create("verdi", ADMIN_PWD).getService(GroupService.class);

        try {
            groupService2.update(groupUR);
            fail("This should not happen");
        } catch (ForbiddenException e) {
            assertNotNull(e);
        }

        // 4. update as puccini, owner of group 6 - success
        GroupService groupService3 = CLIENT_FACTORY.create("puccini", ADMIN_PWD).getService(GroupService.class);

        groupTO = groupService3.update(groupUR).readEntity(new GenericType<ProvisioningResult<GroupTO>>() {
        }).getEntity();
        assertEquals("Director", groupTO.getName());

        // issue SYNCOPE-15
        assertNotNull(groupTO.getCreationDate());
        assertNotNull(groupTO.getLastChangeDate());
        assertEquals("admin", groupTO.getCreator());
        assertEquals("puccini", groupTO.getLastModifier());
        assertTrue(groupTO.getCreationDate().isBefore(groupTO.getLastChangeDate()));
    }

    @Test
    public void unlink() throws IOException {
        GroupTO actual = createGroup(getSample("unlink")).getEntity();
        assertNotNull(actual);

        assertNotNull(RESOURCE_SERVICE.readConnObject(RESOURCE_NAME_LDAP, AnyTypeKind.GROUP.name(), actual.getKey()));

        ResourceDR resourceDR = new ResourceDR.Builder().key(actual.getKey()).
                action(ResourceDeassociationAction.UNLINK).resource(RESOURCE_NAME_LDAP).build();

        assertNotNull(parseBatchResponse(GROUP_SERVICE.deassociate(resourceDR)));

        actual = GROUP_SERVICE.read(actual.getKey());
        assertNotNull(actual);
        assertTrue(actual.getResources().isEmpty());

        assertNotNull(RESOURCE_SERVICE.readConnObject(RESOURCE_NAME_LDAP, AnyTypeKind.GROUP.name(), actual.getKey()));
    }

    @Test
    public void link() throws IOException {
        GroupCR groupCR = getSample("link");
        groupCR.getResources().clear();

        GroupTO actual = createGroup(groupCR).getEntity();
        assertNotNull(actual);

        try {
            RESOURCE_SERVICE.readConnObject(RESOURCE_NAME_LDAP, AnyTypeKind.GROUP.name(), actual.getKey());
            fail("This should not happen");
        } catch (Exception e) {
            assertNotNull(e);
        }

        ResourceAR resourceAR = new ResourceAR.Builder().key(actual.getKey()).
                action(ResourceAssociationAction.LINK).resource(RESOURCE_NAME_LDAP).build();

        assertNotNull(parseBatchResponse(GROUP_SERVICE.associate(resourceAR)));

        actual = GROUP_SERVICE.read(actual.getKey());
        assertFalse(actual.getResources().isEmpty());

        try {
            RESOURCE_SERVICE.readConnObject(RESOURCE_NAME_LDAP, AnyTypeKind.GROUP.name(), actual.getKey());
            fail("This should not happen");
        } catch (Exception e) {
            assertNotNull(e);
        }
    }

    @Test
    public void unassign() throws IOException {
        GroupTO groupTO = null;

        try {
            groupTO = createGroup(getSample("unassign")).getEntity();
            assertNotNull(groupTO);

            assertNotNull(RESOURCE_SERVICE.readConnObject(
                    RESOURCE_NAME_LDAP, AnyTypeKind.GROUP.name(), groupTO.getKey()));

            ResourceDR resourceDR = new ResourceDR();
            resourceDR.setKey(groupTO.getKey());
            resourceDR.setAction(ResourceDeassociationAction.UNASSIGN);
            resourceDR.getResources().add(RESOURCE_NAME_LDAP);

            assertNotNull(parseBatchResponse(GROUP_SERVICE.deassociate(resourceDR)));

            groupTO = GROUP_SERVICE.read(groupTO.getKey());
            assertNotNull(groupTO);
            assertTrue(groupTO.getResources().isEmpty());

            try {
                RESOURCE_SERVICE.readConnObject(RESOURCE_NAME_LDAP, AnyTypeKind.GROUP.name(), groupTO.getKey());
                fail("This should not happen");
            } catch (Exception e) {
                assertNotNull(e);
            }
        } finally {
            if (groupTO != null) {
                GROUP_SERVICE.delete(groupTO.getKey());
            }
        }
    }

    @Test
    public void assign() throws IOException {
        GroupCR groupCR = getSample("assign");
        groupCR.getResources().clear();

        GroupTO groupTO = null;
        try {
            groupTO = createGroup(groupCR).getEntity();
            assertNotNull(groupTO);

            try {
                RESOURCE_SERVICE.readConnObject(RESOURCE_NAME_LDAP, AnyTypeKind.GROUP.name(), groupTO.getKey());
                fail("This should not happen");
            } catch (Exception e) {
                assertNotNull(e);
            }

            ResourceAR resourceAR = new ResourceAR.Builder().key(groupTO.getKey()).
                    action(ResourceAssociationAction.ASSIGN).resource(RESOURCE_NAME_LDAP).build();

            assertNotNull(parseBatchResponse(GROUP_SERVICE.associate(resourceAR)));

            groupTO = GROUP_SERVICE.read(groupTO.getKey());
            assertFalse(groupTO.getResources().isEmpty());
            assertNotNull(RESOURCE_SERVICE.readConnObject(
                    RESOURCE_NAME_LDAP, AnyTypeKind.GROUP.name(), groupTO.getKey()));
        } finally {
            if (groupTO != null) {
                GROUP_SERVICE.delete(groupTO.getKey());
            }
        }
    }

    @Test
    public void deprovision() throws IOException {
        GroupTO groupTO = null;

        try {
            groupTO = createGroup(getSample("deprovision")).getEntity();
            assertNotNull(groupTO);
            assertNotNull(groupTO.getKey());

            assertNotNull(
                    RESOURCE_SERVICE.readConnObject(RESOURCE_NAME_LDAP, AnyTypeKind.GROUP.name(), groupTO.getKey()));

            ResourceDR resourceDR = new ResourceDR.Builder().key(groupTO.getKey()).
                    action(ResourceDeassociationAction.DEPROVISION).resource(RESOURCE_NAME_LDAP).build();

            assertNotNull(parseBatchResponse(GROUP_SERVICE.deassociate(resourceDR)));

            groupTO = GROUP_SERVICE.read(groupTO.getKey());
            assertNotNull(groupTO);
            assertFalse(groupTO.getResources().isEmpty());

            try {
                RESOURCE_SERVICE.readConnObject(RESOURCE_NAME_LDAP, AnyTypeKind.GROUP.name(), groupTO.getKey());
                fail("This should not happen");
            } catch (Exception e) {
                assertNotNull(e);
            }
        } finally {
            if (groupTO != null) {
                GROUP_SERVICE.delete(groupTO.getKey());
            }
        }
    }

    @Test
    public void provision() throws IOException {
        GroupCR groupCR = getSample("provision");
        groupCR.getResources().clear();

        GroupTO groupTO = null;
        try {
            groupTO = createGroup(groupCR).getEntity();
            assertNotNull(groupTO);

            try {
                RESOURCE_SERVICE.readConnObject(RESOURCE_NAME_LDAP, AnyTypeKind.GROUP.name(), groupTO.getKey());
                fail("This should not happen");
            } catch (Exception e) {
                assertNotNull(e);
            }

            ResourceAR resourceAR = new ResourceAR.Builder().key(groupTO.getKey()).
                    action(ResourceAssociationAction.PROVISION).resource(RESOURCE_NAME_LDAP).build();

            assertNotNull(parseBatchResponse(GROUP_SERVICE.associate(resourceAR)));

            groupTO = GROUP_SERVICE.read(groupTO.getKey());
            assertTrue(groupTO.getResources().isEmpty());

            assertNotNull(RESOURCE_SERVICE.readConnObject(
                    RESOURCE_NAME_LDAP, AnyTypeKind.GROUP.name(), groupTO.getKey()));
        } finally {
            if (groupTO != null) {
                GROUP_SERVICE.delete(groupTO.getKey());
            }
        }
    }

    @Test
    public void deprovisionUnlinked() throws IOException {
        GroupCR groupCR = getSample("deprovision");
        groupCR.getResources().clear();

        GroupTO groupTO = null;
        try {
            groupTO = createGroup(groupCR).getEntity();
            assertNotNull(groupTO);

            try {
                RESOURCE_SERVICE.readConnObject(RESOURCE_NAME_LDAP, AnyTypeKind.GROUP.name(), groupTO.getKey());
                fail("This should not happen");
            } catch (Exception e) {
                assertNotNull(e);
            }

            ResourceAR resourceAR = new ResourceAR.Builder().key(groupTO.getKey()).
                    action(ResourceAssociationAction.PROVISION).resource(RESOURCE_NAME_LDAP).build();

            assertNotNull(parseBatchResponse(GROUP_SERVICE.associate(resourceAR)));

            groupTO = GROUP_SERVICE.read(groupTO.getKey());
            assertTrue(groupTO.getResources().isEmpty());

            assertNotNull(RESOURCE_SERVICE.readConnObject(
                    RESOURCE_NAME_LDAP, AnyTypeKind.GROUP.name(), groupTO.getKey()));

            ResourceDR resourceDR = new ResourceDR.Builder().key(groupTO.getKey()).
                    action(ResourceDeassociationAction.DEPROVISION).resource(RESOURCE_NAME_LDAP).build();

            assertNotNull(parseBatchResponse(GROUP_SERVICE.deassociate(resourceDR)));

            groupTO = GROUP_SERVICE.read(groupTO.getKey());
            assertNotNull(groupTO);
            assertTrue(groupTO.getResources().isEmpty());

            try {
                RESOURCE_SERVICE.readConnObject(RESOURCE_NAME_LDAP, AnyTypeKind.GROUP.name(), groupTO.getKey());
                fail("This should not happen");
            } catch (Exception e) {
                assertNotNull(e);
            }
        } finally {
            if (groupTO != null) {
                GROUP_SERVICE.delete(groupTO.getKey());
            }
        }
    }

    @Test
    public void createWithMandatorySchema() {
        // 1. create a mandatory schema
        PlainSchemaTO badge = new PlainSchemaTO();
        badge.setKey("badge" + getUUIDString());
        badge.setMandatoryCondition("true");
        SCHEMA_SERVICE.create(SchemaType.PLAIN, badge);

        // 2. create a group *without* an attribute for that schema: it works
        GroupCR groupCR = getSample("lastGroup");
        GroupTO groupTO = createGroup(groupCR).getEntity();
        assertNotNull(groupTO);
        assertFalse(groupTO.getPlainAttr(badge.getKey()).isPresent());

        // 3. add the new mandatory schema to the default group type
        AnyTypeTO type = ANY_TYPE_SERVICE.read(AnyTypeKind.GROUP.name());
        String typeClassName = type.getClasses().get(0);
        AnyTypeClassTO typeClass = ANY_TYPE_CLASS_SERVICE.read(typeClassName);
        typeClass.getPlainSchemas().add(badge.getKey());
        ANY_TYPE_CLASS_SERVICE.update(typeClass);
        typeClass = ANY_TYPE_CLASS_SERVICE.read(typeClassName);
        assertTrue(typeClass.getPlainSchemas().contains(badge.getKey()));

        try {
            // 4. update group: failure since no values are provided and it is mandatory
            GroupUR groupUR = new GroupUR();
            groupUR.setKey(groupTO.getKey());

            try {
                updateGroup(groupUR);
                fail("This should not happen");
            } catch (SyncopeClientException e) {
                assertEquals(ClientExceptionType.RequiredValuesMissing, e.getType());
            }

            // 5. also add an actual attribute for badge - it will work
            groupUR.getPlainAttrs().add(attrAddReplacePatch(badge.getKey(), "xxxxxxxxxx"));

            groupTO = updateGroup(groupUR).getEntity();
            assertNotNull(groupTO);
            assertNotNull(groupTO.getPlainAttr(badge.getKey()));
        } finally {
            // restore the original group class
            typeClass.getPlainSchemas().remove(badge.getKey());
            ANY_TYPE_CLASS_SERVICE.update(typeClass);
            typeClass = ANY_TYPE_CLASS_SERVICE.read(typeClassName);
            assertFalse(typeClass.getPlainSchemas().contains(badge.getKey()));
        }
    }

    @Test
    public void encrypted() throws Exception {
        // 1. create encrypted schema with secret key as system property
        PlainSchemaTO encrypted = new PlainSchemaTO();
        encrypted.setKey("encrypted" + getUUIDString());
        encrypted.setType(AttrSchemaType.Encrypted);
        encrypted.setCipherAlgorithm(CipherAlgorithm.SHA512);
        encrypted.setSecretKey("${obscureSecretKey}");
        SCHEMA_SERVICE.create(SchemaType.PLAIN, encrypted);

        // 2. add the new schema to the default group type
        AnyTypeTO type = ANY_TYPE_SERVICE.read(AnyTypeKind.GROUP.name());
        String typeClassName = type.getClasses().get(0);
        AnyTypeClassTO typeClass = ANY_TYPE_CLASS_SERVICE.read(typeClassName);
        typeClass.getPlainSchemas().add(encrypted.getKey());
        ANY_TYPE_CLASS_SERVICE.update(typeClass);
        typeClass = ANY_TYPE_CLASS_SERVICE.read(typeClassName);
        assertTrue(typeClass.getPlainSchemas().contains(encrypted.getKey()));

        // 3. create group, verify that the correct encrypted value is returned
        GroupCR groupCR = getSample("encrypted");
        groupCR.getPlainAttrs().add(new Attr.Builder(encrypted.getKey()).value("testvalue").build());
        GroupTO group = createGroup(groupCR).getEntity();

        assertEquals(Encryptor.getInstance(System.getProperty("obscureSecretKey")).
                encode("testvalue", encrypted.getCipherAlgorithm()),
                group.getPlainAttr(encrypted.getKey()).get().getValues().get(0));

        // 4. update schema to return cleartext values
        encrypted.setAnyTypeClass(typeClassName);
        encrypted.setCipherAlgorithm(CipherAlgorithm.AES);
        encrypted.setConversionPattern(SyncopeConstants.ENCRYPTED_DECODE_CONVERSION_PATTERN);
        SCHEMA_SERVICE.update(SchemaType.PLAIN, encrypted);

        // 5. update group, verify that the cleartext value is returned
        GroupUR groupUR = new GroupUR();
        groupUR.setKey(group.getKey());
        groupUR.getPlainAttrs().add(new AttrPatch.Builder(
                new Attr.Builder(encrypted.getKey()).value("testvalue").build()).build());
        group = updateGroup(groupUR).getEntity();

        assertEquals("testvalue", group.getPlainAttr(encrypted.getKey()).get().getValues().get(0));

        // 6. update schema again to disallow cleartext values
        encrypted.setConversionPattern(null);
        SCHEMA_SERVICE.update(SchemaType.PLAIN, encrypted);

        group = GROUP_SERVICE.read(group.getKey());
        assertNotEquals("testvalue", group.getPlainAttr(encrypted.getKey()).get().getValues().get(0));
    }

    @Test
    public void anonymous() {
        GroupService unauthenticated = CLIENT_FACTORY.create().getService(GroupService.class);
        try {
            unauthenticated.search(new AnyQuery.Builder().realm("/even").build());
            fail("This should not happen");
        } catch (AccessControlException e) {
            assertNotNull(e);
        }

        SyncopeClient anonymous = CLIENT_FACTORY.create(
                new AnonymousAuthenticationHandler(ANONYMOUS_UNAME, ANONYMOUS_KEY));
        try {
            anonymous.getService(GroupService.class).
                    search(new AnyQuery.Builder().realm("/even").build());
            fail("This should not happen");
        } catch (ForbiddenException e) {
            assertNotNull(e);
        }

        assertFalse(anonymous.getService(SyncopeService.class).
                searchAssignableGroups("/even", null, 1, 100).getResult().isEmpty());
    }

    @Test
    public void uDynMembership() {
        assertTrue(USER_SERVICE.read("c9b2dec2-00a7-4855-97c0-d854842b4b24").getDynMemberships().isEmpty());

        GroupCR groupCR = getBasicSample("uDynMembership");
        groupCR.setUDynMembershipCond("cool==true");
        GroupTO group = createGroup(groupCR).getEntity();
        assertNotNull(group);
        final String groupKey = group.getKey();

        List<MembershipTO> memberships = USER_SERVICE.read(
                "c9b2dec2-00a7-4855-97c0-d854842b4b24").getDynMemberships();
        assertTrue(memberships.stream().anyMatch(m -> m.getGroupKey().equals(groupKey)));
        assertEquals(1, GROUP_SERVICE.read(group.getKey()).getDynamicUserMembershipCount());

        GroupUR groupUR = new GroupUR();
        groupUR.setKey(group.getKey());
        groupUR.setUDynMembershipCond("cool==false");
        GROUP_SERVICE.update(groupUR);

        assertTrue(USER_SERVICE.read("c9b2dec2-00a7-4855-97c0-d854842b4b24").getDynMemberships().isEmpty());
        assertEquals(0, GROUP_SERVICE.read(group.getKey()).getDynamicUserMembershipCount());
    }

    @Test
    public void aDynMembership() {
        String fiql = SyncopeClient.getAnyObjectSearchConditionBuilder(PRINTER).is("location").notNullValue().query();

        // 1. create group with a given aDynMembership condition
        GroupCR groupCR = getBasicSample("aDynMembership");
        groupCR.getADynMembershipConds().put(PRINTER, fiql);
        GroupTO group = createGroup(groupCR).getEntity();
        assertEquals(fiql, group.getADynMembershipConds().get(PRINTER));

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

        group = GROUP_SERVICE.read(group.getKey());
        String groupKey = group.getKey();
        assertEquals(fiql, group.getADynMembershipConds().get(PRINTER));

        // verify that the condition is dynamically applied
        AnyObjectCR newAnyCR = AnyObjectITCase.getSample("aDynMembership");
        newAnyCR.getResources().clear();
        AnyObjectTO newAny = createAnyObject(newAnyCR).getEntity();
        assertNotNull(newAny.getPlainAttr("location"));
        List<MembershipTO> memberships = ANY_OBJECT_SERVICE.read(
                "fc6dbc3a-6c07-4965-8781-921e7401a4a5").getDynMemberships();
        assertTrue(memberships.stream().anyMatch(m -> m.getGroupKey().equals(groupKey)));

        memberships = ANY_OBJECT_SERVICE.read(
                "8559d14d-58c2-46eb-a2d4-a7d35161e8f8").getDynMemberships();
        assertTrue(memberships.stream().anyMatch(m -> m.getGroupKey().equals(groupKey)));

        memberships = ANY_OBJECT_SERVICE.read(newAny.getKey()).getDynMemberships();
        assertTrue(memberships.stream().anyMatch(m -> m.getGroupKey().equals(groupKey)));

        // 2. update group and change aDynMembership condition
        fiql = SyncopeClient.getAnyObjectSearchConditionBuilder(PRINTER).is("location").nullValue().query();

        GroupUR groupUR = new GroupUR();
        groupUR.setKey(group.getKey());
        groupUR.getADynMembershipConds().put(PRINTER, fiql);

        group = updateGroup(groupUR).getEntity();
        assertEquals(fiql, group.getADynMembershipConds().get(PRINTER));

        group = GROUP_SERVICE.read(group.getKey());
        assertEquals(fiql, group.getADynMembershipConds().get(PRINTER));

        // verify that the condition is dynamically applied
        AnyObjectUR anyObjectUR = new AnyObjectUR();
        anyObjectUR.setKey(newAny.getKey());
        anyObjectUR.getPlainAttrs().add(new AttrPatch.Builder(new Attr.Builder("location").build()).
                operation(PatchOperation.DELETE).
                build());
        newAny = updateAnyObject(anyObjectUR).getEntity();
        assertFalse(newAny.getPlainAttr("location").isPresent());

        memberships = ANY_OBJECT_SERVICE.read(
                "fc6dbc3a-6c07-4965-8781-921e7401a4a5").getDynMemberships();
        assertFalse(memberships.stream().anyMatch(m -> m.getGroupKey().equals(groupKey)));
        memberships = ANY_OBJECT_SERVICE.read(
                "8559d14d-58c2-46eb-a2d4-a7d35161e8f8").getDynMemberships();
        assertFalse(memberships.stream().anyMatch(m -> m.getGroupKey().equals(groupKey)));
        memberships = ANY_OBJECT_SERVICE.read(newAny.getKey()).getDynMemberships();
        assertTrue(memberships.stream().anyMatch(m -> m.getGroupKey().equals(groupKey)));
    }

    @Test
    public void aDynMembershipCount() {
        // Create a new printer as a dynamic member of a new group
        GroupCR groupCR = getBasicSample("aDynamicMembership");
        String fiql = SyncopeClient.getAnyObjectSearchConditionBuilder(PRINTER).is("location").equalTo("home").query();
        groupCR.getADynMembershipConds().put(PRINTER, fiql);
        GroupTO group = createGroup(groupCR).getEntity();

        AnyObjectCR printerCR = new AnyObjectCR();
        printerCR.setRealm(SyncopeConstants.ROOT_REALM);
        printerCR.setName("Printer_" + getUUIDString());
        printerCR.setType(PRINTER);
        printerCR.getPlainAttrs().add(new Attr.Builder("location").value("home").build());
        AnyObjectTO printer = createAnyObject(printerCR).getEntity();

        group = GROUP_SERVICE.read(group.getKey());
        assertEquals(0, group.getStaticAnyObjectMembershipCount());
        assertEquals(1, group.getDynamicAnyObjectMembershipCount());

        ANY_OBJECT_SERVICE.delete(printer.getKey());
        GROUP_SERVICE.delete(group.getKey());
    }

    @Test
    public void aStaticMembershipCount() {
        // Create a new printer as a static member of a new group
        GroupCR groupCR = getBasicSample("aStaticMembership");
        GroupTO group = createGroup(groupCR).getEntity();

        AnyObjectCR printerCR = new AnyObjectCR();
        printerCR.setRealm(SyncopeConstants.ROOT_REALM);
        printerCR.setName("Printer_" + getUUIDString());
        printerCR.setType(PRINTER);
        printerCR.getMemberships().add(new MembershipTO.Builder(group.getKey()).build());
        AnyObjectTO printer = createAnyObject(printerCR).getEntity();

        group = GROUP_SERVICE.read(group.getKey());
        assertEquals(0, group.getDynamicAnyObjectMembershipCount());
        assertEquals(1, group.getStaticAnyObjectMembershipCount());

        ANY_OBJECT_SERVICE.delete(printer.getKey());
        GROUP_SERVICE.delete(group.getKey());
    }

    @Test
    public void capabilitiesOverride() {
        // resource with no capability override
        ResourceTO ldap = RESOURCE_SERVICE.read(RESOURCE_NAME_LDAP);
        assertNotNull(ldap);
        assertFalse(ldap.isOverrideCapabilities());
        assertTrue(ldap.getCapabilitiesOverride().isEmpty());

        // connector with all required for create and update
        ConnInstanceTO conn = CONNECTOR_SERVICE.read(ldap.getConnector(), null);
        assertNotNull(conn);
        assertTrue(conn.getCapabilities().contains(ConnectorCapability.CREATE));
        assertTrue(conn.getCapabilities().contains(ConnectorCapability.UPDATE));

        try {
            // 1. create succeeds
            GroupCR groupCR = getSample("syncope714");
            groupCR.getPlainAttrs().add(attr("title", "first"));
            groupCR.getResources().add(RESOURCE_NAME_LDAP);

            ProvisioningResult<GroupTO> result = createGroup(groupCR);
            assertNotNull(result);
            assertEquals(1, result.getPropagationStatuses().size());
            assertEquals(RESOURCE_NAME_LDAP, result.getPropagationStatuses().get(0).getResource());
            assertEquals(ExecStatus.SUCCESS, result.getPropagationStatuses().get(0).getStatus());
            GroupTO group = result.getEntity();

            // 2. update succeeds
            GroupUR groupUR = new GroupUR();
            groupUR.setKey(group.getKey());
            groupUR.getPlainAttrs().add(new AttrPatch.Builder(attr("title", "second")).
                    operation(PatchOperation.ADD_REPLACE).build());

            result = updateGroup(groupUR);
            assertNotNull(result);
            assertEquals(1, result.getPropagationStatuses().size());
            assertEquals(RESOURCE_NAME_LDAP, result.getPropagationStatuses().get(0).getResource());
            assertEquals(ExecStatus.SUCCESS, result.getPropagationStatuses().get(0).getStatus());
            group = result.getEntity();

            // 3. set capability override with only search allowed, but not enable
            ldap.getCapabilitiesOverride().add(ConnectorCapability.SEARCH);
            RESOURCE_SERVICE.update(ldap);
            ldap = RESOURCE_SERVICE.read(RESOURCE_NAME_LDAP);
            assertNotNull(ldap);
            assertFalse(ldap.isOverrideCapabilities());
            assertEquals(1, ldap.getCapabilitiesOverride().size());
            assertTrue(ldap.getCapabilitiesOverride().contains(ConnectorCapability.SEARCH));

            // 4. update succeeds again
            groupUR = new GroupUR();
            groupUR.setKey(group.getKey());
            groupUR.getPlainAttrs().add(new AttrPatch.Builder(attr("title", "third")).
                    operation(PatchOperation.ADD_REPLACE).build());

            result = updateGroup(groupUR);
            assertNotNull(result);
            assertEquals(1, result.getPropagationStatuses().size());
            assertEquals(RESOURCE_NAME_LDAP, result.getPropagationStatuses().get(0).getResource());
            assertEquals(ExecStatus.SUCCESS, result.getPropagationStatuses().get(0).getStatus());
            group = result.getEntity();

            // 5. enable capability override
            ldap.setOverrideCapabilities(true);
            RESOURCE_SERVICE.update(ldap);
            ldap = RESOURCE_SERVICE.read(RESOURCE_NAME_LDAP);
            assertNotNull(ldap);
            assertTrue(ldap.isOverrideCapabilities());
            assertEquals(1, ldap.getCapabilitiesOverride().size());
            assertTrue(ldap.getCapabilitiesOverride().contains(ConnectorCapability.SEARCH));

            // 6. update now fails
            groupUR = new GroupUR();
            groupUR.setKey(group.getKey());
            groupUR.getPlainAttrs().add(new AttrPatch.Builder(attr("title", "fourth")).
                    operation(PatchOperation.ADD_REPLACE).build());

            result = updateGroup(groupUR);
            assertNotNull(result);
            assertEquals(1, result.getPropagationStatuses().size());
            assertEquals(RESOURCE_NAME_LDAP, result.getPropagationStatuses().get(0).getResource());
            assertEquals(ExecStatus.NOT_ATTEMPTED, result.getPropagationStatuses().get(0).getStatus());
        } finally {
            ldap.getCapabilitiesOverride().clear();
            ldap.setOverrideCapabilities(false);
            RESOURCE_SERVICE.update(ldap);
        }
    }

    @Test
    public void typeExtensions() {
        TypeExtensionTO typeExtension = new TypeExtensionTO();
        typeExtension.setAnyType(AnyTypeKind.USER.name());
        typeExtension.getAuxClasses().add("csv");

        GroupCR groupCR = getBasicSample("typeExtensions");
        groupCR.getTypeExtensions().add(typeExtension);

        GroupTO groupTO = createGroup(groupCR).getEntity();
        assertNotNull(groupTO);
        assertEquals(1, groupTO.getTypeExtensions().size());
        assertEquals(1, groupTO.getTypeExtension(AnyTypeKind.USER.name()).get().getAuxClasses().size());
        assertTrue(groupTO.getTypeExtension(AnyTypeKind.USER.name()).get().getAuxClasses().contains("csv"));

        typeExtension = new TypeExtensionTO();
        typeExtension.setAnyType(AnyTypeKind.USER.name());
        typeExtension.getAuxClasses().add("csv");
        typeExtension.getAuxClasses().add("other");

        GroupUR groupUR = new GroupUR();
        groupUR.setKey(groupTO.getKey());
        groupUR.getTypeExtensions().add(typeExtension);

        groupTO = updateGroup(groupUR).getEntity();
        assertNotNull(groupTO);
        assertEquals(1, groupTO.getTypeExtensions().size());
        assertEquals(2, groupTO.getTypeExtension(AnyTypeKind.USER.name()).get().getAuxClasses().size());
        assertTrue(groupTO.getTypeExtension(AnyTypeKind.USER.name()).get().getAuxClasses().contains("csv"));
        assertTrue(groupTO.getTypeExtension(AnyTypeKind.USER.name()).get().getAuxClasses().contains("other"));
    }

    @Test
    public void provisionMembers() throws InterruptedException {
        assumeFalse(ElasticsearchDetector.isElasticSearchEnabled(ADMIN_CLIENT.platform()));

        // 1. create group without resources
        GroupCR groupCR = getBasicSample("forProvision");
        GroupTO groupTO = createGroup(groupCR).getEntity();

        // 2. create user with such group assigned
        UserCR userCR = UserITCase.getUniqueSample("forProvision@syncope.apache.org");
        userCR.getMemberships().add(new MembershipTO.Builder(groupTO.getKey()).build());
        UserTO userTO = createUser(userCR).getEntity();

        // 3. modify the group by assiging the LDAP resource
        GroupUR groupUR = new GroupUR();
        groupUR.setKey(groupTO.getKey());
        groupUR.getResources().add(new StringPatchItem.Builder().value(RESOURCE_NAME_LDAP).build());
        ProvisioningResult<GroupTO> groupUpdateResult = updateGroup(groupUR);
        groupTO = groupUpdateResult.getEntity();

        PropagationStatus propStatus = groupUpdateResult.getPropagationStatuses().get(0);
        assertEquals(RESOURCE_NAME_LDAP, propStatus.getResource());
        assertEquals(ExecStatus.SUCCESS, propStatus.getStatus());

        // 4. verify that the user above is not found on LDAP
        try {
            RESOURCE_SERVICE.readConnObject(RESOURCE_NAME_LDAP, AnyTypeKind.USER.name(), userTO.getKey());
            fail("This should not happen");
        } catch (SyncopeClientException e) {
            assertEquals(ClientExceptionType.NotFound, e.getType());
        }

        try {
            // 5. provision group members
            ExecTO exec = GROUP_SERVICE.provisionMembers(groupTO.getKey(), ProvisionAction.PROVISION);
            assertNotNull(exec.getRefKey());

            AtomicReference<List<ExecTO>> execs = new AtomicReference<>();
            await().atMost(MAX_WAIT_SECONDS, TimeUnit.SECONDS).pollInterval(1, TimeUnit.SECONDS).until(() -> {
                try {
                    execs.set(TASK_SERVICE.read(TaskType.SCHEDULED, exec.getRefKey(), true).getExecutions());
                    return !execs.get().isEmpty();
                } catch (Exception e) {
                    return false;
                }
            });
            assertEquals(TaskJob.Status.SUCCESS.name(), execs.get().get(0).getStatus());

            // 6. verify that the user above is now fond on LDAP
            ConnObjectTO userOnLdap =
                    RESOURCE_SERVICE.readConnObject(RESOURCE_NAME_LDAP, AnyTypeKind.USER.name(), userTO.getKey());
            assertNotNull(userOnLdap);
        } finally {
            GROUP_SERVICE.delete(groupTO.getKey());
            USER_SERVICE.delete(userTO.getKey());
        }
    }

    @Test
    public void issue178() {
        GroupCR groupCR = new GroupCR();
        String groupName = "torename" + getUUIDString();
        groupCR.setName(groupName);
        groupCR.setRealm("/");

        GroupTO actual = createGroup(groupCR).getEntity();

        assertNotNull(actual);
        assertEquals(groupName, actual.getName());

        GroupUR groupUR = new GroupUR();
        groupUR.setKey(actual.getKey());
        String renamedGroup = "renamed" + getUUIDString();
        groupUR.setName(new StringReplacePatchItem.Builder().value(renamedGroup).build());

        actual = updateGroup(groupUR).getEntity();
        assertNotNull(actual);
        assertEquals(renamedGroup, actual.getName());
    }

    @Test
    public void issueSYNCOPE632() {
        DerSchemaTO orig = SCHEMA_SERVICE.read(SchemaType.DERIVED, "displayProperty");
        DerSchemaTO modified = SerializationUtils.clone(orig);
        modified.setExpression("icon + '_' + show");

        GroupCR groupCR = GroupITCase.getSample("lastGroup");
        GroupTO groupTO = null;
        try {
            SCHEMA_SERVICE.update(SchemaType.DERIVED, modified);

            // 0. create group
            groupCR.getPlainAttrs().add(attr("icon", "anIcon"));
            groupCR.getPlainAttrs().add(attr("show", "true"));
            groupCR.getResources().clear();

            groupTO = createGroup(groupCR).getEntity();
            assertNotNull(groupTO);

            // 1. create new LDAP resource having ConnObjectKey mapped to a derived attribute
            ResourceTO newLDAP = RESOURCE_SERVICE.read(RESOURCE_NAME_LDAP);
            newLDAP.setKey("new-ldap");
            newLDAP.setPropagationPriority(0);

            for (ProvisionTO provision : newLDAP.getProvisions()) {
                provision.getVirSchemas().clear();
            }

            MappingTO mapping = newLDAP.getProvision(AnyTypeKind.GROUP.name()).get().getMapping();

            ItemTO connObjectKey = mapping.getConnObjectKeyItem();
            connObjectKey.setIntAttrName("displayProperty");
            connObjectKey.setPurpose(MappingPurpose.PROPAGATION);
            mapping.setConnObjectKeyItem(connObjectKey);
            mapping.setConnObjectLink("'cn=' + displayProperty + ',ou=groups,o=isp'");

            ItemTO description = new ItemTO();
            description.setIntAttrName("key");
            description.setExtAttrName("description");
            description.setPurpose(MappingPurpose.PROPAGATION);
            mapping.add(description);

            newLDAP = createResource(newLDAP);
            assertNotNull(newLDAP);

            // 2. update group and give the resource created above
            GroupUR groupUR = new GroupUR();
            groupUR.setKey(groupTO.getKey());
            groupUR.getResources().add(new StringPatchItem.Builder().
                    operation(PatchOperation.ADD_REPLACE).
                    value("new-ldap").build());

            groupTO = updateGroup(groupUR).getEntity();
            assertNotNull(groupTO);

            // 3. update the group
            groupUR = new GroupUR();
            groupUR.setKey(groupTO.getKey());
            groupUR.getPlainAttrs().add(attrAddReplacePatch("icon", "anotherIcon"));

            groupTO = updateGroup(groupUR).getEntity();
            assertNotNull(groupTO);

            // 4. check that a single group exists in LDAP for the group created and updated above
            int entries = 0;
            DirContext ctx = null;
            try {
                ctx = getLdapResourceDirContext(null, null);

                SearchControls ctls = new SearchControls();
                ctls.setReturningAttributes(new String[] { "*", "+" });
                ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);

                NamingEnumeration<SearchResult> result =
                        ctx.search("ou=groups,o=isp", "(description=" + groupTO.getKey() + ')', ctls);
                while (result.hasMore()) {
                    result.next();
                    entries++;
                }
            } catch (Exception e) {
                // ignore
            } finally {
                if (ctx != null) {
                    try {
                        ctx.close();
                    } catch (NamingException e) {
                        // ignore
                    }
                }
            }

            assertEquals(1, entries);
        } finally {
            SCHEMA_SERVICE.update(SchemaType.DERIVED, orig);
            if (groupTO != null) {
                GROUP_SERVICE.delete(groupTO.getKey());
            }
            RESOURCE_SERVICE.delete("new-ldap");
        }
    }

    @Test
    public void issueSYNCOPE717() {
        String doubleSchemaName = "double" + getUUIDString();

        // 1. create double schema without conversion pattern
        PlainSchemaTO schema = new PlainSchemaTO();
        schema.setKey(doubleSchemaName);
        schema.setType(AttrSchemaType.Double);

        schema = createSchema(SchemaType.PLAIN, schema);
        assertNotNull(schema);
        assertNull(schema.getConversionPattern());

        AnyTypeClassTO minimalGroup = ANY_TYPE_CLASS_SERVICE.read("minimal group");
        assertNotNull(minimalGroup);
        minimalGroup.getPlainSchemas().add(doubleSchemaName);
        ANY_TYPE_CLASS_SERVICE.update(minimalGroup);

        // 2. create group, provide valid input value
        GroupCR groupCR = GroupITCase.getBasicSample("syncope717");
        groupCR.getPlainAttrs().add(attr(doubleSchemaName, "11.23"));

        GroupTO groupTO = createGroup(groupCR).getEntity();
        assertNotNull(groupTO);
        assertEquals("11.23", groupTO.getPlainAttr(doubleSchemaName).get().getValues().get(0));

        // 3. update schema, set conversion pattern
        schema = SCHEMA_SERVICE.read(SchemaType.PLAIN, schema.getKey());
        schema.setConversionPattern("0.000");
        SCHEMA_SERVICE.update(SchemaType.PLAIN, schema);

        // 4. re-read group, verify that pattern was applied
        groupTO = GROUP_SERVICE.read(groupTO.getKey());
        assertNotNull(groupTO);
        assertEquals("11.230", groupTO.getPlainAttr(doubleSchemaName).get().getValues().get(0));

        // 5. modify group with new double value
        GroupUR groupUR = new GroupUR();
        groupUR.setKey(groupTO.getKey());
        groupUR.getPlainAttrs().add(new AttrPatch.Builder(attr(doubleSchemaName, "11.257")).build());

        groupTO = updateGroup(groupUR).getEntity();
        assertNotNull(groupTO);
        assertEquals("11.257", groupTO.getPlainAttr(doubleSchemaName).get().getValues().get(0));

        // 6. update schema, unset conversion pattern
        schema.setConversionPattern(null);
        SCHEMA_SERVICE.update(SchemaType.PLAIN, schema);

        // 7. modify group with new double value, verify that no pattern is applied
        groupUR = new GroupUR();
        groupUR.setKey(groupTO.getKey());
        groupUR.getPlainAttrs().add(new AttrPatch.Builder(attr(doubleSchemaName, "11.23")).build());

        groupTO = updateGroup(groupUR).getEntity();
        assertNotNull(groupTO);
        assertEquals("11.23", groupTO.getPlainAttr(doubleSchemaName).get().getValues().get(0));
    }

    @Test
    public void issueSYNCOPE1467() {
        GroupTO groupTO = null;
        try {
            GroupCR groupCR = new GroupCR();
            groupCR.setRealm(SyncopeConstants.ROOT_REALM);
            groupCR.setName("issueSYNCOPE1467");
            groupCR.getResources().add(RESOURCE_NAME_LDAP);

            groupTO = createGroup(groupCR).getEntity();
            assertNotNull(groupTO);
            assertTrue(groupTO.getResources().contains(RESOURCE_NAME_LDAP));

            ConnObjectTO connObjectTO =
                    RESOURCE_SERVICE.readConnObject(RESOURCE_NAME_LDAP, AnyTypeKind.GROUP.name(), groupTO.getKey());
            assertNotNull(connObjectTO);
            assertEquals("issueSYNCOPE1467", connObjectTO.getAttr("cn").get().getValues().get(0));

            GroupUR groupUR = new GroupUR();
            groupUR.setKey(groupTO.getKey());
            groupUR.setName(new StringReplacePatchItem.Builder().value("fixedSYNCOPE1467").build());

            assertNotNull(updateGroup(groupUR).getEntity());

            // Assert resources are present
            ResourceTO ldap = RESOURCE_SERVICE.read(RESOURCE_NAME_LDAP);
            assertNotNull(ldap);

            connObjectTO = RESOURCE_SERVICE.
                    readConnObject(RESOURCE_NAME_LDAP, AnyTypeKind.GROUP.name(), groupTO.getKey());
            assertNotNull(connObjectTO);
            assertEquals("fixedSYNCOPE1467", connObjectTO.getAttr("cn").get().getValues().get(0));
        } finally {
            if (groupTO.getKey() != null) {
                GROUP_SERVICE.delete(groupTO.getKey());
            }
        }
    }

    @Test
    public void issueSYNCOPE1472() {
        // 1. update group artDirector by assigning twice resource-testdb and auxiliary class csv
        GroupUR groupUR = new GroupUR();
        groupUR.setKey("ece66293-8f31-4a84-8e8d-23da36e70846");
        groupUR.getResources().add(new StringPatchItem.Builder()
                .value(RESOURCE_NAME_TESTDB)
                .operation(PatchOperation.ADD_REPLACE)
                .build());
        groupUR.getAuxClasses().add(new StringPatchItem.Builder()
                .operation(PatchOperation.ADD_REPLACE)
                .value("csv")
                .build());
        for (int i = 0; i < 2; i++) {
            updateGroup(groupUR);
        }

        // 2. remove resources and auxiliary classes
        groupUR.getResources().clear();
        groupUR.getResources().add(new StringPatchItem.Builder()
                .value(RESOURCE_NAME_TESTDB)
                .operation(PatchOperation.DELETE)
                .build());
        groupUR.getAuxClasses().clear();
        groupUR.getAuxClasses().add(new StringPatchItem.Builder()
                .value("csv")
                .operation(PatchOperation.DELETE)
                .build());

        updateGroup(groupUR);

        GroupTO groupTO = GROUP_SERVICE.read("ece66293-8f31-4a84-8e8d-23da36e70846");
        assertFalse(groupTO.getResources().contains(RESOURCE_NAME_TESTDB), "Should not contain removed resources");
        assertFalse(groupTO.getAuxClasses().contains("csv"), "Should not contain removed auxiliary classes");
    }
}
