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

[Notification Template API] Event Handler Implementation #250

Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
6401241
Add Notification Template API SMS template functions
RushanNanayakkara Jul 2, 2024
e19c8ea
Merge remote-tracking branch 'upstream/master' into ft_notification_t…
RushanNanayakkara Aug 24, 2024
8dcafb4
Merge remote-tracking branch 'upstream/master' into ft_notification_t…
RushanNanayakkara Sep 8, 2024
3e91c12
Add Notification Template API SMS template functions
RushanNanayakkara Sep 24, 2024
ffd5c3d
Add system notification template related functions.
RushanNanayakkara Sep 26, 2024
f12d380
Allow partial deletion for system template types
RushanNanayakkara Sep 29, 2024
269cf57
Merge remote-tracking branch 'upstream/master' into ft_notification_t…
RushanNanayakkara Sep 29, 2024
9d494c3
Remove partial deletion for system template types and add deleteCusto…
RushanNanayakkara Oct 5, 2024
4a1e0b6
Merge remote-tracking branch 'upstream/master' into ft_notification_t…
RushanNanayakkara Oct 5, 2024
b07a9cd
Merge remote-tracking branch 'upstream/master' into ft_notification_t…
RushanNanayakkara Oct 15, 2024
bceca94
Get main app through application management service
RushanNanayakkara Oct 16, 2024
bdbae4c
Add deleteAllNotificationTemplates function
RushanNanayakkara Oct 17, 2024
f3b34a6
Clear cache when all templates or a type are removed.
RushanNanayakkara Oct 18, 2024
9595a60
Merge remote-tracking branch 'upstream/master' into ft_notification_t…
RushanNanayakkara Oct 18, 2024
4252c14
Refactor code
RushanNanayakkara Oct 20, 2024
b828356
Addressing comments
RushanNanayakkara Oct 21, 2024
26a332f
Code refactoring
RushanNanayakkara Oct 21, 2024
cef6060
addressing comments
RushanNanayakkara Oct 22, 2024
e012ab9
Bump governance version
RushanNanayakkara Oct 23, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -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;";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/*
* Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org) All Rights Reserved.
*
RushanNanayakkara marked this conversation as resolved.
Show resolved Hide resolved
* WSO2 Inc. 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 {
RushanNanayakkara marked this conversation as resolved.
Show resolved Hide resolved
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;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -110,6 +112,20 @@ protected void activate(ComponentContext context) {
log.error("Error registering Email Template Mgt Service.");
}

// Register Notification Template Mgt Service as an OSGi service.
NotificationTemplateManagerImpl notificationTemplateManager = new NotificationTemplateManagerImpl();
Hashtable<String, String> serviceProperties = new Hashtable<>();
serviceProperties.put("service.name", "NotificationTemplateManager");
AmshikaH marked this conversation as resolved.
Show resolved Hide resolved
ServiceRegistration notificationTemplateSR = bundleCtx.registerService(
NotificationTemplateManager.class.getName(), notificationTemplateManager, serviceProperties);
if (notificationTemplateSR != null) {
if (log.isDebugEnabled()) {
log.debug("Notification Template Mgt Service registered.");
}
AmshikaH marked this conversation as resolved.
Show resolved Hide resolved
} else {
log.error("Error registering Notification Template Mgt Service.");
}

// Register EmailTemplateManagerImpl.
ServiceRegistration notificationManagerSR = bundleCtx
.registerService(NotificationTemplateManager.class.getName(), emailTemplateManager, null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,23 @@ public void deleteNotificationTemplates(String displayName, String notificationC
}
}

@Override
public void deleteAllNotificationTemplates(String displayName, String notificationChannel, String tenantDomain)
throws NotificationTemplateManagerServerException {

String templateType = I18nEmailUtil.getNormalizedName(displayName);
RushanNanayakkara marked this conversation as resolved.
Show resolved Hide resolved
String path = buildTemplateRootDirectoryPath(templateType, 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.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,19 @@ List<String> 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.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
}
}
Loading
Loading