Skip to content

Commit

Permalink
Introduce B2B notification template inheritance.
Browse files Browse the repository at this point in the history
  • Loading branch information
dhaura committed Dec 5, 2024
1 parent f4e67d7 commit 24ad216
Show file tree
Hide file tree
Showing 8 changed files with 498 additions and 167 deletions.
11 changes: 11 additions & 0 deletions components/email-mgt/org.wso2.carbon.email.mgt/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@
<groupId>org.wso2.carbon.utils</groupId>
<artifactId>org.wso2.carbon.database.utils</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon.identity.organization.management</groupId>
<artifactId>org.wso2.carbon.identity.organization.resource.hierarchy.traverse.service</artifactId>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
Expand Down Expand Up @@ -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}",
Expand Down Expand Up @@ -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}",
</Import-Package>
</instructions>
</configuration>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,33 @@ default List<EmailTemplate> getEmailTemplateType(
throw new I18nEmailMgtException("Method not implemented");
}

/**
* Retrieves all email templates of a specific type for a given tenant and application UUID.
* <p>
* This method validates and fetches email templates based on the specified type. The behavior of the method
* depends on the {@code resolve} parameter:
* <ul>
* <li><b>Resolved Template (resolve = true):</b> Retrieves the templates resolved through the ancestor
* organization hierarchy.</li>
* <li><b>Current org's or app's template (resolve = false):</b> Retrieves the templates specific to the
* current organization or application.</li>
* </ul>
*
* @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<EmailTemplate> 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.
*
Expand Down Expand Up @@ -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.
* <p>
* This method resolves and retrieves an email template based on the provided parameters. The behavior is
* dependent on the {@code resolve} parameter:
* <ul>
* <li><b>Resolved template (resolve = true):</b> Retrieves the template resolved through the ancestor
* organization hierarchy.</li>
* <li><b>Current org's or app's template (resolve = false):</b> Retrieves the template specific to the
* current organization or application only.</li>
* </ul>
*
* @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.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -59,14 +55,14 @@
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.
*/
public class EmailTemplateManagerImpl implements EmailTemplateManager, NotificationTemplateManager {

private TemplatePersistenceManager templatePersistenceManager;
private TemplatePersistenceManager userDefinedTemplatePersistenceManager;

private static final Log log = LogFactory.getLog(EmailTemplateManagerImpl.class);

Expand All @@ -82,6 +78,8 @@ public EmailTemplateManagerImpl() {

TemplatePersistenceManagerFactory templatePersistenceManagerFactory = new TemplatePersistenceManagerFactory();
this.templatePersistenceManager = templatePersistenceManagerFactory.getTemplatePersistenceManager();
this.userDefinedTemplatePersistenceManager =
templatePersistenceManagerFactory.getUserDefinedTemplatePersistenceManager();
}

@Override
Expand Down Expand Up @@ -169,72 +167,52 @@ public void deleteEmailTemplateType(String emailTemplateDisplayName, String tena
public List<String> 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);
}
}

@Override
public List<EmailTemplate> getAllEmailTemplates(String tenantDomain) throws I18nEmailMgtException {

try {
if (OrganizationManagementUtil.isOrganization(tenantDomain)) {
// Return the root organization's email templates.
tenantDomain = getRootOrgTenantDomain(tenantDomain);
}
List<NotificationTemplate> 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);
}
}

@Override
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<EmailTemplate> 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<EmailTemplate> getEmailTemplateType(String templateDisplayName, String tenantDomain,
String applicationUuid) throws I18nEmailMgtException {

return getEmailTemplateType(templateDisplayName, tenantDomain, applicationUuid, false);
}

@Override
public List<EmailTemplate> getEmailTemplateType(
String templateDisplayName, String tenantDomain, String applicationUuid) throws I18nEmailMgtException {
String templateDisplayName, String tenantDomain, String applicationUuid, boolean resolve)
throws I18nEmailMgtException {

validateTemplateType(templateDisplayName, tenantDomain);

Expand All @@ -247,9 +225,14 @@ public List<EmailTemplate> getEmailTemplateType(
throw new I18nEmailMgtClientException(EMAIL_TEMPLATE_TYPE_NOT_FOUND, message);
}

List<NotificationTemplate> notificationTemplates =
templatePersistenceManager.listNotificationTemplates(templateDisplayName,
NotificationChannels.EMAIL_CHANNEL.getChannelType(), applicationUuid, tenantDomain);
List<NotificationTemplate> 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.";
Expand All @@ -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) {
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -817,18 +809,4 @@ private List<EmailTemplate> getEmailTemplateList(List<NotificationTemplate> 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);
}
}
Loading

0 comments on commit 24ad216

Please sign in to comment.