Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce B2B Notification Template Inheritance #291

Merged
15 changes: 15 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,14 @@
<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>commons-collections.wso2</groupId>
<artifactId>commons-collections</artifactId>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
Expand Down Expand Up @@ -147,6 +155,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 +183,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);
dhaura marked this conversation as resolved.
Show resolved Hide resolved
}

@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);
dhaura marked this conversation as resolved.
Show resolved Hide resolved
}

@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
Loading