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: + *

+ * + * @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)