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 new file mode 100644 index 00000000..f24acf81 --- /dev/null +++ b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/NotificationTemplateManagerImpl.java @@ -0,0 +1,716 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.email.mgt; + +import org.apache.commons.lang.StringUtils; +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.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; +import org.wso2.carbon.identity.governance.exceptions.notiification.NotificationTemplateManagerServerException; +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; + +import static org.wso2.carbon.email.mgt.constants.TemplateMgtConstants.DEFAULT_EMAIL_NOTIFICATION_LOCALE; +import static org.wso2.carbon.email.mgt.constants.TemplateMgtConstants.DEFAULT_SMS_NOTIFICATION_LOCALE; +import static org.wso2.carbon.email.mgt.util.I18nEmailUtil.normalizeLocaleFormat; + +/** + * Provides functionality to manage notification templates. + */ +public class NotificationTemplateManagerImpl implements NotificationTemplateManager { + + private static final Log log = LogFactory.getLog(NotificationTemplateManagerImpl.class); + + private final TemplatePersistenceManager userDefinedTemplatePersistenceManager; + private final TemplatePersistenceManager systemTemplatePersistenceManager; + private final TemplatePersistenceManager templatePersistenceManager; + + public NotificationTemplateManagerImpl() { + + TemplatePersistenceManagerFactory templatePersistenceManagerFactory = new TemplatePersistenceManagerFactory(); + this.userDefinedTemplatePersistenceManager = + templatePersistenceManagerFactory.getUserDefinedTemplatePersistenceManager(); + this.systemTemplatePersistenceManager = templatePersistenceManagerFactory.getSystemTemplatePersistenceManager(); + this.templatePersistenceManager = templatePersistenceManagerFactory.getTemplatePersistenceManager(); + } + + /** + * {@inheritDoc} + */ + @Override + public List getAllNotificationTemplateTypes(String notificationChannel, String tenantDomain) + 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<>(); + } catch (NotificationTemplateManagerServerException ex) { + 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); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void addNotificationTemplateType(String notificationChannel, String displayName, String tenantDomain) + throws NotificationTemplateManagerException { + + // For new additions display name is trimmed to avoid allowing surrounding white spaces. + // This is not done for existing display names for backward compatibility. + displayName = displayName.trim(); + validateDisplayNameOfTemplateType(displayName); + try { + if (templatePersistenceManager + .isNotificationTemplateTypeExists(displayName, notificationChannel, tenantDomain)) { + // This error is caught in the catch block below to generate the + // NotificationTemplateManagerServerException. + throw new NotificationTemplateManagerInternalException( + TemplateMgtConstants.ErrorCodes.TEMPLATE_TYPE_ALREADY_EXISTS, StringUtils.EMPTY); + } + templatePersistenceManager.addNotificationTemplateType(displayName, notificationChannel, + tenantDomain); + } catch (NotificationTemplateManagerServerException e) { + String code = I18nEmailUtil.prependOperationScenarioToErrorCode( + TemplateMgtConstants.ErrorMessages.ERROR_CODE_ERROR_ADDING_TEMPLATE.getCode(), + TemplateMgtConstants.ErrorScenarios.NOTIFICATION_TEMPLATE_MANAGER); + String message = String.format( + TemplateMgtConstants.ErrorMessages.ERROR_CODE_ERROR_ADDING_TEMPLATE.getMessage(), displayName, + tenantDomain); + throw new NotificationTemplateManagerException(code, message, e); + } catch (NotificationTemplateManagerInternalException e) { + if (TemplateMgtConstants.ErrorCodes.TEMPLATE_TYPE_ALREADY_EXISTS.equals(e.getErrorCode())) { + String code = I18nEmailUtil.prependOperationScenarioToErrorCode( + TemplateMgtConstants.ErrorMessages.ERROR_CODE_TEMPLATE_TYPE_ALREADY_EXISTS.getCode(), + TemplateMgtConstants.ErrorScenarios.NOTIFICATION_TEMPLATE_MANAGER); + String message = String.format( + TemplateMgtConstants.ErrorMessages.ERROR_CODE_TEMPLATE_TYPE_ALREADY_EXISTS.getMessage(), + displayName, tenantDomain); + throw new NotificationTemplateManagerServerException(code, message, e); + } + if (log.isDebugEnabled()) { + log.debug("Error when adding template type : " + displayName + " to tenant : " + tenantDomain, e); + } + } + } + + /** + * {@inheritDoc} + */ + @Override + public void deleteNotificationTemplateType(String notificationChannel, String templateDisplayName, + String tenantDomain) + throws NotificationTemplateManagerException { + + validateDisplayNameOfTemplateType(templateDisplayName); + verifyTemplateTypeExists(templateDisplayName, notificationChannel, tenantDomain); + + // System template types are cannot be deleted since these are hard coded values. + if (systemTemplatePersistenceManager.isNotificationTemplateTypeExists(templateDisplayName, notificationChannel, + null)) { + String code = I18nEmailUtil.prependOperationScenarioToErrorCode( + TemplateMgtConstants.ErrorMessages.ERROR_CODE_SYSTEM_RESOURCE_DELETION_NOT_ALLOWED.getCode(), + TemplateMgtConstants.ErrorScenarios.NOTIFICATION_TEMPLATE_MANAGER); + String message = String.format( + TemplateMgtConstants.ErrorMessages.ERROR_CODE_SYSTEM_RESOURCE_DELETION_NOT_ALLOWED.getMessage(), + "System template types are not eligible for deletion."); + throw new NotificationTemplateManagerServerException(code, message); + } + + try { + templatePersistenceManager.deleteNotificationTemplateType(templateDisplayName, + notificationChannel, tenantDomain); + } catch (NotificationTemplateManagerException ex) { + String errorMsg = String.format + ("Error deleting template type %s from %s tenant.", templateDisplayName, tenantDomain); + throw handleServerException(errorMsg, ex); + } + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isNotificationTemplateTypeExists(String notificationChannel, String templateTypeDisplayName, + String tenantDomain) + throws NotificationTemplateManagerException { + + try { + return templatePersistenceManager.isNotificationTemplateTypeExists(templateTypeDisplayName, + notificationChannel, tenantDomain); + } catch (NotificationTemplateManagerServerException e) { + String error = String.format("Error when retrieving templates of %s tenant.", tenantDomain); + throw handleServerException(error, e); + } + } + + /** + * {@inheritDoc} + */ + @Override + public List getAllNotificationTemplates(String notificationChannel, String tenantDomain) + throws NotificationTemplateManagerException { + + try { + if (OrganizationManagementUtil.isOrganization(tenantDomain)) { + // Return the root organization's email templates. + tenantDomain = getRootOrgTenantDomain(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); + } + } + + /** + * {@inheritDoc} + */ + @Override + public List getNotificationTemplatesOfType(String notificationChannel, + String templateDisplayName, String tenantDomain) + throws NotificationTemplateManagerException { + + return getNotificationTemplatesOfType(notificationChannel, templateDisplayName, tenantDomain, null); + } + + /** + * {@inheritDoc} + */ + @Override + public List getNotificationTemplatesOfType(String notificationChannel, + 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); + } + } + /** + * {@inheritDoc} + */ + @Override + public NotificationTemplate getNotificationTemplate(String notificationChannel, String templateType, String locale, + String tenantDomain) + throws NotificationTemplateManagerException { + + return getNotificationTemplate(notificationChannel, templateType, locale, tenantDomain, null); + } + + /** + * {@inheritDoc} + */ + @Override + public NotificationTemplate getNotificationTemplate(String notificationChannel, String templateType, String locale, + String tenantDomain, String applicationUuid) + 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); + + String defaultLocale = getDefaultNotificationLocale(notificationChannel); + if (notificationTemplate == null) { + if (StringUtils.equalsIgnoreCase(locale, defaultLocale)) { + // Template is not available in the default locale. Therefore, breaking the flow at the consuming side + // to avoid NPE. + String code = I18nEmailUtil.prependOperationScenarioToErrorCode( + TemplateMgtConstants.ErrorMessages.ERROR_CODE_TEMPLATE_NOT_FOUND.getCode(), + TemplateMgtConstants.ErrorScenarios.NOTIFICATION_TEMPLATE_MANAGER); + String errorMessage = String + .format(TemplateMgtConstants.ErrorMessages.ERROR_CODE_TEMPLATE_NOT_FOUND.getMessage(), + templateType, tenantDomain); + throw new NotificationTemplateManagerServerException(code, errorMessage); + } else { + if (log.isDebugEnabled()) { + String message = String + .format("'%s' template in '%s' locale was not found in '%s' tenant. Trying to return the " + + "template in default locale : '%s'", templateType, locale, tenantDomain, + defaultLocale); + log.debug(message); + } + // Try to get the template type in default locale. + return getNotificationTemplate(notificationChannel, templateType, defaultLocale, tenantDomain); + } + } + return notificationTemplate; + } + + /** + * {@inheritDoc} + */ + @Override + public List getAllSystemNotificationTemplatesOfType(String notificationChannel, + String templateDisplayName) throws NotificationTemplateManagerException { + + verifySystemTemplateTypeExists(templateDisplayName, notificationChannel); + return systemTemplatePersistenceManager.listNotificationTemplates(templateDisplayName, + notificationChannel, null, null); + } + + /** + * {@inheritDoc} + */ + @Override + public NotificationTemplate getSystemNotificationTemplate(String notificationChannel, String templateType, + String locale) + throws NotificationTemplateManagerException { + + validateTemplateLocale(locale); + locale = normalizeLocaleFormat(locale); + validateDisplayNameOfTemplateType(templateType); + verifySystemTemplateTypeExists(templateType, notificationChannel); + NotificationTemplate notificationTemplate = + systemTemplatePersistenceManager.getNotificationTemplate(templateType,locale, notificationChannel, + null, null); + + String defaultLocale = getDefaultNotificationLocale(notificationChannel); + if (notificationTemplate == null) { + if (StringUtils.equalsIgnoreCase(locale, defaultLocale)) { + // Template is not available in the default locale. Therefore, breaking the flow at the consuming side + // to avoid NPE. + String code = I18nEmailUtil.prependOperationScenarioToErrorCode( + TemplateMgtConstants.ErrorMessages.ERROR_CODE_TEMPLATE_NOT_FOUND.getCode(), + TemplateMgtConstants.ErrorScenarios.NOTIFICATION_TEMPLATE_MANAGER); + String errorMessage = String + .format(TemplateMgtConstants.ErrorMessages.ERROR_CODE_SYSTEM_TEMPLATE_NOT_FOUND.getMessage(), + templateType); + throw new NotificationTemplateManagerServerException(code, errorMessage); + } else { + if (log.isDebugEnabled()) { + String message = String + .format("'%s' system template in '%s' locale was not found. Trying to return the " + + "template in default locale : '%s'", templateType, locale, + defaultLocale); + log.debug(message); + } + // Try to get the template type in default locale. + return getSystemNotificationTemplate(notificationChannel, templateType, defaultLocale); + } + } + return notificationTemplate; + } + + /** + * {@inheritDoc} + */ + @Override + public void addNotificationTemplate(NotificationTemplate notificationTemplate, String tenantDomain) + throws NotificationTemplateManagerException { + + addNotificationTemplate(notificationTemplate, tenantDomain, null); + } + + /** + * {@inheritDoc} + */ + @Override + public void addNotificationTemplate(NotificationTemplate notificationTemplate, String tenantDomain, + String applicationUuid) throws NotificationTemplateManagerException { + + // For new additions display name is trimmed to avoid allowing surrounding white spaces. + // This is not done for existing display names for backward compatibility. + notificationTemplate.setDisplayName(notificationTemplate.getDisplayName().trim()); + validateNotificationTemplate(notificationTemplate); + String displayName = notificationTemplate.getDisplayName(); + String locale = notificationTemplate.getLocale(); + String notificationChannel = notificationTemplate.getNotificationChannel(); + locale = normalizeLocaleFormat(locale); + if (notificationTemplate.getLocale() != null && !notificationTemplate.getLocale().equals(locale)) { + notificationTemplate.setLocale(locale); + } + verifyTemplateTypeExists(displayName, notificationChannel, tenantDomain); + if (userDefinedTemplatePersistenceManager.isNotificationTemplateExists(displayName, locale, notificationChannel, + applicationUuid, tenantDomain)) { + String code = I18nEmailUtil.prependOperationScenarioToErrorCode( + TemplateMgtConstants.ErrorMessages.ERROR_CODE_TEMPLATE_ALREADY_EXISTS.getCode(), + TemplateMgtConstants.ErrorScenarios.NOTIFICATION_TEMPLATE_MANAGER); + String message = String.format( + TemplateMgtConstants.ErrorMessages.ERROR_CODE_TEMPLATE_ALREADY_EXISTS.getMessage(), displayName, + tenantDomain); + throw new NotificationTemplateManagerServerException(code, message); + } + try { + userDefinedTemplatePersistenceManager.addOrUpdateNotificationTemplate(notificationTemplate, applicationUuid, + tenantDomain); + } catch (NotificationTemplateManagerServerException e) { + String code = I18nEmailUtil.prependOperationScenarioToErrorCode( + TemplateMgtConstants.ErrorMessages.ERROR_CODE_ERROR_ADDING_TEMPLATE.getCode(), + TemplateMgtConstants.ErrorScenarios.NOTIFICATION_TEMPLATE_MANAGER); + String message = + String.format(TemplateMgtConstants.ErrorMessages.ERROR_CODE_ERROR_ADDING_TEMPLATE.getMessage(), + displayName, tenantDomain); + throw new NotificationTemplateManagerServerException(code, message, e); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void updateNotificationTemplate(NotificationTemplate notificationTemplate, String tenantDomain) + throws NotificationTemplateManagerException { + + updateNotificationTemplate(notificationTemplate, tenantDomain, null); + } + + /** + * {@inheritDoc} + */ + @Override + public void updateNotificationTemplate(NotificationTemplate notificationTemplate, String tenantDomain, + String applicationUuid) throws NotificationTemplateManagerException { + + validateNotificationTemplate(notificationTemplate); + String displayName = notificationTemplate.getDisplayName(); + String locale = notificationTemplate.getLocale(); + String notificationChannel = notificationTemplate.getNotificationChannel(); + locale = normalizeLocaleFormat(locale); + if (notificationTemplate.getLocale() != null && !notificationTemplate.getLocale().equals(locale)) { + notificationTemplate.setLocale(locale); + } + verifyTemplateTypeExists(displayName, notificationChannel, tenantDomain); + if (!userDefinedTemplatePersistenceManager.isNotificationTemplateExists( + displayName, locale, notificationChannel, applicationUuid, tenantDomain)) { + String code = I18nEmailUtil.prependOperationScenarioToErrorCode( + TemplateMgtConstants.ErrorMessages.ERROR_CODE_TEMPLATE_NOT_FOUND.getCode(), + TemplateMgtConstants.ErrorScenarios.NOTIFICATION_TEMPLATE_MANAGER); + String message = String.format( + TemplateMgtConstants.ErrorMessages.ERROR_CODE_TEMPLATE_NOT_FOUND.getMessage(), displayName, + tenantDomain); + throw new NotificationTemplateManagerServerException(code, message); + } + try { + userDefinedTemplatePersistenceManager.addOrUpdateNotificationTemplate(notificationTemplate, applicationUuid, + tenantDomain); + } catch (NotificationTemplateManagerServerException e) { + String code = I18nEmailUtil.prependOperationScenarioToErrorCode( + TemplateMgtConstants.ErrorMessages.ERROR_CODE_ERROR_UPDATING_TEMPLATE.getCode(), + TemplateMgtConstants.ErrorScenarios.NOTIFICATION_TEMPLATE_MANAGER); + String message = + String.format(TemplateMgtConstants.ErrorMessages.ERROR_CODE_ERROR_UPDATING_TEMPLATE.getMessage(), + displayName, locale, tenantDomain); + throw new NotificationTemplateManagerServerException(code, message, e); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void deleteNotificationTemplate(String notificationChannel, String templateDisplayName, String locale, + String tenantDomain) + throws NotificationTemplateManagerException { + + deleteNotificationTemplate(notificationChannel, templateDisplayName, locale, tenantDomain, null); + } + + /** + * {@inheritDoc} + */ + @Override + public void deleteNotificationTemplate(String notificationChannel, String templateDisplayName, String locale, + String tenantDomain, String applicationUuid) + throws NotificationTemplateManagerException { + + // Validate the name and locale code. + if (StringUtils.isBlank(templateDisplayName)) { + String errorCode = + I18nEmailUtil.prependOperationScenarioToErrorCode( + TemplateMgtConstants.ErrorMessages.ERROR_CODE_INVALID_TEMPLATE_DISPLAY_NAME.getCode(), + TemplateMgtConstants.ErrorScenarios.NOTIFICATION_TEMPLATE_MANAGER); + throw new NotificationTemplateManagerClientException( errorCode, + TemplateMgtConstants.ErrorMessages.ERROR_CODE_INVALID_TEMPLATE_DISPLAY_NAME.getMessage()); + } + if (StringUtils.isBlank(locale)) { + String errorCode = + I18nEmailUtil.prependOperationScenarioToErrorCode( + TemplateMgtConstants.ErrorMessages.ERROR_CODE_INVALID_LOCALE.getCode(), + TemplateMgtConstants.ErrorScenarios.NOTIFICATION_TEMPLATE_MANAGER); + throw new NotificationTemplateManagerClientException(errorCode, + TemplateMgtConstants.ErrorMessages.ERROR_CODE_INVALID_LOCALE.getMessage()); + } + locale = normalizeLocaleFormat(locale); + try { + userDefinedTemplatePersistenceManager.deleteNotificationTemplate(templateDisplayName, locale, + notificationChannel, applicationUuid, tenantDomain); + } catch (NotificationTemplateManagerServerException ex) { + String msg = String.format("Error deleting %s:%s template from %s tenant registry.", templateDisplayName, + locale, tenantDomain); + throw handleServerException(msg, ex); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void resetNotificationTemplateType(String notificationChannel, String templateType, String tenantDomain) + throws NotificationTemplateManagerException { + + try { + templatePersistenceManager.deleteAllNotificationTemplates(templateType, notificationChannel, + tenantDomain); + } catch (NotificationTemplateManagerException e) { + String msg = String.format("Error deleting custom templates for %s template type %s from %s .", + notificationChannel, templateType, tenantDomain); + throw handleServerException(msg, e); + } + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isNotificationTemplateExists(String notificationChannel, String templateDisplayName, String locale, + String tenantDomain) + throws NotificationTemplateManagerException { + + return isNotificationTemplateExists(notificationChannel, templateDisplayName, locale, tenantDomain, null); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isNotificationTemplateExists(String notificationChannel, String templateDisplayName, String locale, + String tenantDomain, String applicationUuid) + throws NotificationTemplateManagerException { + + try { + locale = normalizeLocaleFormat(locale); + return userDefinedTemplatePersistenceManager.isNotificationTemplateExists(templateDisplayName, locale, + notificationChannel, applicationUuid, tenantDomain); + } catch (NotificationTemplateManagerServerException e) { + String error = String.format("Error when retrieving notification templates of %s tenant.", tenantDomain); + throw new NotificationTemplateManagerServerException(error, e); + } + } + + private void validateDisplayNameOfTemplateType(String templateDisplayName) + throws NotificationTemplateManagerClientException { + + if (StringUtils.isBlank(templateDisplayName)) { + String errorCode = + I18nEmailUtil.prependOperationScenarioToErrorCode( + TemplateMgtConstants.ErrorMessages.ERROR_CODE_EMPTY_TEMPLATE_NAME.getCode(), + TemplateMgtConstants.ErrorScenarios.NOTIFICATION_TEMPLATE_MANAGER); + throw new NotificationTemplateManagerClientException(errorCode, + TemplateMgtConstants.ErrorMessages.ERROR_CODE_EMPTY_TEMPLATE_NAME.getMessage()); + } + } + + 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 { + + log.error(errorMsg); + return new NotificationTemplateManagerServerException(errorMsg, ex); + } + + private void validateTemplateLocale(String locale) throws NotificationTemplateManagerClientException { + + if (StringUtils.isBlank(locale)) { + String errorCode = + I18nEmailUtil.prependOperationScenarioToErrorCode( + TemplateMgtConstants.ErrorMessages.ERROR_CODE_EMPTY_LOCALE.getCode(), + TemplateMgtConstants.ErrorScenarios.NOTIFICATION_TEMPLATE_MANAGER); + throw new NotificationTemplateManagerClientException(errorCode, + TemplateMgtConstants.ErrorMessages.ERROR_CODE_EMPTY_LOCALE.getMessage()); + } + if (!locale.matches("^[a-z]{2}_[A-Z]{2}$")) { + String errorCode = + I18nEmailUtil.prependOperationScenarioToErrorCode( + TemplateMgtConstants.ErrorMessages.ERROR_CODE_INVALID_LOCALE.getCode(), + TemplateMgtConstants.ErrorScenarios.NOTIFICATION_TEMPLATE_MANAGER); + throw new NotificationTemplateManagerClientException(errorCode, + TemplateMgtConstants.ErrorMessages.ERROR_CODE_INVALID_LOCALE.getMessage()); + } + } + + private void validateNotificationTemplate(NotificationTemplate notificationTemplate) + throws NotificationTemplateManagerClientException { + + if (notificationTemplate == null) { + String errorCode = + I18nEmailUtil.prependOperationScenarioToErrorCode( + TemplateMgtConstants.ErrorMessages.ERROR_CODE_NULL_TEMPLATE_OBJECT.getCode(), + TemplateMgtConstants.ErrorScenarios.NOTIFICATION_TEMPLATE_MANAGER); + throw new NotificationTemplateManagerClientException(errorCode, + TemplateMgtConstants.ErrorMessages.ERROR_CODE_NULL_TEMPLATE_OBJECT.getMessage()); + } + String displayName = notificationTemplate.getDisplayName(); + validateDisplayNameOfTemplateType(displayName); + String normalizedDisplayName = I18nEmailUtil.getNormalizedName(displayName); + if (!StringUtils.equalsIgnoreCase(normalizedDisplayName, notificationTemplate.getType())) { + if (log.isDebugEnabled()) { + String message = String.format("In the template normalizedDisplayName : %s is not equal to the " + + "template type : %s. Therefore template type is sent to : %s", normalizedDisplayName, + notificationTemplate.getType(), normalizedDisplayName); + log.debug(message); + } + notificationTemplate.setType(normalizedDisplayName); + } + validateTemplateLocale(notificationTemplate.getLocale()); + String body = notificationTemplate.getBody(); + String subject = notificationTemplate.getSubject(); + String footer = notificationTemplate.getFooter(); + if (StringUtils.isBlank(notificationTemplate.getNotificationChannel())) { + String errorCode = + I18nEmailUtil.prependOperationScenarioToErrorCode( + TemplateMgtConstants.ErrorMessages.ERROR_CODE_EMPTY_TEMPLATE_CHANNEL.getCode(), + TemplateMgtConstants.ErrorScenarios.NOTIFICATION_TEMPLATE_MANAGER); + throw new NotificationTemplateManagerClientException(errorCode, + TemplateMgtConstants.ErrorMessages.ERROR_CODE_EMPTY_TEMPLATE_CHANNEL.getMessage()); + } + if (NotificationChannels.SMS_CHANNEL.getChannelType() + .equalsIgnoreCase(notificationTemplate.getNotificationChannel())) { + if (StringUtils.isBlank(body)) { + String errorCode = + I18nEmailUtil.prependOperationScenarioToErrorCode( + TemplateMgtConstants.ErrorMessages.ERROR_CODE_INVALID_SMS_TEMPLATE.getCode(), + TemplateMgtConstants.ErrorScenarios.NOTIFICATION_TEMPLATE_MANAGER); + throw new NotificationTemplateManagerClientException(errorCode, + TemplateMgtConstants.ErrorMessages.ERROR_CODE_INVALID_SMS_TEMPLATE.getMessage()); + } + if (StringUtils.isNotBlank(subject) || StringUtils.isNotBlank(footer)) { + String errorCode = + I18nEmailUtil.prependOperationScenarioToErrorCode( + TemplateMgtConstants.ErrorMessages.ERROR_CODE_INVALID_SMS_TEMPLATE_CONTENT.getCode(), + TemplateMgtConstants.ErrorScenarios.NOTIFICATION_TEMPLATE_MANAGER); + throw new NotificationTemplateManagerClientException(errorCode, + TemplateMgtConstants.ErrorMessages.ERROR_CODE_INVALID_SMS_TEMPLATE_CONTENT.getMessage()); + } + } else { + if (StringUtils.isBlank(subject) || StringUtils.isBlank(body)) { + String errorCode = + I18nEmailUtil.prependOperationScenarioToErrorCode( + TemplateMgtConstants.ErrorMessages.ERROR_CODE_INVALID_EMAIL_TEMPLATE.getCode(), + TemplateMgtConstants.ErrorScenarios.NOTIFICATION_TEMPLATE_MANAGER); + throw new NotificationTemplateManagerClientException(errorCode, + TemplateMgtConstants.ErrorMessages.ERROR_CODE_INVALID_EMAIL_TEMPLATE.getMessage()); + } + } + } + + private String getDefaultNotificationLocale(String notificationChannel) { + + if (NotificationChannels.SMS_CHANNEL.getChannelType().equals(notificationChannel)) { + return DEFAULT_SMS_NOTIFICATION_LOCALE; + } else { + return DEFAULT_EMAIL_NOTIFICATION_LOCALE; + } + } + + private void verifySystemTemplateTypeExists(String templateType, String notificationChannel) + throws NotificationTemplateManagerServerException { + + if (!systemTemplatePersistenceManager.isNotificationTemplateTypeExists(templateType, notificationChannel, + null)) { + String code = I18nEmailUtil.prependOperationScenarioToErrorCode( + TemplateMgtConstants.ErrorMessages.ERROR_CODE_SYSTEM_TEMPLATE_TYPE_NOT_FOUND.getCode(), + TemplateMgtConstants.ErrorScenarios.NOTIFICATION_TEMPLATE_MANAGER); + String message = String.format( + TemplateMgtConstants.ErrorMessages.ERROR_CODE_SYSTEM_TEMPLATE_TYPE_NOT_FOUND.getMessage(), + templateType); + throw new NotificationTemplateManagerServerException(code, message); + } + } + + private void verifyTemplateTypeExists(String templateType, String notificationChannel, String tenantDomain) + throws NotificationTemplateManagerServerException { + + if (!templatePersistenceManager.isNotificationTemplateTypeExists(templateType, notificationChannel, + tenantDomain)) { + String code = I18nEmailUtil.prependOperationScenarioToErrorCode( + TemplateMgtConstants.ErrorMessages.ERROR_CODE_TEMPLATE_TYPE_NOT_FOUND.getCode(), + TemplateMgtConstants.ErrorScenarios.NOTIFICATION_TEMPLATE_MANAGER); + String message = String.format( + TemplateMgtConstants.ErrorMessages.ERROR_CODE_TEMPLATE_TYPE_NOT_FOUND.getMessage(), + templateType, tenantDomain); + throw new NotificationTemplateManagerServerException(code, message); + } + } +} diff --git a/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/constants/I18nMgtConstants.java b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/constants/I18nMgtConstants.java index 5215ec2c..0a4b7a47 100644 --- a/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/constants/I18nMgtConstants.java +++ b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/constants/I18nMgtConstants.java @@ -65,6 +65,10 @@ private I18nMgtConstants() {} public static final String NOTIFICATION_TEMPLATES_STORAGE_CONFIG = "DataStorageType.NotificationTemplates"; public static final String NOTIFICATION_TEMPLATES_LEGACY_TENANTS = "NotificationTemplates.LegacyTenants.Tenant"; + public static final String SERVICE_PROPERTY_KEY_SERVICE_NAME = "service.name"; + public static final String SERVICE_PROPERTY_VAL_EMAIL_TEMPLATE_MANAGER = "EmailTemplateManager"; + public static final String SERVICE_PROPERTY_VAL_NOTIFICATION_TEMPLATE_MANAGER = "NotificationTemplateManager"; + public static class ErrorMsg { private ErrorMsg() { diff --git a/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/constants/SQLConstants.java b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/constants/SQLConstants.java index e6a96e0d..97852514 100644 --- a/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/constants/SQLConstants.java +++ b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/constants/SQLConstants.java @@ -97,4 +97,7 @@ public class SQLConstants { public static final String DELETE_APP_NOTIFICATION_TEMPLATES_BY_TYPE_SQL = "DELETE FROM IDN_NOTIFICATION_APP_TEMPLATE WHERE TYPE_ID = (" + GET_NOTIFICATION_TYPE_ID_SQL + ") AND APP_ID = :APP_ID; AND TENANT_ID = :TENANT_ID;"; + public static final String DELETE_ALL_APP_NOTIFICATION_TEMPLATES_BY_TYPE_SQL = + "DELETE FROM IDN_NOTIFICATION_APP_TEMPLATE WHERE TYPE_ID = (" + GET_NOTIFICATION_TYPE_ID_SQL + + ") AND TENANT_ID = :TENANT_ID;"; } diff --git a/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/constants/TemplateMgtConstants.java b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/constants/TemplateMgtConstants.java new file mode 100644 index 00000000..aea6a620 --- /dev/null +++ b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/constants/TemplateMgtConstants.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2023-2024, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.email.mgt.constants; + +public class TemplateMgtConstants { + + private TemplateMgtConstants() {} + + public static final String DEFAULT_EMAIL_NOTIFICATION_LOCALE = "en_US"; + public static final String DEFAULT_SMS_NOTIFICATION_LOCALE = "en_US"; + + /** + * Class which contains the error scenarios. + */ + public static class ErrorScenarios { + + // NTM - NOTIFICATION TEMPLATE MANAGER + public static final String NOTIFICATION_TEMPLATE_MANAGER = "NTM"; + } + + /** + * Class which contains the error codes for template management. + */ + public static class ErrorCodes { + + public static final String TEMPLATE_TYPE_ALREADY_EXISTS = "65001"; + public static final String TEMPLATE_TYPE_NOT_FOUND = "65002"; + public static final String TEMPLATE_ALREADY_EXISTS = "65003"; + public static final String TEMPLATE_NOT_FOUND = "65004"; + public static final String ERROR_ADDING_TEMPLATE = "65005"; + public static final String ERROR_UPDATING_TEMPLATE = "65006"; + public static final String ERROR_SYSTEM_RESOURCE_DELETION_NOT_ALLOWED = "65007"; + public static final String ERROR_RESOLVING_MAIN_APPLICATION = "65008"; + } + + /** + * Enum which contains error codes and corresponding error messages. + */ + public enum ErrorMessages { + + ERROR_CODE_EMPTY_TEMPLATE_NAME("60001", "Notification template name cannot be empty."), + ERROR_CODE_EMPTY_LOCALE("60002", "Locale code cannot be empty"), + ERROR_CODE_INVALID_LOCALE("60003", "Locale code is invalid."), + ERROR_CODE_EMPTY_TEMPLATE_CHANNEL("60004", "Notification template channel cannot be empty"), + ERROR_CODE_INVALID_SMS_TEMPLATE("60005", "Body of a SMS template cannot be empty."), + ERROR_CODE_INVALID_SMS_TEMPLATE_CONTENT("60006", "SMS template cannot have a subject or footer"), + ERROR_CODE_INVALID_EMAIL_TEMPLATE("60007", "Subject/Body/Footer sections of an email template " + + "cannot be empty."), + ERROR_CODE_INVALID_TEMPLATE_DISPLAY_NAME("60008", "Invalid template display name."), + ERROR_CODE_NULL_TEMPLATE_OBJECT("60009", "Notification template is not provided."), + ERROR_CODE_TEMPLATE_TYPE_ALREADY_EXISTS(ErrorCodes.TEMPLATE_TYPE_ALREADY_EXISTS, + "Notification template type : %s already exists in tenant : %s"), + ERROR_CODE_TEMPLATE_TYPE_NOT_FOUND(ErrorCodes.TEMPLATE_TYPE_NOT_FOUND, "Notification template type :" + + " %s doesn't exist in tenant : %s"), + ERROR_CODE_TEMPLATE_ALREADY_EXISTS(ErrorCodes.TEMPLATE_ALREADY_EXISTS, "Notification template : %s" + + " already exists in tenant : %s"), + ERROR_CODE_TEMPLATE_NOT_FOUND(ErrorCodes.TEMPLATE_NOT_FOUND, "Notification template : %s " + + "doesn't exist in tenant : %s"), + ERROR_CODE_SYSTEM_TEMPLATE_TYPE_NOT_FOUND(ErrorCodes.TEMPLATE_TYPE_NOT_FOUND, + "System notification template type : %s doesn't exist."), + ERROR_CODE_SYSTEM_TEMPLATE_NOT_FOUND(ErrorCodes.TEMPLATE_NOT_FOUND, "System notification " + + "template : %s doesn't exist"), + ERROR_CODE_ERROR_ADDING_TEMPLATE(ErrorCodes.ERROR_ADDING_TEMPLATE, "Error when adding template : %s" + + " to tenant : %s"), + ERROR_CODE_ERROR_UPDATING_TEMPLATE(ErrorCodes.ERROR_UPDATING_TEMPLATE, "Error when updating " + + "template : %s on tenant : %s"), + ERROR_CODE_SYSTEM_RESOURCE_DELETION_NOT_ALLOWED(ErrorCodes.ERROR_SYSTEM_RESOURCE_DELETION_NOT_ALLOWED, + "System resource deletion not allowed. %S"), + ERROR_CODE_ERROR_RESOLVING_MAIN_APPLICATION(ErrorCodes.ERROR_RESOLVING_MAIN_APPLICATION, + "Error when resolving main application : %s"); + + private final String code; + private final String message; + + ErrorMessages(String code, String message) { + + this.code = code; + this.message = message; + } + + public String getCode() { + + return code; + } + + public String getMessage() { + + return message; + } + + @Override + public String toString() { + + return code + " - " + message; + } + } +} 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 72acf3fb..93b356bb 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 @@ -28,6 +28,7 @@ import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.email.mgt.EmailTemplateManager; import org.wso2.carbon.email.mgt.EmailTemplateManagerImpl; +import org.wso2.carbon.email.mgt.NotificationTemplateManagerImpl; import org.wso2.carbon.email.mgt.SMSProviderPayloadTemplateManager; import org.wso2.carbon.email.mgt.SMSProviderPayloadTemplateManagerImpl; import org.wso2.carbon.email.mgt.constants.I18nMgtConstants; @@ -61,6 +62,7 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.HashMap; +import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -71,6 +73,9 @@ import javax.xml.stream.XMLStreamReader; import static org.wso2.carbon.email.mgt.constants.I18nMgtConstants.NOTIFICATION_TEMPLATES_LEGACY_TENANTS; +import static org.wso2.carbon.email.mgt.constants.I18nMgtConstants.SERVICE_PROPERTY_KEY_SERVICE_NAME; +import static org.wso2.carbon.email.mgt.constants.I18nMgtConstants.SERVICE_PROPERTY_VAL_EMAIL_TEMPLATE_MANAGER; +import static org.wso2.carbon.email.mgt.constants.I18nMgtConstants.SERVICE_PROPERTY_VAL_NOTIFICATION_TEMPLATE_MANAGER; import static org.wso2.carbon.email.mgt.constants.I18nMgtConstants.SMS_PROVIDER; import static org.wso2.carbon.email.mgt.constants.I18nMgtConstants.SMS_PROVIDER_POST_BODY_TEMPLATES_DIR_PATH; import static org.wso2.carbon.email.mgt.constants.I18nMgtConstants.TEMPLATE_BODY; @@ -111,12 +116,28 @@ protected void activate(ComponentContext context) { } // Register EmailTemplateManagerImpl. + Hashtable emailTemplateManagerServiceProperties = new Hashtable<>(); + emailTemplateManagerServiceProperties.put(SERVICE_PROPERTY_KEY_SERVICE_NAME, + SERVICE_PROPERTY_VAL_EMAIL_TEMPLATE_MANAGER); ServiceRegistration notificationManagerSR = bundleCtx - .registerService(NotificationTemplateManager.class.getName(), emailTemplateManager, null); + .registerService(NotificationTemplateManager.class.getName(), emailTemplateManager, + emailTemplateManagerServiceProperties); if (notificationManagerSR != null) { - if (log.isDebugEnabled()) { - log.debug("Notification Template Mgt Service registered."); - } + log.debug("Notification Template Mgt Service registered."); + } else { + log.error("Error registering Notification Template Mgt Service."); + } + + // Register Notification Template Mgt Service as an OSGi service. + NotificationTemplateManagerImpl notificationTemplateManager = new NotificationTemplateManagerImpl(); + Hashtable notificationTemplateManagerServiceProperties = new Hashtable<>(); + notificationTemplateManagerServiceProperties.put(SERVICE_PROPERTY_KEY_SERVICE_NAME, + SERVICE_PROPERTY_VAL_NOTIFICATION_TEMPLATE_MANAGER); + ServiceRegistration notificationTemplateSR = bundleCtx + .registerService(NotificationTemplateManager.class.getName(), notificationTemplateManager, + notificationTemplateManagerServiceProperties); + if (notificationTemplateSR != null) { + log.debug("Notification Template Mgt Service registered."); } else { log.error("Error registering Notification Template Mgt Service."); } diff --git a/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/store/DBBasedTemplateManager.java b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/store/DBBasedTemplateManager.java index df6eaa65..a1155bbe 100644 --- a/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/store/DBBasedTemplateManager.java +++ b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/store/DBBasedTemplateManager.java @@ -328,6 +328,25 @@ public void deleteNotificationTemplates(String displayName, String notificationC } } + @Override + public void deleteAllNotificationTemplates(String displayName, String notificationChannel, String tenantDomain) + throws NotificationTemplateManagerServerException { + + String templateTypeKey = displayName.toLowerCase(); + int tenantId = getTenantId(tenantDomain); + + orgNotificationTemplateDAO.removeNotificationTemplates(templateTypeKey, notificationChannel, tenantId); + if (log.isDebugEnabled()) { + log.debug(String.format("Org %s templates for type: %s for tenant: %s successfully deleted.", + notificationChannel, displayName, tenantDomain)); + } + appNotificationTemplateDAO.removeAllNotificationTemplates(templateTypeKey, notificationChannel, tenantId); + if (log.isDebugEnabled()) { + log.debug(String.format("App %s templates for type: %s for all applications for tenant: %s " + + "successfully deleted.", notificationChannel, displayName, tenantDomain)); + } + } + /** * Get the tenant id of the given tenant domain. * @param tenantDomain diff --git a/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/store/HybridTemplateManager.java b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/store/HybridTemplateManager.java index 0f0a5b18..513bb5a5 100644 --- a/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/store/HybridTemplateManager.java +++ b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/store/HybridTemplateManager.java @@ -102,6 +102,20 @@ public void deleteNotificationTemplateType(String displayName, String notificati } } + @Override + public void deleteAllNotificationTemplates(String displayName, String notificationChannel, String tenantDomain) + throws NotificationTemplateManagerServerException { + + if (dbBasedTemplateManager.isNotificationTemplateTypeExists(displayName, notificationChannel, tenantDomain)) { + dbBasedTemplateManager.deleteAllNotificationTemplates(displayName, notificationChannel, tenantDomain); + } + + if (registryBasedTemplateManager.isNotificationTemplateTypeExists(displayName, notificationChannel, + tenantDomain)) { + registryBasedTemplateManager.deleteAllNotificationTemplates(displayName, notificationChannel, tenantDomain); + } + } + @Override public void addOrUpdateNotificationTemplate(NotificationTemplate notificationTemplate, String applicationUuid, String tenantDomain) throws NotificationTemplateManagerServerException { diff --git a/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/store/RegistryBasedTemplateManager.java b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/store/RegistryBasedTemplateManager.java index f8910253..e1beb019 100644 --- a/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/store/RegistryBasedTemplateManager.java +++ b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/store/RegistryBasedTemplateManager.java @@ -297,6 +297,23 @@ public void deleteNotificationTemplates(String displayName, String notificationC } } + @Override + public void deleteAllNotificationTemplates(String displayName, String notificationChannel, String tenantDomain) + throws NotificationTemplateManagerServerException { + + String path = buildTemplateRootDirectoryPath(I18nEmailUtil.getNormalizedName(displayName), + notificationChannel, null); + + try { + Collection templates = (Collection) resourceMgtService.getIdentityResource(path, tenantDomain); + for (String subPath : templates.getChildren()) { + resourceMgtService.deleteIdentityResource(subPath, tenantDomain); + } + } catch (IdentityRuntimeException | RegistryException e) { + throw new NotificationTemplateManagerServerException("Error while deleting notification templates.", e); + } + } + /** * Get the notification template from resource. * diff --git a/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/store/SystemDefaultTemplateManager.java b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/store/SystemDefaultTemplateManager.java index 75ca2331..d340a305 100644 --- a/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/store/SystemDefaultTemplateManager.java +++ b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/store/SystemDefaultTemplateManager.java @@ -112,6 +112,13 @@ public void deleteNotificationTemplateType(String displayName, String notificati throw new UnsupportedOperationException(); } + @Override + public void deleteAllNotificationTemplates(String displayName, String notificationChannel, String tenantDomain) + throws NotificationTemplateManagerServerException { + + throw new UnsupportedOperationException(); + } + @Override public void addOrUpdateNotificationTemplate(NotificationTemplate notificationTemplate, String applicationUuid, String tenantDomain) throws NotificationTemplateManagerServerException { diff --git a/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/store/TemplatePersistenceManager.java b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/store/TemplatePersistenceManager.java index 69321c11..a058f1eb 100644 --- a/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/store/TemplatePersistenceManager.java +++ b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/store/TemplatePersistenceManager.java @@ -73,6 +73,19 @@ List listNotificationTemplateTypes(String notificationChannel, String te void deleteNotificationTemplateType(String displayName, String notificationChannel, String tenantDomain) throws NotificationTemplateManagerServerException; + /** + * Delete both organization level and application level notification templates under a notification template type. + * + * @param displayName Display Name. + * @param notificationChannel Notification channel. + * @param tenantDomain Tenant domain. + * @throws NotificationTemplateManagerServerException If an error occurred while resetting the template type. + */ + default void deleteAllNotificationTemplates(String displayName, String notificationChannel, String tenantDomain) + throws NotificationTemplateManagerServerException { + // not implemented + } + /** * Update the notification template if exists or add a new template if not exists. * diff --git a/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/store/TemplatePersistenceManagerFactory.java b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/store/TemplatePersistenceManagerFactory.java index 022e4274..00e919cc 100644 --- a/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/store/TemplatePersistenceManagerFactory.java +++ b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/store/TemplatePersistenceManagerFactory.java @@ -33,7 +33,8 @@ public class TemplatePersistenceManagerFactory { private static final Log log = LogFactory.getLog(TemplatePersistenceManagerFactory.class); /** - * Returns a {@link TemplatePersistenceManager} implementation based on the configuration. + * Returns a {@link TemplatePersistenceManager} implementation based on the configuration that handles both system + * templates and user defined templates. * * If the storage type is configured as database, an instance of {@link DBBasedTemplateManager} will be returned. * If the storage type is configured as hybrid, an instance of {@link HybridTemplateManager} will be returned. @@ -66,4 +67,60 @@ public TemplatePersistenceManager getTemplatePersistenceManager() { } return new UnifiedTemplateManager(persistenceManager); } + + /** + * Returns a {@link TemplatePersistenceManager} implementation based on the configuration that handles only user + * defined templates. + * + * If the storage type is configured as database, an instance of {@link DBBasedTemplateManager} will be returned. + * If the storage type is configured as hybrid, an instance of {@link HybridTemplateManager} will be returned. + * If the storage type is configured as registry, an instance of {@link RegistryBasedTemplateManager} will be returned. + * For any other case, an instance of {@link DBBasedTemplateManager} will be returned. + * + * @return an implementation of {@link TemplatePersistenceManager}. + */ + public TemplatePersistenceManager getUserDefinedTemplatePersistenceManager() { + + String notificationTemplatesStorageType = IdentityUtil.getProperty(NOTIFICATION_TEMPLATES_STORAGE_CONFIG); + + TemplatePersistenceManager persistenceManager = new DBBasedTemplateManager(); + + if (StringUtils.isNotBlank(notificationTemplatesStorageType)) { + switch (notificationTemplatesStorageType) { + case "hybrid": + persistenceManager = new HybridTemplateManager(); + log.info("Hybrid template persistent manager initialized."); + break; + case "registry": + persistenceManager = new RegistryBasedTemplateManager(); + log.warn("Registry based template persistent manager initialized."); + break; + } + } + + if (log.isDebugEnabled()) { + log.debug("Template persistent manager initialized with the type: " + persistenceManager.getClass()); + } + return persistenceManager; + } + + /** + * Returns a {@link TemplatePersistenceManager} implementation based on the configuration that handles only + * system templates. + * + * If the storage type is configured as database, an instance of {@link DBBasedTemplateManager} will be returned. + * If the storage type is configured as hybrid, an instance of {@link HybridTemplateManager} will be returned. + * If the storage type is configured as registry, an instance of {@link RegistryBasedTemplateManager} will be returned. + * For any other case, an instance of {@link DBBasedTemplateManager} will be returned. + * + * @return an implementation of {@link TemplatePersistenceManager}. + */ + public TemplatePersistenceManager getSystemTemplatePersistenceManager() { + + SystemDefaultTemplateManager inMemoryTemplateManager = new SystemDefaultTemplateManager(); + if (log.isDebugEnabled()) { + log.debug("Template persistent manager initialized with the type: " + inMemoryTemplateManager.getClass()); + } + return inMemoryTemplateManager; + } } 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 9ba6f3c4..52ba3e0a 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 @@ -82,6 +82,16 @@ public void deleteNotificationTemplateType(String displayName, String notificati } } + @Override + public void deleteAllNotificationTemplates(String displayName, String notificationChannel, String tenantDomain) + throws NotificationTemplateManagerServerException { + + if (templatePersistenceManager.isNotificationTemplateTypeExists(displayName, notificationChannel, + tenantDomain)) { + templatePersistenceManager.deleteAllNotificationTemplates(displayName, notificationChannel, tenantDomain); + } + } + @Override public void addOrUpdateNotificationTemplate(NotificationTemplate notificationTemplate, String applicationUuid, String tenantDomain) throws NotificationTemplateManagerServerException { diff --git a/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/store/dao/AppNotificationTemplateDAO.java b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/store/dao/AppNotificationTemplateDAO.java index 53dc2568..03191064 100644 --- a/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/store/dao/AppNotificationTemplateDAO.java +++ b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/store/dao/AppNotificationTemplateDAO.java @@ -38,6 +38,7 @@ import static org.wso2.carbon.email.mgt.constants.I18nMgtConstants.NotificationTableColumns.TENANT_ID; import static org.wso2.carbon.email.mgt.constants.I18nMgtConstants.NotificationTableColumns.TYPE_ID; import static org.wso2.carbon.email.mgt.constants.I18nMgtConstants.NotificationTableColumns.TYPE_KEY; +import static org.wso2.carbon.email.mgt.constants.SQLConstants.DELETE_ALL_APP_NOTIFICATION_TEMPLATES_BY_TYPE_SQL; import static org.wso2.carbon.email.mgt.constants.SQLConstants.DELETE_APP_NOTIFICATION_TEMPLATES_BY_TYPE_SQL; import static org.wso2.carbon.email.mgt.constants.SQLConstants.DELETE_APP_NOTIFICATION_TEMPLATE_SQL; import static org.wso2.carbon.email.mgt.constants.SQLConstants.GET_APP_NOTIFICATION_TEMPLATE_SQL; @@ -275,4 +276,24 @@ public void removeNotificationTemplates(String templateType, String channelName, throw new NotificationTemplateManagerServerException(error, e); } } + + public void removeAllNotificationTemplates(String templateType, String channelName, int tenantId) + throws NotificationTemplateManagerServerException { + + NamedJdbcTemplate namedJdbcTemplate = JdbcUtils.getNewNamedJdbcTemplate(); + try { + namedJdbcTemplate.executeUpdate(DELETE_ALL_APP_NOTIFICATION_TEMPLATES_BY_TYPE_SQL, + preparedStatement -> { + preparedStatement.setString(TYPE_KEY, templateType.toLowerCase()); + preparedStatement.setString(CHANNEL, channelName); + preparedStatement.setInt(TENANT_ID, tenantId); + preparedStatement.setInt(TENANT_ID, tenantId); + }); + } catch (DataAccessException e) { + String error = + String.format("Error while deleting %s templates of type %s from all applications in %s tenant.", + channelName, templateType, tenantId); + throw new NotificationTemplateManagerServerException(error, e); + } + } } diff --git a/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/store/dao/cache/CacheBackedAppNotificationTemplateDAO.java b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/store/dao/cache/CacheBackedAppNotificationTemplateDAO.java index 8717c7ee..4c3c0bee 100644 --- a/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/store/dao/cache/CacheBackedAppNotificationTemplateDAO.java +++ b/components/email-mgt/org.wso2.carbon.email.mgt/src/main/java/org/wso2/carbon/email/mgt/store/dao/cache/CacheBackedAppNotificationTemplateDAO.java @@ -20,17 +20,26 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.database.utils.jdbc.NamedJdbcTemplate; +import org.wso2.carbon.database.utils.jdbc.exceptions.DataAccessException; import org.wso2.carbon.email.mgt.cache.AppNotificationTemplateCache; import org.wso2.carbon.email.mgt.cache.AppNotificationTemplateCacheKey; import org.wso2.carbon.email.mgt.cache.AppNotificationTemplateListCache; import org.wso2.carbon.email.mgt.cache.AppNotificationTemplateListCacheKey; +import org.wso2.carbon.email.mgt.cache.OrgNotificationTemplateListCacheKey; import org.wso2.carbon.email.mgt.store.dao.AppNotificationTemplateDAO; +import org.wso2.carbon.identity.core.util.JdbcUtils; import org.wso2.carbon.identity.governance.exceptions.notiification.NotificationTemplateManagerServerException; import org.wso2.carbon.identity.governance.model.NotificationTemplate; import java.util.ArrayList; import java.util.List; +import static org.wso2.carbon.email.mgt.constants.I18nMgtConstants.NotificationTableColumns.CHANNEL; +import static org.wso2.carbon.email.mgt.constants.I18nMgtConstants.NotificationTableColumns.TENANT_ID; +import static org.wso2.carbon.email.mgt.constants.I18nMgtConstants.NotificationTableColumns.TYPE_KEY; +import static org.wso2.carbon.email.mgt.constants.SQLConstants.DELETE_ALL_APP_NOTIFICATION_TEMPLATES_BY_TYPE_SQL; + /** * This class provides the cache backed implementation for {@link AppNotificationTemplateDAO}. */ @@ -186,4 +195,15 @@ public void removeNotificationTemplates(String templateType, String channelName, new AppNotificationTemplateListCacheKey(templateType, channelName, applicationUuid); templateListCache.clearCacheEntry(listCacheKey, tenantId); } + + public void removeAllNotificationTemplates(String templateType, String channelName, int tenantId) + throws NotificationTemplateManagerServerException { + + super.removeAllNotificationTemplates(templateType, channelName, tenantId); + + appNotificationTemplateCache.clear(tenantId); + // Clearing full template list cache for tenant since it's not possible to remove all entries for a template + // type at once. + templateListCache.clear(tenantId); + } } diff --git a/pom.xml b/pom.xml index 4cacc690..296ed608 100644 --- a/pom.xml +++ b/pom.xml @@ -477,7 +477,7 @@ - 1.10.0 + 1.11.11 [1.0.0, 3.0.0)