From 442bcd96b5186ccc3d3a115c6cc63d1c4696ed3b Mon Sep 17 00:00:00 2001 From: thisarawelmilla Date: Wed, 29 Oct 2025 15:55:50 +0530 Subject: [PATCH 1/4] Improvement to sms configuration management --- ...NotificationSenderManagementConstants.java | 10 ++ .../tenant/config/dto/Authentication.java | 157 ++++++++++++++++++ .../tenant/config/dto/SMSSenderDTO.java | 138 +++++++++++++++ .../DefaultChannelConfigurationHandler.java | 7 +- .../config/utils/NotificationSenderUtils.java | 47 ++++-- 5 files changed, 348 insertions(+), 11 deletions(-) create mode 100644 components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/dto/Authentication.java diff --git a/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/NotificationSenderManagementConstants.java b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/NotificationSenderManagementConstants.java index 3599fca61..6040ae39a 100644 --- a/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/NotificationSenderManagementConstants.java +++ b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/NotificationSenderManagementConstants.java @@ -53,6 +53,16 @@ private NotificationSenderManagementConstants() { public static final String SMS_PROVIDER = "SMS_PROVIDER"; public static final String PUSH_PROVIDER = "PUSH_PROVIDER"; + // Authentication properties + public static final String USERNAME_AUTH_PROP = "username"; + public static final String PASSWORD_AUTH_PROP = "password"; + public static final String CLIENT_ID_AUTH_PROP = "clientId"; + public static final String CLIENT_SECRET_AUTH_PROP = "clientSecret"; + public static final String HEADER_AUTH_PROP = "header"; + public static final String VALUE_AUTH_PROP = "value"; + public static final String ACCESS_TOKEN_AUTH_PROP = "accessToken"; + public static final String AUTH_PROP_PREFIX = "authPrefix"; + // Email Sender's main properties. public static final String NAME = "name"; public static final String SMTP_SERVER_HOST = "smtpServerHost"; diff --git a/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/dto/Authentication.java b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/dto/Authentication.java new file mode 100644 index 000000000..901b31603 --- /dev/null +++ b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/dto/Authentication.java @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2025, 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.identity.notification.sender.tenant.config.dto; + +import org.apache.commons.lang.StringUtils; +import java.util.HashMap; +import java.util.Map; +import java.util.NoSuchElementException; + +import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.ACCESS_TOKEN_AUTH_PROP; +import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.CLIENT_ID_AUTH_PROP; +import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.CLIENT_SECRET_AUTH_PROP; +import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.HEADER_AUTH_PROP; +import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.PASSWORD_AUTH_PROP; +import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.USERNAME_AUTH_PROP; +import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.VALUE_AUTH_PROP; + +/** + * Authentication class which hold supported authentication types and their properties. + */ +public class Authentication { + + private final Type type; + private final Map authProperties; + + public Authentication(AuthenticationBuilder builder) { + + type = builder.authType; + authProperties = builder.propertiesMap; + } + + public Authentication.Type getType() { + + return type; + } + + public Map getProperties() { + + return authProperties; + } + + /** + * This Builder build endpoint by taking the authentication type and properties as input. + */ + public static class AuthenticationBuilder { + + private final Type authType; + private Map propertiesMap; + + public AuthenticationBuilder (String type, Map authPropertiesMap) { + + this.authType = Type.valueOfName(type); + this.propertiesMap = authPropertiesMap; + } + + public Authentication build() { + + Map authProperties = new HashMap<>(); + switch (authType) { + case BASIC: + authProperties.put(USERNAME_AUTH_PROP, getProperty(Type.BASIC, propertiesMap, USERNAME_AUTH_PROP)); + authProperties.put(PASSWORD_AUTH_PROP, getProperty(Type.BASIC, propertiesMap, PASSWORD_AUTH_PROP)); + break; + case BEARER: + authProperties.put(ACCESS_TOKEN_AUTH_PROP, + getProperty(Type.BEARER, propertiesMap, ACCESS_TOKEN_AUTH_PROP)); + break; + case CLIENT_CRED: + authProperties.put(CLIENT_ID_AUTH_PROP, + getProperty(Type.CLIENT_CRED, propertiesMap, CLIENT_ID_AUTH_PROP)); + authProperties.put(CLIENT_SECRET_AUTH_PROP, + getProperty(Type.CLIENT_CRED, propertiesMap, CLIENT_SECRET_AUTH_PROP)); + break; + case API_KEY: + authProperties.put(HEADER_AUTH_PROP, getProperty(Type.BEARER, propertiesMap, HEADER_AUTH_PROP)); + authProperties.put(VALUE_AUTH_PROP, getProperty(Type.BEARER, propertiesMap, VALUE_AUTH_PROP)); + break; + case NONE: + break; + default: + throw new IllegalArgumentException(String.format("An invalid authentication type '%s' is " + + "provided for the authentication configuration of the endpoint.", authType.name())); + } + propertiesMap = authProperties; + return new Authentication(this); + } + + private String getProperty(Type authType, Map actionEndpointProperties, + String propertyName) { + + if (actionEndpointProperties != null && actionEndpointProperties.containsKey(propertyName)) { + String propValue = actionEndpointProperties.get(propertyName); + if (StringUtils.isNotBlank(propValue)) { + return propValue; + } + throw new IllegalArgumentException(String.format("The Property %s cannot be blank.", propertyName)); + } + + throw new NoSuchElementException(String.format("The property %s must be provided as an authentication " + + "property for the %s authentication type.", propertyName, authType.name())); + } + } + + /** + * Authentication Type. + */ + public enum Type { + + NONE("NONE"), + BEARER("BEARER"), + CLIENT_CRED("CLIENT_CREDENTIAL"), + BASIC("BASIC"), + API_KEY("API_KEY"); + + private final String name; + + Type(String name) { + + this.name = name; + } + + public String getName() { + + return name; + } + + public static Type valueOfName(String name) { + + if (name == null || name.isEmpty()) { + throw new IllegalArgumentException("Authentication type cannot be null or empty."); + } + + for (Type type : Type.values()) { + if (type.name.equalsIgnoreCase(name)) { + return type; + } + } + throw new IllegalArgumentException("Invalid authentication type: " + name); + } + } +} diff --git a/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/dto/SMSSenderDTO.java b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/dto/SMSSenderDTO.java index 42efe23e8..6cd486b73 100644 --- a/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/dto/SMSSenderDTO.java +++ b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/dto/SMSSenderDTO.java @@ -18,9 +18,18 @@ package org.wso2.carbon.identity.notification.sender.tenant.config.dto; +import org.apache.commons.lang.StringUtils; +import org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants; +import org.wso2.carbon.identity.notification.sender.tenant.config.exception.NotificationSenderManagementException; + import java.util.HashMap; import java.util.Map; +import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.PASSWORD_AUTH_PROP; +import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.USERNAME_AUTH_PROP; +import static org.wso2.carbon.identity.notification.sender.tenant.config.dto.Authentication.Type.BASIC; + + /** * DTO for SMS sender. */ @@ -34,6 +43,7 @@ public class SMSSenderDTO { private String sender; private String contentType; private Map properties = new HashMap<>(); + private Authentication authentication; public String getName() { @@ -114,4 +124,132 @@ public void setProperties(Map properties) { this.properties = properties; } + + public void setAuthentication(Authentication authentication) { + + this.authentication = authentication; + } + + public Authentication getAuthentication() { + + return authentication; + } + + /** + * Builder for SMSSenderDTO. + */ + public static class Builder { + + private String name; + private String provider; + private String providerURL; + private String key; + private String secret; + private String sender; + private String contentType; + private final Map properties = new HashMap<>(); + private String authType; + private final Map authProperties = new HashMap<>(); + + public Builder name(String name) { + + this.name = name; + return this; + } + + public Builder provider(String provider) { + + this.provider = provider; + return this; + } + + public Builder providerURL(String providerURL) { + + this.providerURL = providerURL; + return this; + } + + public Builder key(String key) { + + this.key = key; + return this; + } + + public Builder secret(String secret) { + + this.secret = secret; + return this; + } + + public Builder sender(String sender) { + + this.sender = sender; + return this; + } + + public Builder contentType(String contentType) { + + this.contentType = contentType; + return this; + } + + public Builder addProperty(String key, String value) { + + properties.put(key, value); + return this; + } + + public Builder authType(String authType) { + + this.authType = authType; + return this; + } + + public Builder addAuthPropertiesString(String key, String value) { + + authProperties.put(key, value); + return this; + } + + public SMSSenderDTO build() throws NotificationSenderManagementException { + + SMSSenderDTO smsSenderDTO = new SMSSenderDTO(); + if (StringUtils.isNotEmpty(authType)) { + Authentication authentication = new Authentication.AuthenticationBuilder( + authType, authProperties).build(); + validateAuthConfig(authentication); + smsSenderDTO.setAuthentication(authentication); + } + + smsSenderDTO.setName(this.name); + smsSenderDTO.setProvider(this.provider); + smsSenderDTO.setProviderURL(this.providerURL); + smsSenderDTO.setKey(this.key); + smsSenderDTO.setSecret(this.secret); + + + smsSenderDTO.setSender(this.sender); + smsSenderDTO.setContentType(this.contentType); + smsSenderDTO.setProperties(this.properties); + return smsSenderDTO; + } + + private void validateAuthConfig(Authentication authentication) throws NotificationSenderManagementException { + + if (StringUtils.isEmpty(key) && StringUtils.isEmpty(secret)) { + + if (!BASIC.equals(authentication.getType())) { + return; + } + key(authentication.getProperties().get(USERNAME_AUTH_PROP)); + secret(authentication.getProperties().get(PASSWORD_AUTH_PROP)); + } + + if (!StringUtils.equals(key, authentication.getProperties().get(USERNAME_AUTH_PROP)) || + !StringUtils.equals(secret, authentication.getProperties().get(PASSWORD_AUTH_PROP))) { + throw new NotificationSenderManagementException( + NotificationSenderManagementConstants.ErrorMessage.ERROR_CODE_CHANNEL_TYPE_UPDATE_NOT_ALLOWED); + } + } + } } diff --git a/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/handlers/DefaultChannelConfigurationHandler.java b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/handlers/DefaultChannelConfigurationHandler.java index 06dd900db..e2dd99df2 100644 --- a/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/handlers/DefaultChannelConfigurationHandler.java +++ b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/handlers/DefaultChannelConfigurationHandler.java @@ -59,6 +59,7 @@ import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.TransformerException; +import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.AUTH_TYPE; import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.CONTENT_TYPE; import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.DEFAULT_HANDLER_NAME; import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.DEFAULT_SMS_PUBLISHER; @@ -257,7 +258,11 @@ private Resource buildResourceFromSmsSender(SMSSenderDTO smsSender) smsSenderAttributes.put(SECRET, smsSender.getSecret()); smsSenderAttributes.put(SENDER, smsSender.getSender()); smsSenderAttributes.put(CONTENT_TYPE, smsSender.getContentType()); - smsSenderAttributes.putAll(smsSender.getProperties()); + if (smsSender.getAuthentication() != null) { + smsSenderAttributes.put(AUTH_TYPE, smsSender.getAuthentication().getType().name()); + smsSenderAttributes.putAll(smsSender.getAuthentication().getProperties()); + smsSenderAttributes.putAll(smsSender.getProperties()); + } List resourceAttributes = smsSenderAttributes.entrySet().stream().filter(attribute -> attribute.getValue() != null) .map(attribute -> new Attribute(attribute.getKey(), attribute.getValue())) diff --git a/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/utils/NotificationSenderUtils.java b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/utils/NotificationSenderUtils.java index 0eb6517f4..29bed48fe 100644 --- a/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/utils/NotificationSenderUtils.java +++ b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/utils/NotificationSenderUtils.java @@ -33,6 +33,7 @@ import org.wso2.carbon.identity.notification.sender.tenant.config.dto.EmailSenderDTO; import org.wso2.carbon.identity.notification.sender.tenant.config.dto.PushSenderDTO; import org.wso2.carbon.identity.notification.sender.tenant.config.dto.SMSSenderDTO; +import org.wso2.carbon.identity.notification.sender.tenant.config.exception.NotificationSenderManagementException; import org.wso2.carbon.identity.notification.sender.tenant.config.exception.NotificationSenderManagementServerException; import org.wso2.carbon.identity.notification.sender.tenant.config.internal.NotificationSenderTenantConfigDataHolder; import org.wso2.carbon.identity.organization.management.service.OrganizationManager; @@ -62,6 +63,8 @@ import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.ADAPTER_TYPE_EMAIL_VALUE; import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.ADAPTER_TYPE_HTTP_VALUE; import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.ADAPTER_TYPE_KEY; +import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.AUTH_PROP_PREFIX; +import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.AUTH_TYPE; import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.BASIC; import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.CLIENT_CREDENTIAL; import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.CLIENT_HTTP_METHOD_PROPERTY; @@ -375,6 +378,15 @@ private static void addToElementToSMSEventPublisher(SMSSenderDTO smsSender, Map< } else { adapterProperties.put(HTTP_URL_PROPERTY, StringUtils.EMPTY); } + if (smsSender.getAuthentication() != null) { + if (StringUtils.isNotEmpty(smsSender.getAuthentication().getType().getName())) { + adapterProperties.put(AUTH_TYPE, smsSender.getAuthentication().getType().getName()); + } + for (Map.Entry property : smsSender.getAuthentication().getProperties().entrySet()) { + adapterProperties.put(AUTH_PROP_PREFIX + property.getKey(), property.getValue()); + } + } + // Default client method is httpPost. Can be changed by configuring properties. adapterProperties.put(CLIENT_HTTP_METHOD_PROPERTY, CONSTANT_HTTP_POST); for (Map.Entry property : properties.entrySet()) { @@ -435,8 +447,9 @@ private static String generateSmsSendAPIBody(String smsSendAPIBodyTemplate, SMSS */ public static SMSSenderDTO buildSmsSenderFromResource(Resource resource) { - SMSSenderDTO smsSender = new SMSSenderDTO(); - smsSender.setName(resource.getResourceName()); + SMSSenderDTO.Builder smsSenderBuilder = new SMSSenderDTO.Builder(); + smsSenderBuilder.name(resource.getResourceName()); + // Skip STREAM_NAME, STREAM_VERSION and PUBLISHER_TYPE_PROPERTY properties which are stored for internal use. Map attributesMap = resource.getAttributes().stream() @@ -446,28 +459,42 @@ public static SMSSenderDTO buildSmsSenderFromResource(Resource resource) { attributesMap.forEach((key, value) -> { switch (key) { case PROVIDER: - smsSender.setProvider(value); + smsSenderBuilder.provider(value); break; case PROVIDER_URL: - smsSender.setProviderURL(value); + smsSenderBuilder.providerURL(value); break; case KEY: - smsSender.setKey(value); + smsSenderBuilder.key(value); break; case SECRET: - smsSender.setSecret(value); + smsSenderBuilder.secret(value); break; case SENDER: - smsSender.setSender(value); + smsSenderBuilder.sender(value); break; case CONTENT_TYPE: - smsSender.setContentType(value); + smsSenderBuilder.contentType(value); + break; + case AUTH_TYPE: + smsSenderBuilder.authType(value); break; default: - smsSender.getProperties().put(key, value); + if (StringUtils.startsWith(key, AUTH_PROP_PREFIX)) { + String authPropertyKey = StringUtils.removeStart(key, AUTH_PROP_PREFIX); + smsSenderBuilder.addAuthPropertiesString(authPropertyKey, value); + } else { + smsSenderBuilder.addProperty(key, value); + } } }); - return smsSender; + + try { + return smsSenderBuilder.build(); + } catch (NotificationSenderManagementException e) { + // This exception won't occur as we are not setting any invalid values. + return null; + } } /** From 9256f621aac16df36a1cfb5539e00c51f072ff00 Mon Sep 17 00:00:00 2001 From: thisarawelmilla Date: Sat, 1 Nov 2025 09:09:06 +0530 Subject: [PATCH 2/4] Improvement to sms configuration management --- .../pom.xml | 9 ++ ...NotificationSenderManagementConstants.java | 8 +- .../tenant/config/dto/AuthProperty.java | 81 ++++++++++++++ .../tenant/config/dto/Authentication.java | 74 ++++++++----- .../tenant/config/dto/SMSSenderDTO.java | 34 ++++-- .../DefaultChannelConfigurationHandler.java | 27 ++++- .../config/utils/NotificationSenderUtils.java | 49 +++++++-- .../tenant/config/utils/TokenManager.java | 103 ++++++++++++++++++ pom.xml | 7 +- 9 files changed, 340 insertions(+), 52 deletions(-) create mode 100644 components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/dto/AuthProperty.java create mode 100644 components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/utils/TokenManager.java diff --git a/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/pom.xml b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/pom.xml index 2a9032623..0f8d8f224 100644 --- a/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/pom.xml +++ b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/pom.xml @@ -94,6 +94,10 @@ org.wso2.carbon.identity.framework org.wso2.carbon.identity.secret.mgt.core + + org.wso2.carbon.identity.framework + org.wso2.carbon.identity.external.api.token.handler + @@ -145,6 +149,11 @@ org.wso2.carbon.identity.application.common; version="${carbon.identity.framework.imp.pkg.version.range}", org.wso2.carbon.identity.application.common.util; version="${carbon.identity.framework.imp.pkg.version.range}", + org.wso2.carbon.identity.external.api.token.handler.*; version="${carbon.identity.framework.imp.pkg.version.range}", + org.wso2.carbon.identity.external.api.client.api.model; version="${carbon.identity.framework.imp.pkg.version.range}", + org.wso2.carbon.identity.external.api.client.api.exception; version="${carbon.identity.framework.imp.pkg.version.range}", + org.wso2.carbon.identity.external.api.client.api.service; version="${carbon.identity.framework.imp.pkg.version.range}", + org.wso2.carbon.idp.mgt.model; version="${carbon.identity.framework.imp.pkg.version.range}", org.wso2.carbon.identity.configuration.mgt.core; diff --git a/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/NotificationSenderManagementConstants.java b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/NotificationSenderManagementConstants.java index 6040ae39a..7539b1124 100644 --- a/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/NotificationSenderManagementConstants.java +++ b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/NotificationSenderManagementConstants.java @@ -56,12 +56,14 @@ private NotificationSenderManagementConstants() { // Authentication properties public static final String USERNAME_AUTH_PROP = "username"; public static final String PASSWORD_AUTH_PROP = "password"; - public static final String CLIENT_ID_AUTH_PROP = "clientId"; - public static final String CLIENT_SECRET_AUTH_PROP = "clientSecret"; + public static final String CLIENT_ID_AUTH_PROP = "client_id"; + public static final String CLIENT_SECRET_AUTH_PROP = "client_secret"; public static final String HEADER_AUTH_PROP = "header"; public static final String VALUE_AUTH_PROP = "value"; public static final String ACCESS_TOKEN_AUTH_PROP = "accessToken"; - public static final String AUTH_PROP_PREFIX = "authPrefix"; + public static final String SCOPE_AUTH_PROP = "scope"; + public static final String AUTH_INTERNAL_PROP_PREFIX = "auth.internal."; + public static final String AUTH_EXTERNAL_PROP_PREFIX = "auth.external."; // Email Sender's main properties. public static final String NAME = "name"; diff --git a/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/dto/AuthProperty.java b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/dto/AuthProperty.java new file mode 100644 index 000000000..27e7cbaaa --- /dev/null +++ b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/dto/AuthProperty.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2025, 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.identity.notification.sender.tenant.config.dto; + +/** + * Authentication Property DTO. + */ +public class AuthProperty { + private final String name; + private final String value; + private final Scope scope; + + public AuthProperty(Builder authPropertyBuilder) { + + this.name = authPropertyBuilder.name; + this.value = authPropertyBuilder.value; + this.scope = authPropertyBuilder.scope; + } + + public String getName() { + + return name; + } + + public String getValue() { + + return value; + } + + public Scope getScope() { + + return scope; + } + + /** + * Authentication Property Builder. + */ + public static class Builder { + + private final String name; + private final String value; + private final Scope scope; + + public Builder(String name, String value, Scope scope) { + + this.name = name; + this.value = value; + this.scope = scope; + } + + public AuthProperty build() { + + return new AuthProperty(this); + } + } + + /** + * Enum for Property Scope. + */ + public enum Scope { + + INTERNAL, + EXTERNAL; + } +} diff --git a/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/dto/Authentication.java b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/dto/Authentication.java index 901b31603..ecb23e79b 100644 --- a/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/dto/Authentication.java +++ b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/dto/Authentication.java @@ -19,7 +19,9 @@ package org.wso2.carbon.identity.notification.sender.tenant.config.dto; import org.apache.commons.lang.StringUtils; -import java.util.HashMap; + +import java.util.ArrayList; +import java.util.List; import java.util.Map; import java.util.NoSuchElementException; @@ -28,21 +30,22 @@ import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.CLIENT_SECRET_AUTH_PROP; import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.HEADER_AUTH_PROP; import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.PASSWORD_AUTH_PROP; +import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.SCOPE_AUTH_PROP; import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.USERNAME_AUTH_PROP; import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.VALUE_AUTH_PROP; /** - * Authentication class which hold supported authentication types and their properties. + * Authentication configuration for the notification sending provider. */ public class Authentication { private final Type type; - private final Map authProperties; + private final List authProperties; public Authentication(AuthenticationBuilder builder) { type = builder.authType; - authProperties = builder.propertiesMap; + authProperties = builder.resolvedAuthProperties; } public Authentication.Type getType() { @@ -50,18 +53,32 @@ public Authentication.Type getType() { return type; } - public Map getProperties() { + public List getProperties() { return authProperties; } + public AuthProperty getProperty(String propertyName) { + + return this.authProperties.stream() + .filter(property -> propertyName.equals(property.getName())) + .findFirst() + .orElse(null); + } + + public void setInternalAuthProperty(String key, String value) { + + authProperties.add(new AuthProperty.Builder(key, value, AuthProperty.Scope.INTERNAL).build()); + } + /** * This Builder build endpoint by taking the authentication type and properties as input. */ public static class AuthenticationBuilder { private final Type authType; - private Map propertiesMap; + private final Map propertiesMap; + private final List resolvedAuthProperties = new ArrayList<>(); public AuthenticationBuilder (String type, Map authPropertiesMap) { @@ -69,27 +86,31 @@ public AuthenticationBuilder (String type, Map authPropertiesMap this.propertiesMap = authPropertiesMap; } + public AuthenticationBuilder setInternalAuthProperty(String key, String value) { + + resolvedAuthProperties.add(new AuthProperty.Builder(key, value, AuthProperty.Scope.INTERNAL).build()); + return this; + } + public Authentication build() { - Map authProperties = new HashMap<>(); switch (authType) { case BASIC: - authProperties.put(USERNAME_AUTH_PROP, getProperty(Type.BASIC, propertiesMap, USERNAME_AUTH_PROP)); - authProperties.put(PASSWORD_AUTH_PROP, getProperty(Type.BASIC, propertiesMap, PASSWORD_AUTH_PROP)); + resolvedAuthProperties.add(getProperty(Type.BASIC, propertiesMap, USERNAME_AUTH_PROP)); + resolvedAuthProperties.add(getProperty(Type.BASIC, propertiesMap, PASSWORD_AUTH_PROP)); break; case BEARER: - authProperties.put(ACCESS_TOKEN_AUTH_PROP, - getProperty(Type.BEARER, propertiesMap, ACCESS_TOKEN_AUTH_PROP)); + resolvedAuthProperties.add(getProperty(Type.BEARER, propertiesMap, ACCESS_TOKEN_AUTH_PROP)); break; - case CLIENT_CRED: - authProperties.put(CLIENT_ID_AUTH_PROP, - getProperty(Type.CLIENT_CRED, propertiesMap, CLIENT_ID_AUTH_PROP)); - authProperties.put(CLIENT_SECRET_AUTH_PROP, - getProperty(Type.CLIENT_CRED, propertiesMap, CLIENT_SECRET_AUTH_PROP)); + case CLIENT_CREDENTIAL: + resolvedAuthProperties.add(getProperty(Type.CLIENT_CREDENTIAL, propertiesMap, CLIENT_ID_AUTH_PROP)); + resolvedAuthProperties.add( + getProperty(Type.CLIENT_CREDENTIAL, propertiesMap, CLIENT_SECRET_AUTH_PROP)); + resolvedAuthProperties.add(getProperty(Type.CLIENT_CREDENTIAL, propertiesMap, SCOPE_AUTH_PROP)); break; case API_KEY: - authProperties.put(HEADER_AUTH_PROP, getProperty(Type.BEARER, propertiesMap, HEADER_AUTH_PROP)); - authProperties.put(VALUE_AUTH_PROP, getProperty(Type.BEARER, propertiesMap, VALUE_AUTH_PROP)); + resolvedAuthProperties.add(getProperty(Type.BEARER, propertiesMap, HEADER_AUTH_PROP)); + resolvedAuthProperties.add(getProperty(Type.BEARER, propertiesMap, VALUE_AUTH_PROP)); break; case NONE: break; @@ -97,23 +118,22 @@ public Authentication build() { throw new IllegalArgumentException(String.format("An invalid authentication type '%s' is " + "provided for the authentication configuration of the endpoint.", authType.name())); } - propertiesMap = authProperties; return new Authentication(this); } - private String getProperty(Type authType, Map actionEndpointProperties, - String propertyName) { + private AuthProperty getProperty(Type authType, Map actionEndpointProperties, + String propName) { - if (actionEndpointProperties != null && actionEndpointProperties.containsKey(propertyName)) { - String propValue = actionEndpointProperties.get(propertyName); + if (actionEndpointProperties != null && actionEndpointProperties.containsKey(propName)) { + String propValue = actionEndpointProperties.get(propName); if (StringUtils.isNotBlank(propValue)) { - return propValue; + return new AuthProperty.Builder(propName, propValue, AuthProperty.Scope.EXTERNAL).build(); } - throw new IllegalArgumentException(String.format("The Property %s cannot be blank.", propertyName)); + throw new IllegalArgumentException(String.format("The Property %s cannot be blank.", propName)); } throw new NoSuchElementException(String.format("The property %s must be provided as an authentication " + - "property for the %s authentication type.", propertyName, authType.name())); + "property for the %s authentication type.", propName, authType.name())); } } @@ -124,7 +144,7 @@ public enum Type { NONE("NONE"), BEARER("BEARER"), - CLIENT_CRED("CLIENT_CREDENTIAL"), + CLIENT_CREDENTIAL("CLIENT_CREDENTIAL"), BASIC("BASIC"), API_KEY("API_KEY"); diff --git a/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/dto/SMSSenderDTO.java b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/dto/SMSSenderDTO.java index 6cd486b73..08b3ce3ab 100644 --- a/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/dto/SMSSenderDTO.java +++ b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/dto/SMSSenderDTO.java @@ -21,6 +21,7 @@ import org.apache.commons.lang.StringUtils; import org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants; import org.wso2.carbon.identity.notification.sender.tenant.config.exception.NotificationSenderManagementException; +import org.wso2.carbon.identity.notification.sender.tenant.config.utils.TokenManager; import java.util.HashMap; import java.util.Map; @@ -135,6 +136,24 @@ public Authentication getAuthentication() { return authentication; } + public void getToken() { + + // check allowed grant to call + TokenManager tokenManager = new TokenManager(); + Map authProps = new HashMap<>(); + authProps.put("client_id", "TESTID"); + authProps.put("client_secret", "TESTSECRET"); + authProps.put("scope", "testing"); + Authentication tempAuth = new Authentication.AuthenticationBuilder( + Authentication.Type.CLIENT_CREDENTIAL.name(), authProps).build(); + tokenManager.setAuthentication(tempAuth); + try { + tokenManager.getToken(); + } catch (Exception e) { + throw new IllegalArgumentException("Error while acquiring token for the SMS sender", e); + } + } + /** * Builder for SMSSenderDTO. */ @@ -205,7 +224,7 @@ public Builder authType(String authType) { return this; } - public Builder addAuthPropertiesString(String key, String value) { + public Builder addAuthProperties(String key, String value) { authProperties.put(key, value); return this; @@ -226,8 +245,6 @@ public SMSSenderDTO build() throws NotificationSenderManagementException { smsSenderDTO.setProviderURL(this.providerURL); smsSenderDTO.setKey(this.key); smsSenderDTO.setSecret(this.secret); - - smsSenderDTO.setSender(this.sender); smsSenderDTO.setContentType(this.contentType); smsSenderDTO.setProperties(this.properties); @@ -236,17 +253,18 @@ public SMSSenderDTO build() throws NotificationSenderManagementException { private void validateAuthConfig(Authentication authentication) throws NotificationSenderManagementException { + /* If key and secret are not provided in the DTO, fetch them from the authentication + configuration for only if the BASIC auth type is configured. */ if (StringUtils.isEmpty(key) && StringUtils.isEmpty(secret)) { - if (!BASIC.equals(authentication.getType())) { return; } - key(authentication.getProperties().get(USERNAME_AUTH_PROP)); - secret(authentication.getProperties().get(PASSWORD_AUTH_PROP)); + key(authentication.getProperty(USERNAME_AUTH_PROP).getValue()); + secret(authentication.getProperty(PASSWORD_AUTH_PROP).getValue()); } - if (!StringUtils.equals(key, authentication.getProperties().get(USERNAME_AUTH_PROP)) || - !StringUtils.equals(secret, authentication.getProperties().get(PASSWORD_AUTH_PROP))) { + if (!StringUtils.equals(key, authentication.getProperty(USERNAME_AUTH_PROP).getValue()) || + !StringUtils.equals(secret, authentication.getProperty(PASSWORD_AUTH_PROP).getValue())) { throw new NotificationSenderManagementException( NotificationSenderManagementConstants.ErrorMessage.ERROR_CODE_CHANNEL_TYPE_UPDATE_NOT_ALLOWED); } diff --git a/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/handlers/DefaultChannelConfigurationHandler.java b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/handlers/DefaultChannelConfigurationHandler.java index e2dd99df2..90f2e963f 100644 --- a/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/handlers/DefaultChannelConfigurationHandler.java +++ b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/handlers/DefaultChannelConfigurationHandler.java @@ -36,6 +36,8 @@ import org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants; import org.wso2.carbon.identity.notification.sender.tenant.config.clustering.EventPublisherClusterDeleteMessage; import org.wso2.carbon.identity.notification.sender.tenant.config.clustering.EventPublisherClusterInvalidationMessage; +import org.wso2.carbon.identity.notification.sender.tenant.config.dto.AuthProperty; +import org.wso2.carbon.identity.notification.sender.tenant.config.dto.Authentication; import org.wso2.carbon.identity.notification.sender.tenant.config.dto.EmailSenderDTO; import org.wso2.carbon.identity.notification.sender.tenant.config.dto.SMSSenderDTO; import org.wso2.carbon.identity.notification.sender.tenant.config.exception.NotificationSenderManagementClientException; @@ -59,6 +61,8 @@ import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.TransformerException; +import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.AUTH_EXTERNAL_PROP_PREFIX; +import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.AUTH_INTERNAL_PROP_PREFIX; import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.AUTH_TYPE; import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.CONTENT_TYPE; import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.DEFAULT_HANDLER_NAME; @@ -258,15 +262,12 @@ private Resource buildResourceFromSmsSender(SMSSenderDTO smsSender) smsSenderAttributes.put(SECRET, smsSender.getSecret()); smsSenderAttributes.put(SENDER, smsSender.getSender()); smsSenderAttributes.put(CONTENT_TYPE, smsSender.getContentType()); - if (smsSender.getAuthentication() != null) { - smsSenderAttributes.put(AUTH_TYPE, smsSender.getAuthentication().getType().name()); - smsSenderAttributes.putAll(smsSender.getAuthentication().getProperties()); - smsSenderAttributes.putAll(smsSender.getProperties()); - } + smsSenderAttributes.putAll(smsSender.getProperties()); List resourceAttributes = smsSenderAttributes.entrySet().stream().filter(attribute -> attribute.getValue() != null) .map(attribute -> new Attribute(attribute.getKey(), attribute.getValue())) .collect(Collectors.toList()); + addSmsSenderAuthenticationToResource(smsSenderAttributes, smsSender.getAuthentication()); resource.setAttributes(resourceAttributes); // Set file. ResourceFile file = new ResourceFile(); @@ -278,6 +279,22 @@ private Resource buildResourceFromSmsSender(SMSSenderDTO smsSender) return resource; } + private void addSmsSenderAuthenticationToResource( + Map smsSenderAttributes, Authentication authentication) { + + if (authentication != null) { + smsSenderAttributes.put(AUTH_TYPE, authentication.getType().name()); + for (AuthProperty property : authentication.getProperties()) { + if (property.getScope() == AuthProperty.Scope.INTERNAL) { + smsSenderAttributes.put(AUTH_INTERNAL_PROP_PREFIX + property.getName(), property.getValue()); + } else { + smsSenderAttributes.put(AUTH_EXTERNAL_PROP_PREFIX + property.getName(), property.getValue()); + } + } + } + + } + private void reDeployEventPublisherConfiguration(Resource resource) { ResourceFile file = resource.getFiles().get(0); diff --git a/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/utils/NotificationSenderUtils.java b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/utils/NotificationSenderUtils.java index 29bed48fe..91429b33b 100644 --- a/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/utils/NotificationSenderUtils.java +++ b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/utils/NotificationSenderUtils.java @@ -30,6 +30,7 @@ import org.wso2.carbon.identity.notification.push.provider.PushProvider; import org.wso2.carbon.identity.notification.push.provider.exception.PushProviderException; import org.wso2.carbon.identity.notification.push.provider.model.PushSenderData; +import org.wso2.carbon.identity.notification.sender.tenant.config.dto.AuthProperty; import org.wso2.carbon.identity.notification.sender.tenant.config.dto.EmailSenderDTO; import org.wso2.carbon.identity.notification.sender.tenant.config.dto.PushSenderDTO; import org.wso2.carbon.identity.notification.sender.tenant.config.dto.SMSSenderDTO; @@ -43,6 +44,7 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Locale; @@ -63,7 +65,8 @@ import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.ADAPTER_TYPE_EMAIL_VALUE; import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.ADAPTER_TYPE_HTTP_VALUE; import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.ADAPTER_TYPE_KEY; -import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.AUTH_PROP_PREFIX; +import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.AUTH_EXTERNAL_PROP_PREFIX; +import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.AUTH_INTERNAL_PROP_PREFIX; import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.AUTH_TYPE; import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.BASIC; import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.CLIENT_CREDENTIAL; @@ -202,6 +205,25 @@ public static InputStream generateSMSPublisher(SMSSenderDTO smsSender) return new ByteArrayInputStream(outputStream.toByteArray()); } + /** + * Convert AuthProperty list to a map with proper prefixes. + * + * @param authProperties List of AuthProperty. + * @return Map of AuthProperty with proper prefixes. + */ + public static Map convertAuthPropertiesToMap(List authProperties) { + + Map authPropertiesMap = new HashMap<>(); + for (AuthProperty property : authProperties) { + if (property.getScope() == AuthProperty.Scope.INTERNAL) { + authPropertiesMap.put(AUTH_INTERNAL_PROP_PREFIX + property.getName(), property.getValue()); + } else { + authPropertiesMap.put(AUTH_EXTERNAL_PROP_PREFIX + property.getName(), property.getValue()); + } + } + return authPropertiesMap; + } + private static void addEventPublisherAttributes(EmailSenderDTO emailSender, Document document, Element root) { Map eventPublisherAttributes = new HashMap<>(); @@ -382,9 +404,7 @@ private static void addToElementToSMSEventPublisher(SMSSenderDTO smsSender, Map< if (StringUtils.isNotEmpty(smsSender.getAuthentication().getType().getName())) { adapterProperties.put(AUTH_TYPE, smsSender.getAuthentication().getType().getName()); } - for (Map.Entry property : smsSender.getAuthentication().getProperties().entrySet()) { - adapterProperties.put(AUTH_PROP_PREFIX + property.getKey(), property.getValue()); - } + adapterProperties.putAll(convertAuthPropertiesToMap(smsSender.getAuthentication().getProperties())); } // Default client method is httpPost. Can be changed by configuring properties. @@ -456,6 +476,7 @@ public static SMSSenderDTO buildSmsSenderFromResource(Resource resource) { .filter(attribute -> !(INTERNAL_PROPERTIES.contains(attribute.getKey()))) .filter(attribute -> attribute.getValue() != null) .collect(Collectors.toMap(Attribute::getKey, Attribute::getValue)); + List internalAuthProperties = new ArrayList<>(); attributesMap.forEach((key, value) -> { switch (key) { case PROVIDER: @@ -480,9 +501,16 @@ public static SMSSenderDTO buildSmsSenderFromResource(Resource resource) { smsSenderBuilder.authType(value); break; default: - if (StringUtils.startsWith(key, AUTH_PROP_PREFIX)) { - String authPropertyKey = StringUtils.removeStart(key, AUTH_PROP_PREFIX); - smsSenderBuilder.addAuthPropertiesString(authPropertyKey, value); + if (StringUtils.startsWith(key, AUTH_INTERNAL_PROP_PREFIX)) { + AuthProperty internalAuthProperty = new AuthProperty.Builder( + StringUtils.removeStart(key, AUTH_INTERNAL_PROP_PREFIX), + value, + AuthProperty.Scope.INTERNAL) + .build(); + internalAuthProperties.add(internalAuthProperty); + } else if (StringUtils.startsWith(key, AUTH_INTERNAL_PROP_PREFIX)) { + smsSenderBuilder.addAuthProperties( + StringUtils.removeStart(key, AUTH_INTERNAL_PROP_PREFIX), value); } else { smsSenderBuilder.addProperty(key, value); } @@ -490,7 +518,12 @@ public static SMSSenderDTO buildSmsSenderFromResource(Resource resource) { }); try { - return smsSenderBuilder.build(); + SMSSenderDTO smsSenderDTO = smsSenderBuilder.build(); + internalAuthProperties.forEach(internalAuthProperty -> + smsSenderDTO.getAuthentication().setInternalAuthProperty( + internalAuthProperty.getName(), internalAuthProperty.getValue()) + ); + return smsSenderDTO; } catch (NotificationSenderManagementException e) { // This exception won't occur as we are not setting any invalid values. return null; diff --git a/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/utils/TokenManager.java b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/utils/TokenManager.java new file mode 100644 index 000000000..502daeafe --- /dev/null +++ b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/utils/TokenManager.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2025, 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.identity.notification.sender.tenant.config.utils; + +import org.apache.commons.lang.StringUtils; +import org.wso2.carbon.identity.external.api.client.api.model.APIClientConfig; +import org.wso2.carbon.identity.external.api.token.handler.api.exception.TokenHandlerException; +import org.wso2.carbon.identity.external.api.token.handler.api.model.GrantContext; +import org.wso2.carbon.identity.external.api.token.handler.api.model.TokenRequestContext; +import org.wso2.carbon.identity.external.api.token.handler.api.model.TokenResponse; +import org.wso2.carbon.identity.external.api.token.handler.api.service.TokenAcquirerService; +import org.wso2.carbon.identity.notification.sender.tenant.config.dto.AuthProperty; +import org.wso2.carbon.identity.notification.sender.tenant.config.dto.Authentication; + +import java.util.HashMap; +import java.util.Map; + +/** + * Manager class for handling Client Credentials Token acquisition and management. + */ +public class TokenManager { + + private final TokenAcquirerService tokenAcquirerService; + private TokenResponse tokenResponse; + private Authentication authentication; + + public TokenManager() { + + this.tokenAcquirerService = new TokenAcquirerService(buildAPIClientConfig()); + } + + public void setAuthentication(Authentication authentication) { + + this.authentication = authentication; + } + + public String getToken() throws TokenHandlerException { + + if (tokenResponse != null && StringUtils.isBlank(tokenResponse.getAccessToken())) { + return tokenResponse.getAccessToken(); + } + return getNewToken(false); + } + + public String getRefreshToken() { + + return tokenResponse.getRefreshToken(); + } + + public String getNewToken(Boolean withRefreshTokenGrant) throws TokenHandlerException { + + TokenRequestContext tokenRequestContext = buildTokenRequestContext(authentication); + tokenAcquirerService.setTokenRequestContext(tokenRequestContext); + tokenResponse = tokenAcquirerService.getNewAccessToken(); + return tokenResponse.getAccessToken(); + } + + private TokenRequestContext buildTokenRequestContext(Authentication authentication) throws TokenHandlerException { + + // only for credentials grant type <= think where this check should go + // properly set the grant context details with switch + Map authPropertiesMap = new HashMap<>(); + for (AuthProperty authProperty : authentication.getProperties()) { + if (authProperty.getScope() == AuthProperty.Scope.EXTERNAL) { + authPropertiesMap.put(authProperty.getName(), authProperty.getValue()); + } + } + + GrantContext grantContext = new GrantContext.Builder() + .grantType(GrantContext.GrantType.CLIENT_CREDENTIAL) + .properties(authPropertiesMap) + .build(); + + // get endpoint url from prop + TokenRequestContext.Builder builder = new TokenRequestContext.Builder() + .grantContext(grantContext) + .endpointUrl("https://customauth.free.beeceptor.com/todos"); + + return builder.build(); + } + + private APIClientConfig buildAPIClientConfig() { + + APIClientConfig.Builder configBuilder = new APIClientConfig.Builder(); + return configBuilder.build(); + } +} diff --git a/pom.xml b/pom.xml index 7be94e750..fa1567357 100644 --- a/pom.xml +++ b/pom.xml @@ -174,6 +174,11 @@ org.wso2.carbon.identity.secret.mgt.core ${carbon.identity.framework.version} + + org.wso2.carbon.identity.framework + org.wso2.carbon.identity.external.api.token.handler + ${carbon.identity.framework.version} + @@ -534,7 +539,7 @@ [2.1.0,3.0.0) - 7.8.249 + 7.8.596-SNAPSHOT [7.1.0, 8.0.0) From ea9d7d68c8c1bb6b189788342c6d477ed5336e9a Mon Sep 17 00:00:00 2001 From: thisarawelmilla Date: Tue, 4 Nov 2025 22:43:48 +0530 Subject: [PATCH 3/4] Improvement to sms configuration management --- .../pom.xml | 6 + ...NotificationSenderManagementConstants.java | 29 ++- .../tenant/config/dto/AuthProperty.java | 81 -------- .../tenant/config/dto/Authentication.java | 174 +++++++++++++----- .../tenant/config/dto/SMSSenderDTO.java | 123 ++++++++----- .../DefaultChannelConfigurationHandler.java | 24 +-- .../config/utils/NotificationSenderUtils.java | 98 ++++++---- .../tenant/config/utils/TokenManager.java | 112 +++++++---- pom.xml | 9 + 9 files changed, 377 insertions(+), 279 deletions(-) delete mode 100644 components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/dto/AuthProperty.java diff --git a/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/pom.xml b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/pom.xml index 0f8d8f224..29b422606 100644 --- a/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/pom.xml +++ b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/pom.xml @@ -70,6 +70,10 @@ org.wso2.carbon.identity.notification.push org.wso2.carbon.identity.notification.push.provider + + org.apache.httpcomponents.wso2 + httpcore + org.testng @@ -190,6 +194,8 @@ org.wso2.carbon.identity.secret.mgt.core; version="${carbon.identity.framework.imp.pkg.version.range}", org.wso2.carbon.identity.secret.mgt.core.exception; version="${carbon.identity.framework.imp.pkg.version.range}", org.wso2.carbon.identity.secret.mgt.core.model; version="${carbon.identity.framework.imp.pkg.version.range}", + + org.apache.http.*; version="${httpcore.version.osgi.import.range}" diff --git a/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/NotificationSenderManagementConstants.java b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/NotificationSenderManagementConstants.java index 7539b1124..161e5ed02 100644 --- a/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/NotificationSenderManagementConstants.java +++ b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/NotificationSenderManagementConstants.java @@ -53,15 +53,9 @@ private NotificationSenderManagementConstants() { public static final String SMS_PROVIDER = "SMS_PROVIDER"; public static final String PUSH_PROVIDER = "PUSH_PROVIDER"; - // Authentication properties - public static final String USERNAME_AUTH_PROP = "username"; - public static final String PASSWORD_AUTH_PROP = "password"; - public static final String CLIENT_ID_AUTH_PROP = "client_id"; - public static final String CLIENT_SECRET_AUTH_PROP = "client_secret"; - public static final String HEADER_AUTH_PROP = "header"; - public static final String VALUE_AUTH_PROP = "value"; - public static final String ACCESS_TOKEN_AUTH_PROP = "accessToken"; - public static final String SCOPE_AUTH_PROP = "scope"; + // Notification sender authentication properties + public static final String AUTH_HEADER = "authorization"; + public static final String AUTH_TYPE_PREFIX = "auth.authType"; public static final String AUTH_INTERNAL_PROP_PREFIX = "auth.internal."; public static final String AUTH_EXTERNAL_PROP_PREFIX = "auth.external."; @@ -178,6 +172,14 @@ public enum ErrorMessage { ERROR_CODE_CONNECTED_APPLICATION_EXISTS("60008", "Unable to disable.", "There are applications using this connection."), + ERROR_CODE_MISSING_AUTH_TYPE("60009", "Missing authentication type.", + "Authentication type must be provided in the authentication configuration."), + ERROR_CODE_UNSUPPORTED_AUTH_TYPE("60010", "Unsupported authentication type.", + "Unsupported authentication type is provided for authentication configuration."), + ERROR_CODE_BLANK_AUTH_PROPERTY("60011", "Blank authentication property value.", + "The authentication property %s cannot be blank or empty."), + ERROR_CODE_MISSING_AUTH_PROPERTY("60012", "Missing authentication property.", + "The property %s must be included as an authentication property."), // Server errors 650xx. ERROR_CODE_NO_ACTIVE_PUBLISHERS_FOUND("65001", "No active notification senders found.", @@ -239,7 +241,14 @@ public enum ErrorMessage { ERROR_CODE_ERROR_WHILE_DECRYPTING_CREDENTIALS("65024", "Error while decrypting credentials.", "Error while decrypting credentials for notification sender: %s."), ERROR_CODE_ERROR_WHILE_DELETING_CREDENTIALS("65025", "Error while deleting credentials.", - "Error while deleting credentials for notification sender: %s."); + "Error while deleting credentials for notification sender: %s."), + ERROR_CODE_ERROR_UNSUPPORTED_AUTH_TYPE_FOR_TOKEN_RETRIEVAL("65026", + "Unsupported authentication type.", "Unsupported authentication type for access " + + "token request, only supported for client credential type"), + ERROR_CODE_ERROR_WHILE_TOKEN_REQUEST_BUILDING("65027", "Error while building token request.", + "Error while building token request context for Client Credential grant."), + ERROR_CODE_ERROR_WHILE_RETRIEVING_TOKEN("65028", "Error while retrieving access token.", + "Error occurred while retrieving access token for notification sender."); private final String code; private final String message; diff --git a/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/dto/AuthProperty.java b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/dto/AuthProperty.java deleted file mode 100644 index 27e7cbaaa..000000000 --- a/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/dto/AuthProperty.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2025, 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.identity.notification.sender.tenant.config.dto; - -/** - * Authentication Property DTO. - */ -public class AuthProperty { - private final String name; - private final String value; - private final Scope scope; - - public AuthProperty(Builder authPropertyBuilder) { - - this.name = authPropertyBuilder.name; - this.value = authPropertyBuilder.value; - this.scope = authPropertyBuilder.scope; - } - - public String getName() { - - return name; - } - - public String getValue() { - - return value; - } - - public Scope getScope() { - - return scope; - } - - /** - * Authentication Property Builder. - */ - public static class Builder { - - private final String name; - private final String value; - private final Scope scope; - - public Builder(String name, String value, Scope scope) { - - this.name = name; - this.value = value; - this.scope = scope; - } - - public AuthProperty build() { - - return new AuthProperty(this); - } - } - - /** - * Enum for Property Scope. - */ - public enum Scope { - - INTERNAL, - EXTERNAL; - } -} diff --git a/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/dto/Authentication.java b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/dto/Authentication.java index ecb23e79b..1ee0199c9 100644 --- a/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/dto/Authentication.java +++ b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/dto/Authentication.java @@ -19,33 +19,36 @@ package org.wso2.carbon.identity.notification.sender.tenant.config.dto; import org.apache.commons.lang.StringUtils; - -import java.util.ArrayList; -import java.util.List; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.http.Header; +import org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.ErrorMessage; +import org.wso2.carbon.identity.notification.sender.tenant.config.exception.NotificationSenderManagementClientException; +import org.wso2.carbon.identity.notification.sender.tenant.config.exception.NotificationSenderManagementException; +import org.wso2.carbon.identity.notification.sender.tenant.config.exception.NotificationSenderManagementServerException; +import org.wso2.carbon.identity.notification.sender.tenant.config.utils.NotificationSenderUtils; +import org.wso2.carbon.identity.notification.sender.tenant.config.utils.TokenManager; + +import java.util.HashMap; import java.util.Map; -import java.util.NoSuchElementException; - -import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.ACCESS_TOKEN_AUTH_PROP; -import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.CLIENT_ID_AUTH_PROP; -import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.CLIENT_SECRET_AUTH_PROP; -import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.HEADER_AUTH_PROP; -import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.PASSWORD_AUTH_PROP; -import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.SCOPE_AUTH_PROP; -import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.USERNAME_AUTH_PROP; -import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.VALUE_AUTH_PROP; /** * Authentication configuration for the notification sending provider. */ public class Authentication { + private static final Log LOG = LogFactory.getLog(Authentication.class); private final Type type; - private final List authProperties; + private final Map authProperties; + private final Map internalAuthProperties; + private Header authHeader; public Authentication(AuthenticationBuilder builder) { type = builder.authType; authProperties = builder.resolvedAuthProperties; + internalAuthProperties = builder.internalAuthProperties; + authHeader = builder.authHeader; } public Authentication.Type getType() { @@ -53,22 +56,50 @@ public Authentication.Type getType() { return type; } - public List getProperties() { + public Map getProperties() { return authProperties; } - public AuthProperty getProperty(String propertyName) { + public String getProperty(String propertyName) { + + return authProperties.get(propertyName); + } + + public void addInternalProperty(String propKey, String propValue) { + + authProperties.put(propKey, propValue); + } + + public Map getInternalProperties() { + + return internalAuthProperties; + } + + public Header getAuthHeader() throws NotificationSenderManagementServerException { - return this.authProperties.stream() - .filter(property -> propertyName.equals(property.getName())) - .findFirst() - .orElse(null); + if (type == Type.CLIENT_CREDENTIAL && authHeader == null) { + if (LOG.isDebugEnabled()) { + LOG.debug("Auth header is null for CLIENT_CREDENTIAL type. Building new auth header."); + } + authHeader = rebuildAuthHeader(); + } + return authHeader; } - public void setInternalAuthProperty(String key, String value) { + public Header rebuildAuthHeader() throws NotificationSenderManagementServerException { - authProperties.add(new AuthProperty.Builder(key, value, AuthProperty.Scope.INTERNAL).build()); + if (type == Type.CLIENT_CREDENTIAL) { + if (LOG.isDebugEnabled()) { + LOG.debug("Rebuilding auth header for CLIENT_CREDENTIAL authentication type."); + } + TokenManager.getInstance().retrieveToken(this); + authHeader = NotificationSenderUtils.buildAuthenticationHeader(type, internalAuthProperties); + if (LOG.isDebugEnabled()) { + LOG.debug("Successfully rebuilt auth header for CLIENT_CREDENTIAL authentication type."); + } + } + return authHeader; } /** @@ -78,62 +109,74 @@ public static class AuthenticationBuilder { private final Type authType; private final Map propertiesMap; - private final List resolvedAuthProperties = new ArrayList<>(); + private final Map resolvedAuthProperties = new HashMap<>(); + private final Map internalAuthProperties = new HashMap<>(); + private Header authHeader; - public AuthenticationBuilder (String type, Map authPropertiesMap) { + public AuthenticationBuilder (String type, Map authPropertiesMap) + throws NotificationSenderManagementClientException { this.authType = Type.valueOfName(type); this.propertiesMap = authPropertiesMap; } - public AuthenticationBuilder setInternalAuthProperty(String key, String value) { + public AuthenticationBuilder internalAuthProperty(String propKey, String propValue) { - resolvedAuthProperties.add(new AuthProperty.Builder(key, value, AuthProperty.Scope.INTERNAL).build()); + resolvedAuthProperties.put(propKey, propValue); return this; } - public Authentication build() { + public Authentication build() throws NotificationSenderManagementException { + + if (LOG.isDebugEnabled()) { + LOG.debug("Building authentication configuration for type: " + authType); + } switch (authType) { case BASIC: - resolvedAuthProperties.add(getProperty(Type.BASIC, propertiesMap, USERNAME_AUTH_PROP)); - resolvedAuthProperties.add(getProperty(Type.BASIC, propertiesMap, PASSWORD_AUTH_PROP)); + resolvedAuthProperties.put(Property.USERNAME.getName(), getProperty(Property.USERNAME)); + resolvedAuthProperties.put(Property.PASSWORD.getName(), getProperty(Property.PASSWORD)); break; case BEARER: - resolvedAuthProperties.add(getProperty(Type.BEARER, propertiesMap, ACCESS_TOKEN_AUTH_PROP)); + resolvedAuthProperties.put(Property.ACCESS_TOKEN.getName(), getProperty(Property.ACCESS_TOKEN)); break; case CLIENT_CREDENTIAL: - resolvedAuthProperties.add(getProperty(Type.CLIENT_CREDENTIAL, propertiesMap, CLIENT_ID_AUTH_PROP)); - resolvedAuthProperties.add( - getProperty(Type.CLIENT_CREDENTIAL, propertiesMap, CLIENT_SECRET_AUTH_PROP)); - resolvedAuthProperties.add(getProperty(Type.CLIENT_CREDENTIAL, propertiesMap, SCOPE_AUTH_PROP)); + resolvedAuthProperties.put(Property.CLIENT_ID.getName(), getProperty(Property.CLIENT_ID)); + resolvedAuthProperties.put(Property.CLIENT_SECRET.getName(), getProperty(Property.CLIENT_SECRET)); + resolvedAuthProperties.put(Property.SCOPE.getName(), getProperty(Property.SCOPE)); + resolvedAuthProperties.put( + Property.TOKEN_ENDPOINT.getName(), getProperty(Property.TOKEN_ENDPOINT)); break; case API_KEY: - resolvedAuthProperties.add(getProperty(Type.BEARER, propertiesMap, HEADER_AUTH_PROP)); - resolvedAuthProperties.add(getProperty(Type.BEARER, propertiesMap, VALUE_AUTH_PROP)); + resolvedAuthProperties.put(Property.HEADER.getName(), getProperty(Property.HEADER)); + resolvedAuthProperties.put(Property.VALUE.getName(), getProperty(Property.VALUE)); break; case NONE: break; - default: - throw new IllegalArgumentException(String.format("An invalid authentication type '%s' is " + - "provided for the authentication configuration of the endpoint.", authType.name())); + } + authHeader = NotificationSenderUtils.buildAuthenticationHeader(authType, resolvedAuthProperties); + + if (LOG.isDebugEnabled()) { + LOG.debug("Successfully built authentication configuration for type: " + authType); } return new Authentication(this); } - private AuthProperty getProperty(Type authType, Map actionEndpointProperties, - String propName) { + private String getProperty(Property propName) throws NotificationSenderManagementClientException { - if (actionEndpointProperties != null && actionEndpointProperties.containsKey(propName)) { - String propValue = actionEndpointProperties.get(propName); + if (propertiesMap != null && propertiesMap.containsKey(propName.getName())) { + String propValue = propertiesMap.get(propName.getName()); if (StringUtils.isNotBlank(propValue)) { - return new AuthProperty.Builder(propName, propValue, AuthProperty.Scope.EXTERNAL).build(); + return propValue; } - throw new IllegalArgumentException(String.format("The Property %s cannot be blank.", propName)); + LOG.error("Authentication property '" + propName.getName() + "' is blank."); + throw new NotificationSenderManagementClientException( + ErrorMessage.ERROR_CODE_BLANK_AUTH_PROPERTY, propName.getName()); } - throw new NoSuchElementException(String.format("The property %s must be provided as an authentication " + - "property for the %s authentication type.", propName, authType.name())); + LOG.error("Required authentication property '" + propName.getName() + "' is missing."); + throw new NotificationSenderManagementClientException( + ErrorMessage.ERROR_CODE_MISSING_AUTH_PROPERTY, propName.getName()); } } @@ -160,10 +203,12 @@ public String getName() { return name; } - public static Type valueOfName(String name) { + + public static Type valueOfName(String name) throws NotificationSenderManagementClientException { if (name == null || name.isEmpty()) { - throw new IllegalArgumentException("Authentication type cannot be null or empty."); + LOG.error("Authentication type is missing or empty."); + throw new NotificationSenderManagementClientException(ErrorMessage.ERROR_CODE_MISSING_AUTH_TYPE, name); } for (Type type : Type.values()) { @@ -171,7 +216,36 @@ public static Type valueOfName(String name) { return type; } } - throw new IllegalArgumentException("Invalid authentication type: " + name); + LOG.error("Unsupported authentication type: " + name); + throw new NotificationSenderManagementClientException(ErrorMessage.ERROR_CODE_UNSUPPORTED_AUTH_TYPE, name); + } + } + + /** + * Authentication Property Enum. + */ + public enum Property { + + USERNAME("username"), + PASSWORD("password"), + HEADER("header"), + VALUE("value"), + ACCESS_TOKEN("accessToken"), + CLIENT_ID("client_id"), + CLIENT_SECRET("client_secret"), + SCOPE("scope"), + TOKEN_ENDPOINT("token_endpoint"); + + private final String name; + + Property(String name) { + + this.name = name; + } + + public String getName() { + + return name; } } } diff --git a/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/dto/SMSSenderDTO.java b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/dto/SMSSenderDTO.java index 08b3ce3ab..a19c947de 100644 --- a/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/dto/SMSSenderDTO.java +++ b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/dto/SMSSenderDTO.java @@ -19,23 +19,24 @@ package org.wso2.carbon.identity.notification.sender.tenant.config.dto; import org.apache.commons.lang.StringUtils; -import org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.ErrorMessage; +import org.wso2.carbon.identity.notification.sender.tenant.config.dto.Authentication.Property; +import org.wso2.carbon.identity.notification.sender.tenant.config.exception.NotificationSenderManagementClientException; import org.wso2.carbon.identity.notification.sender.tenant.config.exception.NotificationSenderManagementException; -import org.wso2.carbon.identity.notification.sender.tenant.config.utils.TokenManager; import java.util.HashMap; import java.util.Map; -import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.PASSWORD_AUTH_PROP; -import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.USERNAME_AUTH_PROP; import static org.wso2.carbon.identity.notification.sender.tenant.config.dto.Authentication.Type.BASIC; - /** * DTO for SMS sender. */ public class SMSSenderDTO { - + + private static final Log LOG = LogFactory.getLog(SMSSenderDTO.class); private String name; private String provider; private String providerURL; @@ -44,7 +45,7 @@ public class SMSSenderDTO { private String sender; private String contentType; private Map properties = new HashMap<>(); - private Authentication authentication; + private Authentication authentication = null; public String getName() { @@ -136,24 +137,6 @@ public Authentication getAuthentication() { return authentication; } - public void getToken() { - - // check allowed grant to call - TokenManager tokenManager = new TokenManager(); - Map authProps = new HashMap<>(); - authProps.put("client_id", "TESTID"); - authProps.put("client_secret", "TESTSECRET"); - authProps.put("scope", "testing"); - Authentication tempAuth = new Authentication.AuthenticationBuilder( - Authentication.Type.CLIENT_CREDENTIAL.name(), authProps).build(); - tokenManager.setAuthentication(tempAuth); - try { - tokenManager.getToken(); - } catch (Exception e) { - throw new IllegalArgumentException("Error while acquiring token for the SMS sender", e); - } - } - /** * Builder for SMSSenderDTO. */ @@ -224,7 +207,7 @@ public Builder authType(String authType) { return this; } - public Builder addAuthProperties(String key, String value) { + public Builder addAuthProperty(String key, String value) { authProperties.put(key, value); return this; @@ -232,14 +215,12 @@ public Builder addAuthProperties(String key, String value) { public SMSSenderDTO build() throws NotificationSenderManagementException { - SMSSenderDTO smsSenderDTO = new SMSSenderDTO(); - if (StringUtils.isNotEmpty(authType)) { - Authentication authentication = new Authentication.AuthenticationBuilder( - authType, authProperties).build(); - validateAuthConfig(authentication); - smsSenderDTO.setAuthentication(authentication); + if (LOG.isDebugEnabled()) { + LOG.debug("Building SMSSenderDTO for provider: " + this.provider); } + SMSSenderDTO smsSenderDTO = new SMSSenderDTO(); + smsSenderDTO.setAuthentication(buildAuthConfig()); smsSenderDTO.setName(this.name); smsSenderDTO.setProvider(this.provider); smsSenderDTO.setProviderURL(this.providerURL); @@ -248,26 +229,80 @@ public SMSSenderDTO build() throws NotificationSenderManagementException { smsSenderDTO.setSender(this.sender); smsSenderDTO.setContentType(this.contentType); smsSenderDTO.setProperties(this.properties); + + if (LOG.isDebugEnabled()) { + LOG.debug("Successfully built SMSSenderDTO for provider: " + this.provider); + } return smsSenderDTO; } - private void validateAuthConfig(Authentication authentication) throws NotificationSenderManagementException { + private Authentication buildAuthConfig() throws NotificationSenderManagementException { - /* If key and secret are not provided in the DTO, fetch them from the authentication - configuration for only if the BASIC auth type is configured. */ - if (StringUtils.isEmpty(key) && StringUtils.isEmpty(secret)) { - if (!BASIC.equals(authentication.getType())) { - return; + if (LOG.isDebugEnabled()) { + LOG.debug("Building authentication configuration for SMS sender. Auth type: " + authType); + } + + Authentication authentication = null; + if (StringUtils.isNotEmpty(authType)) { + authentication = new Authentication.AuthenticationBuilder(authType, authProperties).build(); + } + + if (authentication != null) { + boolean isBasic = BASIC.equals(authentication.getType()); + + // Non-basic: key or secret updates not allowed + if (!isBasic) { + if (StringUtils.isNotEmpty(key) || StringUtils.isNotEmpty(secret)) { + LOG.error("Key or secret updates not allowed for non-BASIC authentication type: " + + authentication.getType()); + throw new NotificationSenderManagementClientException( + ErrorMessage.ERROR_CODE_CHANNEL_TYPE_UPDATE_NOT_ALLOWED); + } + return authentication; + } + + // BASIC: validate or assign key and secret + String existingKey = authentication.getProperty(Property.USERNAME.getName()); + String existingSecret = authentication.getProperty(Property.PASSWORD.getName()); + + if (StringUtils.isNotBlank(key) && !StringUtils.equals(key, existingKey)) { + LOG.error("Key update not allowed for BASIC authentication. Attempted to change existing key."); + throw new NotificationSenderManagementClientException( + ErrorMessage.ERROR_CODE_CHANNEL_TYPE_UPDATE_NOT_ALLOWED); + } + if (StringUtils.isBlank(key)) { + if (LOG.isDebugEnabled()) { + LOG.debug("Key not provided. Using existing key from authentication configuration."); + } + key(existingKey); } - key(authentication.getProperty(USERNAME_AUTH_PROP).getValue()); - secret(authentication.getProperty(PASSWORD_AUTH_PROP).getValue()); + + if (StringUtils.isNotBlank(secret) && !StringUtils.equals(secret, existingSecret)) { + LOG.error("Secret update not allowed for BASIC authentication. Attempted to change existing secret."); + throw new NotificationSenderManagementClientException( + ErrorMessage.ERROR_CODE_CHANNEL_TYPE_UPDATE_NOT_ALLOWED); + } + if (StringUtils.isBlank(secret)) { + if (LOG.isDebugEnabled()) { + LOG.debug("Secret not provided. Using existing secret from authentication configuration."); + } + secret(existingSecret); + } + + return authentication; } - if (!StringUtils.equals(key, authentication.getProperty(USERNAME_AUTH_PROP).getValue()) || - !StringUtils.equals(secret, authentication.getProperty(PASSWORD_AUTH_PROP).getValue())) { - throw new NotificationSenderManagementException( - NotificationSenderManagementConstants.ErrorMessage.ERROR_CODE_CHANNEL_TYPE_UPDATE_NOT_ALLOWED); + // If authType not provided, then creating BASIC if key and secret provided + if (StringUtils.isNotBlank(key) && StringUtils.isNotBlank(secret)) { + if (LOG.isDebugEnabled()) { + LOG.debug("Auth type not provided. Creating BASIC authentication with provided key and secret."); + } + Map authProps = new HashMap<>(); + authProps.put(Property.USERNAME.getName(), key); + authProps.put(Property.PASSWORD.getName(), secret); + return new Authentication.AuthenticationBuilder(BASIC.toString(), authProps).build(); } + return null; } } } diff --git a/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/handlers/DefaultChannelConfigurationHandler.java b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/handlers/DefaultChannelConfigurationHandler.java index 90f2e963f..29544ca37 100644 --- a/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/handlers/DefaultChannelConfigurationHandler.java +++ b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/handlers/DefaultChannelConfigurationHandler.java @@ -36,14 +36,13 @@ import org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants; import org.wso2.carbon.identity.notification.sender.tenant.config.clustering.EventPublisherClusterDeleteMessage; import org.wso2.carbon.identity.notification.sender.tenant.config.clustering.EventPublisherClusterInvalidationMessage; -import org.wso2.carbon.identity.notification.sender.tenant.config.dto.AuthProperty; -import org.wso2.carbon.identity.notification.sender.tenant.config.dto.Authentication; import org.wso2.carbon.identity.notification.sender.tenant.config.dto.EmailSenderDTO; import org.wso2.carbon.identity.notification.sender.tenant.config.dto.SMSSenderDTO; import org.wso2.carbon.identity.notification.sender.tenant.config.exception.NotificationSenderManagementClientException; import org.wso2.carbon.identity.notification.sender.tenant.config.exception.NotificationSenderManagementException; import org.wso2.carbon.identity.notification.sender.tenant.config.exception.NotificationSenderManagementServerException; import org.wso2.carbon.identity.notification.sender.tenant.config.internal.NotificationSenderTenantConfigDataHolder; +import org.wso2.carbon.identity.notification.sender.tenant.config.utils.NotificationSenderUtils; import org.wso2.carbon.identity.tenant.resource.manager.exception.TenantResourceManagementClientException; import org.wso2.carbon.identity.tenant.resource.manager.exception.TenantResourceManagementException; import org.wso2.carbon.identity.tenant.resource.manager.exception.TenantResourceManagementServerException; @@ -61,9 +60,6 @@ import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.TransformerException; -import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.AUTH_EXTERNAL_PROP_PREFIX; -import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.AUTH_INTERNAL_PROP_PREFIX; -import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.AUTH_TYPE; import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.CONTENT_TYPE; import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.DEFAULT_HANDLER_NAME; import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.DEFAULT_SMS_PUBLISHER; @@ -263,11 +259,11 @@ private Resource buildResourceFromSmsSender(SMSSenderDTO smsSender) smsSenderAttributes.put(SENDER, smsSender.getSender()); smsSenderAttributes.put(CONTENT_TYPE, smsSender.getContentType()); smsSenderAttributes.putAll(smsSender.getProperties()); + NotificationSenderUtils.addAuthenticationProperties(smsSenderAttributes, smsSender.getAuthentication()); List resourceAttributes = smsSenderAttributes.entrySet().stream().filter(attribute -> attribute.getValue() != null) .map(attribute -> new Attribute(attribute.getKey(), attribute.getValue())) .collect(Collectors.toList()); - addSmsSenderAuthenticationToResource(smsSenderAttributes, smsSender.getAuthentication()); resource.setAttributes(resourceAttributes); // Set file. ResourceFile file = new ResourceFile(); @@ -279,22 +275,6 @@ private Resource buildResourceFromSmsSender(SMSSenderDTO smsSender) return resource; } - private void addSmsSenderAuthenticationToResource( - Map smsSenderAttributes, Authentication authentication) { - - if (authentication != null) { - smsSenderAttributes.put(AUTH_TYPE, authentication.getType().name()); - for (AuthProperty property : authentication.getProperties()) { - if (property.getScope() == AuthProperty.Scope.INTERNAL) { - smsSenderAttributes.put(AUTH_INTERNAL_PROP_PREFIX + property.getName(), property.getValue()); - } else { - smsSenderAttributes.put(AUTH_EXTERNAL_PROP_PREFIX + property.getName(), property.getValue()); - } - } - } - - } - private void reDeployEventPublisherConfiguration(Resource resource) { ResourceFile file = resource.getFiles().get(0); diff --git a/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/utils/NotificationSenderUtils.java b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/utils/NotificationSenderUtils.java index 91429b33b..bd2e2cdff 100644 --- a/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/utils/NotificationSenderUtils.java +++ b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/utils/NotificationSenderUtils.java @@ -19,6 +19,8 @@ package org.wso2.carbon.identity.notification.sender.tenant.config.utils; import org.apache.commons.lang.StringUtils; +import org.apache.http.Header; +import org.apache.http.message.BasicHeader; import org.w3c.dom.Attr; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -30,7 +32,8 @@ import org.wso2.carbon.identity.notification.push.provider.PushProvider; import org.wso2.carbon.identity.notification.push.provider.exception.PushProviderException; import org.wso2.carbon.identity.notification.push.provider.model.PushSenderData; -import org.wso2.carbon.identity.notification.sender.tenant.config.dto.AuthProperty; +import org.wso2.carbon.identity.notification.sender.tenant.config.dto.Authentication; +import org.wso2.carbon.identity.notification.sender.tenant.config.dto.Authentication.Property; import org.wso2.carbon.identity.notification.sender.tenant.config.dto.EmailSenderDTO; import org.wso2.carbon.identity.notification.sender.tenant.config.dto.PushSenderDTO; import org.wso2.carbon.identity.notification.sender.tenant.config.dto.SMSSenderDTO; @@ -44,7 +47,8 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; -import java.util.ArrayList; +import java.nio.charset.StandardCharsets; +import java.util.Base64; import java.util.HashMap; import java.util.List; import java.util.Locale; @@ -66,8 +70,9 @@ import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.ADAPTER_TYPE_HTTP_VALUE; import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.ADAPTER_TYPE_KEY; import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.AUTH_EXTERNAL_PROP_PREFIX; +import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.AUTH_HEADER; import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.AUTH_INTERNAL_PROP_PREFIX; -import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.AUTH_TYPE; +import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.AUTH_TYPE_PREFIX; import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.BASIC; import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.CLIENT_CREDENTIAL; import static org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.CLIENT_HTTP_METHOD_PROPERTY; @@ -208,20 +213,20 @@ public static InputStream generateSMSPublisher(SMSSenderDTO smsSender) /** * Convert AuthProperty list to a map with proper prefixes. * - * @param authProperties List of AuthProperty. - * @return Map of AuthProperty with proper prefixes. + * @param authentication Authentication object. + * @param mapToBeUpdated Map to be updated with authentication properties. */ - public static Map convertAuthPropertiesToMap(List authProperties) { - - Map authPropertiesMap = new HashMap<>(); - for (AuthProperty property : authProperties) { - if (property.getScope() == AuthProperty.Scope.INTERNAL) { - authPropertiesMap.put(AUTH_INTERNAL_PROP_PREFIX + property.getName(), property.getValue()); - } else { - authPropertiesMap.put(AUTH_EXTERNAL_PROP_PREFIX + property.getName(), property.getValue()); - } + public static void addAuthenticationProperties(Map mapToBeUpdated, Authentication authentication) { + + if (authentication != null) { + mapToBeUpdated.put(AUTH_TYPE_PREFIX, authentication.getType().name()); + authentication.getProperties().forEach((propKey, propValue) -> + mapToBeUpdated.put(AUTH_EXTERNAL_PROP_PREFIX + propKey, propValue) + ); + authentication.getInternalProperties().forEach((propKey, propValue) -> + mapToBeUpdated.put(AUTH_INTERNAL_PROP_PREFIX + propKey, propValue) + ); } - return authPropertiesMap; } private static void addEventPublisherAttributes(EmailSenderDTO emailSender, Document document, Element root) { @@ -400,12 +405,7 @@ private static void addToElementToSMSEventPublisher(SMSSenderDTO smsSender, Map< } else { adapterProperties.put(HTTP_URL_PROPERTY, StringUtils.EMPTY); } - if (smsSender.getAuthentication() != null) { - if (StringUtils.isNotEmpty(smsSender.getAuthentication().getType().getName())) { - adapterProperties.put(AUTH_TYPE, smsSender.getAuthentication().getType().getName()); - } - adapterProperties.putAll(convertAuthPropertiesToMap(smsSender.getAuthentication().getProperties())); - } + addAuthenticationProperties(adapterProperties, smsSender.getAuthentication()); // Default client method is httpPost. Can be changed by configuring properties. adapterProperties.put(CLIENT_HTTP_METHOD_PROPERTY, CONSTANT_HTTP_POST); @@ -476,7 +476,7 @@ public static SMSSenderDTO buildSmsSenderFromResource(Resource resource) { .filter(attribute -> !(INTERNAL_PROPERTIES.contains(attribute.getKey()))) .filter(attribute -> attribute.getValue() != null) .collect(Collectors.toMap(Attribute::getKey, Attribute::getValue)); - List internalAuthProperties = new ArrayList<>(); + Map internalAuthProp = new HashMap<>(); attributesMap.forEach((key, value) -> { switch (key) { case PROVIDER: @@ -497,31 +497,27 @@ public static SMSSenderDTO buildSmsSenderFromResource(Resource resource) { case CONTENT_TYPE: smsSenderBuilder.contentType(value); break; - case AUTH_TYPE: + case AUTH_TYPE_PREFIX: smsSenderBuilder.authType(value); break; default: - if (StringUtils.startsWith(key, AUTH_INTERNAL_PROP_PREFIX)) { - AuthProperty internalAuthProperty = new AuthProperty.Builder( - StringUtils.removeStart(key, AUTH_INTERNAL_PROP_PREFIX), - value, - AuthProperty.Scope.INTERNAL) - .build(); - internalAuthProperties.add(internalAuthProperty); + if (StringUtils.startsWith(key, AUTH_EXTERNAL_PROP_PREFIX)) { + smsSenderBuilder.addAuthProperty( + StringUtils.removeStart(key, AUTH_EXTERNAL_PROP_PREFIX), value); } else if (StringUtils.startsWith(key, AUTH_INTERNAL_PROP_PREFIX)) { - smsSenderBuilder.addAuthProperties( - StringUtils.removeStart(key, AUTH_INTERNAL_PROP_PREFIX), value); + internalAuthProp.put(StringUtils.removeStart(key, AUTH_INTERNAL_PROP_PREFIX), value); } else { smsSenderBuilder.addProperty(key, value); } + break; } }); try { SMSSenderDTO smsSenderDTO = smsSenderBuilder.build(); - internalAuthProperties.forEach(internalAuthProperty -> - smsSenderDTO.getAuthentication().setInternalAuthProperty( - internalAuthProperty.getName(), internalAuthProperty.getValue()) + internalAuthProp.keySet().forEach(internalAuthProperty -> + smsSenderDTO.getAuthentication().addInternalProperty( + internalAuthProperty, internalAuthProp.get(internalAuthProperty)) ); return smsSenderDTO; } catch (NotificationSenderManagementException e) { @@ -694,4 +690,36 @@ public static PushSenderData buildPushSenderData(PushSenderDTO pushSenderDTO) { pushSenderData.setProviderId(pushSenderDTO.getProviderId()); return pushSenderData; } + + /** + * Build authentication header. + * + * @param authType Authentication type. + * @param authProperties Authentication properties. + * @return Header object. + */ + public static Header buildAuthenticationHeader(Authentication.Type authType, Map authProperties) { + + switch (authType) { + case BASIC: + String credentials = authProperties.get(Property.USERNAME.getName()) + ":" + + authProperties.get(Property.PASSWORD.getName()); + byte[] encodedBytes = Base64.getEncoder().encode(credentials.getBytes(StandardCharsets.UTF_8)); + return new org.apache.http.message.BasicHeader( + AUTH_HEADER, + "Basic " + new String(encodedBytes, StandardCharsets.UTF_8)); + case BEARER: + return new BasicHeader( + AUTH_HEADER, + "Bearer " + authProperties.get(Property.ACCESS_TOKEN.toString()) + ); + case API_KEY: + return new BasicHeader( + authProperties.get(Property.HEADER.toString()), + authProperties.get(Property.VALUE.toString()) + ); + default: + return null; + } + } } diff --git a/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/utils/TokenManager.java b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/utils/TokenManager.java index 502daeafe..4477bfa6b 100644 --- a/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/utils/TokenManager.java +++ b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/utils/TokenManager.java @@ -18,81 +18,119 @@ package org.wso2.carbon.identity.notification.sender.tenant.config.utils; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.wso2.carbon.identity.external.api.client.api.model.APIClientConfig; import org.wso2.carbon.identity.external.api.token.handler.api.exception.TokenHandlerException; import org.wso2.carbon.identity.external.api.token.handler.api.model.GrantContext; import org.wso2.carbon.identity.external.api.token.handler.api.model.TokenRequestContext; import org.wso2.carbon.identity.external.api.token.handler.api.model.TokenResponse; import org.wso2.carbon.identity.external.api.token.handler.api.service.TokenAcquirerService; -import org.wso2.carbon.identity.notification.sender.tenant.config.dto.AuthProperty; +import org.wso2.carbon.identity.notification.sender.tenant.config.NotificationSenderManagementConstants.ErrorMessage; import org.wso2.carbon.identity.notification.sender.tenant.config.dto.Authentication; - -import java.util.HashMap; -import java.util.Map; +import org.wso2.carbon.identity.notification.sender.tenant.config.exception.NotificationSenderManagementServerException; /** * Manager class for handling Client Credentials Token acquisition and management. */ public class TokenManager { + private static final Log LOG = LogFactory.getLog(TokenManager.class); private final TokenAcquirerService tokenAcquirerService; - private TokenResponse tokenResponse; - private Authentication authentication; + private static final TokenManager tokenManager = new TokenManager(); - public TokenManager() { + private TokenManager() { this.tokenAcquirerService = new TokenAcquirerService(buildAPIClientConfig()); } - public void setAuthentication(Authentication authentication) { + public static TokenManager getInstance() { - this.authentication = authentication; + return tokenManager; } - public String getToken() throws TokenHandlerException { + public void retrieveToken(Authentication authentication) throws NotificationSenderManagementServerException { - if (tokenResponse != null && StringUtils.isBlank(tokenResponse.getAccessToken())) { - return tokenResponse.getAccessToken(); + if (LOG.isDebugEnabled()) { + LOG.debug("Retrieving token for authentication type: " + authentication.getType()); } - return getNewToken(false); - } - public String getRefreshToken() { + TokenRequestContext tokenRequestContext = buildTokenRequestContext(authentication); + tokenAcquirerService.setTokenRequestContext(tokenRequestContext); + + TokenResponse tokenResponse; + String refreshToken = authentication.getInternalProperties().get("RefreshToken"); + + try { + if (refreshToken != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("Attempting to retrieve access token using refresh token grant."); + } + try { + tokenResponse = tokenAcquirerService.getNewAccessTokenFromRefreshGrant(refreshToken); + if (LOG.isDebugEnabled()) { + LOG.debug("Successfully retrieved access token using refresh token grant."); + } + } catch (TokenHandlerException e) { + LOG.warn("Failed to retrieve access token using refresh token grant. Falling back to client " + + "credentials grant.", e); + tokenResponse = tokenAcquirerService.getNewAccessToken(); + if (LOG.isDebugEnabled()) { + LOG.debug("Successfully retrieved access token using client credentials grant."); + } + } + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("No refresh token available. Retrieving access token using client credentials grant."); + } + tokenResponse = tokenAcquirerService.getNewAccessToken(); + if (LOG.isDebugEnabled()) { + LOG.debug("Successfully retrieved access token using client credentials grant."); + } + } + } catch (TokenHandlerException e) { + LOG.error("Error while retrieving token.", e); + throw new NotificationSenderManagementServerException( + ErrorMessage.ERROR_CODE_ERROR_WHILE_RETRIEVING_TOKEN, null, e); + } - return tokenResponse.getRefreshToken(); + addInternalProperties(tokenResponse, authentication); } - public String getNewToken(Boolean withRefreshTokenGrant) throws TokenHandlerException { + private void addInternalProperties(TokenResponse tokenResponse, Authentication authentication) { - TokenRequestContext tokenRequestContext = buildTokenRequestContext(authentication); - tokenAcquirerService.setTokenRequestContext(tokenRequestContext); - tokenResponse = tokenAcquirerService.getNewAccessToken(); - return tokenResponse.getAccessToken(); + authentication.addInternalProperty("RefreshToken", tokenResponse.getRefreshToken()); + authentication.addInternalProperty("AccessToken", tokenResponse.getAccessToken()); } - private TokenRequestContext buildTokenRequestContext(Authentication authentication) throws TokenHandlerException { + private TokenRequestContext buildTokenRequestContext(Authentication authentication) + throws NotificationSenderManagementServerException { - // only for credentials grant type <= think where this check should go - // properly set the grant context details with switch - Map authPropertiesMap = new HashMap<>(); - for (AuthProperty authProperty : authentication.getProperties()) { - if (authProperty.getScope() == AuthProperty.Scope.EXTERNAL) { - authPropertiesMap.put(authProperty.getName(), authProperty.getValue()); - } + if (authentication.getType() != Authentication.Type.CLIENT_CREDENTIAL) { + LOG.error("Unsupported authentication type for token retrieval: " + authentication.getType()); + throw new NotificationSenderManagementServerException( + ErrorMessage.ERROR_CODE_ERROR_UNSUPPORTED_AUTH_TYPE_FOR_TOKEN_RETRIEVAL, null); } - GrantContext grantContext = new GrantContext.Builder() + try { + if (LOG.isDebugEnabled()) { + LOG.debug("Building token request context for client credentials grant."); + } + GrantContext grantContext = new GrantContext.Builder() .grantType(GrantContext.GrantType.CLIENT_CREDENTIAL) - .properties(authPropertiesMap) + .properties(authentication.getProperties()) .build(); - // get endpoint url from prop - TokenRequestContext.Builder builder = new TokenRequestContext.Builder() - .grantContext(grantContext) - .endpointUrl("https://customauth.free.beeceptor.com/todos"); + TokenRequestContext.Builder builder = new TokenRequestContext.Builder() + .grantContext(grantContext) + .endpointUrl(authentication.getProperty(Authentication.Property.TOKEN_ENDPOINT.getName())); - return builder.build(); + return builder.build(); + } catch (TokenHandlerException e) { + LOG.error("Error while building token request context.", e); + throw new NotificationSenderManagementServerException( + ErrorMessage.ERROR_CODE_ERROR_WHILE_TOKEN_REQUEST_BUILDING, null, e); + } } private APIClientConfig buildAPIClientConfig() { diff --git a/pom.xml b/pom.xml index fa1567357..78dfb9987 100644 --- a/pom.xml +++ b/pom.xml @@ -295,6 +295,12 @@ ${com.fasterxml.jackson.databind.version} + + org.apache.httpcomponents.wso2 + httpcore + ${httpcore.version} + + org.wso2.carbon.identity.organization.management.core @@ -558,6 +564,9 @@ 2.9.0 [2.3.1,3.0.0) + 4.4.14.wso2v1 + [4.3.0, 5.0.0) + 5.1.2 3.8.0 From 1799c16989c2f3d0e8caaba27496e93694067b1a Mon Sep 17 00:00:00 2001 From: thisarawelmilla Date: Mon, 10 Nov 2025 11:33:21 +0530 Subject: [PATCH 4/4] Improvement to sms configuration management --- .../pom.xml.versionsBackup | 93 ++++ .../pom.xml.versionsBackup | 223 ++++++++ .../pom.xml.versionsBackup | 198 ++++++++ .../findbugs-exclude-filter.xml | 34 ++ .../pom.xml.versionsBackup | 221 ++++++++ .../tenant/config/dto/SMSSenderDTO.java | 3 +- .../tenant/config/dto/AuthenticationTest.java | 263 ++++++++++ .../tenant/config/dto/SMSSenderDTOTest.java | 345 +++++++++++++ .../tenant/config/utils/TokenManagerTest.java | 181 +++++++ .../src/test/resources/testng.xml | 3 + .../pom.xml.versionsBackup | 80 +++ .../pom.xml.versionsBackup | 131 +++++ .../pom.xml.versionsBackup | 82 +++ .../pom.xml.versionsBackup | 129 +++++ pom.xml.versionsBackup | 476 ++++++++++++++++++ .../pom.xml.versionsBackup | 113 +++++ 16 files changed, 2574 insertions(+), 1 deletion(-) create mode 100644 components/email-mgt/org.wso2.carbon.email.mgt.ui/pom.xml.versionsBackup create mode 100644 components/email-mgt/org.wso2.carbon.email.mgt/pom.xml.versionsBackup create mode 100644 components/event-handler-notification/org.wso2.carbon.identity.event.handler.notification/pom.xml.versionsBackup create mode 100644 components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/findbugs-exclude-filter.xml create mode 100644 components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/pom.xml.versionsBackup create mode 100644 components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/test/java/org/wso2/carbon/identity/notification/sender/tenant/config/dto/AuthenticationTest.java create mode 100644 components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/test/java/org/wso2/carbon/identity/notification/sender/tenant/config/dto/SMSSenderDTOTest.java create mode 100644 components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/test/java/org/wso2/carbon/identity/notification/sender/tenant/config/utils/TokenManagerTest.java create mode 100644 features/org.wso2.carbon.email.mgt.feature/pom.xml.versionsBackup create mode 100644 features/org.wso2.carbon.email.mgt.server.feature/pom.xml.versionsBackup create mode 100644 features/org.wso2.carbon.email.mgt.ui.feature/pom.xml.versionsBackup create mode 100644 features/org.wso2.carbon.event.handler.notification.server.feature/pom.xml.versionsBackup create mode 100644 pom.xml.versionsBackup create mode 100644 service-stubs/identity/org.wso2.carbon.email.mgt.stub/pom.xml.versionsBackup diff --git a/components/email-mgt/org.wso2.carbon.email.mgt.ui/pom.xml.versionsBackup b/components/email-mgt/org.wso2.carbon.email.mgt.ui/pom.xml.versionsBackup new file mode 100644 index 000000000..f144bc222 --- /dev/null +++ b/components/email-mgt/org.wso2.carbon.email.mgt.ui/pom.xml.versionsBackup @@ -0,0 +1,93 @@ + + + + + org.wso2.carbon.identity.event.handler.notification + identity-event-handler-notification + 1.8.3-SNAPSHOT + ../../../pom.xml + + + 4.0.0 + org.wso2.carbon.email.mgt.ui + bundle + WSO2 Carbon - Email Management UI + A custom wso2 products or solution + + + + org.apache.axis2.wso2 + axis2 + + + org.wso2.carbon + org.wso2.carbon.ui + + + org.wso2.carbon.identity.framework + org.wso2.carbon.identity.base + + + org.apache.ws.commons.axiom.wso2 + axiom + + + org.ops4j.pax.logging + pax-logging-api + + + org.wso2.carbon.identity.event.handler.notification + org.wso2.carbon.email.mgt.stub + + + org.wso2.orbit.org.owasp.encoder + encoder + + + + + + + org.apache.felix + maven-bundle-plugin + true + + + + ${project.artifactId} + + + org.wso2.carbon.email.mgt.ui.*;version="${identity.event.handler.notification.exp.pkg.version}", + + + org.apache.axis2;version="${axis2.wso2.imp.pkg.version.range}", + org.apache.axis2.client;version="${axis2.wso2.imp.pkg.version.range}", + org.apache.axis2.context;version="${axis2.wso2.imp.pkg.version.range}", + org.apache.commons.logging;version="${commons.logging.imp.pkg.version.range}", + org.wso2.carbon.email.mgt.model.xsd.*;version="${identity.event.handler.notification.imp.pkg.version.range}", + org.wso2.carbon.email.mgt.stub.*;version="${identity.event.handler.notification.imp.pkg.version.range}", + + UIBundle + + + + + + + diff --git a/components/email-mgt/org.wso2.carbon.email.mgt/pom.xml.versionsBackup b/components/email-mgt/org.wso2.carbon.email.mgt/pom.xml.versionsBackup new file mode 100644 index 000000000..0d9bee2fc --- /dev/null +++ b/components/email-mgt/org.wso2.carbon.email.mgt/pom.xml.versionsBackup @@ -0,0 +1,223 @@ + + + + + + org.wso2.carbon.identity.event.handler.notification + identity-event-handler-notification + 1.8.3-SNAPSHOT + ../../../pom.xml + + + 4.0.0 + org.wso2.carbon.email.mgt + bundle + WSO2 Carbon - Email Management + A custom wso2 products or solution + + + + org.wso2.carbon.identity.governance + org.wso2.carbon.identity.governance + + + org.apache.axis2.transport + axis2-transport-mail + + + org.wso2.carbon + org.wso2.carbon.registry.core + + + org.wso2.carbon + org.wso2.carbon.core + + + org.wso2.carbon + org.wso2.carbon.user.core + + + org.wso2.carbon + javax.cache.wso2 + + + org.apache.ws.commons.axiom.wso2 + axiom + + + org.ops4j.pax.logging + pax-logging-api + + + org.wso2.carbon + org.wso2.carbon.utils + + + org.wso2.carbon.identity.framework + org.wso2.carbon.identity.base + + + org.wso2.carbon.identity.framework + org.wso2.carbon.identity.core + + + org.wso2.carbon.commons + org.wso2.carbon.tenant.common + + + com.google.code.gson + gson + + + org.testng + testng + test + + + org.powermock + powermock-module-testng + test + + + org.powermock + powermock-api-mockito + test + + + + + + + org.apache.felix + maven-bundle-plugin + true + + + + ${project.artifactId} + + + org.wso2.carbon.email.mgt.internal, + + + !org.wso2.carbon.email.mgt.internal, + org.wso2.carbon.email.mgt.*;version="${identity.event.handler.notification.exp.pkg.version}", + + + javax.cache, + javax.xml.namespace, + 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.osgi.framework; version="${osgi.framework.imp.pkg.version.range}", + org.osgi.service.component; version="${osgi.service.component.imp.pkg.version.range}", + + org.wso2.carbon.stratos.common.*; version="${carbon.commons.imp.pkg.version}", + + com.google.gson.*; version="${com.google.code.gson.osgi.version.range}", + + org.wso2.carbon.core;version="${carbon.kernel.imp.pkg.version.range}", + org.wso2.carbon.context;version="${carbon.kernel.imp.pkg.version.range}", + org.wso2.carbon.user.core.*;version="${carbon.kernel.imp.pkg.version.range}", + org.wso2.carbon.utils;version="${carbon.kernel.imp.pkg.version.range}", + org.wso2.carbon.utils.multitenancy;version="${carbon.kernel.imp.pkg.version.range}", + org.wso2.carbon.user.api; version="${carbon.user.api.imp.pkg.version.range}", + org.wso2.carbon.identity.core.*; version="${carbon.identity.framework.imp.pkg.version.range}", + org.wso2.carbon.registry.core.*;version="${carbon.kernel.registry.imp.pkg.version}", + org.wso2.carbon.identity.base; version="${carbon.identity.framework.imp.pkg.version.range}", + org.wso2.carbon.identity.governance.*;version="${identity.governance.imp.pkg.version.range}" + + + + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven.surefire.plugin.version} + + + src/test/resources/testng.xml + + + + + org.jacoco + jacoco-maven-plugin + ${jacoco.version} + + + default-prepare-agent + + prepare-agent + + + + default-prepare-agent-integration + + prepare-agent-integration + + + + default-report + + report + + + + default-report-integration + + report-integration + + + + default-check + + check + + + + + BUNDLE + + + COMPLEXITY + COVEREDRATIO + + + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 8 + 8 + + + + + + + diff --git a/components/event-handler-notification/org.wso2.carbon.identity.event.handler.notification/pom.xml.versionsBackup b/components/event-handler-notification/org.wso2.carbon.identity.event.handler.notification/pom.xml.versionsBackup new file mode 100644 index 000000000..9b2e1373e --- /dev/null +++ b/components/event-handler-notification/org.wso2.carbon.identity.event.handler.notification/pom.xml.versionsBackup @@ -0,0 +1,198 @@ + + + + + org.wso2.carbon.identity.event.handler.notification + identity-event-handler-notification + 1.8.3-SNAPSHOT + ../../../pom.xml + + 4.0.0 + + org.wso2.carbon.identity.event.handler.notification + bundle + WSO2 Carbon - Notification Event Handling Management + A custom wso2 products or solution + + + + org.wso2.carbon.identity.governance + org.wso2.carbon.identity.governance + + + org.apache.axis2.transport + axis2-transport-mail + + + org.wso2.carbon + org.wso2.carbon.registry.core + + + org.wso2.carbon + org.wso2.carbon.core + + + org.wso2.carbon + org.wso2.carbon.user.core + + + org.wso2.carbon + javax.cache.wso2 + + + org.apache.ws.commons.axiom.wso2 + axiom + + + org.ops4j.pax.logging + pax-logging-api + + + org.wso2.carbon + org.wso2.carbon.utils + + + org.wso2.carbon.identity.framework + org.wso2.carbon.identity.event + + + org.wso2.carbon.identity.framework + org.wso2.carbon.identity.core + + + org.wso2.carbon.identity.framework + org.wso2.carbon.identity.application.authentication.framework + + + org.wso2.carbon.identity.event.handler.notification + org.wso2.carbon.email.mgt + + + org.wso2.carbon.identity.organization.management.core + org.wso2.carbon.identity.organization.management.service + + + org.wso2.carbon.identity.branding.preference.management + org.wso2.carbon.identity.branding.preference.management.core + provided + + + org.wso2.carbon.identity.framework + org.wso2.carbon.identity.central.log.mgt + + + com.fasterxml.jackson.core + jackson-databind + provided + + + + org.wso2.carbon.analytics-common + org.wso2.carbon.event.output.adapter.core + + + org.wso2.carbon.analytics-common + org.wso2.carbon.event.stream.core + + + org.wso2.carbon.analytics-common + org.wso2.carbon.event.publisher.core + + + org.wso2.carbon.analytics-common + org.wso2.carbon.databridge.commons + + + org.testng + testng + test + + + org.mockito + mockito-all + test + + + + + + + org.apache.felix + maven-bundle-plugin + true + + + + ${project.artifactId} + + + org.wso2.carbon.identity.event.handler.notification.internal, + + + !org.wso2.carbon.identity.event.handler.notification.internal, + org.wso2.carbon.identity.event.handler.notification.*;version="${identity.event.handler.notification.exp.pkg.version}", + + + javax.cache, + javax.xml.namespace, + + org.apache.axis2; version="${axis2.wso2.imp.pkg.version.range}", + org.apache.axis2.context; version="${axis2.wso2.imp.pkg.version.range}", + org.apache.axis2.engine; version="${axis2.wso2.imp.pkg.version.range}", + org.apache.axis2.description; version="${axis2.wso2.imp.pkg.version.range}", + org.apache.axis2.transport.http; version="${axis2.wso2.imp.pkg.version.range}", + + 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.wso2.osgi.version.range}", + + org.osgi.framework; version="${osgi.framework.imp.pkg.version.range}", + org.osgi.service.component; version="${osgi.service.component.imp.pkg.version.range}", + + org.wso2.carbon.stratos.common.*; version="${carbon.commons.imp.pkg.version}", + + org.wso2.carbon.core;version="${carbon.kernel.imp.pkg.version.range}", + org.wso2.carbon.context; version="${carbon.kernel.imp.pkg.version.range}", + org.wso2.carbon.user.core.*;version="${carbon.kernel.imp.pkg.version.range}", + org.wso2.carbon.utils;version="${carbon.kernel.imp.pkg.version.range}", + org.wso2.carbon.utils.multitenancy;version="${carbon.kernel.imp.pkg.version.range}", + org.wso2.carbon.identity.core.*; version="${carbon.identity.framework.imp.pkg.version.range}", + org.wso2.carbon.user.api; version="${carbon.user.api.imp.pkg.version.range}", + org.wso2.carbon.registry.core.*;version="${carbon.kernel.registry.imp.pkg.version}", + org.wso2.carbon.identity.base; version="${carbon.identity.framework.imp.pkg.version.range}", + org.wso2.carbon.identity.event; version="${carbon.identity.framework.imp.pkg.version.range}", + org.wso2.carbon.identity.event.event; version="${carbon.identity.framework.imp.pkg.version.range}", + org.wso2.carbon.identity.event.handler; version="${carbon.identity.framework.imp.pkg.version.range}", + org.wso2.carbon.identity.application.authentication.framework.config; version="${carbon.identity.framework.imp.pkg.version.range}", + org.wso2.carbon.event.output.adapter.core.*; version="${carbon.analytics.common.version.range}", + org.wso2.carbon.event.stream.core.*; version="${carbon.analytics.common.version.range}", + org.wso2.carbon.event.publisher.core.*; version="${carbon.analytics.common.version.range}", + org.wso2.carbon.databridge.commons.*; version="${carbon.analytics.common.version.range}", + org.wso2.carbon.email.mgt.*; version="${identity.event.handler.notification.imp.pkg.version.range}", + org.wso2.carbon.identity.central.log.mgt.*; version="${carbon.identity.framework.imp.pkg.version.range}", + org.wso2.carbon.identity.governance.*; version="${identity.governance.imp.pkg.version.range}", + org.wso2.carbon.identity.branding.preference.management.core.*; version="${identity.branding.preference.management.version.range}", + org.wso2.carbon.identity.organization.management.service;version="${org.wso2.identity.organization.mgt.core.imp.pkg.version.range}", + org.wso2.carbon.identity.organization.management.service.constant;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}", + + + + + + + diff --git a/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/findbugs-exclude-filter.xml b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/findbugs-exclude-filter.xml new file mode 100644 index 000000000..1517c11fd --- /dev/null +++ b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/findbugs-exclude-filter.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + diff --git a/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/pom.xml.versionsBackup b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/pom.xml.versionsBackup new file mode 100644 index 000000000..6f4336f92 --- /dev/null +++ b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/pom.xml.versionsBackup @@ -0,0 +1,221 @@ + + + + 4.0.0 + + + org.wso2.carbon.identity.event.handler.notification + identity-event-handler-notification + 1.8.3-SNAPSHOT + ../../../pom.xml + + + org.wso2.carbon.identity.notification.sender.tenant.config + bundle + WSO2 Carbon - Identity Notification Sender Configuration + Tenant wise Identity Notification Sender Configuration + + + + + org.wso2.carbon + org.wso2.carbon.core + + + org.wso2.carbon.identity.governance + org.wso2.carbon.identity.tenant.resource.manager + + + org.apache.felix + org.apache.felix.scr.ds-annotations + provided + + + org.wso2.carbon.identity.organization.management.core + org.wso2.carbon.identity.organization.management.service + + + org.wso2.carbon.identity.framework + org.wso2.carbon.identity.configuration.mgt.core + + + org.wso2.carbon.identity.framework + org.wso2.carbon.identity.application.mgt + + + org.wso2.carbon.identity.framework + org.wso2.carbon.identity.core + + + + org.testng + testng + test + + + org.mockito + mockito-inline + test + + + org.wso2.carbon.identity.event.handler.notification + org.wso2.carbon.email.mgt + + + + + + + org.apache.felix + maven-bundle-plugin + true + + + ${project.artifactId} + ${project.artifactId} + + org.wso2.carbon.identity.notification.sender.tenant.config.internal, + + + !org.wso2.carbon.identity.notification.sender.tenant.config.internal, + org.wso2.carbon.identity.notification.sender.tenant.config.*, + + + javax.xml.parsers; version="[0.0.0, 1.0.0)", + javax.xml.transform; version="[0.0.0, 1.0.0)", + javax.xml.transform.dom; version="[0.0.0, 1.0.0)", + javax.xml.transform.stream; version="[0.0.0, 1.0.0)", + org.w3c.dom; version="[0.0.0, 1.0.0)", + + org.apache.axis2.clustering; version="${axis2.osgi.version.range}", + org.apache.axis2.context; version="${axis2.osgi.version.range}", + org.apache.axis2.engine; version="${axis2.osgi.version.range}", + + org.apache.commons.lang; version="${commons-lang.wso2.osgi.version.range}", + org.apache.commons.logging; version="${commons.logging.imp.pkg.version.range}", + + org.osgi.framework; version="${osgi.framework.imp.pkg.version.range}", + org.osgi.service.component; version="${osgi.service.component.imp.pkg.version.range}", + org.osgi.service.component.annotations; version="${osgi.service.component.imp.pkg.version.range}", + + org.wso2.carbon.base.api; version="${carbon.kernel.carbon.base.pkg.version}", + org.wso2.carbon.context; version="${carbon.kernel.imp.pkg.version.range}", + + org.wso2.carbon.email.mgt; version="${identity.event.handler.notification.imp.pkg.version.range}", + org.wso2.carbon.email.mgt.model; version="${identity.event.handler.notification.imp.pkg.version.range}", + + org.wso2.carbon.event.publisher.core; version="${carbon.analytics.common.version.range}", + org.wso2.carbon.event.publisher.core.config; version="${carbon.analytics.common.version.range}", + org.wso2.carbon.event.publisher.core.exception; version="${carbon.analytics.common.version.range}", + + org.wso2.carbon.identity.application.mgt; version="${carbon.identity.framework.imp.pkg.version.range}", + org.wso2.carbon.identity.application.common; version="${carbon.identity.framework.imp.pkg.version.range}", + org.wso2.carbon.identity.application.common.util; version="${carbon.identity.framework.imp.pkg.version.range}", + + org.wso2.carbon.idp.mgt.model; version="${carbon.identity.framework.imp.pkg.version.range}", + + org.wso2.carbon.identity.configuration.mgt.core; + version="${carbon.identity.framework.imp.pkg.version.range}", + org.wso2.carbon.identity.configuration.mgt.core.exception; + version="${carbon.identity.framework.imp.pkg.version.range}", + org.wso2.carbon.identity.configuration.mgt.core.model; + version="${carbon.identity.framework.imp.pkg.version.range}", + org.wso2.carbon.identity.configuration.mgt.core.constant; + version="${carbon.identity.framework.imp.pkg.version.range}", + org.wso2.carbon.identity.core.util; + version="${carbon.identity.framework.imp.pkg.version.range}", + + org.wso2.carbon.identity.tenant.resource.manager.core; version="${identity.governance.imp.pkg.version.range}", + org.wso2.carbon.identity.tenant.resource.manager.exception; version="${identity.governance.imp.pkg.version.range}", + org.wso2.carbon.identity.tenant.resource.manager.util; version="${identity.governance.imp.pkg.version.range}", + org.wso2.carbon.utils; version="${carbon.kernel.imp.pkg.version.range}", + + org.wso2.carbon.identity.organization.management.service; + version="${org.wso2.identity.organization.mgt.core.imp.pkg.version.range}", + org.wso2.carbon.identity.organization.management.service.util; + 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}" + + + + + + com.github.spotbugs + spotbugs-maven-plugin + + Medium + + + + org.codehaus.mojo + findbugs-maven-plugin + + Max + Low + true + ${project.build.directory}/findbugs + + ${mavan.findbugsplugin.exclude.file} + + + com.h3xstream.findsecbugs + findsecbugs-plugin + LATEST + + + + + + analyze-compile + compile + + check + + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + + + validate + validate + + + https://raw.githubusercontent.com/wso2/code-quality-tools/master/checkstyle/checkstyle.xml + + + https://raw.githubusercontent.com/wso2/code-quality-tools/master/checkstyle/suppressions.xml + + UTF-8 + true + true + true + + + check + + + + + + + diff --git a/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/dto/SMSSenderDTO.java b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/dto/SMSSenderDTO.java index a19c947de..547d5c309 100644 --- a/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/dto/SMSSenderDTO.java +++ b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/main/java/org/wso2/carbon/identity/notification/sender/tenant/config/dto/SMSSenderDTO.java @@ -278,7 +278,8 @@ private Authentication buildAuthConfig() throws NotificationSenderManagementExce } if (StringUtils.isNotBlank(secret) && !StringUtils.equals(secret, existingSecret)) { - LOG.error("Secret update not allowed for BASIC authentication. Attempted to change existing secret."); + LOG.error("Secret update not allowed for BASIC authentication. " + + "Attempted to change existing secret."); throw new NotificationSenderManagementClientException( ErrorMessage.ERROR_CODE_CHANNEL_TYPE_UPDATE_NOT_ALLOWED); } diff --git a/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/test/java/org/wso2/carbon/identity/notification/sender/tenant/config/dto/AuthenticationTest.java b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/test/java/org/wso2/carbon/identity/notification/sender/tenant/config/dto/AuthenticationTest.java new file mode 100644 index 000000000..e98eb2745 --- /dev/null +++ b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/test/java/org/wso2/carbon/identity/notification/sender/tenant/config/dto/AuthenticationTest.java @@ -0,0 +1,263 @@ +/* + * Copyright (c) 2025, 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.identity.notification.sender.tenant.config.dto; + +import org.apache.http.Header; +import org.mockito.MockedStatic; +import org.testng.Assert; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; +import org.wso2.carbon.identity.notification.sender.tenant.config.dto.Authentication.Property; +import org.wso2.carbon.identity.notification.sender.tenant.config.dto.Authentication.Type; +import org.wso2.carbon.identity.notification.sender.tenant.config.exception.NotificationSenderManagementClientException; +import org.wso2.carbon.identity.notification.sender.tenant.config.utils.NotificationSenderUtils; + +import java.util.HashMap; +import java.util.Map; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; + +/** + * Unit tests for {@link Authentication}. + */ +public class AuthenticationTest { + + private Map authProperties; + private Header mockHeader; + + @BeforeMethod + public void setUp() { + authProperties = new HashMap<>(); + mockHeader = mock(Header.class); + } + + @AfterMethod + public void tearDown() { + authProperties.clear(); + } + + @Test + public void testAuthenticationBuilderWithBasicAuth() throws Exception { + authProperties.put(Property.USERNAME.getName(), "testuser"); + authProperties.put(Property.PASSWORD.getName(), "testpass"); + + try (MockedStatic mockedUtils = mockStatic(NotificationSenderUtils.class)) { + mockedUtils.when(() -> NotificationSenderUtils.buildAuthenticationHeader( + eq(Type.BASIC), any())).thenReturn(mockHeader); + + Authentication auth = new Authentication.AuthenticationBuilder("BASIC", authProperties).build(); + + Assert.assertNotNull(auth); + Assert.assertEquals(auth.getType(), Type.BASIC); + Assert.assertEquals(auth.getProperty(Property.USERNAME.getName()), "testuser"); + Assert.assertEquals(auth.getProperty(Property.PASSWORD.getName()), "testpass"); + } + } + + @Test + public void testAuthenticationBuilderWithBearerAuth() throws Exception { + authProperties.put(Property.ACCESS_TOKEN.getName(), "test-access-token"); + + try (MockedStatic mockedUtils = mockStatic(NotificationSenderUtils.class)) { + mockedUtils.when(() -> NotificationSenderUtils.buildAuthenticationHeader( + eq(Type.BEARER), any())).thenReturn(mockHeader); + + Authentication auth = new Authentication.AuthenticationBuilder("BEARER", authProperties).build(); + + Assert.assertNotNull(auth); + Assert.assertEquals(auth.getType(), Type.BEARER); + Assert.assertEquals(auth.getProperty(Property.ACCESS_TOKEN.getName()), "test-access-token"); + } + } + + @Test + public void testAuthenticationBuilderWithClientCredential() throws Exception { + authProperties.put(Property.CLIENT_ID.getName(), "test-client-id"); + authProperties.put(Property.CLIENT_SECRET.getName(), "test-client-secret"); + authProperties.put(Property.SCOPE.getName(), "test-scope"); + authProperties.put(Property.TOKEN_ENDPOINT.getName(), "https://test.com/token"); + + try (MockedStatic mockedUtils = mockStatic(NotificationSenderUtils.class)) { + mockedUtils.when(() -> NotificationSenderUtils.buildAuthenticationHeader( + eq(Type.CLIENT_CREDENTIAL), any())).thenReturn(mockHeader); + + Authentication auth = new Authentication.AuthenticationBuilder("CLIENT_CREDENTIAL", authProperties).build(); + + Assert.assertNotNull(auth); + Assert.assertEquals(auth.getType(), Type.CLIENT_CREDENTIAL); + Assert.assertEquals(auth.getProperty(Property.CLIENT_ID.getName()), "test-client-id"); + Assert.assertEquals(auth.getProperty(Property.CLIENT_SECRET.getName()), "test-client-secret"); + Assert.assertEquals(auth.getProperty(Property.SCOPE.getName()), "test-scope"); + Assert.assertEquals(auth.getProperty(Property.TOKEN_ENDPOINT.getName()), "https://test.com/token"); + } + } + + @Test + public void testAuthenticationBuilderWithApiKey() throws Exception { + authProperties.put(Property.HEADER.getName(), "X-API-KEY"); + authProperties.put(Property.VALUE.getName(), "test-api-key-value"); + + try (MockedStatic mockedUtils = mockStatic(NotificationSenderUtils.class)) { + mockedUtils.when(() -> NotificationSenderUtils.buildAuthenticationHeader( + eq(Type.API_KEY), any())).thenReturn(mockHeader); + + Authentication auth = new Authentication.AuthenticationBuilder("API_KEY", authProperties).build(); + + Assert.assertNotNull(auth); + Assert.assertEquals(auth.getType(), Type.API_KEY); + Assert.assertEquals(auth.getProperty(Property.HEADER.getName()), "X-API-KEY"); + Assert.assertEquals(auth.getProperty(Property.VALUE.getName()), "test-api-key-value"); + } + } + + @Test + public void testAuthenticationBuilderWithNoneType() throws Exception { + try (MockedStatic mockedUtils = mockStatic(NotificationSenderUtils.class)) { + mockedUtils.when(() -> NotificationSenderUtils.buildAuthenticationHeader( + eq(Type.NONE), any())).thenReturn(mockHeader); + + Authentication auth = new Authentication.AuthenticationBuilder("NONE", authProperties).build(); + + Assert.assertNotNull(auth); + Assert.assertEquals(auth.getType(), Type.NONE); + } + } + + @Test(expectedExceptions = NotificationSenderManagementClientException.class) + public void testAuthenticationBuilderWithMissingProperty() throws Exception { + authProperties.put(Property.USERNAME.getName(), "testuser"); + // Missing password property + + new Authentication.AuthenticationBuilder("BASIC", authProperties).build(); + } + + @Test(expectedExceptions = NotificationSenderManagementClientException.class) + public void testAuthenticationBuilderWithBlankProperty() throws Exception { + authProperties.put(Property.USERNAME.getName(), "testuser"); + authProperties.put(Property.PASSWORD.getName(), ""); + + new Authentication.AuthenticationBuilder("BASIC", authProperties).build(); + } + + @Test(expectedExceptions = NotificationSenderManagementClientException.class) + public void testAuthenticationBuilderWithNullAuthType() throws Exception { + new Authentication.AuthenticationBuilder(null, authProperties).build(); + } + + @Test(expectedExceptions = NotificationSenderManagementClientException.class) + public void testAuthenticationBuilderWithEmptyAuthType() throws Exception { + new Authentication.AuthenticationBuilder("", authProperties).build(); + } + + @Test(expectedExceptions = NotificationSenderManagementClientException.class) + public void testAuthenticationBuilderWithUnsupportedAuthType() throws Exception { + new Authentication.AuthenticationBuilder("UNSUPPORTED_TYPE", authProperties).build(); + } + + @Test + public void testTypeValueOfName() throws Exception { + Assert.assertEquals(Type.valueOfName("BASIC"), Type.BASIC); + Assert.assertEquals(Type.valueOfName("BEARER"), Type.BEARER); + Assert.assertEquals(Type.valueOfName("CLIENT_CREDENTIAL"), Type.CLIENT_CREDENTIAL); + Assert.assertEquals(Type.valueOfName("API_KEY"), Type.API_KEY); + Assert.assertEquals(Type.valueOfName("NONE"), Type.NONE); + } + + @Test + public void testTypeValueOfNameCaseInsensitive() throws Exception { + Assert.assertEquals(Type.valueOfName("basic"), Type.BASIC); + Assert.assertEquals(Type.valueOfName("Bearer"), Type.BEARER); + Assert.assertEquals(Type.valueOfName("client_credential"), Type.CLIENT_CREDENTIAL); + } + + @Test(expectedExceptions = NotificationSenderManagementClientException.class) + public void testTypeValueOfNameWithNull() throws Exception { + Type.valueOfName(null); + } + + @Test(expectedExceptions = NotificationSenderManagementClientException.class) + public void testTypeValueOfNameWithEmpty() throws Exception { + Type.valueOfName(""); + } + + @Test(expectedExceptions = NotificationSenderManagementClientException.class) + public void testTypeValueOfNameWithInvalid() throws Exception { + Type.valueOfName("INVALID_TYPE"); + } + + @Test + public void testGetters() throws Exception { + authProperties.put(Property.USERNAME.getName(), "testuser"); + authProperties.put(Property.PASSWORD.getName(), "testpass"); + + try (MockedStatic mockedUtils = mockStatic(NotificationSenderUtils.class)) { + mockedUtils.when(() -> NotificationSenderUtils.buildAuthenticationHeader( + eq(Type.BASIC), any())).thenReturn(mockHeader); + + Authentication auth = new Authentication.AuthenticationBuilder("BASIC", authProperties).build(); + + Assert.assertEquals(auth.getType(), Type.BASIC); + Assert.assertNotNull(auth.getProperties()); + Assert.assertEquals(auth.getProperties().size(), 2); + Assert.assertEquals(auth.getProperty(Property.USERNAME.getName()), "testuser"); + } + } + + @Test + public void testAddInternalProperty() throws Exception { + authProperties.put(Property.USERNAME.getName(), "testuser"); + authProperties.put(Property.PASSWORD.getName(), "testpass"); + + try (MockedStatic mockedUtils = mockStatic(NotificationSenderUtils.class)) { + mockedUtils.when(() -> NotificationSenderUtils.buildAuthenticationHeader( + eq(Type.BASIC), any())).thenReturn(mockHeader); + + Authentication auth = new Authentication.AuthenticationBuilder("BASIC", authProperties).build(); + + auth.addInternalProperty("testKey", "testValue"); + Assert.assertEquals(auth.getProperty("testKey"), "testValue"); + } + } + + @Test + public void testPropertyEnum() { + Assert.assertEquals(Property.USERNAME.getName(), "username"); + Assert.assertEquals(Property.PASSWORD.getName(), "password"); + Assert.assertEquals(Property.HEADER.getName(), "header"); + Assert.assertEquals(Property.VALUE.getName(), "value"); + Assert.assertEquals(Property.ACCESS_TOKEN.getName(), "accessToken"); + Assert.assertEquals(Property.CLIENT_ID.getName(), "client_id"); + Assert.assertEquals(Property.CLIENT_SECRET.getName(), "client_secret"); + Assert.assertEquals(Property.SCOPE.getName(), "scope"); + Assert.assertEquals(Property.TOKEN_ENDPOINT.getName(), "token_endpoint"); + } + + @Test + public void testTypeEnum() { + Assert.assertEquals(Type.NONE.getName(), "NONE"); + Assert.assertEquals(Type.BEARER.getName(), "BEARER"); + Assert.assertEquals(Type.CLIENT_CREDENTIAL.getName(), "CLIENT_CREDENTIAL"); + Assert.assertEquals(Type.BASIC.getName(), "BASIC"); + Assert.assertEquals(Type.API_KEY.getName(), "API_KEY"); + } +} diff --git a/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/test/java/org/wso2/carbon/identity/notification/sender/tenant/config/dto/SMSSenderDTOTest.java b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/test/java/org/wso2/carbon/identity/notification/sender/tenant/config/dto/SMSSenderDTOTest.java new file mode 100644 index 000000000..e31a45086 --- /dev/null +++ b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/test/java/org/wso2/carbon/identity/notification/sender/tenant/config/dto/SMSSenderDTOTest.java @@ -0,0 +1,345 @@ +/* + * Copyright (c) 2025, 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.identity.notification.sender.tenant.config.dto; + +import org.apache.http.Header; +import org.mockito.MockedStatic; +import org.testng.Assert; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; +import org.wso2.carbon.identity.notification.sender.tenant.config.dto.Authentication.Property; +import org.wso2.carbon.identity.notification.sender.tenant.config.dto.Authentication.Type; +import org.wso2.carbon.identity.notification.sender.tenant.config.exception.NotificationSenderManagementClientException; +import org.wso2.carbon.identity.notification.sender.tenant.config.utils.NotificationSenderUtils; + +import java.util.HashMap; +import java.util.Map; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; + +/** + * Unit tests for {@link SMSSenderDTO}. + */ +public class SMSSenderDTOTest { + + private SMSSenderDTO.Builder builder; + private Header mockHeader; + + @BeforeMethod + public void setUp() { + builder = new SMSSenderDTO.Builder(); + mockHeader = mock(Header.class); + } + + @AfterMethod + public void tearDown() { + builder = null; + } + + @Test + public void testBuildSimpleSMSSender() throws Exception { + SMSSenderDTO dto = builder + .name("TestSender") + .provider("TestProvider") + .providerURL("https://test.provider.com") + .sender("+1234567890") + .contentType("application/json") + .build(); + + Assert.assertNotNull(dto); + Assert.assertEquals(dto.getName(), "TestSender"); + Assert.assertEquals(dto.getProvider(), "TestProvider"); + Assert.assertEquals(dto.getProviderURL(), "https://test.provider.com"); + Assert.assertEquals(dto.getSender(), "+1234567890"); + Assert.assertEquals(dto.getContentType(), "application/json"); + Assert.assertNull(dto.getAuthentication()); + } + + @Test + public void testBuildWithBasicAuthUsingKeyAndSecret() throws Exception { + try (MockedStatic mockedUtils = mockStatic(NotificationSenderUtils.class)) { + mockedUtils.when(() -> NotificationSenderUtils.buildAuthenticationHeader( + eq(Type.BASIC), any())).thenReturn(mockHeader); + + SMSSenderDTO dto = builder + .name("TestSender") + .provider("TestProvider") + .providerURL("https://test.provider.com") + .key("testuser") + .secret("testpass") + .build(); + + Assert.assertNotNull(dto); + Assert.assertNotNull(dto.getAuthentication()); + Assert.assertEquals(dto.getAuthentication().getType(), Type.BASIC); + Assert.assertEquals(dto.getKey(), "testuser"); + Assert.assertEquals(dto.getSecret(), "testpass"); + } + } + + @Test + public void testBuildWithBearerAuth() throws Exception { + try (MockedStatic mockedUtils = mockStatic(NotificationSenderUtils.class)) { + mockedUtils.when(() -> NotificationSenderUtils.buildAuthenticationHeader( + eq(Type.BEARER), any())).thenReturn(mockHeader); + + SMSSenderDTO dto = builder + .name("TestSender") + .provider("TestProvider") + .providerURL("https://test.provider.com") + .authType("BEARER") + .addAuthProperty(Property.ACCESS_TOKEN.getName(), "test-token") + .build(); + + Assert.assertNotNull(dto); + Assert.assertNotNull(dto.getAuthentication()); + Assert.assertEquals(dto.getAuthentication().getType(), Type.BEARER); + } + } + + @Test + public void testBuildWithClientCredentialAuth() throws Exception { + try (MockedStatic mockedUtils = mockStatic(NotificationSenderUtils.class)) { + mockedUtils.when(() -> NotificationSenderUtils.buildAuthenticationHeader( + eq(Type.CLIENT_CREDENTIAL), any())).thenReturn(mockHeader); + + SMSSenderDTO dto = builder + .name("TestSender") + .provider("TestProvider") + .providerURL("https://test.provider.com") + .authType("CLIENT_CREDENTIAL") + .addAuthProperty(Property.CLIENT_ID.getName(), "test-client-id") + .addAuthProperty(Property.CLIENT_SECRET.getName(), "test-client-secret") + .addAuthProperty(Property.SCOPE.getName(), "test-scope") + .addAuthProperty(Property.TOKEN_ENDPOINT.getName(), "https://test.com/token") + .build(); + + Assert.assertNotNull(dto); + Assert.assertNotNull(dto.getAuthentication()); + Assert.assertEquals(dto.getAuthentication().getType(), Type.CLIENT_CREDENTIAL); + } + } + + @Test + public void testBuildWithApiKeyAuth() throws Exception { + try (MockedStatic mockedUtils = mockStatic(NotificationSenderUtils.class)) { + mockedUtils.when(() -> NotificationSenderUtils.buildAuthenticationHeader( + eq(Type.API_KEY), any())).thenReturn(mockHeader); + + SMSSenderDTO dto = builder + .name("TestSender") + .provider("TestProvider") + .providerURL("https://test.provider.com") + .authType("API_KEY") + .addAuthProperty(Property.HEADER.getName(), "X-API-KEY") + .addAuthProperty(Property.VALUE.getName(), "test-api-key") + .build(); + + Assert.assertNotNull(dto); + Assert.assertNotNull(dto.getAuthentication()); + Assert.assertEquals(dto.getAuthentication().getType(), Type.API_KEY); + } + } + + @Test + public void testBuildWithProperties() throws Exception { + SMSSenderDTO dto = builder + .name("TestSender") + .provider("TestProvider") + .providerURL("https://test.provider.com") + .addProperty("customKey1", "customValue1") + .addProperty("customKey2", "customValue2") + .build(); + + Assert.assertNotNull(dto); + Assert.assertNotNull(dto.getProperties()); + Assert.assertEquals(dto.getProperties().size(), 2); + Assert.assertEquals(dto.getProperties().get("customKey1"), "customValue1"); + Assert.assertEquals(dto.getProperties().get("customKey2"), "customValue2"); + } + + @Test(expectedExceptions = NotificationSenderManagementClientException.class) + public void testBuildWithNonBasicAuthAndKeyProvided() throws Exception { + try (MockedStatic mockedUtils = mockStatic(NotificationSenderUtils.class)) { + mockedUtils.when(() -> NotificationSenderUtils.buildAuthenticationHeader( + eq(Type.BEARER), any())).thenReturn(mockHeader); + + builder + .name("TestSender") + .provider("TestProvider") + .providerURL("https://test.provider.com") + .authType("BEARER") + .addAuthProperty(Property.ACCESS_TOKEN.getName(), "test-token") + .key("should-not-be-allowed") + .build(); + } + } + + @Test(expectedExceptions = NotificationSenderManagementClientException.class) + public void testBuildWithNonBasicAuthAndSecretProvided() throws Exception { + try (MockedStatic mockedUtils = mockStatic(NotificationSenderUtils.class)) { + mockedUtils.when(() -> NotificationSenderUtils.buildAuthenticationHeader( + eq(Type.BEARER), any())).thenReturn(mockHeader); + + builder + .name("TestSender") + .provider("TestProvider") + .providerURL("https://test.provider.com") + .authType("BEARER") + .addAuthProperty(Property.ACCESS_TOKEN.getName(), "test-token") + .secret("should-not-be-allowed") + .build(); + } + } + + @Test + public void testBuildWithBasicAuthUsingExistingCredentials() throws Exception { + try (MockedStatic mockedUtils = mockStatic(NotificationSenderUtils.class)) { + mockedUtils.when(() -> NotificationSenderUtils.buildAuthenticationHeader( + eq(Type.BASIC), any())).thenReturn(mockHeader); + + // Build with BASIC auth and existing credentials + SMSSenderDTO dto = builder + .name("TestSender") + .provider("TestProvider") + .providerURL("https://test.provider.com") + .authType("BASIC") + .addAuthProperty(Property.USERNAME.getName(), "existinguser") + .addAuthProperty(Property.PASSWORD.getName(), "existingpass") + .build(); + + Assert.assertNotNull(dto); + Assert.assertNotNull(dto.getAuthentication()); + Assert.assertEquals(dto.getAuthentication().getType(), Type.BASIC); + Assert.assertEquals(dto.getKey(), "existinguser"); + Assert.assertEquals(dto.getSecret(), "existingpass"); + } + } + + @Test(expectedExceptions = NotificationSenderManagementClientException.class) + public void testBuildWithBasicAuthKeyMismatch() throws Exception { + try (MockedStatic mockedUtils = mockStatic(NotificationSenderUtils.class)) { + mockedUtils.when(() -> NotificationSenderUtils.buildAuthenticationHeader( + eq(Type.BASIC), any())).thenReturn(mockHeader); + + builder + .name("TestSender") + .provider("TestProvider") + .providerURL("https://test.provider.com") + .authType("BASIC") + .addAuthProperty(Property.USERNAME.getName(), "existinguser") + .addAuthProperty(Property.PASSWORD.getName(), "existingpass") + .key("differentuser") + .build(); + } + } + + @Test(expectedExceptions = NotificationSenderManagementClientException.class) + public void testBuildWithBasicAuthSecretMismatch() throws Exception { + try (MockedStatic mockedUtils = mockStatic(NotificationSenderUtils.class)) { + mockedUtils.when(() -> NotificationSenderUtils.buildAuthenticationHeader( + eq(Type.BASIC), any())).thenReturn(mockHeader); + + builder + .name("TestSender") + .provider("TestProvider") + .providerURL("https://test.provider.com") + .authType("BASIC") + .addAuthProperty(Property.USERNAME.getName(), "existinguser") + .addAuthProperty(Property.PASSWORD.getName(), "existingpass") + .secret("differentpass") + .build(); + } + } + + @Test + public void testSettersAndGetters() throws Exception { + SMSSenderDTO dto = new SMSSenderDTO(); + + dto.setName("TestName"); + dto.setProvider("TestProvider"); + dto.setProviderURL("https://test.com"); + dto.setKey("testkey"); + dto.setSecret("testsecret"); + dto.setSender("+1234567890"); + dto.setContentType("application/json"); + + Map props = new HashMap<>(); + props.put("key1", "value1"); + dto.setProperties(props); + + Assert.assertEquals(dto.getName(), "TestName"); + Assert.assertEquals(dto.getProvider(), "TestProvider"); + Assert.assertEquals(dto.getProviderURL(), "https://test.com"); + Assert.assertEquals(dto.getKey(), "testkey"); + Assert.assertEquals(dto.getSecret(), "testsecret"); + Assert.assertEquals(dto.getSender(), "+1234567890"); + Assert.assertEquals(dto.getContentType(), "application/json"); + Assert.assertEquals(dto.getProperties().get("key1"), "value1"); + } + + @Test + public void testBuildWithOnlyKeyNoSecret() throws Exception { + SMSSenderDTO dto = builder + .name("TestSender") + .provider("TestProvider") + .providerURL("https://test.provider.com") + .key("testuser") + .build(); + + Assert.assertNotNull(dto); + Assert.assertNull(dto.getAuthentication(), "Authentication should be null when only key is provided"); + } + + @Test + public void testBuildWithOnlySecretNoKey() throws Exception { + SMSSenderDTO dto = builder + .name("TestSender") + .provider("TestProvider") + .providerURL("https://test.provider.com") + .secret("testpass") + .build(); + + Assert.assertNotNull(dto); + Assert.assertNull(dto.getAuthentication(), "Authentication should be null when only secret is provided"); + } + + @Test + public void testSetAuthentication() throws Exception { + try (MockedStatic mockedUtils = mockStatic(NotificationSenderUtils.class)) { + mockedUtils.when(() -> NotificationSenderUtils.buildAuthenticationHeader( + eq(Type.BASIC), any())).thenReturn(mockHeader); + + Map authProps = new HashMap<>(); + authProps.put(Property.USERNAME.getName(), "testuser"); + authProps.put(Property.PASSWORD.getName(), "testpass"); + Authentication auth = new Authentication.AuthenticationBuilder("BASIC", authProps).build(); + + SMSSenderDTO dto = new SMSSenderDTO(); + dto.setAuthentication(auth); + + Assert.assertNotNull(dto.getAuthentication()); + Assert.assertEquals(dto.getAuthentication().getType(), Type.BASIC); + } + } +} diff --git a/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/test/java/org/wso2/carbon/identity/notification/sender/tenant/config/utils/TokenManagerTest.java b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/test/java/org/wso2/carbon/identity/notification/sender/tenant/config/utils/TokenManagerTest.java new file mode 100644 index 000000000..1ad77ad2a --- /dev/null +++ b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/test/java/org/wso2/carbon/identity/notification/sender/tenant/config/utils/TokenManagerTest.java @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2025, 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.identity.notification.sender.tenant.config.utils; + +import org.apache.http.Header; +import org.mockito.MockedStatic; +import org.testng.Assert; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; +import org.wso2.carbon.identity.notification.sender.tenant.config.dto.Authentication; +import org.wso2.carbon.identity.notification.sender.tenant.config.exception.NotificationSenderManagementClientException; + +import java.util.HashMap; +import java.util.Map; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; + +/** + * Unit tests for {@link TokenManager}. + * Note: TokenManager is a singleton with complex initialization that depends on external configuration. + * These tests focus on testing the authentication building and validation logic through the Authentication class. + */ +public class TokenManagerTest { + + private Map authProperties; + private Header mockHeader; + + @BeforeMethod + public void setUp() { + authProperties = new HashMap<>(); + mockHeader = mock(Header.class); + } + + @AfterMethod + public void tearDown() { + authProperties.clear(); + } + + @Test + public void testAuthenticationWithClientCredential() throws Exception { + authProperties.put(Authentication.Property.CLIENT_ID.getName(), "test-client-id"); + authProperties.put(Authentication.Property.CLIENT_SECRET.getName(), "test-client-secret"); + authProperties.put(Authentication.Property.SCOPE.getName(), "test-scope"); + authProperties.put(Authentication.Property.TOKEN_ENDPOINT.getName(), "https://test.com/token"); + + try (MockedStatic mockedUtils = mockStatic(NotificationSenderUtils.class)) { + mockedUtils.when(() -> NotificationSenderUtils.buildAuthenticationHeader( + eq(Authentication.Type.CLIENT_CREDENTIAL), any())).thenReturn(mockHeader); + + Authentication auth = new Authentication.AuthenticationBuilder("CLIENT_CREDENTIAL", authProperties).build(); + + Assert.assertNotNull(auth); + Assert.assertEquals(auth.getType(), Authentication.Type.CLIENT_CREDENTIAL); + Assert.assertEquals(auth.getProperty(Authentication.Property.CLIENT_ID.getName()), "test-client-id"); + Assert.assertEquals(auth.getProperty(Authentication.Property.CLIENT_SECRET.getName()), + "test-client-secret"); + Assert.assertEquals(auth.getProperty(Authentication.Property.SCOPE.getName()), "test-scope"); + Assert.assertEquals(auth.getProperty(Authentication.Property.TOKEN_ENDPOINT.getName()), + "https://test.com/token"); + } + } + + @Test + public void testAuthenticationWithBasicType() throws Exception { + authProperties.put(Authentication.Property.USERNAME.getName(), "testuser"); + authProperties.put(Authentication.Property.PASSWORD.getName(), "testpass"); + + try (MockedStatic mockedUtils = mockStatic(NotificationSenderUtils.class)) { + mockedUtils.when(() -> NotificationSenderUtils.buildAuthenticationHeader( + eq(Authentication.Type.BASIC), any())).thenReturn(mockHeader); + + Authentication auth = new Authentication.AuthenticationBuilder("BASIC", authProperties).build(); + + Assert.assertNotNull(auth); + Assert.assertEquals(auth.getType(), Authentication.Type.BASIC); + Assert.assertNotEquals(auth.getType(), Authentication.Type.CLIENT_CREDENTIAL); + } + } + + @Test + public void testAuthenticationWithBearerType() throws Exception { + authProperties.put(Authentication.Property.ACCESS_TOKEN.getName(), "test-access-token"); + + try (MockedStatic mockedUtils = mockStatic(NotificationSenderUtils.class)) { + mockedUtils.when(() -> NotificationSenderUtils.buildAuthenticationHeader( + eq(Authentication.Type.BEARER), any())).thenReturn(mockHeader); + + Authentication auth = new Authentication.AuthenticationBuilder("BEARER", authProperties).build(); + + Assert.assertNotNull(auth); + Assert.assertEquals(auth.getType(), Authentication.Type.BEARER); + } + } + + @Test(expectedExceptions = NotificationSenderManagementClientException.class) + public void testAuthenticationWithMissingClientId() throws Exception { + authProperties.put(Authentication.Property.CLIENT_SECRET.getName(), "test-client-secret"); + authProperties.put(Authentication.Property.SCOPE.getName(), "test-scope"); + authProperties.put(Authentication.Property.TOKEN_ENDPOINT.getName(), "https://test.com/token"); + + new Authentication.AuthenticationBuilder("CLIENT_CREDENTIAL", authProperties).build(); + } + + @Test(expectedExceptions = NotificationSenderManagementClientException.class) + public void testAuthenticationWithMissingClientSecret() throws Exception { + authProperties.put(Authentication.Property.CLIENT_ID.getName(), "test-client-id"); + authProperties.put(Authentication.Property.SCOPE.getName(), "test-scope"); + authProperties.put(Authentication.Property.TOKEN_ENDPOINT.getName(), "https://test.com/token"); + + new Authentication.AuthenticationBuilder("CLIENT_CREDENTIAL", authProperties).build(); + } + + @Test(expectedExceptions = NotificationSenderManagementClientException.class) + public void testAuthenticationWithMissingTokenEndpoint() throws Exception { + authProperties.put(Authentication.Property.CLIENT_ID.getName(), "test-client-id"); + authProperties.put(Authentication.Property.CLIENT_SECRET.getName(), "test-client-secret"); + authProperties.put(Authentication.Property.SCOPE.getName(), "test-scope"); + + new Authentication.AuthenticationBuilder("CLIENT_CREDENTIAL", authProperties).build(); + } + + @Test + public void testAuthenticationInternalProperties() throws Exception { + authProperties.put(Authentication.Property.CLIENT_ID.getName(), "test-client-id"); + authProperties.put(Authentication.Property.CLIENT_SECRET.getName(), "test-client-secret"); + authProperties.put(Authentication.Property.SCOPE.getName(), "test-scope"); + authProperties.put(Authentication.Property.TOKEN_ENDPOINT.getName(), "https://test.com/token"); + + try (MockedStatic mockedUtils = mockStatic(NotificationSenderUtils.class)) { + mockedUtils.when(() -> NotificationSenderUtils.buildAuthenticationHeader( + eq(Authentication.Type.CLIENT_CREDENTIAL), any())).thenReturn(mockHeader); + + Authentication auth = new Authentication.AuthenticationBuilder("CLIENT_CREDENTIAL", authProperties).build(); + + // Test adding internal properties (simulating what TokenManager would do) + auth.addInternalProperty("AccessToken", "test-access-token"); + auth.addInternalProperty("RefreshToken", "test-refresh-token"); + + Assert.assertEquals(auth.getProperty("AccessToken"), "test-access-token"); + Assert.assertEquals(auth.getProperty("RefreshToken"), "test-refresh-token"); + } + } + + @Test + public void testAuthenticationGetInternalProperties() throws Exception { + authProperties.put(Authentication.Property.CLIENT_ID.getName(), "test-client-id"); + authProperties.put(Authentication.Property.CLIENT_SECRET.getName(), "test-client-secret"); + authProperties.put(Authentication.Property.SCOPE.getName(), "test-scope"); + authProperties.put(Authentication.Property.TOKEN_ENDPOINT.getName(), "https://test.com/token"); + + try (MockedStatic mockedUtils = mockStatic(NotificationSenderUtils.class)) { + mockedUtils.when(() -> NotificationSenderUtils.buildAuthenticationHeader( + eq(Authentication.Type.CLIENT_CREDENTIAL), any())).thenReturn(mockHeader); + + Authentication auth = new Authentication.AuthenticationBuilder("CLIENT_CREDENTIAL", authProperties).build(); + + Map internalProps = auth.getInternalProperties(); + Assert.assertNotNull(internalProps); + } + } +} diff --git a/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/test/resources/testng.xml b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/test/resources/testng.xml index 34b0fbd57..9ef250b60 100644 --- a/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/test/resources/testng.xml +++ b/components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config/src/test/resources/testng.xml @@ -22,8 +22,11 @@ + + + diff --git a/features/org.wso2.carbon.email.mgt.feature/pom.xml.versionsBackup b/features/org.wso2.carbon.email.mgt.feature/pom.xml.versionsBackup new file mode 100644 index 000000000..a87031f36 --- /dev/null +++ b/features/org.wso2.carbon.email.mgt.feature/pom.xml.versionsBackup @@ -0,0 +1,80 @@ + + + + + + org.wso2.carbon.identity.event.handler.notification + identity-event-handler-notification + 1.8.3-SNAPSHOT + ../../pom.xml + + + + 4.0.0 + org.wso2.carbon.email.mgt.feature + pom + Email Management Feature + http://wso2.org + This feature contains the bundles required for Email-Mgt functionality + + + + org.wso2.carbon.identity.event.handler.notification + org.wso2.carbon.email.mgt.server.feature + zip + + + org.wso2.carbon.identity.event.handler.notification + org.wso2.carbon.email.mgt.ui.feature + zip + + + + + + + org.wso2.maven + carbon-p2-plugin + ${carbon.p2.plugin.version} + + + 4-p2-feature-generation + package + + p2-feature-gen + + + org.wso2.carbon.email.mgt + ../../etc/feature.properties + + + org.wso2.carbon.identity.event.handler.notification:org.wso2.carbon.email.mgt.server.feature + + + org.wso2.carbon.identity.event.handler.notification:org.wso2.carbon.email.mgt.ui.feature + + + + + + + + + + diff --git a/features/org.wso2.carbon.email.mgt.server.feature/pom.xml.versionsBackup b/features/org.wso2.carbon.email.mgt.server.feature/pom.xml.versionsBackup new file mode 100644 index 000000000..1db9830d7 --- /dev/null +++ b/features/org.wso2.carbon.email.mgt.server.feature/pom.xml.versionsBackup @@ -0,0 +1,131 @@ + + + + + + org.wso2.carbon.identity.event.handler.notification + identity-event-handler-notification + 1.8.3-SNAPSHOT + ../../pom.xml + + + 4.0.0 + org.wso2.carbon.email.mgt.server.feature + pom + Email management server feature + http://wso2.org + This feature contains the core bundles required for Back-end functionality of Email-Mgt + management + + + + org.wso2.carbon.identity.event.handler.notification + org.wso2.carbon.email.mgt + + + org.wso2.carbon.identity.event.handler.notification + org.wso2.carbon.identity.notification.sender.tenant.config + + + + + + + maven-resources-plugin + + + prefilter-resources + generate-resources + + copy-resources + + + src/main/resources + + + resources + + email-admin-config.xml + sms-templates-admin-config.xml + sms-providers-api-body-templates.xml + p2.inf + + + + + + + + + org.wso2.maven + carbon-p2-plugin + ${carbon.p2.plugin.version} + + + 4-p2-feature-generation + package + + p2-feature-gen + + + org.wso2.carbon.email.mgt.server + ../../etc/feature.properties + + + org.wso2.carbon.p2.category.type:server + + + + + org.wso2.carbon.identity.event.handler.notification:org.wso2.carbon.email.mgt + org.wso2.carbon.identity.event.handler.notification:org.wso2.carbon.identity.notification.sender.tenant.config + + + org.wso2.carbon.core:compatible:${carbon.kernel.feature.version} + org.wso2.carbon.identity.core.server:greaterOrEqual:${carbon.identity.framework.version} + + + + + + + org.apache.maven.plugins + maven-antrun-plugin + 1.1 + + + clean_target + install + + + + + + + + + run + + + + + + + + diff --git a/features/org.wso2.carbon.email.mgt.ui.feature/pom.xml.versionsBackup b/features/org.wso2.carbon.email.mgt.ui.feature/pom.xml.versionsBackup new file mode 100644 index 000000000..f3ef94942 --- /dev/null +++ b/features/org.wso2.carbon.email.mgt.ui.feature/pom.xml.versionsBackup @@ -0,0 +1,82 @@ + + + + + + org.wso2.carbon.identity.event.handler.notification + identity-event-handler-notification + 1.8.3-SNAPSHOT + ../../pom.xml + + + 4.0.0 + org.wso2.carbon.email.mgt.ui.feature + pom + Email Mgt UI Feature + http://wso2.org + This feature contains the bundles required for Front-end Email Mgt functionality + + + + org.wso2.carbon.identity.event.handler.notification + org.wso2.carbon.email.mgt.ui + + + org.wso2.carbon.identity.event.handler.notification + org.wso2.carbon.email.mgt.stub + + + + + + + org.wso2.maven + carbon-p2-plugin + ${carbon.p2.plugin.version} + + + 4-p2-feature-generation + package + + p2-feature-gen + + + org.wso2.carbon.email.mgt.ui + ../../etc/feature.properties + + + org.wso2.carbon.p2.category.type:console + org.eclipse.equinox.p2.type.group:false + + + + org.wso2.carbon.identity.event.handler.notification:org.wso2.carbon.email.mgt.ui + org.wso2.carbon.identity.event.handler.notification:org.wso2.carbon.email.mgt.stub + + + org.wso2.carbon.core:compatible:${carbon.kernel.feature.version} + + + + + + + + + diff --git a/features/org.wso2.carbon.event.handler.notification.server.feature/pom.xml.versionsBackup b/features/org.wso2.carbon.event.handler.notification.server.feature/pom.xml.versionsBackup new file mode 100644 index 000000000..2ca8a5aff --- /dev/null +++ b/features/org.wso2.carbon.event.handler.notification.server.feature/pom.xml.versionsBackup @@ -0,0 +1,129 @@ + + + + + + org.wso2.carbon.identity.event.handler.notification + identity-event-handler-notification + 1.8.3-SNAPSHOT + ../../pom.xml + + + 4.0.0 + org.wso2.carbon.event.handler.notification.server.feature + pom + Notification Event management server feature + http://wso2.org + This feature contains the core bundles required for Back-end functionality of Notification-Event-Handling + management + + + + org.wso2.carbon.identity.event.handler.notification + org.wso2.carbon.identity.event.handler.notification + + + + + + + maven-resources-plugin + + + prefilter-resources + generate-resources + + copy-resources + + + src/main/resources + + + resources + + EmailPublisher.xml + SMSPublisher.xml + id_gov_notify_stream_1.0.0.json + p2.inf + id_gov_sms_notify_stream_1.0.0.json + + + + + + + + + org.wso2.maven + carbon-p2-plugin + ${carbon.p2.plugin.version} + + + 4-p2-feature-generation + package + + p2-feature-gen + + + org.wso2.carbon.event.handler.notification.server + ../../etc/feature.properties + + + org.wso2.carbon.p2.category.type:server + + + + + org.wso2.carbon.identity.event.handler.notification:org.wso2.carbon.identity.event.handler.notification + + + org.wso2.carbon.core:compatible:${carbon.kernel.feature.version} + org.wso2.carbon.identity.core.server:greaterOrEqual:${carbon.identity.framework.version} + org.wso2.carbon.event.output.adapter.server:compatible:${carbon.analytics.common.version} + org.wso2.carbon.event.output.adapter.email.server:compatible:${carbon.analytics.common.version} + org.wso2.carbon.email.mgt.server:compatible:${identity.event.handler.notification.exp.pkg.version} + + + + + + + org.apache.maven.plugins + maven-antrun-plugin + 1.1 + + + clean_target + install + + + + + + + + + run + + + + + + + diff --git a/pom.xml.versionsBackup b/pom.xml.versionsBackup new file mode 100644 index 000000000..91a5fddca --- /dev/null +++ b/pom.xml.versionsBackup @@ -0,0 +1,476 @@ + + + + + org.wso2.carbon.identity.event.handler.notification + identity-event-handler-notification + pom + 1.8.3-SNAPSHOT + 4.0.0 + http://wso2.org + + + org.wso2 + wso2 + 1.4 + + + + https://github.com/wso2-extensions/identity-event-handler-notification.git + scm:git:https://github.com/wso2-extensions/identity-event-handler-notification.git + scm:git:https://github.com/wso2-extensions/identity-event-handler-notification.git + HEAD + + + + components/email-mgt/org.wso2.carbon.email.mgt + components/email-mgt/org.wso2.carbon.email.mgt.ui + components/event-handler-notification/org.wso2.carbon.identity.event.handler.notification + components/notification-sender-config/org.wso2.carbon.identity.notification.sender.tenant.config + service-stubs/identity/org.wso2.carbon.email.mgt.stub + + features/org.wso2.carbon.email.mgt.server.feature + features/org.wso2.carbon.email.mgt.ui.feature + features/org.wso2.carbon.email.mgt.feature + features/org.wso2.carbon.event.handler.notification.server.feature + + + + + + + + + + + org.apache.axis2.wso2 + axis2 + ${axis2.wso2.version} + + + org.apache.axis2.wso2 + axis2-client + ${axis2.wso2.version} + + + org.apache.ws.commons.axiom.wso2 + axiom + ${axiom.wso2.version} + + + org.apache.axis2.transport + axis2-transport-mail + ${axis2-transports.version} + + + org.wso2.orbit.org.owasp.encoder + encoder + ${encoder.wso2.version} + + + + + org.wso2.carbon + org.wso2.carbon.registry.core + ${carbon.kernel.version} + + + org.wso2.carbon + org.wso2.carbon.core + ${carbon.kernel.version} + + + org.wso2.carbon + org.wso2.carbon.user.core + ${carbon.kernel.version} + + + org.wso2.carbon + javax.cache.wso2 + ${carbon.kernel.version} + + + org.wso2.carbon + org.wso2.carbon.utils + ${carbon.kernel.version} + + + org.wso2.carbon + org.wso2.carbon.ui + ${carbon.kernel.version} + + + + + org.wso2.carbon.commons + org.wso2.carbon.tenant.common + ${carbon.commons.version} + + + + + org.wso2.carbon.identity.framework + org.wso2.carbon.identity.base + ${carbon.identity.framework.version} + + + org.wso2.carbon.identity.framework + org.wso2.carbon.identity.event + ${carbon.identity.framework.version} + + + org.wso2.carbon.identity.framework + org.wso2.carbon.identity.core + ${carbon.identity.framework.version} + + + org.wso2.carbon.identity.framework + org.wso2.carbon.identity.application.authentication.framework + ${carbon.identity.framework.version} + + + org.wso2.carbon.identity.framework + org.wso2.carbon.identity.central.log.mgt + ${carbon.identity.framework.version} + + + org.wso2.carbon.identity.framework + org.wso2.carbon.identity.configuration.mgt.core + ${carbon.identity.framework.version} + + + org.wso2.carbon.identity.framework + org.wso2.carbon.identity.application.mgt + ${carbon.identity.framework.version} + + + + + org.wso2.carbon.analytics-common + org.wso2.carbon.event.output.adapter.core + ${carbon.analytics.common.version} + + + org.wso2.carbon.analytics-common + org.wso2.carbon.event.stream.core + ${carbon.analytics.common.version} + + + org.wso2.carbon.analytics-common + org.wso2.carbon.event.publisher.core + ${carbon.analytics.common.version} + + + org.wso2.carbon.analytics-common + org.wso2.carbon.databridge.commons + ${carbon.analytics.common.version} + + + + + org.wso2.carbon.identity.governance + org.wso2.carbon.identity.governance + ${identity.governance.version} + + + org.wso2.carbon.identity.framework + org.wso2.carbon.identity.base + + + org.wso2.carbon.identity.framework + org.wso2.carbon.identity.event + + + + + org.wso2.carbon.identity.governance + org.wso2.carbon.identity.tenant.resource.manager + ${identity.governance.version} + + + + + org.wso2.carbon.identity.event.handler.notification + org.wso2.carbon.email.mgt + ${project.version} + + + org.wso2.carbon.identity.event.handler.notification + org.wso2.carbon.email.mgt.server.feature + ${project.version} + zip + + + org.wso2.carbon.identity.event.handler.notification + org.wso2.carbon.email.mgt.ui.feature + ${project.version} + zip + + + org.wso2.carbon.identity.event.handler.notification + org.wso2.carbon.email.mgt.ui + ${project.version} + + + org.wso2.carbon.identity.event.handler.notification + org.wso2.carbon.identity.notification.sender.tenant.config + ${project.version} + + + org.wso2.carbon.identity.event.handler.notification + org.wso2.carbon.email.mgt.stub + ${project.version} + + + org.wso2.carbon.identity.event.handler.notification + org.wso2.carbon.identity.event.handler.notification + ${project.version} + + + org.wso2.carbon.identity.branding.preference.management + org.wso2.carbon.identity.branding.preference.management.core + ${identity.branding.preference.management.version} + + + commons-lang.wso2 + commons-lang + ${commons-lang.wso2.version} + + + + com.google.code.gson + gson + ${com.google.code.gson.version} + + + + com.fasterxml.jackson.core + jackson-databind + ${com.fasterxml.jackson.databind.version} + + + + + org.wso2.carbon.identity.organization.management.core + org.wso2.carbon.identity.organization.management.service + ${identity.organization.management.core.version} + + + + + org.testng + testng + ${testng.version} + test + + + org.powermock + powermock-module-testng + ${powermock.version} + test + + + org.powermock + powermock-api-mockito + ${powermock.version} + test + + + org.mockito + mockito-all + ${mockito.version} + test + + + org.mockito + mockito-inline + ${mockito.inline.version} + test + + + + org.jacoco + org.jacoco.agent + runtime + ${jacoco.version} + + + + org.ops4j.pax.logging + pax-logging-api + ${pax.logging.api.version} + + + org.apache.felix + org.apache.felix.scr.ds-annotations + ${apache.felix.scr.ds.annotations.version} + + + + + + + + + org.apache.felix + maven-bundle-plugin + ${maven.bundle.plugin.version} + true + + NONE + + ${buildNumber} + + + + + org.codehaus.mojo + findbugs-maven-plugin + ${maven.findbugsplugin.version} + + + org.apache.maven.plugins + maven-checkstyle-plugin + ${maven.checkstyleplugin.version} + + + + + + + + org.apache.maven.plugins + maven-release-plugin + + clean install + true + + + + org.apache.maven.plugins + maven-deploy-plugin + + + org.codehaus.mojo + buildnumber-maven-plugin + + + org.apache.maven.plugins + maven-javadoc-plugin + + 1.8 + + + + attach-javadocs + + jar + + + + none + + + + + + + + + + 1.5.77 + [1.0.0, 3.0.0) + + + ${project.version} + [1.2.0, 2.0.0) + + [1.7.0, 2.0.0) + [1.2.0, 2.0.0) + + 1.0.8 + [1.0.1, 2.0.0) + + + 1.6.1-wso2v38 + [1.6.1-wso2v38, 2.0.0) + 1.2.11-wso2v16 + [1.2.11, 2.0.0) + 2.0.0-wso2v38 + 1.2.0.wso2v1 + + 2.6.0.wso2v1 + [1.2,2.0) + [2.6.0,3.0.0) + [2.6.0,3.0.0) + + + 4.9.10 + 4.9.10 + [4.5.0, 5.0.0) + + [1.0.1, 2.0.0) + [1.0.1, 2.0.0) + [1.0.0, 2.0.0) + [1.6.1, 2.0.0) + + + 4.7.11 + [4.7.11, 5.0.0) + + + 5.25.617 + [5.14.67, 8.0.0) + + + 1.0.93 + [1.0.0,2.0.0) + + + + 5.2.10 + [5.2.10,6.0.0) + + + 2.9.0 + [2.3.1,3.0.0) + + + 1.5.3 + 2.3.1 + 3.2.0 + 1.4 + + + 6.9.10 + 1.7.0 + 1.10.19 + 3.8.0 + 0.7.9 + 2.18.1 + + + 1.10.1 + + 1.2.4 + 2.17 + 3.0.5 + findbugs-exclude-filter.xml + + 2.13.3 + + diff --git a/service-stubs/identity/org.wso2.carbon.email.mgt.stub/pom.xml.versionsBackup b/service-stubs/identity/org.wso2.carbon.email.mgt.stub/pom.xml.versionsBackup new file mode 100644 index 000000000..c35c9e71b --- /dev/null +++ b/service-stubs/identity/org.wso2.carbon.email.mgt.stub/pom.xml.versionsBackup @@ -0,0 +1,113 @@ + + + + + + org.wso2.carbon.identity.event.handler.notification + identity-event-handler-notification + 1.8.3-SNAPSHOT + ../../../pom.xml + + + 4.0.0 + org.wso2.carbon.email.mgt.stub + bundle + WSO2 Carbon - Email Management Stub + http://wso2.org + + + + + org.apache.maven.plugins + maven-antrun-plugin + 1.1 + + + source-code-generation + process-resources + + run + + + + + + + + + + + + + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + add-source + generate-sources + + add-source + + + + + target/generated-code/src + + + + + + + + org.apache.felix + maven-bundle-plugin + true + + + ${project.artifactId} + ${project.artifactId} + + org.wso2.carbon.email.mgt.model.xsd;version="${identity.event.handler.notification.exp.pkg.version}", + org.wso2.carbon.email.mgt.exceptions.xsd;version="${identity.event.handler.notification.exp.pkg.version}", + org.wso2.carbon.email.mgt.stub;version="${identity.event.handler.notification.exp.pkg.version}", + + + + + + + + + + org.apache.axis2.wso2 + axis2 + + + org.apache.axis2.wso2 + axis2-client + + +