diff --git a/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/store/HybridTemplateManager.java b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/store/HybridTemplateManager.java index 513bb5a5..850f49bc 100644 --- a/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/store/HybridTemplateManager.java +++ b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/store/HybridTemplateManager.java @@ -18,16 +18,31 @@ package org.wso2.carbon.email.mgt.store; +import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.email.mgt.internal.I18nMgtDataHolder; +import org.wso2.carbon.identity.application.common.IdentityApplicationManagementException; +import org.wso2.carbon.identity.application.mgt.ApplicationManagementService; +import org.wso2.carbon.identity.core.ThreadLocalAwareExecutors; import org.wso2.carbon.identity.governance.exceptions.notiification.NotificationTemplateManagerServerException; import org.wso2.carbon.identity.governance.model.NotificationTemplate; +import org.wso2.carbon.identity.organization.management.service.OrganizationManager; +import org.wso2.carbon.identity.organization.management.service.exception.OrganizationManagementException; +import org.wso2.carbon.identity.organization.management.service.model.BasicOrganization; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.Base64; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutorService; +import java.util.stream.Collectors; /** * This class is responsible for on-demand migrating notification templates from the registry to the database. @@ -38,6 +53,7 @@ public class HybridTemplateManager implements TemplatePersistenceManager { private static final Log log = LogFactory.getLog(HybridTemplateManager.class); + private final ExecutorService executorService = ThreadLocalAwareExecutors.newFixedThreadPool(1); private TemplatePersistenceManager dbBasedTemplateManager = new DBBasedTemplateManager(); private TemplatePersistenceManager registryBasedTemplateManager = new RegistryBasedTemplateManager(); @@ -137,6 +153,8 @@ public void addOrUpdateNotificationTemplate(NotificationTemplate notificationTem if (registryBasedTemplateManager.isNotificationTemplateExists(displayName, locale, notificationChannel, applicationUuid, tenantDomain)) { + NotificationTemplate registryBasedTemplate = registryBasedTemplateManager.getNotificationTemplate(displayName, + locale, notificationChannel, applicationUuid, tenantDomain); // registryBasedTemplateManager.deleteNotificationTemplate(displayName, locale, notificationChannel, // applicationUuid, tenantDomain); @@ -148,6 +166,12 @@ public void addOrUpdateNotificationTemplate(NotificationTemplate notificationTem "Moved %s template: %s for locale: %s in tenant: %s from registry to the database.", notificationChannel, displayName, locale, tenantDomain)); } + + String usernameInContext = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername(); + CompletableFuture.runAsync( + () -> migrateChildOrgTemplates(registryBasedTemplate, tenantDomain, applicationUuid, + usernameInContext), + executorService); } } @@ -277,4 +301,89 @@ private List mergeAndRemoveDuplicates(List list1, List list2) { uniqueElements.addAll(list2); return new ArrayList<>(uniqueElements); } + + private void migrateChildOrgTemplates(NotificationTemplate parentTemplate, String parentTenantDomain, + String parentAppId, String usernameInContext) { + + String cursor = null; + int pageSize = 100; + try { + String displayName = parentTemplate.getDisplayName(); + String locale = parentTemplate.getLocale(); + String notificationChannel = parentTemplate.getNotificationChannel(); + + PrivilegedCarbonContext.startTenantFlow(); + PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(parentTenantDomain, true); + PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(usernameInContext); + + OrganizationManager organizationManager = I18nMgtDataHolder.getInstance().getOrganizationManager(); + ApplicationManagementService applicationManagementService = + I18nMgtDataHolder.getInstance().getApplicationManagementService(); + do { + try { + List childOrganizations = + organizationManager.getOrganizations(pageSize, cursor, null, "DESC", "", false); + Map childAppIds = new HashMap<>(); + if (StringUtils.isNotBlank(parentAppId)) { + childAppIds = applicationManagementService.getChildAppIds(parentAppId, parentTenantDomain, + childOrganizations.stream().map(BasicOrganization::getId).collect(Collectors.toList())); + if (childAppIds.isEmpty()) { + continue; + } + } + for (BasicOrganization childOrganization : childOrganizations) { + String childTenantDomain = organizationManager.resolveTenantDomain(childOrganization.getId()); + String childAppId = childAppIds.get(childTenantDomain); + + if (StringUtils.isNotBlank(parentAppId) && StringUtils.isBlank(childAppId)) { + continue; + } + + NotificationTemplate childNotificationTemplate = + registryBasedTemplateManager.getNotificationTemplate( + displayName, locale, notificationChannel, childAppId, childTenantDomain); + if (childNotificationTemplate != null) { + if (!areNotificationTemplatesEqual(parentTemplate, childNotificationTemplate) && + !dbBasedTemplateManager.isNotificationTemplateExists(displayName, locale, + notificationChannel, childAppId, childTenantDomain)) { + dbBasedTemplateManager.addOrUpdateNotificationTemplate(childNotificationTemplate, + childAppId, childTenantDomain); + } + + registryBasedTemplateManager.deleteNotificationTemplates(displayName, notificationChannel, + childAppId, childTenantDomain); + migrateChildOrgTemplates(childNotificationTemplate, childTenantDomain, childAppId, + usernameInContext); + } + } + cursor = childOrganizations.isEmpty() ? null : Base64.getEncoder().encodeToString( + childOrganizations.get(childOrganizations.size() - 1).getCreated() + .getBytes(StandardCharsets.UTF_8)); + } catch (OrganizationManagementException e) { + log.error("Error occurred while retrieving child organizations of organization " + + "with tenant domain: " + parentTenantDomain, e); + } catch (IdentityApplicationManagementException e){ + log.error("Error occurred while retrieving child app ids of application with id: " + + parentAppId + " and tenant domain: " + parentTenantDomain, e); + } catch (NotificationTemplateManagerServerException e) { + log.error("Error occurred while migrating child organization templates of parent template: " + + displayName + " for locale: " + locale + " and notification channel: " + + notificationChannel, e); + } + } while (cursor != null); + } finally { + PrivilegedCarbonContext.endTenantFlow(); + } + } + + private boolean areNotificationTemplatesEqual(NotificationTemplate template1, NotificationTemplate template2) { + + return StringUtils.equals(template1.getDisplayName(), template2.getDisplayName()) && + StringUtils.equals(template1.getLocale(), template2.getLocale()) && + StringUtils.equals(template1.getNotificationChannel(), template2.getNotificationChannel()) && + StringUtils.equals(template1.getContentType(), template2.getContentType()) && + StringUtils.equals(template1.getBody(), template2.getBody()) && + StringUtils.equals(template1.getSubject(), template2.getSubject()) && + StringUtils.equals(template1.getFooter(), template2.getFooter()); + } } diff --git a/pom.xml b/pom.xml index 62f7a871..9ea73dc8 100644 --- a/pom.xml +++ b/pom.xml @@ -522,7 +522,7 @@ [2.1.0,3.0.0) - 7.1.0 + 7.7.2 [7.1.0, 8.0.0)