From 24ad216453ac5b44c0542d9d6fc6dbdcf000d902 Mon Sep 17 00:00:00 2001 From: dhaura Date: Thu, 5 Dec 2024 10:55:39 +0530 Subject: [PATCH 1/7] Introduce B2B notification template inheritance. --- .../org.wso2.carbon.email.mgt/pom.xml | 11 + .../email/mgt/EmailTemplateManager.java | 54 ++++ .../email/mgt/EmailTemplateManagerImpl.java | 126 +++----- .../mgt/NotificationTemplateManagerImpl.java | 118 ++++--- .../email/mgt/internal/I18nMgtDataHolder.java | 22 ++ .../mgt/internal/I18nMgtServiceComponent.java | 17 + .../mgt/store/UnifiedTemplateManager.java | 302 ++++++++++++++++-- pom.xml | 15 +- 8 files changed, 498 insertions(+), 167 deletions(-) diff --git a/components/email-mgt/org.wso2.carbon.email.mgt/pom.xml b/components/email-mgt/org.wso2.carbon.email.mgt/pom.xml index b07ce1a4..11dcb7f6 100644 --- a/components/email-mgt/org.wso2.carbon.email.mgt/pom.xml +++ b/components/email-mgt/org.wso2.carbon.email.mgt/pom.xml @@ -92,6 +92,10 @@ org.wso2.carbon.utils org.wso2.carbon.database.utils + + org.wso2.carbon.identity.organization.management + org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service + com.google.code.gson gson @@ -147,6 +151,7 @@ org.apache.axiom.*; version="${axiom.wso2.imp.pkg.version.range}", org.apache.commons.logging; version="${commons.logging.imp.pkg.version.range}", org.apache.commons.lang.*; version="${commons-lang.version.range}", + org.apache.commons.collections; version="${commons-collections.wso2.version.range}", org.osgi.framework; version="${osgi.framework.imp.pkg.version.range}", org.osgi.service.component; version="${osgi.service.component.imp.pkg.version.range}", @@ -174,6 +179,12 @@ version="${org.wso2.identity.organization.mgt.core.imp.pkg.version.range}", org.wso2.carbon.identity.organization.management.service.exception; version="${org.wso2.identity.organization.mgt.core.imp.pkg.version.range}", + org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service; + version="${org.wso2.identity.organization.mgt.imp.pkg.version.range}", + org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.exception; + version="${org.wso2.identity.organization.mgt.imp.pkg.version.range}", + org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.strategy; + version="${org.wso2.identity.organization.mgt.imp.pkg.version.range}", diff --git a/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/EmailTemplateManager.java b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/EmailTemplateManager.java index 3b971230..0c467a00 100644 --- a/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/EmailTemplateManager.java +++ b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/EmailTemplateManager.java @@ -143,6 +143,33 @@ default List getEmailTemplateType( throw new I18nEmailMgtException("Method not implemented"); } + /** + * Retrieves all email templates of a specific type for a given tenant and application UUID. + *

+ * This method validates and fetches email templates based on the specified type. The behavior of the method + * depends on the {@code resolve} parameter: + *

    + *
  • Resolved Template (resolve = true): Retrieves the templates resolved through the ancestor + * organization hierarchy.
  • + *
  • Current org's or app's template (resolve = false): Retrieves the templates specific to the + * current organization or application.
  • + *
+ * + * @param templateDisplayName the display name of the email template type (e.g., "Welcome Email"). + * @param tenantDomain the tenant domain of the organization to retrieve the template from. + * @param applicationUuid the UUID of the application associated with the template. + * @param resolve a flag indicating whether to retrieve resolved template ({@code true}) or template + * specific to the current organization or application ({@code false}). + * @return a list of {@link EmailTemplate} objects matching the specified type and criteria. + * @throws I18nEmailMgtException if any unexpected error occurs while retrieving email templates. + */ + default List getEmailTemplateType(String templateDisplayName, String tenantDomain, + String applicationUuid, boolean resolve) + throws I18nEmailMgtException { + + throw new I18nEmailMgtException("getEmailTemplateType method not implemented in " + this.getClass().getName()); + } + /** * Get all available email templates in a tenant's registry. * @@ -234,6 +261,33 @@ EmailTemplate getEmailTemplate(String templateType, String tenantDomain, String applicationUuid) throws I18nEmailMgtException; + /** + * Retrieves an email template for a specified type, locale, tenant domain, and application UUID. + *

+ * This method resolves and retrieves an email template based on the provided parameters. The behavior is + * dependent on the {@code resolve} parameter: + *

    + *
  • Resolved template (resolve = true): Retrieves the template resolved through the ancestor + * organization hierarchy.
  • + *
  • Current org's or app's template (resolve = false): Retrieves the template specific to the + * current organization or application only.
  • + *
+ * + * @param templateType the type of the email template. + * @param locale the locale of the email template (e.g., "en_US"). + * @param tenantDomain the tenant domain of the organization to retrieve the template from. + * @param applicationUuid the UUID of the application associated with the template. + * @param resolve a flag indicating whether to retrieve resolved template ({@code true}) or template + * specific to the current organization or application ({@code false}). + * @return the {@link EmailTemplate} matching the specified criteria. + * @throws I18nEmailMgtException if any unexpected error occurs while retrieving email template. + */ + default EmailTemplate getEmailTemplate(String templateType, String locale, String tenantDomain, + String applicationUuid, boolean resolve) throws I18nEmailMgtException { + + throw new I18nEmailMgtException("getEmailTemplate method not implemented in " + this.getClass().getName()); + } + /** * Check whether the given email template type exists for the application. * diff --git a/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/EmailTemplateManagerImpl.java b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/EmailTemplateManagerImpl.java index 9e59caf1..c3227562 100644 --- a/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/EmailTemplateManagerImpl.java +++ b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/EmailTemplateManagerImpl.java @@ -32,7 +32,6 @@ import org.wso2.carbon.email.mgt.internal.I18nMgtDataHolder; import org.wso2.carbon.email.mgt.model.EmailTemplate; import org.wso2.carbon.email.mgt.util.I18nEmailUtil; -import org.wso2.carbon.identity.application.common.IdentityApplicationManagementServerException; import org.wso2.carbon.identity.base.IdentityValidationUtil; import org.wso2.carbon.identity.governance.IdentityGovernanceUtil; import org.wso2.carbon.identity.governance.IdentityMgtConstants; @@ -43,9 +42,6 @@ import org.wso2.carbon.identity.governance.model.NotificationTemplate; import org.wso2.carbon.identity.governance.service.notification.NotificationChannels; import org.wso2.carbon.identity.governance.service.notification.NotificationTemplateManager; -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.util.OrganizationManagementUtil; import java.util.ArrayList; import java.util.List; @@ -59,7 +55,6 @@ import static org.wso2.carbon.email.mgt.util.I18nEmailUtil.buildNotificationTemplateFromEmailTemplate; import static org.wso2.carbon.email.mgt.util.I18nEmailUtil.normalizeLocaleFormat; import static org.wso2.carbon.identity.base.IdentityValidationUtil.ValidatorPattern.REGISTRY_INVALID_CHARS_EXISTS; -import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.ErrorMessages.ERROR_CODE_ERROR_RESOLVING_MAIN_APPLICATION; /** * Provides functionality to manage email templates used in notification emails. @@ -67,6 +62,7 @@ public class EmailTemplateManagerImpl implements EmailTemplateManager, NotificationTemplateManager { private TemplatePersistenceManager templatePersistenceManager; + private TemplatePersistenceManager userDefinedTemplatePersistenceManager; private static final Log log = LogFactory.getLog(EmailTemplateManagerImpl.class); @@ -82,6 +78,8 @@ public EmailTemplateManagerImpl() { TemplatePersistenceManagerFactory templatePersistenceManagerFactory = new TemplatePersistenceManagerFactory(); this.templatePersistenceManager = templatePersistenceManagerFactory.getTemplatePersistenceManager(); + this.userDefinedTemplatePersistenceManager = + templatePersistenceManagerFactory.getUserDefinedTemplatePersistenceManager(); } @Override @@ -169,17 +167,11 @@ public void deleteEmailTemplateType(String emailTemplateDisplayName, String tena public List getAvailableTemplateTypes(String tenantDomain) throws I18nEmailMgtServerException { try { - if (OrganizationManagementUtil.isOrganization(tenantDomain)) { - // Return the root organization's email template types. - tenantDomain = getRootOrgTenantDomain(tenantDomain); - } return templatePersistenceManager.listNotificationTemplateTypes( NotificationChannels.EMAIL_CHANNEL.getChannelType(), tenantDomain); } catch (NotificationTemplateManagerServerException ex) { String errorMsg = String.format("Error when retrieving email template types of %s tenant.", tenantDomain); throw new I18nEmailMgtServerException(errorMsg, ex); - } catch (OrganizationManagementException e) { - throw new I18nEmailMgtServerException(e.getMessage(), e); } } @@ -187,18 +179,12 @@ public List getAvailableTemplateTypes(String tenantDomain) throws I18nEm public List getAllEmailTemplates(String tenantDomain) throws I18nEmailMgtException { try { - if (OrganizationManagementUtil.isOrganization(tenantDomain)) { - // Return the root organization's email templates. - tenantDomain = getRootOrgTenantDomain(tenantDomain); - } List notificationTemplates = templatePersistenceManager.listAllNotificationTemplates( NotificationChannels.EMAIL_CHANNEL.getChannelType(), tenantDomain); return getEmailTemplateList(notificationTemplates); } catch (NotificationTemplateManagerServerException e) { String error = String.format("Error when retrieving email templates of %s tenant.", tenantDomain); throw new I18nEmailMgtServerException(error, e); - } catch (OrganizationManagementException e) { - throw new I18nEmailMgtServerException(e.getMessage(), e); } } @@ -206,35 +192,27 @@ public List getAllEmailTemplates(String tenantDomain) throws I18n public EmailTemplate getEmailTemplate(String templateDisplayName, String locale, String tenantDomain) throws I18nEmailMgtException { - try { - if (OrganizationManagementUtil.isOrganization(tenantDomain)) { - // Return the root organization's email template. - tenantDomain = getRootOrgTenantDomain(tenantDomain); - } - return getEmailTemplate(templateDisplayName, locale, tenantDomain, null); - } catch (OrganizationManagementException e) { - throw new I18nEmailMgtServerException(e.getMessage(), e); - } + return getEmailTemplate(templateDisplayName, locale, tenantDomain, null, true); } @Override public List getEmailTemplateType(String templateDisplayName, String tenantDomain) throws I18nEmailMgtException { - try { - if (OrganizationManagementUtil.isOrganization(tenantDomain)) { - // Return the root organization's email template type. - tenantDomain = getRootOrgTenantDomain(tenantDomain); - } - return getEmailTemplateType(templateDisplayName, tenantDomain, null); - } catch (OrganizationManagementException e) { - throw new I18nEmailMgtServerException(e.getMessage(), e); - } + return getEmailTemplateType(templateDisplayName, tenantDomain, null, true); + } + + @Override + public List getEmailTemplateType(String templateDisplayName, String tenantDomain, + String applicationUuid) throws I18nEmailMgtException { + + return getEmailTemplateType(templateDisplayName, tenantDomain, applicationUuid, false); } @Override public List getEmailTemplateType( - String templateDisplayName, String tenantDomain, String applicationUuid) throws I18nEmailMgtException { + String templateDisplayName, String tenantDomain, String applicationUuid, boolean resolve) + throws I18nEmailMgtException { validateTemplateType(templateDisplayName, tenantDomain); @@ -247,9 +225,14 @@ public List getEmailTemplateType( throw new I18nEmailMgtClientException(EMAIL_TEMPLATE_TYPE_NOT_FOUND, message); } - List notificationTemplates = - templatePersistenceManager.listNotificationTemplates(templateDisplayName, - NotificationChannels.EMAIL_CHANNEL.getChannelType(), applicationUuid, tenantDomain); + List notificationTemplates; + if (resolve) { + notificationTemplates = templatePersistenceManager.listNotificationTemplates(templateDisplayName, + NotificationChannels.EMAIL_CHANNEL.getChannelType(), applicationUuid, tenantDomain); + } else { + notificationTemplates = userDefinedTemplatePersistenceManager.listNotificationTemplates(templateDisplayName, + NotificationChannels.EMAIL_CHANNEL.getChannelType(), applicationUuid, tenantDomain); + } return getEmailTemplateList(notificationTemplates); } catch (NotificationTemplateManagerServerException ex) { String error = "Error when retrieving '%s' template type from %s tenant registry."; @@ -274,37 +257,39 @@ private String getDefaultNotificationLocale(String notificationChannel) { @Override public NotificationTemplate getNotificationTemplate(String notificationChannel, String templateType, String locale, - String tenantDomain) throws NotificationTemplateManagerException { + String tenantDomain) + throws NotificationTemplateManagerException { - return getNotificationTemplate(notificationChannel, templateType, locale, tenantDomain, null); + return getNotificationTemplate(notificationChannel, templateType, locale, tenantDomain, null, true); } @Override public NotificationTemplate getNotificationTemplate(String notificationChannel, String templateType, String locale, - String tenantDomain, String applicationUuid) throws NotificationTemplateManagerException { + String tenantDomain, String applicationUuid) + throws NotificationTemplateManagerException { + + return getNotificationTemplate(notificationChannel, templateType, locale, tenantDomain, applicationUuid, false); + } + + @Override + public NotificationTemplate getNotificationTemplate(String notificationChannel, String templateType, String locale, + String tenantDomain, String applicationUuid, boolean resolve) + throws NotificationTemplateManagerException { - try { - if (OrganizationManagementUtil.isOrganization(tenantDomain)) { - // Return the root organization's notification template. - tenantDomain = getRootOrgTenantDomain(tenantDomain); - // If it's application specific template is required, get the root organization's application. - if (StringUtils.isNotBlank(applicationUuid)) { - applicationUuid = I18nMgtDataHolder.getInstance().getApplicationManagementService().getMainAppId(applicationUuid); - } - } - } catch (OrganizationManagementException e) { - throw new NotificationTemplateManagerException(e.getMessage(), e); - } catch (IdentityApplicationManagementServerException e) { - throw new NotificationTemplateManagerException(ERROR_CODE_ERROR_RESOLVING_MAIN_APPLICATION.getCode(), - ERROR_CODE_ERROR_RESOLVING_MAIN_APPLICATION.getMessage(), e); - } // Resolve channel to either SMS or EMAIL. notificationChannel = resolveNotificationChannel(notificationChannel); validateTemplateLocale(locale); locale = normalizeLocaleFormat(locale); validateDisplayNameOfTemplateType(templateType); - NotificationTemplate notificationTemplate = templatePersistenceManager.getNotificationTemplate(templateType, - locale, notificationChannel, applicationUuid, tenantDomain); + NotificationTemplate notificationTemplate; + + if (resolve) { + notificationTemplate = templatePersistenceManager.getNotificationTemplate(templateType, + locale, notificationChannel, applicationUuid, tenantDomain); + } else { + notificationTemplate = userDefinedTemplatePersistenceManager.getNotificationTemplate(templateType, + locale, notificationChannel, applicationUuid, tenantDomain); + } // Handle not having the requested SMS template type in required locale for this tenantDomain. if (notificationTemplate == null) { @@ -603,11 +588,18 @@ public void deleteEmailTemplate(String templateTypeName, String localeCode, Stri public EmailTemplate getEmailTemplate(String templateType, String locale, String tenantDomain, String applicationUuid) throws I18nEmailMgtException { + return getEmailTemplate(templateType, locale, tenantDomain, applicationUuid, false); + } + + @Override + public EmailTemplate getEmailTemplate(String templateType, String locale, String tenantDomain, + String applicationUuid, boolean resolve) throws I18nEmailMgtException { + locale = normalizeLocaleFormat(locale); try { NotificationTemplate notificationTemplate = getNotificationTemplate( NotificationChannels.EMAIL_CHANNEL.getChannelType(), templateType, locale, - tenantDomain, applicationUuid); + tenantDomain, applicationUuid, resolve); return buildEmailTemplate(notificationTemplate); } catch (NotificationTemplateManagerException exception) { String errorCode = exception.getErrorCode(); @@ -817,18 +809,4 @@ private List getEmailTemplateList(List noti } return emailTemplates; } - - /** - * Get the root organization's tenantDomain matching to the given tenant domain. - * - * @return Root organization tenant domain. - * @throws OrganizationManagementException If an error occurred while getting the root organization tenant domain. - */ - private String getRootOrgTenantDomain(String tenantDomain) throws OrganizationManagementException { - - OrganizationManager organizationManager = I18nMgtDataHolder.getInstance().getOrganizationManager(); - String orgId = organizationManager.resolveOrganizationId(tenantDomain); - String primaryOrgId = organizationManager.getPrimaryOrganizationId(orgId); - return organizationManager.resolveTenantDomain(primaryOrgId); - } } diff --git a/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/NotificationTemplateManagerImpl.java b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/NotificationTemplateManagerImpl.java index fddb01b4..ffaccb78 100644 --- a/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/NotificationTemplateManagerImpl.java +++ b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/NotificationTemplateManagerImpl.java @@ -22,12 +22,10 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.email.mgt.constants.TemplateMgtConstants; -import org.wso2.carbon.email.mgt.internal.I18nMgtDataHolder; import org.wso2.carbon.email.mgt.store.SystemDefaultTemplateManager; import org.wso2.carbon.email.mgt.store.TemplatePersistenceManager; import org.wso2.carbon.email.mgt.store.TemplatePersistenceManagerFactory; import org.wso2.carbon.email.mgt.util.I18nEmailUtil; -import org.wso2.carbon.identity.application.common.IdentityApplicationManagementServerException; import org.wso2.carbon.identity.governance.exceptions.notiification.NotificationTemplateManagerClientException; import org.wso2.carbon.identity.governance.exceptions.notiification.NotificationTemplateManagerException; import org.wso2.carbon.identity.governance.exceptions.notiification.NotificationTemplateManagerInternalException; @@ -35,9 +33,6 @@ import org.wso2.carbon.identity.governance.model.NotificationTemplate; import org.wso2.carbon.identity.governance.service.notification.NotificationChannels; import org.wso2.carbon.identity.governance.service.notification.NotificationTemplateManager; -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.util.OrganizationManagementUtil; import java.util.ArrayList; import java.util.List; @@ -74,10 +69,6 @@ public List getAllNotificationTemplateTypes(String notificationChannel, throws NotificationTemplateManagerException { try { - if (OrganizationManagementUtil.isOrganization(tenantDomain)) { - // Return the root organization's template types. - tenantDomain = getRootOrgTenantDomain(tenantDomain); - } List templateTypes = templatePersistenceManager .listNotificationTemplateTypes(notificationChannel, tenantDomain); return templateTypes != null ? templateTypes : new ArrayList<>(); @@ -85,8 +76,6 @@ public List getAllNotificationTemplateTypes(String notificationChannel, String errorMsg = String.format("Error when retrieving %s template types of %s tenant.", notificationChannel.toLowerCase(), tenantDomain); throw new NotificationTemplateManagerServerException(errorMsg, ex); - } catch (OrganizationManagementException e) { - throw new NotificationTemplateManagerServerException(e.getMessage(), e); } } @@ -192,18 +181,26 @@ public boolean isNotificationTemplateTypeExists(String notificationChannel, Stri public List getAllNotificationTemplates(String notificationChannel, String tenantDomain) throws NotificationTemplateManagerException { + return getAllNotificationTemplates(notificationChannel, tenantDomain, false); + } + + /** + * {@inheritDoc} + */ + @Override + public List getAllNotificationTemplates(String notificationChannel, String tenantDomain, + boolean resolve) + throws NotificationTemplateManagerException { + try { - if (OrganizationManagementUtil.isOrganization(tenantDomain)) { - // Return the root organization's email templates. - tenantDomain = getRootOrgTenantDomain(tenantDomain); + if (resolve) { + return templatePersistenceManager.listAllNotificationTemplates(notificationChannel, tenantDomain); } return userDefinedTemplatePersistenceManager.listAllNotificationTemplates( notificationChannel, tenantDomain); } catch (NotificationTemplateManagerServerException e) { String error = String.format("Error when retrieving templates of %s tenant.", tenantDomain); throw handleServerException(error, e); - } catch (OrganizationManagementException e) { - throw handleServerException(e.getMessage(), e); } } @@ -223,27 +220,39 @@ public List getNotificationTemplatesOfType(String notifica */ @Override public List getNotificationTemplatesOfType(String notificationChannel, - String templateDisplayName, String tenantDomain, String applicationUuid) + String templateDisplayName, String tenantDomain, + String applicationUuid) throws NotificationTemplateManagerException { - try { - if (OrganizationManagementUtil.isOrganization(tenantDomain)) { - // Return the root organization's email templates. - tenantDomain = getRootOrgTenantDomain(tenantDomain); - } - verifyTemplateTypeExists(templateDisplayName, notificationChannel, tenantDomain); - return userDefinedTemplatePersistenceManager.listNotificationTemplates(templateDisplayName, - notificationChannel, applicationUuid, tenantDomain); - } catch (OrganizationManagementException e) { - throw handleServerException(e.getMessage(), e); + return getNotificationTemplatesOfType(notificationChannel, templateDisplayName, tenantDomain, applicationUuid, + false); + } + + /** + * {@inheritDoc} + */ + @Override + public List getNotificationTemplatesOfType(String notificationChannel, + String templateDisplayName, String tenantDomain, + String applicationUuid, boolean resolve) + throws NotificationTemplateManagerException { + + verifyTemplateTypeExists(templateDisplayName, notificationChannel, tenantDomain); + + if (resolve) { + return templatePersistenceManager.listNotificationTemplates(templateDisplayName, notificationChannel, + applicationUuid, tenantDomain); } + return userDefinedTemplatePersistenceManager.listNotificationTemplates(templateDisplayName, + notificationChannel, applicationUuid, tenantDomain); } + /** * {@inheritDoc} */ @Override public NotificationTemplate getNotificationTemplate(String notificationChannel, String templateType, String locale, - String tenantDomain) + String tenantDomain) throws NotificationTemplateManagerException { return getNotificationTemplate(notificationChannel, templateType, locale, tenantDomain, null); @@ -254,36 +263,33 @@ public NotificationTemplate getNotificationTemplate(String notificationChannel, */ @Override public NotificationTemplate getNotificationTemplate(String notificationChannel, String templateType, String locale, - String tenantDomain, String applicationUuid) + String tenantDomain, String applicationUuid) + throws NotificationTemplateManagerException { + + return getNotificationTemplate(notificationChannel, templateType, locale, tenantDomain, applicationUuid, false); + } + + /** + * {@inheritDoc} + */ + @Override + public NotificationTemplate getNotificationTemplate(String notificationChannel, String templateType, String locale, + String tenantDomain, String applicationUuid, boolean resolve) throws NotificationTemplateManagerException { - try { - if (OrganizationManagementUtil.isOrganization(tenantDomain)) { - // To return the root organization's notification template. - tenantDomain = getRootOrgTenantDomain(tenantDomain); - // If it's application specific template is required, get the root organization's application. - if (StringUtils.isNotBlank(applicationUuid)) { - applicationUuid = I18nMgtDataHolder.getInstance().getApplicationManagementService() - .getMainAppId(applicationUuid); - } - } - } catch (OrganizationManagementException e) { - throw new NotificationTemplateManagerException(e.getMessage(), e); - } catch (IdentityApplicationManagementServerException e) { - String code = I18nEmailUtil.prependOperationScenarioToErrorCode( - TemplateMgtConstants.ErrorMessages.ERROR_CODE_ERROR_RESOLVING_MAIN_APPLICATION.getCode(), - TemplateMgtConstants.ErrorScenarios.NOTIFICATION_TEMPLATE_MANAGER); - String message = String.format( - TemplateMgtConstants.ErrorMessages.ERROR_CODE_ERROR_RESOLVING_MAIN_APPLICATION.getMessage(), - applicationUuid, tenantDomain); - throw new NotificationTemplateManagerException(code, message, e); - } validateTemplateLocale(locale); locale = normalizeLocaleFormat(locale); validateDisplayNameOfTemplateType(templateType); verifyTemplateTypeExists(templateType, notificationChannel, tenantDomain); - NotificationTemplate notificationTemplate = userDefinedTemplatePersistenceManager.getNotificationTemplate( - templateType, locale, notificationChannel, applicationUuid, tenantDomain); + + NotificationTemplate notificationTemplate; + if (resolve) { + notificationTemplate = templatePersistenceManager.getNotificationTemplate(templateType, locale, + notificationChannel, applicationUuid, tenantDomain); + } else { + notificationTemplate = userDefinedTemplatePersistenceManager.getNotificationTemplate( + templateType, locale, notificationChannel, applicationUuid, tenantDomain); + } String defaultLocale = getDefaultNotificationLocale(notificationChannel); if (notificationTemplate == null) { @@ -576,14 +582,6 @@ private void validateDisplayNameOfTemplateType(String templateDisplayName) } } - private String getRootOrgTenantDomain(String tenantDomain) throws OrganizationManagementException { - - OrganizationManager organizationManager = I18nMgtDataHolder.getInstance().getOrganizationManager(); - String orgId = organizationManager.resolveOrganizationId(tenantDomain); - String primaryOrgId = organizationManager.getPrimaryOrganizationId(orgId); - return organizationManager.resolveTenantDomain(primaryOrgId); - } - private NotificationTemplateManagerServerException handleServerException(String errorMsg, Throwable ex) throws NotificationTemplateManagerServerException { diff --git a/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/internal/I18nMgtDataHolder.java b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/internal/I18nMgtDataHolder.java index 39c2886f..9975b289 100644 --- a/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/internal/I18nMgtDataHolder.java +++ b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/internal/I18nMgtDataHolder.java @@ -22,6 +22,7 @@ import org.wso2.carbon.identity.core.persistence.registry.RegistryResourceMgtService; import org.wso2.carbon.identity.governance.model.NotificationTemplate; import org.wso2.carbon.identity.organization.management.service.OrganizationManager; +import org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.OrgResourceResolverService; import org.wso2.carbon.registry.core.service.RegistryService; import org.wso2.carbon.user.core.service.RealmService; @@ -34,6 +35,7 @@ public class I18nMgtDataHolder{ private RegistryResourceMgtService registryResourceMgtService; private OrganizationManager organizationManager; private ApplicationManagementService applicationManagementService; + private OrgResourceResolverService orgResourceResolverService; private List defaultEmailTemplates = new ArrayList<>(); private List defaultSMSTemplates = new ArrayList<>(); private List legacyTenants = new ArrayList<>(); @@ -162,6 +164,26 @@ public List getLegacyTenants() { return legacyTenants; } + /** + * Get the organization resource resolver service. + * + * @return Organization resource resolver service. + */ + public OrgResourceResolverService getOrgResourceResolverService() { + + return orgResourceResolverService; + } + + /** + * Set the organization resource resolver service. + * + * @param orgResourceResolverService Organization resource resolver service instance. + */ + public void setOrgResourceResolverService(OrgResourceResolverService orgResourceResolverService) { + + this.orgResourceResolverService = orgResourceResolverService; + } + /** * Sets whether the unicode support for template content is enabled or not. * diff --git a/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/internal/I18nMgtServiceComponent.java b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/internal/I18nMgtServiceComponent.java index a095312c..7768d361 100644 --- a/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/internal/I18nMgtServiceComponent.java +++ b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/internal/I18nMgtServiceComponent.java @@ -39,6 +39,7 @@ import org.wso2.carbon.identity.governance.service.notification.NotificationChannels; import org.wso2.carbon.identity.governance.service.notification.NotificationTemplateManager; import org.wso2.carbon.identity.organization.management.service.OrganizationManager; +import org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.OrgResourceResolverService; import org.wso2.carbon.registry.core.service.RegistryService; import org.wso2.carbon.user.core.service.RealmService; import org.osgi.service.component.annotations.Activate; @@ -424,5 +425,21 @@ protected void unsetOrganizationManager(OrganizationManager organizationManager) dataHolder.getInstance().setOrganizationManager(null); } + + @Reference( + name = "org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service", + service = OrgResourceResolverService.class, + cardinality = ReferenceCardinality.MANDATORY, + policy = ReferencePolicy.DYNAMIC, + unbind = "unsetOrgResourceResolverService") + protected void setOrgResourceResolverService(OrgResourceResolverService orgResourceResolverService) { + + dataHolder.setOrgResourceResolverService(orgResourceResolverService); + } + + protected void unsetOrgResourceResolverService(OrgResourceResolverService orgResourceResolverService) { + + dataHolder.setOrgResourceResolverService(null); + } } diff --git a/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/store/UnifiedTemplateManager.java b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/store/UnifiedTemplateManager.java index 52ba3e0a..f91d3a39 100644 --- a/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/store/UnifiedTemplateManager.java +++ b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/store/UnifiedTemplateManager.java @@ -18,14 +18,25 @@ package org.wso2.carbon.email.mgt.store; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang.StringUtils; +import org.wso2.carbon.email.mgt.internal.I18nMgtDataHolder; +import org.wso2.carbon.identity.core.util.LambdaExceptionUtils; 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.resource.hierarchy.traverse.service.OrgResourceResolverService; +import org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.exception.OrgResourceHierarchyTraverseException; +import org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.strategy.FirstFoundAggregationStrategy; +import org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.strategy.MergeAllAggregationStrategy; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; /** @@ -54,18 +65,56 @@ public void addNotificationTemplateType(String displayName, String notificationC public boolean isNotificationTemplateTypeExists(String displayName, String notificationChannel, String tenantDomain) throws NotificationTemplateManagerServerException { - return systemDefaultTemplateManager.isNotificationTemplateTypeExists(displayName, notificationChannel, - tenantDomain) || - templatePersistenceManager.isNotificationTemplateTypeExists(displayName, notificationChannel, + boolean templateTypeExists = + systemDefaultTemplateManager.isNotificationTemplateTypeExists(displayName, notificationChannel, tenantDomain); + + if (templateTypeExists) { + return true; + } + + try { + OrganizationManager organizationManager = I18nMgtDataHolder.getInstance().getOrganizationManager(); + String organizationId = organizationManager.resolveOrganizationId(tenantDomain); + + OrgResourceResolverService orgResourceResolverService = + I18nMgtDataHolder.getInstance().getOrgResourceResolverService(); + return orgResourceResolverService.getResourcesFromOrgHierarchy( + organizationId, + LambdaExceptionUtils.rethrowFunction( + orgId -> notificationTemplateTypeExistenceRetriever(displayName, notificationChannel, + orgId)), + new FirstFoundAggregationStrategy<>()); + } catch (OrganizationManagementException | OrgResourceHierarchyTraverseException e) { + String errorMsg = String.format("Unexpected server error occurred while checking the existence of " + + "email template type: %s for tenant: %s", displayName, tenantDomain); + throw new NotificationTemplateManagerServerException(errorMsg, e); + } } @Override public List listNotificationTemplateTypes(String notificationChannel, String tenantDomain) throws NotificationTemplateManagerServerException { - List dbBasedTemplateTypes = templatePersistenceManager.listNotificationTemplateTypes - (notificationChannel, tenantDomain); + List dbBasedTemplateTypes; + try { + OrganizationManager organizationManager = I18nMgtDataHolder.getInstance().getOrganizationManager(); + String organizationId = organizationManager.resolveOrganizationId(tenantDomain); + + OrgResourceResolverService orgResourceResolverService = + I18nMgtDataHolder.getInstance().getOrgResourceResolverService(); + dbBasedTemplateTypes = orgResourceResolverService.getResourcesFromOrgHierarchy( + organizationId, + LambdaExceptionUtils.rethrowFunction( + orgId -> notificationTemplateTypesRetriever(notificationChannel, orgId)), + new MergeAllAggregationStrategy<>(this::mergeAndRemoveDuplicates)); + } catch (OrganizationManagementException | OrgResourceHierarchyTraverseException e) { + String errorMsg = String.format( + "Unexpected server error occurred while resolving all email templates for tenant: %s", + tenantDomain); + throw new NotificationTemplateManagerServerException(errorMsg, e); + } + List inMemoryTemplateTypes = systemDefaultTemplateManager.listNotificationTemplateTypes(notificationChannel, tenantDomain); @@ -124,10 +173,34 @@ public boolean isNotificationTemplateExists(String displayName, String locale, S String applicationUuid, String tenantDomain) throws NotificationTemplateManagerServerException { - return systemDefaultTemplateManager.isNotificationTemplateExists(displayName, locale, notificationChannel, - applicationUuid, tenantDomain) || - templatePersistenceManager.isNotificationTemplateExists(displayName, locale, notificationChannel, - applicationUuid, tenantDomain); + boolean templateExists = + systemDefaultTemplateManager.isNotificationTemplateExists(displayName, locale, notificationChannel, + null, tenantDomain); + + if (templateExists) { + return true; + } + + try { + OrganizationManager organizationManager = I18nMgtDataHolder.getInstance().getOrganizationManager(); + String organizationId = organizationManager.resolveOrganizationId(tenantDomain); + + OrgResourceResolverService orgResourceResolverService = + I18nMgtDataHolder.getInstance().getOrgResourceResolverService(); + return orgResourceResolverService.getResourcesFromOrgHierarchy( + organizationId, + LambdaExceptionUtils.rethrowFunction( + orgId -> notificationTemplateExistenceRetriever(displayName, locale, notificationChannel, + applicationUuid, orgId)), + new FirstFoundAggregationStrategy<>()); + } catch (OrganizationManagementException | OrgResourceHierarchyTraverseException e) { + String errorMsg = String.format("Unexpected server error occurred while checking the existence of " + + "email template with type: %s for tenant: %s", displayName, tenantDomain); + if (applicationUuid != null) { + errorMsg += String.format(" and application id: %s", applicationUuid); + } + throw new NotificationTemplateManagerServerException(errorMsg, e); + } } @Override @@ -135,13 +208,35 @@ public NotificationTemplate getNotificationTemplate(String displayName, String l String applicationUuid, String tenantDomain) throws NotificationTemplateManagerServerException { - NotificationTemplate notificationTemplate = templatePersistenceManager.getNotificationTemplate(displayName, - locale, notificationChannel, applicationUuid, tenantDomain); + NotificationTemplate notificationTemplate; + try { + OrganizationManager organizationManager = I18nMgtDataHolder.getInstance().getOrganizationManager(); + String organizationId = organizationManager.resolveOrganizationId(tenantDomain); + + OrgResourceResolverService orgResourceResolverService = + I18nMgtDataHolder.getInstance().getOrgResourceResolverService(); + notificationTemplate = orgResourceResolverService.getResourcesFromOrgHierarchy( + organizationId, + applicationUuid, + LambdaExceptionUtils.rethrowFunction( + (orgId, appId) -> notificationTemplateRetriever(displayName, locale, notificationChannel, + orgId, appId)), + new FirstFoundAggregationStrategy<>()); + } catch (OrganizationManagementException | OrgResourceHierarchyTraverseException e) { + String errorMsg = String.format( + "Unexpected server error occurred while resolving email template with type: %s for tenant: %s", + displayName, tenantDomain); + if (applicationUuid != null) { + errorMsg += String.format(" and application id: %s", applicationUuid); + } + throw new NotificationTemplateManagerServerException(errorMsg, e); + } + if (notificationTemplate != null) { return notificationTemplate; } else { return systemDefaultTemplateManager.getNotificationTemplate(displayName, locale, notificationChannel, - applicationUuid, tenantDomain); + null, tenantDomain); } } @@ -150,12 +245,28 @@ public List listNotificationTemplates(String templateType, String applicationUuid, String tenantDomain) throws NotificationTemplateManagerServerException { - List dbBasedTemplates = new ArrayList<>(); - if (templatePersistenceManager.isNotificationTemplateTypeExists(templateType, notificationChannel, - tenantDomain)) { + List dbBasedTemplates; + try { + OrganizationManager organizationManager = I18nMgtDataHolder.getInstance().getOrganizationManager(); + String organizationId = organizationManager.resolveOrganizationId(tenantDomain); + + OrgResourceResolverService orgResourceManagementService = + I18nMgtDataHolder.getInstance().getOrgResourceResolverService(); dbBasedTemplates = - templatePersistenceManager.listNotificationTemplates(templateType, notificationChannel, - applicationUuid, tenantDomain); + orgResourceManagementService.getResourcesFromOrgHierarchy(organizationId, + applicationUuid, + LambdaExceptionUtils.rethrowFunction( + (orgId, appId) -> notificationTemplatesRetriever(templateType, notificationChannel, orgId, + appId)), + new MergeAllAggregationStrategy<>(this::mergeAndRemoveDuplicateTemplates)); + } catch (OrganizationManagementException | OrgResourceHierarchyTraverseException e) { + String errorMsg = String.format( + "Unexpected server error occurred while resolving email templates with type: %s for tenant: %s", + templateType, tenantDomain); + if (applicationUuid != null) { + errorMsg += String.format(" and application id: %s", applicationUuid); + } + throw new NotificationTemplateManagerServerException(errorMsg, e); } List inMemoryBasedTemplates = new ArrayList<>(); @@ -163,7 +274,7 @@ public List listNotificationTemplates(String templateType, tenantDomain)) { inMemoryBasedTemplates = systemDefaultTemplateManager.listNotificationTemplates(templateType, notificationChannel, - applicationUuid, tenantDomain); + null, tenantDomain); } return mergeAndRemoveDuplicateTemplates(dbBasedTemplates, inMemoryBasedTemplates); @@ -173,8 +284,25 @@ public List listNotificationTemplates(String templateType, public List listAllNotificationTemplates(String notificationChannel, String tenantDomain) throws NotificationTemplateManagerServerException { - List dbBasedTemplates = - templatePersistenceManager.listAllNotificationTemplates(notificationChannel, tenantDomain); + List dbBasedTemplates; + try { + OrganizationManager organizationManager = I18nMgtDataHolder.getInstance().getOrganizationManager(); + String organizationId = organizationManager.resolveOrganizationId(tenantDomain); + + OrgResourceResolverService orgResourceManagementService = + I18nMgtDataHolder.getInstance().getOrgResourceResolverService(); + dbBasedTemplates = orgResourceManagementService.getResourcesFromOrgHierarchy( + organizationId, + LambdaExceptionUtils.rethrowFunction( + orgId -> allNotificationTemplatesRetriever(notificationChannel, orgId)), + new MergeAllAggregationStrategy<>(this::mergeAndRemoveDuplicateTemplates)); + } catch (OrganizationManagementException | OrgResourceHierarchyTraverseException e) { + String errorMsg = String.format( + "Unexpected server error occurred while resolving all email templates for tenant: %s", + tenantDomain); + throw new NotificationTemplateManagerServerException(errorMsg, e); + } + List inMemoryBasedTemplates = systemDefaultTemplateManager.listAllNotificationTemplates(notificationChannel, tenantDomain); @@ -207,34 +335,144 @@ public void deleteNotificationTemplates(String displayName, String notificationC /** * Merges two lists and removes duplicates. * - * @param dbBasedTemplates DbBasedTemplates - * @param inMemoryTemplates InMemoryTemplates + * @param primaryTemplates Primary Templates + * @param secondaryTemplates Secondary Templates * @return Merged list without duplicates. */ - private List mergeAndRemoveDuplicates(List dbBasedTemplates, List inMemoryTemplates) { + private List mergeAndRemoveDuplicates(List primaryTemplates, List secondaryTemplates) { + + if (CollectionUtils.isEmpty(primaryTemplates)) { + return secondaryTemplates; + } + if (CollectionUtils.isEmpty(secondaryTemplates)) { + return primaryTemplates; + } Set uniqueElements = new HashSet<>(); - uniqueElements.addAll(dbBasedTemplates); - uniqueElements.addAll(inMemoryTemplates); + uniqueElements.addAll(primaryTemplates); + uniqueElements.addAll(secondaryTemplates); return new ArrayList<>(uniqueElements); } /** * Merges two NotificationTemplate lists and removes duplicate templates. * - * @param dbBasedTemplates DbBasedTemplates - * @param inMemoryTemplates InMemoryTemplates + * @param primaryTemplates Primary Templates + * @param secondaryTemplates Secondary Templates * @return Merged list without duplicates. */ private List mergeAndRemoveDuplicateTemplates( - List dbBasedTemplates, - List inMemoryTemplates) { + List primaryTemplates, + List secondaryTemplates) { + + if (CollectionUtils.isEmpty(primaryTemplates)) { + return secondaryTemplates; + } + + if (CollectionUtils.isEmpty(secondaryTemplates)) { + return primaryTemplates; + } Map templateMap = new HashMap<>(); - dbBasedTemplates.forEach(template -> templateMap.put(template.getDisplayName(), template)); + primaryTemplates.forEach(template -> templateMap.put(template.getDisplayName(), template)); - // Add in-memory templates, only if not already present - inMemoryTemplates.forEach(template -> templateMap.putIfAbsent(template.getDisplayName(), template)); + // Add secondary templates, only if not already present + secondaryTemplates.forEach(template -> templateMap.putIfAbsent(template.getDisplayName(), template)); return new ArrayList<>(templateMap.values()); } + + private Optional notificationTemplateTypeExistenceRetriever(String displayName, String notificationChannel, + String orgId) + throws NotificationTemplateManagerServerException, OrganizationManagementException { + + OrganizationManager organizationManager = I18nMgtDataHolder.getInstance().getOrganizationManager(); + String tenantDomainOfOrg = organizationManager.resolveTenantDomain(orgId); + + boolean templateTypeExists = + templatePersistenceManager.isNotificationTemplateTypeExists(displayName, notificationChannel, + tenantDomainOfOrg); + if (!templateTypeExists) { + return Optional.empty(); + } + return Optional.of(true); + } + + private Optional notificationTemplateExistenceRetriever(String displayName, String locale, + String notificationChannel, String appId, + String orgId) + throws NotificationTemplateManagerServerException, OrganizationManagementException { + + OrganizationManager organizationManager = I18nMgtDataHolder.getInstance().getOrganizationManager(); + String tenantDomainOfOrg = organizationManager.resolveTenantDomain(orgId); + + boolean templateExists = + templatePersistenceManager.isNotificationTemplateExists(displayName, locale, notificationChannel, appId, + tenantDomainOfOrg); + if (!templateExists) { + return Optional.empty(); + } + return Optional.of(true); + } + + private Optional> notificationTemplateTypesRetriever(String notificationChannel, String orgId) + throws NotificationTemplateManagerServerException, OrganizationManagementException { + + OrganizationManager organizationManager = I18nMgtDataHolder.getInstance().getOrganizationManager(); + String tenantDomainOfOrg = organizationManager.resolveTenantDomain(orgId); + List notificationTemplates = + templatePersistenceManager.listNotificationTemplateTypes(notificationChannel, tenantDomainOfOrg); + return Optional.ofNullable(notificationTemplates); + } + + private Optional notificationTemplateRetriever(String displayName, String locale, + String notificationChannel, String orgId, + String appId) + throws OrganizationManagementException, NotificationTemplateManagerServerException { + + OrganizationManager organizationManager = I18nMgtDataHolder.getInstance().getOrganizationManager(); + String tenantDomainOfOrg = organizationManager.resolveTenantDomain(orgId); + NotificationTemplate template = + templatePersistenceManager.getNotificationTemplate(displayName, locale, notificationChannel, appId, + tenantDomainOfOrg); + if (template == null && StringUtils.isNotBlank(appId)) { + template = templatePersistenceManager.getNotificationTemplate(displayName, locale, notificationChannel, + null, tenantDomainOfOrg); + } + return Optional.ofNullable(template); + } + + private Optional> notificationTemplatesRetriever(String templateType, + String notificationChannel, + String orgId, String appId) + throws OrganizationManagementException, NotificationTemplateManagerServerException { + + OrganizationManager organizationManager = I18nMgtDataHolder.getInstance().getOrganizationManager(); + String tenantDomainOfOrg = organizationManager.resolveTenantDomain(orgId); + if (templatePersistenceManager.isNotificationTemplateTypeExists(templateType, + notificationChannel, tenantDomainOfOrg)) { + List notificationTemplates = + templatePersistenceManager.listNotificationTemplates(templateType, notificationChannel, appId, + tenantDomainOfOrg); + if (StringUtils.isNotBlank(appId)) { + List orgNotificationTemplates = + templatePersistenceManager.listNotificationTemplates(templateType, notificationChannel, null, + tenantDomainOfOrg); + notificationTemplates = + mergeAndRemoveDuplicateTemplates(notificationTemplates, orgNotificationTemplates); + } + return Optional.ofNullable(notificationTemplates); + } + return Optional.empty(); + } + + private Optional> allNotificationTemplatesRetriever(String notificationChannel, + String orgId) + throws OrganizationManagementException, NotificationTemplateManagerServerException { + + OrganizationManager organizationManager = I18nMgtDataHolder.getInstance().getOrganizationManager(); + String tenantDomainOfOrg = organizationManager.resolveTenantDomain(orgId); + List notificationTemplates = + templatePersistenceManager.listAllNotificationTemplates(notificationChannel, tenantDomainOfOrg); + return Optional.ofNullable(notificationTemplates); + } } diff --git a/pom.xml b/pom.xml index a3985fd6..405e5c72 100644 --- a/pom.xml +++ b/pom.xml @@ -262,6 +262,11 @@ commons-lang ${commons-lang.wso2.version}
+ + commons-collections.wso2 + commons-collections + ${apache.common.collection.version} + com.google.code.gson @@ -281,6 +286,11 @@ org.wso2.carbon.identity.organization.management.service ${identity.organization.management.core.version} + + org.wso2.carbon.identity.organization.management + org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service + ${identity.organization.management.version} + @@ -477,7 +487,7 @@ - 1.11.11 + 1.11.18 [1.0.0, 3.0.0) @@ -502,6 +512,8 @@ [1.2,2.0) [2.6.0,3.0.0) [2.6.0,3.0.0) + 3.2.0.wso2v1 + [3.2.0,4.0.0) 4.10.24 @@ -529,6 +541,7 @@ 1.0.93 [1.0.0,2.0.0) + 1.4.55 [1.0.0,2.0.0) From d087f1b1ea94c4155713e8ec8a9915d969242b79 Mon Sep 17 00:00:00 2001 From: dhaura Date: Thu, 5 Dec 2024 11:04:47 +0530 Subject: [PATCH 2/7] Bump org mgt version and add commons-collections dependency. --- components/email-mgt/org.wso2.carbon.email.mgt/pom.xml | 4 ++++ pom.xml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/components/email-mgt/org.wso2.carbon.email.mgt/pom.xml b/components/email-mgt/org.wso2.carbon.email.mgt/pom.xml index 11dcb7f6..d521f2c8 100644 --- a/components/email-mgt/org.wso2.carbon.email.mgt/pom.xml +++ b/components/email-mgt/org.wso2.carbon.email.mgt/pom.xml @@ -96,6 +96,10 @@ org.wso2.carbon.identity.organization.management org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service + + commons-collections.wso2 + commons-collections + com.google.code.gson gson diff --git a/pom.xml b/pom.xml index 405e5c72..354b5ce7 100644 --- a/pom.xml +++ b/pom.xml @@ -541,7 +541,7 @@ 1.0.93 [1.0.0,2.0.0) - 1.4.55 + 1.4.58 [1.0.0,2.0.0) From e631725df3f22df5aad8e687f6a8d483171c8b2b Mon Sep 17 00:00:00 2001 From: dhaura Date: Fri, 6 Dec 2024 14:05:15 +0530 Subject: [PATCH 3/7] Add deprecated tag in relevant methods and add descriptive comments. --- .../email/mgt/EmailTemplateManager.java | 6 ++++++ .../email/mgt/EmailTemplateManagerImpl.java | 21 ++++++++++++++++--- .../mgt/NotificationTemplateManagerImpl.java | 9 ++++++++ 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/EmailTemplateManager.java b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/EmailTemplateManager.java index 0c467a00..ff6596b4 100644 --- a/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/EmailTemplateManager.java +++ b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/EmailTemplateManager.java @@ -129,6 +129,8 @@ default List getEmailTemplateType(String templateDisplayName, Str } /** + * @deprecated Use {@link #getEmailTemplateType(String, String, String, boolean)} instead. + *

* Get all email templates of a specific template type for an application, from tenant registry. * * @param templateDisplayName Email template type displace name. @@ -137,6 +139,7 @@ default List getEmailTemplateType(String templateDisplayName, Str * @return A list of email templates that matches to the provided template type. * @throws I18nEmailMgtException if an error occurred. */ + @Deprecated default List getEmailTemplateType( String templateDisplayName, String tenantDomain, String applicationUuid) throws I18nEmailMgtException { @@ -247,6 +250,8 @@ void deleteEmailTemplate(String templateTypeName, String applicationUuid) throws I18nEmailMgtException; /** + * @deprecated Use {@link #getEmailTemplate(String, String, String, String, boolean)} instead. + *

* Get an email template from tenant registry with application UUID. * * @param templateType Email template type. @@ -256,6 +261,7 @@ void deleteEmailTemplate(String templateTypeName, * @return Email template of the application with fallback to organization template. * @throws I18nEmailMgtException If an error occurred while getting the email template. */ + @Deprecated EmailTemplate getEmailTemplate(String templateType, String locale, String tenantDomain, diff --git a/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/EmailTemplateManagerImpl.java b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/EmailTemplateManagerImpl.java index c3227562..7a002d7a 100644 --- a/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/EmailTemplateManagerImpl.java +++ b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/EmailTemplateManagerImpl.java @@ -192,6 +192,8 @@ public List getAllEmailTemplates(String tenantDomain) throws I18n public EmailTemplate getEmailTemplate(String templateDisplayName, String locale, String tenantDomain) throws I18nEmailMgtException { + /* When resolve param is not specified, the default behavior results in resolved templates, + since resolved templates are always required when sending emails at runtime. */ return getEmailTemplate(templateDisplayName, locale, tenantDomain, null, true); } @@ -199,14 +201,19 @@ public EmailTemplate getEmailTemplate(String templateDisplayName, String locale, public List getEmailTemplateType(String templateDisplayName, String tenantDomain) throws I18nEmailMgtException { + /* When resolve param is not specified, the default behavior results in resolved templates, + since resolved templates are always required when sending emails at runtime. */ return getEmailTemplateType(templateDisplayName, tenantDomain, null, true); } + @Deprecated @Override public List getEmailTemplateType(String templateDisplayName, String tenantDomain, String applicationUuid) throws I18nEmailMgtException { - return getEmailTemplateType(templateDisplayName, tenantDomain, applicationUuid, false); + /* When resolve param is not specified, the default behavior results in resolved templates, + since resolved templates are always required when sending emails at runtime. */ + return getEmailTemplateType(templateDisplayName, tenantDomain, applicationUuid, true); } @Override @@ -260,15 +267,20 @@ public NotificationTemplate getNotificationTemplate(String notificationChannel, String tenantDomain) throws NotificationTemplateManagerException { + /* When resolve param is not specified, the default behavior results in resolved templates, + since resolved templates are always required when sending emails at runtime. */ return getNotificationTemplate(notificationChannel, templateType, locale, tenantDomain, null, true); } + @Deprecated @Override public NotificationTemplate getNotificationTemplate(String notificationChannel, String templateType, String locale, String tenantDomain, String applicationUuid) throws NotificationTemplateManagerException { - return getNotificationTemplate(notificationChannel, templateType, locale, tenantDomain, applicationUuid, false); + /* When resolve param is not specified, the default behavior results in resolved templates, + since resolved templates are always required when sending emails at runtime. */ + return getNotificationTemplate(notificationChannel, templateType, locale, tenantDomain, applicationUuid, true); } @Override @@ -584,11 +596,14 @@ public void deleteEmailTemplate(String templateTypeName, String localeCode, Stri } } + @Deprecated @Override public EmailTemplate getEmailTemplate(String templateType, String locale, String tenantDomain, String applicationUuid) throws I18nEmailMgtException { - return getEmailTemplate(templateType, locale, tenantDomain, applicationUuid, false); + /* When resolve param is not specified, the default behavior results in resolved templates, + since resolved templates are always required when sending emails at runtime. */ + return getEmailTemplate(templateType, locale, tenantDomain, applicationUuid, true); } @Override diff --git a/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/NotificationTemplateManagerImpl.java b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/NotificationTemplateManagerImpl.java index ffaccb78..7652f29c 100644 --- a/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/NotificationTemplateManagerImpl.java +++ b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/NotificationTemplateManagerImpl.java @@ -177,10 +177,13 @@ public boolean isNotificationTemplateTypeExists(String notificationChannel, Stri /** * {@inheritDoc} */ + @Deprecated @Override public List getAllNotificationTemplates(String notificationChannel, String tenantDomain) throws NotificationTemplateManagerException { + /* When resolve param is not specified, the default behavior results in unresolved templates, + maintaining backward compatibility with the previous behavior of the method. */ return getAllNotificationTemplates(notificationChannel, tenantDomain, false); } @@ -218,12 +221,15 @@ public List getNotificationTemplatesOfType(String notifica /** * {@inheritDoc} */ + @Deprecated @Override public List getNotificationTemplatesOfType(String notificationChannel, String templateDisplayName, String tenantDomain, String applicationUuid) throws NotificationTemplateManagerException { + /* When resolve param is not specified, the default behavior results in unresolved templates, + maintaining backward compatibility with the previous behavior of the method. */ return getNotificationTemplatesOfType(notificationChannel, templateDisplayName, tenantDomain, applicationUuid, false); } @@ -261,11 +267,14 @@ public NotificationTemplate getNotificationTemplate(String notificationChannel, /** * {@inheritDoc} */ + @Deprecated @Override public NotificationTemplate getNotificationTemplate(String notificationChannel, String templateType, String locale, String tenantDomain, String applicationUuid) throws NotificationTemplateManagerException { + // When resolve param is not specified, the default behavior results in unresolved template, + // maintaining backward compatibility with the previous behavior of the method. return getNotificationTemplate(notificationChannel, templateType, locale, tenantDomain, applicationUuid, false); } From 1eb1c1eabcfc569b87195d0f63132736d3ccd55f Mon Sep 17 00:00:00 2001 From: dhaura Date: Mon, 9 Dec 2024 13:32:58 +0530 Subject: [PATCH 4/7] Update email mgt unit tests. --- .../mgt/ApplicationEmailTemplateTest.java | 59 ++++++++----------- .../mgt/OrganizationEmailTemplateTest.java | 44 +++++++++++--- .../mgt/store/UnifiedTemplateManagerTest.java | 43 +++++++++----- pom.xml | 6 +- 4 files changed, 92 insertions(+), 60 deletions(-) diff --git a/components/email-mgt/org.wso2.carbon.email.mgt/src/test/java/org/wso2/carbon/email/mgt/ApplicationEmailTemplateTest.java b/components/email-mgt/org.wso2.carbon.email.mgt/src/test/java/org/wso2/carbon/email/mgt/ApplicationEmailTemplateTest.java index 5525cec0..2135cb7d 100644 --- a/components/email-mgt/org.wso2.carbon.email.mgt/src/test/java/org/wso2/carbon/email/mgt/ApplicationEmailTemplateTest.java +++ b/components/email-mgt/org.wso2.carbon.email.mgt/src/test/java/org/wso2/carbon/email/mgt/ApplicationEmailTemplateTest.java @@ -17,6 +17,7 @@ */ package org.wso2.carbon.email.mgt; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.MockitoAnnotations.initMocks; import static org.powermock.api.mockito.PowerMockito.mockStatic; import static org.powermock.api.mockito.PowerMockito.when; @@ -24,7 +25,6 @@ import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; import static org.wso2.carbon.email.mgt.constants.I18nMgtConstants.NOTIFICATION_TEMPLATES_STORAGE_CONFIG; -import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.ErrorMessages.ERROR_CODE_ERROR_RESOLVING_MAIN_APPLICATION; import org.apache.commons.lang.StringUtils; import org.mockito.ArgumentMatchers; @@ -42,7 +42,6 @@ import org.wso2.carbon.email.mgt.constants.I18nMgtConstants; import org.wso2.carbon.email.mgt.internal.I18nMgtDataHolder; import org.wso2.carbon.email.mgt.util.I18nEmailUtil; -import org.wso2.carbon.identity.application.common.IdentityApplicationManagementServerException; import org.wso2.carbon.identity.application.mgt.ApplicationManagementService; import org.wso2.carbon.identity.base.IdentityRuntimeException; import org.wso2.carbon.identity.base.IdentityValidationUtil; @@ -54,6 +53,7 @@ import org.wso2.carbon.identity.governance.service.notification.NotificationChannels; import org.wso2.carbon.identity.organization.management.service.OrganizationManager; import org.wso2.carbon.identity.organization.management.service.util.OrganizationManagementUtil; +import org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.OrgResourceResolverService; import org.wso2.carbon.registry.core.Resource; import org.wso2.carbon.utils.CarbonUtils; @@ -81,6 +81,9 @@ public class ApplicationEmailTemplateTest extends PowerMockTestCase { @Mock OrganizationManager organizationManager; + @Mock + OrgResourceResolverService orgResourceResolverService; + @ObjectFactory public IObjectFactory getObjectFactory() { @@ -104,6 +107,7 @@ public void setUp() { when(i18nMgtDataHolder.getRegistryResourceMgtService()).thenReturn(resourceMgtService); when(i18nMgtDataHolder.getApplicationManagementService()).thenReturn(applicationManagementService); when(i18nMgtDataHolder.getOrganizationManager()).thenReturn(organizationManager); + when(i18nMgtDataHolder.getOrgResourceResolverService()).thenReturn(orgResourceResolverService); emailTemplateManager = new EmailTemplateManagerImpl(); mockStatic(OrganizationManagementUtil.class); @@ -127,7 +131,7 @@ public void testGetNotificationTemplate(String notificationChannel, String displ mockRegistryResource(notificationChannel, displayName, type, locale, contentType, content, null, null); mockIsValidTemplate(true, true); NotificationTemplate notificationTemplate = emailTemplateManager - .getNotificationTemplate(notificationChannel, type, locale, tenantDomain, applicationUuid); + .getNotificationTemplate(notificationChannel, type, locale, tenantDomain, applicationUuid, false); validateNotificationTemplate(notificationTemplate, notificationChannel); } @@ -148,35 +152,15 @@ public void testGetNotificationTemplateForSharedApps(String notificationChannel, String locale, String contentType, byte[] content, String applicationUuid) throws Exception { - String rootApplicationId = "root-application-id"; String subOrganizationId = "sub-organization-id"; - String primaryOrganizationId = "primary-organization-id"; - mockRegistryResource(notificationChannel, displayName, type, locale, contentType, content, tenantDomain, - rootApplicationId); + mockRegistryResource(notificationChannel, displayName, type, locale, contentType, content, subOrganizationId, + applicationUuid); // Successful scenario for resolving the root application. - when(OrganizationManagementUtil.isOrganization(ArgumentMatchers.eq(subOrganizationId))).thenReturn(true); - when(applicationManagementService.getMainAppId(ArgumentMatchers.eq(applicationUuid))).thenReturn( - rootApplicationId); - when(organizationManager.resolveOrganizationId(ArgumentMatchers.eq(subOrganizationId))).thenReturn(subOrganizationId); - when(organizationManager.getPrimaryOrganizationId(ArgumentMatchers.eq(subOrganizationId))).thenReturn(primaryOrganizationId); - when(organizationManager.resolveTenantDomain(ArgumentMatchers.eq(primaryOrganizationId))).thenReturn(tenantDomain); NotificationTemplate notificationTemplate = emailTemplateManager.getNotificationTemplate(notificationChannel, type, locale, subOrganizationId, - applicationUuid); + applicationUuid, false); validateNotificationTemplate(notificationTemplate, notificationChannel); - - // Error scenario for resolving the root application. - notificationTemplate = null; - when(applicationManagementService.getMainAppId(ArgumentMatchers.eq(applicationUuid))).thenThrow( - IdentityApplicationManagementServerException.class); - try { - notificationTemplate = emailTemplateManager.getNotificationTemplate(notificationChannel, type, locale, subOrganizationId, applicationUuid); - } catch (NotificationTemplateManagerException e) { - assertEquals(e.getErrorCode(), ERROR_CODE_ERROR_RESOLVING_MAIN_APPLICATION.getCode()); - assertEquals(e.getMessage(), ERROR_CODE_ERROR_RESOLVING_MAIN_APPLICATION.getMessage()); - } - assertNull(notificationTemplate); } /** @@ -199,12 +183,11 @@ public void testGetNotificationTemplateErrors(String notificationChannel, String String locale, String contentType, boolean isValidTemplate, boolean isValidLocale, String errorMsg, String expectedErrorCode, byte[] content, String applicationUuid) throws Exception { - when(OrganizationManagementUtil.isOrganization(tenantDomain)).thenReturn(false); mockIsValidTemplate(isValidTemplate, isValidLocale); try { mockRegistryResource(notificationChannel, displayName, type, locale, contentType, content, null, null); NotificationTemplate notificationTemplate = emailTemplateManager - .getNotificationTemplate(notificationChannel, type, locale, tenantDomain, applicationUuid); + .getNotificationTemplate(notificationChannel, type, locale, tenantDomain, applicationUuid, false); assertNull(notificationTemplate, "Cannot return a notificationTemplate"); } catch (NotificationTemplateManagerException e) { String errorCode = e.getErrorCode(); @@ -227,8 +210,9 @@ public void testGetNotificationTemplateErrors(String notificationChannel, String * @param scenarioCode Error scenario */ @Test(dataProvider = "addNotificationTemplateTypeProvider") - public void TestAddNotificationTemplateType(String templateName, String channel, String domain, String errorCode, - String errorMessage, int scenarioCode, String applicationUuid) { + public void TestAddNotificationTemplateType(String templateName, String channel, String domain, String orgId, + String errorCode, String errorMessage, int scenarioCode, + String applicationUuid) throws Exception { try { if (scenarioCode == 2) { @@ -238,6 +222,12 @@ public void TestAddNotificationTemplateType(String templateName, String channel, when(resourceMgtService.isResourceExists(Matchers.anyString(), Matchers.anyString())) .thenThrow(new IdentityRuntimeException("Test Error")); } + when(organizationManager.resolveOrganizationId(domain)).thenReturn(orgId); + when(orgResourceResolverService.getResourcesFromOrgHierarchy( + ArgumentMatchers.eq(orgId), + any(), + any())) + .thenReturn(false); emailTemplateManager .addNotificationTemplateType(templateName, channel, domain, applicationUuid); } catch (NotificationTemplateManagerException e) { @@ -363,6 +353,7 @@ private Object[][] addNotificationTemplateTypeProvider() { String testTemplateName = "Test template"; String testChannel = "Test Channel"; String testDomain = "Test Domain"; + String testOrgId = "test-org-id"; String applicationUuid = "test-uuid"; int testScenario1 = 1; @@ -378,11 +369,11 @@ private Object[][] addNotificationTemplateTypeProvider() { String errorMessage3 = "TEST runtime exception while looking for the resource : "; return new Object[][]{ - {StringUtils.EMPTY, testChannel, testDomain, expectedErrorCode1, errorMessage1, testScenario1, - applicationUuid}, - {testTemplateName, testChannel, testDomain, expectedErrorCode2, errorMessage2, testScenario2, + {StringUtils.EMPTY, testChannel, testDomain, testOrgId, expectedErrorCode1, errorMessage1, + testScenario1, applicationUuid}, + {testTemplateName, testChannel, testDomain, testOrgId, expectedErrorCode2, errorMessage2, testScenario2, applicationUuid}, - {testTemplateName, testChannel, testDomain, expectedErrorCode3, errorMessage3, testScenario3, + {testTemplateName, testChannel, testDomain, testOrgId, expectedErrorCode3, errorMessage3, testScenario3, applicationUuid} }; } diff --git a/components/email-mgt/org.wso2.carbon.email.mgt/src/test/java/org/wso2/carbon/email/mgt/OrganizationEmailTemplateTest.java b/components/email-mgt/org.wso2.carbon.email.mgt/src/test/java/org/wso2/carbon/email/mgt/OrganizationEmailTemplateTest.java index 6c718b98..e38eb221 100644 --- a/components/email-mgt/org.wso2.carbon.email.mgt/src/test/java/org/wso2/carbon/email/mgt/OrganizationEmailTemplateTest.java +++ b/components/email-mgt/org.wso2.carbon.email.mgt/src/test/java/org/wso2/carbon/email/mgt/OrganizationEmailTemplateTest.java @@ -20,6 +20,7 @@ import org.apache.axiom.om.OMElement; import org.apache.axiom.om.impl.builder.StAXOMBuilder; import org.apache.commons.lang.StringUtils; +import org.mockito.ArgumentMatchers; import org.mockito.Matchers; import org.mockito.Mock; import org.powermock.api.mockito.PowerMockito; @@ -36,13 +37,16 @@ import org.wso2.carbon.email.mgt.util.I18nEmailUtil; import org.wso2.carbon.identity.base.IdentityRuntimeException; import org.wso2.carbon.identity.base.IdentityValidationUtil; +import org.wso2.carbon.identity.common.testng.WithCarbonHome; import org.wso2.carbon.identity.core.persistence.registry.RegistryResourceMgtService; import org.wso2.carbon.identity.core.util.IdentityUtil; import org.wso2.carbon.identity.governance.IdentityMgtConstants; import org.wso2.carbon.identity.governance.exceptions.notiification.NotificationTemplateManagerException; import org.wso2.carbon.identity.governance.model.NotificationTemplate; import org.wso2.carbon.identity.governance.service.notification.NotificationChannels; +import org.wso2.carbon.identity.organization.management.service.OrganizationManager; import org.wso2.carbon.identity.organization.management.service.util.OrganizationManagementUtil; +import org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.OrgResourceResolverService; import org.wso2.carbon.registry.core.Resource; import org.wso2.carbon.utils.CarbonUtils; @@ -59,6 +63,7 @@ import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.MockitoAnnotations.initMocks; import static org.powermock.api.mockito.PowerMockito.mockStatic; import static org.powermock.api.mockito.PowerMockito.when; @@ -79,6 +84,12 @@ public class OrganizationEmailTemplateTest extends PowerMockTestCase { @Mock RegistryResourceMgtService resourceMgtService; + @Mock + OrganizationManager organizationManager; + + @Mock + OrgResourceResolverService orgResourceResolverService; + @Mock I18nMgtDataHolder i18nMgtDataHolder; @@ -92,14 +103,19 @@ public IObjectFactory getObjectFactory() { } private String tenantDomain = "carbon.super"; + private static final String ROOT_ORG_ID = "10084a8d-113f-4211-a0d5-efe36b082211"; @BeforeMethod - public void setUp() { + public void setUp() throws Exception { initMocks(this); mockStatic(I18nMgtDataHolder.class); i18nMgtDataHolder = PowerMockito.mock(I18nMgtDataHolder.class); when(I18nMgtDataHolder.getInstance()).thenReturn(i18nMgtDataHolder); + when(i18nMgtDataHolder.getOrganizationManager()).thenReturn(organizationManager); + when(i18nMgtDataHolder.getOrgResourceResolverService()).thenReturn(orgResourceResolverService); + + when(organizationManager.resolveOrganizationId(tenantDomain)).thenReturn(ROOT_ORG_ID); mockStatic(IdentityUtil.class); when(IdentityUtil.getProperty(NOTIFICATION_TEMPLATES_STORAGE_CONFIG)).thenReturn("registry"); @@ -125,11 +141,10 @@ public void setUp() { public void testGetNotificationTemplate(String notificationChannel, String displayName, String type, String locale, String contentType, byte[] content) throws Exception { - when(OrganizationManagementUtil.isOrganization(tenantDomain)).thenReturn(false); mockRegistryResource(notificationChannel, displayName, type, locale, contentType, content); mockIsValidTemplate(true, true); NotificationTemplate notificationTemplate = emailTemplateManager - .getNotificationTemplate(notificationChannel, type, locale, tenantDomain); + .getNotificationTemplate(notificationChannel, type, locale, tenantDomain, null, false); assertNotNull(notificationTemplate); assertNotNull(notificationTemplate.getBody(), "Template should have a notification body"); assertEquals(notificationTemplate.getNotificationChannel(), notificationChannel); @@ -170,7 +185,7 @@ public void testGetNotificationTemplateErrors(String notificationChannel, String try { mockRegistryResource(notificationChannel, displayName, type, locale, contentType, content); NotificationTemplate notificationTemplate = emailTemplateManager - .getNotificationTemplate(notificationChannel, type, locale, tenantDomain); + .getNotificationTemplate(notificationChannel, type, locale, tenantDomain, null, false); assertNull(notificationTemplate, "Cannot return a notificationTemplate"); } catch (NotificationTemplateManagerException e) { String errorCode = e.getErrorCode(); @@ -193,8 +208,9 @@ public void testGetNotificationTemplateErrors(String notificationChannel, String * @param scenarioCode Error scenario */ @Test(dataProvider = "addNotificationTemplateTypeProvider") - public void TestAddNotificationTemplateType(String templateName, String channel, String domain, String errorCode, - String errorMessage, int scenarioCode) { + public void TestAddNotificationTemplateType(String templateName, String channel, String domain, String orgId, + String errorCode, String errorMessage, int scenarioCode) + throws Exception { try { if (scenarioCode == 2) { @@ -204,6 +220,12 @@ public void TestAddNotificationTemplateType(String templateName, String channel, when(resourceMgtService.isResourceExists(Matchers.anyString(), Matchers.anyString())) .thenThrow(new IdentityRuntimeException("Test Error")); } + when(organizationManager.resolveOrganizationId(domain)).thenReturn(orgId); + when(orgResourceResolverService.getResourcesFromOrgHierarchy( + ArgumentMatchers.eq(orgId), + any(), + any())) + .thenReturn(false); emailTemplateManager .addNotificationTemplateType(templateName, channel, domain); } catch (NotificationTemplateManagerException e) { @@ -370,6 +392,7 @@ private Object[][] addNotificationTemplateTypeProvider() { String testTemplateName = "Test template"; String testChannel = "Test Channel"; String testDomain = "Test Domain"; + String testOrgId = "test-org-id"; int testScenario1 = 1; String expectedErrorCode1 = I18nMgtConstants.ErrorMessages.ERROR_CODE_EMPTY_TEMPLATE_NAME.getCode(); @@ -384,9 +407,12 @@ private Object[][] addNotificationTemplateTypeProvider() { String errorMessage3 = "TEST runtime exception while looking for the resource : "; return new Object[][]{ - {StringUtils.EMPTY, testChannel, testDomain, expectedErrorCode1, errorMessage1, testScenario1}, - {testTemplateName, testChannel, testDomain, expectedErrorCode2, errorMessage2, testScenario2}, - {testTemplateName, testChannel, testDomain, expectedErrorCode3, errorMessage3, testScenario3}, + {StringUtils.EMPTY, testChannel, testDomain, testOrgId, expectedErrorCode1, errorMessage1, + testScenario1}, + {testTemplateName, testChannel, testDomain, testOrgId, expectedErrorCode2, errorMessage2, + testScenario2}, + {testTemplateName, testChannel, testDomain, testOrgId, expectedErrorCode3, errorMessage3, + testScenario3}, }; } diff --git a/components/email-mgt/org.wso2.carbon.email.mgt/src/test/java/org/wso2/carbon/email/mgt/store/UnifiedTemplateManagerTest.java b/components/email-mgt/org.wso2.carbon.email.mgt/src/test/java/org/wso2/carbon/email/mgt/store/UnifiedTemplateManagerTest.java index 83cce954..9a3b4a18 100644 --- a/components/email-mgt/org.wso2.carbon.email.mgt/src/test/java/org/wso2/carbon/email/mgt/store/UnifiedTemplateManagerTest.java +++ b/components/email-mgt/org.wso2.carbon.email.mgt/src/test/java/org/wso2/carbon/email/mgt/store/UnifiedTemplateManagerTest.java @@ -30,17 +30,20 @@ import org.wso2.carbon.identity.core.util.IdentityUtil; import org.wso2.carbon.identity.governance.model.NotificationTemplate; import org.wso2.carbon.identity.governance.service.notification.NotificationChannels; +import org.wso2.carbon.identity.organization.management.service.OrganizationManager; +import org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service.OrgResourceResolverService; import org.wso2.carbon.utils.CarbonUtils; import java.util.ArrayList; import java.util.List; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.MockitoAnnotations.initMocks; import static org.powermock.api.mockito.PowerMockito.mockStatic; import static org.powermock.api.mockito.PowerMockito.when; -import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; import static org.wso2.carbon.email.mgt.constants.I18nMgtConstants.NOTIFICATION_TEMPLATES_STORAGE_CONFIG; @@ -53,6 +56,7 @@ public class UnifiedTemplateManagerTest extends PowerMockTestCase { private static final String tenantDomain = "carbon.super"; + private static final String ROOT_ORG_ID = "10084a8d-113f-4211-a0d5-efe36b082211"; @Mock I18nMgtDataHolder i18nMgtDataHolder; @@ -60,6 +64,10 @@ public class UnifiedTemplateManagerTest extends PowerMockTestCase { TemplatePersistenceManagerFactory templatePersistenceManagerFactory; @Mock TemplatePersistenceManager templatePersistenceManager; + @Mock + OrganizationManager organizationManager; + @Mock + OrgResourceResolverService orgResourceResolverService; UnifiedTemplateManager unifiedTemplateManager; List defaultSystemTemplates; @@ -68,7 +76,7 @@ public class UnifiedTemplateManagerTest extends PowerMockTestCase { @BeforeMethod - public void setUp() { + public void setUp() throws Exception { initTestNotificationTemplates(); @@ -77,6 +85,10 @@ public void setUp() { i18nMgtDataHolder = PowerMockito.mock(I18nMgtDataHolder.class); when(I18nMgtDataHolder.getInstance()).thenReturn(i18nMgtDataHolder); when(i18nMgtDataHolder.getDefaultEmailTemplates()).thenReturn(defaultSystemTemplates); + when(i18nMgtDataHolder.getOrganizationManager()).thenReturn(organizationManager); + when(i18nMgtDataHolder.getOrgResourceResolverService()).thenReturn(orgResourceResolverService); + + mockOrganizationManager(); mockStatic(IdentityUtil.class); when(IdentityUtil.getProperty(NOTIFICATION_TEMPLATES_STORAGE_CONFIG)).thenReturn("registry"); @@ -105,12 +117,11 @@ public void testIsNotificationTemplateExists() throws Exception { tenantDomain); notificationTemplate = positiveNotificationTemplate; - when(templatePersistenceManager.isNotificationTemplateExists( - notificationTemplate.getDisplayName(), - notificationTemplate.getLocale(), - notificationTemplate.getNotificationChannel(), - null, - tenantDomain)).thenReturn(true); + when(orgResourceResolverService.getResourcesFromOrgHierarchy( + eq(ROOT_ORG_ID), + any(), + any())) + .thenReturn(true); assertTrue(unifiedTemplateManager.isNotificationTemplateExists( notificationTemplate.getDisplayName(), notificationTemplate.getLocale(), @@ -118,12 +129,11 @@ public void testIsNotificationTemplateExists() throws Exception { null, tenantDomain)); - when(templatePersistenceManager.isNotificationTemplateExists( - notificationTemplate.getDisplayName(), - notificationTemplate.getLocale(), - notificationTemplate.getNotificationChannel(), - null, - tenantDomain)).thenReturn(false); + when(orgResourceResolverService.getResourcesFromOrgHierarchy( + eq(ROOT_ORG_ID), + any(), + any())) + .thenReturn(false); assertFalse(unifiedTemplateManager.isNotificationTemplateExists( notificationTemplate.getDisplayName(), notificationTemplate.getLocale(), @@ -292,4 +302,9 @@ private void initTestNotificationTemplates() { negativeNotificationTemplate.setDisplayName("dummyDisplayName"); negativeNotificationTemplate.setLocale("en_US"); } + + private void mockOrganizationManager() throws Exception { + + when(organizationManager.resolveOrganizationId(tenantDomain)).thenReturn(ROOT_ORG_ID); + } } diff --git a/pom.xml b/pom.xml index 354b5ce7..d49f80d2 100644 --- a/pom.xml +++ b/pom.xml @@ -487,7 +487,7 @@ - 1.11.18 + 1.11.21 [1.0.0, 3.0.0) @@ -534,7 +534,7 @@ [2.1.0,3.0.0) - 7.1.0 + 7.7.23 [7.1.0, 8.0.0) @@ -560,7 +560,7 @@ 1.4 - 6.9.10 + 7.4.0 2.0.2 2.22.0 3.8.0 From 567e38a811ea643ad56837dd79e9a385f0d5a650 Mon Sep 17 00:00:00 2001 From: dhaura Date: Tue, 10 Dec 2024 11:08:52 +0530 Subject: [PATCH 5/7] Handle NPE in checking template existence. --- .../mgt/store/UnifiedTemplateManager.java | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/store/UnifiedTemplateManager.java b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/store/UnifiedTemplateManager.java index f91d3a39..ecb6d042 100644 --- a/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/store/UnifiedTemplateManager.java +++ b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/store/UnifiedTemplateManager.java @@ -65,11 +65,8 @@ public void addNotificationTemplateType(String displayName, String notificationC public boolean isNotificationTemplateTypeExists(String displayName, String notificationChannel, String tenantDomain) throws NotificationTemplateManagerServerException { - boolean templateTypeExists = - systemDefaultTemplateManager.isNotificationTemplateTypeExists(displayName, notificationChannel, - tenantDomain); - - if (templateTypeExists) { + if (systemDefaultTemplateManager.isNotificationTemplateTypeExists(displayName, notificationChannel, + tenantDomain)) { return true; } @@ -79,12 +76,16 @@ public boolean isNotificationTemplateTypeExists(String displayName, String notif OrgResourceResolverService orgResourceResolverService = I18nMgtDataHolder.getInstance().getOrgResourceResolverService(); - return orgResourceResolverService.getResourcesFromOrgHierarchy( + Boolean templateTypeExists = orgResourceResolverService.getResourcesFromOrgHierarchy( organizationId, LambdaExceptionUtils.rethrowFunction( orgId -> notificationTemplateTypeExistenceRetriever(displayName, notificationChannel, orgId)), new FirstFoundAggregationStrategy<>()); + if (templateTypeExists != null) { + return templateTypeExists; + } + return false; } catch (OrganizationManagementException | OrgResourceHierarchyTraverseException e) { String errorMsg = String.format("Unexpected server error occurred while checking the existence of " + "email template type: %s for tenant: %s", displayName, tenantDomain); @@ -173,11 +174,8 @@ public boolean isNotificationTemplateExists(String displayName, String locale, S String applicationUuid, String tenantDomain) throws NotificationTemplateManagerServerException { - boolean templateExists = - systemDefaultTemplateManager.isNotificationTemplateExists(displayName, locale, notificationChannel, - null, tenantDomain); - - if (templateExists) { + if (systemDefaultTemplateManager.isNotificationTemplateExists(displayName, locale, notificationChannel, + null, tenantDomain)) { return true; } @@ -187,12 +185,16 @@ public boolean isNotificationTemplateExists(String displayName, String locale, S OrgResourceResolverService orgResourceResolverService = I18nMgtDataHolder.getInstance().getOrgResourceResolverService(); - return orgResourceResolverService.getResourcesFromOrgHierarchy( + Boolean templateExists = orgResourceResolverService.getResourcesFromOrgHierarchy( organizationId, LambdaExceptionUtils.rethrowFunction( orgId -> notificationTemplateExistenceRetriever(displayName, locale, notificationChannel, applicationUuid, orgId)), new FirstFoundAggregationStrategy<>()); + if (templateExists != null) { + return templateExists; + } + return false; } catch (OrganizationManagementException | OrgResourceHierarchyTraverseException e) { String errorMsg = String.format("Unexpected server error occurred while checking the existence of " + "email template with type: %s for tenant: %s", displayName, tenantDomain); From c081bc3d1d67eab2e0438badefc3862eb3d23597 Mon Sep 17 00:00:00 2001 From: dhaura Date: Tue, 10 Dec 2024 15:05:20 +0530 Subject: [PATCH 6/7] Add resolve param supported isEmailTemplateExists method. --- .../carbon/email/mgt/EmailTemplateManager.java | 18 ++++++++++++++++++ .../email/mgt/EmailTemplateManagerImpl.java | 15 ++++++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/EmailTemplateManager.java b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/EmailTemplateManager.java index ff6596b4..a28c0908 100644 --- a/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/EmailTemplateManager.java +++ b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/EmailTemplateManager.java @@ -309,4 +309,22 @@ default boolean isEmailTemplateExists(String templateTypeDisplayName, String loc throw new I18nEmailMgtException("Method not implemented"); } + + /** + * Checks if an email template exists for the specified template type, locale, tenant domain, and application UUID. + * + * @param templateTypeDisplayName The display name of the template type. + * @param locale The locale of the email template. + * @param tenantDomain The tenant domain in which to search for the template. + * @param applicationUuid The UUID of the application for which the template exists (optional). + * @param resolve If true, searches for the template by resolving through the organization + * hierarchy; if false, searches only within the specified tenant domain. + * @return True if the email template exists; false otherwise. + * @throws I18nEmailMgtException If an error occurs while checking the existence of the email template. + */ + default boolean isEmailTemplateExists(String templateTypeDisplayName, String locale, String tenantDomain, + String applicationUuid, boolean resolve) throws I18nEmailMgtException { + + throw new I18nEmailMgtException("isEmailTemplateExists method not implemented in " + this.getClass().getName()); + } } diff --git a/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/EmailTemplateManagerImpl.java b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/EmailTemplateManagerImpl.java index 7a002d7a..ab949fdb 100644 --- a/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/EmailTemplateManagerImpl.java +++ b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/EmailTemplateManagerImpl.java @@ -527,9 +527,22 @@ public boolean isEmailTemplateExists(String templateTypeDisplayName, String loca public boolean isEmailTemplateExists(String templateTypeDisplayName, String locale, String tenantDomain, String applicationUuid) throws I18nEmailMgtException { + /* When resolve param is not specified, the default behavior results in resolved template existence, + since resolved template existence is always required when sending emails at runtime. */ + return isEmailTemplateExists(templateTypeDisplayName, locale, tenantDomain, applicationUuid, true); + } + + @Override + public boolean isEmailTemplateExists(String templateTypeDisplayName, String locale, String tenantDomain, + String applicationUuid, boolean resolve) throws I18nEmailMgtException { + try { locale = normalizeLocaleFormat(locale); - return templatePersistenceManager.isNotificationTemplateExists(templateTypeDisplayName, locale, + if (resolve) { + return templatePersistenceManager.isNotificationTemplateExists(templateTypeDisplayName, locale, + NotificationChannels.EMAIL_CHANNEL.getChannelType(), applicationUuid, tenantDomain); + } + return userDefinedTemplatePersistenceManager.isNotificationTemplateExists(templateTypeDisplayName, locale, NotificationChannels.EMAIL_CHANNEL.getChannelType(), applicationUuid, tenantDomain); } catch (NotificationTemplateManagerServerException e) { String error = String.format("Error when retrieving email templates of %s tenant.", tenantDomain); From 6d3e85975ecc08e1845a9dac6c25786b8e86426c Mon Sep 17 00:00:00 2001 From: dhaura Date: Tue, 10 Dec 2024 15:13:11 +0530 Subject: [PATCH 7/7] Deprecate old isEmailTemplateExists method. --- .../java/org/wso2/carbon/email/mgt/EmailTemplateManager.java | 3 +++ .../org/wso2/carbon/email/mgt/EmailTemplateManagerImpl.java | 1 + 2 files changed, 4 insertions(+) diff --git a/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/EmailTemplateManager.java b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/EmailTemplateManager.java index a28c0908..681230aa 100644 --- a/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/EmailTemplateManager.java +++ b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/EmailTemplateManager.java @@ -295,6 +295,8 @@ default EmailTemplate getEmailTemplate(String templateType, String locale, Strin } /** + * @deprecated Use {@link #isEmailTemplateExists(String, String, String, String, boolean)} instead. + *

* Check whether the given email template type exists for the application. * * @param templateTypeDisplayName Display name of the template type. @@ -304,6 +306,7 @@ default EmailTemplate getEmailTemplate(String templateType, String locale, Strin * @return True if the template type exists, false otherwise. * @throws I18nEmailMgtException If an error occurred while checking the existence of the email template. */ + @Deprecated default boolean isEmailTemplateExists(String templateTypeDisplayName, String locale, String tenantDomain, String applicationUuid) throws I18nEmailMgtException { diff --git a/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/EmailTemplateManagerImpl.java b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/EmailTemplateManagerImpl.java index ab949fdb..d8771325 100644 --- a/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/EmailTemplateManagerImpl.java +++ b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/EmailTemplateManagerImpl.java @@ -523,6 +523,7 @@ public boolean isEmailTemplateExists(String templateTypeDisplayName, String loca return isEmailTemplateExists(templateTypeDisplayName, locale, tenantDomain, null); } + @Deprecated @Override public boolean isEmailTemplateExists(String templateTypeDisplayName, String locale, String tenantDomain, String applicationUuid) throws I18nEmailMgtException {