diff --git a/src/main/java/org/ligoj/app/plugin/id/ldap/dao/ProjectCustomerLdapRepository.java b/src/main/java/org/ligoj/app/plugin/id/ldap/dao/ProjectCustomerLdapRepository.java index d871e02..ab0cb0e 100644 --- a/src/main/java/org/ligoj/app/plugin/id/ldap/dao/ProjectCustomerLdapRepository.java +++ b/src/main/java/org/ligoj/app/plugin/id/ldap/dao/ProjectCustomerLdapRepository.java @@ -3,14 +3,7 @@ */ package org.ligoj.app.plugin.id.ldap.dao; -import java.util.Set; -import java.util.stream.Collectors; - -import javax.cache.annotation.CacheKey; -import javax.cache.annotation.CachePut; -import javax.cache.annotation.CacheResult; -import javax.cache.annotation.CacheValue; - +import lombok.extern.slf4j.Slf4j; import org.ligoj.app.iam.IamProvider; import org.ligoj.app.plugin.id.DnUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -21,7 +14,9 @@ import org.springframework.ldap.filter.EqualsFilter; import org.springframework.stereotype.Component; -import lombok.extern.slf4j.Slf4j; +import javax.cache.annotation.*; +import java.util.Set; +import java.util.stream.Collectors; import static org.ligoj.app.plugin.id.ldap.dao.AbstractManagedLdapRepository.OBJECT_CLASS; @@ -72,7 +67,7 @@ public String findById(@CacheKey final String baseDn, @CacheKey final String id) } /** - * Create a new group. There is no synchronized block, so error could occur; this is assumed for performance + * Create a new organizational unit. There is no synchronized block, so error could occur; this is assumed for performance * purpose. * * @param baseDn Base DN. @@ -92,6 +87,23 @@ public void create(@CacheKey final String baseDn, @CacheKey final String ou, @Ca getUser().getTemplate().bind(context); } + /** + * Delete the given organizational unit. + * + * @param baseDn Base DN. + * @param ou The formatted OU. + * @param dn The DN of new customer. Must ends with the OU. + */ + @CacheRemove(cacheName = "customers-by-id") + public void delete(@CacheKey final String baseDn, @CacheKey final String ou, final String dn) { + // Invalidate the customers set + cacheManager.getCache("customers").evict(baseDn); + + // First create the LDAP entry + log.info("Customer (OU) {} will be delete from {}", ou, dn); + getUser().getTemplate().unbind(dn); + } + /** * Map a customer to LDAP. * diff --git a/src/main/java/org/ligoj/app/plugin/id/ldap/resource/LdapPluginResource.java b/src/main/java/org/ligoj/app/plugin/id/ldap/resource/LdapPluginResource.java index 8bebdfc..d20bdd3 100644 --- a/src/main/java/org/ligoj/app/plugin/id/ldap/resource/LdapPluginResource.java +++ b/src/main/java/org/ligoj/app/plugin/id/ldap/resource/LdapPluginResource.java @@ -435,6 +435,17 @@ private String validateAndCreateParent(final String group, final String parentGr return validateParentGroup(group, parentGroup); } + /** + * Return the normalized OU DN. + */ + private String getParentOu(final String ou) { + final var groupTypeLdap = containerScopeResource.findByName(ContainerType.GROUP, ContainerScope.TYPE_PROJECT); + final var parentDn = groupTypeLdap.getDn(); + + // Build the complete normalized DN from the OU and new Group + return "ou=" + ou + "," + parentDn; + } + /** * Validate the group against its direct parent (a normalized OU) and return its DN. */ @@ -443,7 +454,7 @@ private String validateAndCreateParentOu(final String group, final String ou, fi final var parentDn = groupTypeLdap.getDn(); // Build the complete normalized DN from the OU and new Group - final var ouDn = "ou=" + ou + "," + parentDn; + final var ouDn = getParentOu(ou); // Check the target OU exists or not and create the OU as needed if (projectCustomerLdapRepository.findById(parentDn, ou) == null) { @@ -738,7 +749,8 @@ public Collection> findCustomersByName(@PathParam("criteria @Override public void delete(final int subscription, final boolean deleteRemoteData) { - final var projectId = subscriptionRepository.findOne(subscription).getProject().getId(); + final var project = subscriptionRepository.findOne(subscription).getProject(); + final var projectId = project.getId(); final var parameters = subscriptionResource.getParameters(subscription); final var group = parameters.get(IdentityResource.PARAMETER_GROUP); cacheProjectGroupRepository.deleteAllBy("group.id", group, new String[]{"project.id"}, projectId); @@ -751,6 +763,19 @@ public void delete(final int subscription, final boolean deleteRemoteData) { // Perform the deletion repository.delete(groupLdap); } + + // Also try to delete the parent OU. Ignore the failures. + final var ou = parameters.get(IdentityResource.PARAMETER_OU); + if (ou != null) { + final var groupTypeLdap = containerScopeResource.findByName(ContainerType.GROUP, ContainerScope.TYPE_PROJECT); + try { + projectCustomerLdapRepository.delete(groupTypeLdap.getDn(), ou, getParentOu(ou)); + log.info("OU {} has been cleaned, after deleting group {}, project {} and subscription {}", ou, group, project.getPkey(), subscription); + } catch (Exception e) { + // Ignore this failure, this OU might not be empty + log.info("OU {} could not be deleted while deleting group {}, project {} and subscription {}", ou, group, project.getPkey(), subscription); + } + } } } diff --git a/src/test/java/org/ligoj/app/plugin/id/ldap/resource/LdapPluginResourceTest.java b/src/test/java/org/ligoj/app/plugin/id/ldap/resource/LdapPluginResourceTest.java index ad12575..576a7dc 100644 --- a/src/test/java/org/ligoj/app/plugin/id/ldap/resource/LdapPluginResourceTest.java +++ b/src/test/java/org/ligoj/app/plugin/id/ldap/resource/LdapPluginResourceTest.java @@ -301,7 +301,22 @@ void createOuNotExists() { Assertions.assertNotNull(projectCustomerLdapRepository.findById("ou=project,dc=sample,dc=com", "some")); Assertions.assertTrue(projectCustomerLdapRepository.findAll("ou=project,dc=sample,dc=com").contains("some")); + // Attach the new group + final var subscription3 = new Subscription(); + subscription3.setProject(subscription2.getProject()); + subscription3.setNode(subscription.getNode()); + em.persist(subscription3); + + // Add parameters + setGroup(subscription3, "some-new-project-sub"); + setOu(subscription3, "some"); + basicCreate(subscription3); + + // Delete the group, and also try to delete the parent OU. This last step fail silently resource.delete(subscription2.getId(), true); + + // Delete the group, and also delete sucessfully the parent + resource.delete(subscription3.getId(), true); } @Test