From 5f9cee6d8d140e44df9a395dd4532d7c7a2596cd Mon Sep 17 00:00:00 2001 From: VihangaMunasinghe Date: Wed, 25 Mar 2026 00:19:39 +0530 Subject: [PATCH 01/13] Add editDeviceMobile method to handle device updates from mobile --- .../device/handler/DeviceHandlerService.java | 11 +++- .../constant/PushDeviceHandlerConstants.java | 6 ++ .../impl/DeviceHandlerServiceImpl.java | 55 +++++++++++++++++++ 3 files changed, 71 insertions(+), 1 deletion(-) diff --git a/components/org.wso2.carbon.identity.notification.push.device.handler/src/main/java/org/wso2/carbon/identity/notification/push/device/handler/DeviceHandlerService.java b/components/org.wso2.carbon.identity.notification.push.device.handler/src/main/java/org/wso2/carbon/identity/notification/push/device/handler/DeviceHandlerService.java index dbab23e..06cf0ae 100644 --- a/components/org.wso2.carbon.identity.notification.push.device.handler/src/main/java/org/wso2/carbon/identity/notification/push/device/handler/DeviceHandlerService.java +++ b/components/org.wso2.carbon.identity.notification.push.device.handler/src/main/java/org/wso2/carbon/identity/notification/push/device/handler/DeviceHandlerService.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, WSO2 LLC. (http://www.wso2.com). + * Copyright (c) 2025-2026, 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 @@ -92,6 +92,15 @@ Device registerDevice(RegistrationRequest registrationRequest, String tenantDoma */ void editDevice(String deviceId, String path, String value) throws PushDeviceHandlerException; + /** + * Edit the device from mobile. + * + * @param deviceId Device ID. + * @param token Token. + * @throws PushDeviceHandlerException Push Device Handler Exception. + */ + void editDeviceMobile(String deviceId, String token) throws PushDeviceHandlerException; + /** * Get registration discovery data. * diff --git a/components/org.wso2.carbon.identity.notification.push.device.handler/src/main/java/org/wso2/carbon/identity/notification/push/device/handler/constant/PushDeviceHandlerConstants.java b/components/org.wso2.carbon.identity.notification.push.device.handler/src/main/java/org/wso2/carbon/identity/notification/push/device/handler/constant/PushDeviceHandlerConstants.java index d81bdab..55488cd 100644 --- a/components/org.wso2.carbon.identity.notification.push.device.handler/src/main/java/org/wso2/carbon/identity/notification/push/device/handler/constant/PushDeviceHandlerConstants.java +++ b/components/org.wso2.carbon.identity.notification.push.device.handler/src/main/java/org/wso2/carbon/identity/notification/push/device/handler/constant/PushDeviceHandlerConstants.java @@ -30,6 +30,8 @@ public class PushDeviceHandlerConstants { public static final String DEVICE_REGISTRATION_CONTEXT_VALIDITY_PERIOD = "PushAuthenticator.DeviceRegistrationContext.ValidityPeriod"; public static final int DEFAULT_DEVICE_REGISTRATION_CONTEXT_VALIDITY_PERIOD = 180; + public static final String DEVICE_EDIT_REQUEST_DEVICE_NAME = "name"; + public static final String DEVICE_EDIT_REQUEST_DEVICE_TOKEN = "deviceToken"; /** * Private constructor to prevent initialization of the class. @@ -136,6 +138,10 @@ public enum ErrorMessages { ERROR_CODE_FAILED_TO_RESOLVE_PUSH_PROVIDER( "PDH-15013", "Failed to resolve the correct push provider for the request." + ), + ERROR_CODE_DEVICE_EDIT_FAILED( + "PDH-150014", + "Error occurred while editing the device for the device ID: %s." ); private final String code; diff --git a/components/org.wso2.carbon.identity.notification.push.device.handler/src/main/java/org/wso2/carbon/identity/notification/push/device/handler/impl/DeviceHandlerServiceImpl.java b/components/org.wso2.carbon.identity.notification.push.device.handler/src/main/java/org/wso2/carbon/identity/notification/push/device/handler/impl/DeviceHandlerServiceImpl.java index 320092b..c2db437 100644 --- a/components/org.wso2.carbon.identity.notification.push.device.handler/src/main/java/org/wso2/carbon/identity/notification/push/device/handler/impl/DeviceHandlerServiceImpl.java +++ b/components/org.wso2.carbon.identity.notification.push.device.handler/src/main/java/org/wso2/carbon/identity/notification/push/device/handler/impl/DeviceHandlerServiceImpl.java @@ -18,6 +18,7 @@ package org.wso2.carbon.identity.notification.push.device.handler.impl; +import com.nimbusds.jwt.JWTClaimsSet; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -71,7 +72,10 @@ import java.util.UUID; import static org.wso2.carbon.identity.notification.push.device.handler.constant.PushDeviceHandlerConstants.DEFAULT_PUSH_PROVIDER; +import static org.wso2.carbon.identity.notification.push.device.handler.constant.PushDeviceHandlerConstants.DEVICE_EDIT_REQUEST_DEVICE_NAME; +import static org.wso2.carbon.identity.notification.push.device.handler.constant.PushDeviceHandlerConstants.DEVICE_EDIT_REQUEST_DEVICE_TOKEN; import static org.wso2.carbon.identity.notification.push.device.handler.constant.PushDeviceHandlerConstants.ErrorMessages.ERROR_CODE_DEVICE_ALREADY_REGISTERED; +import static org.wso2.carbon.identity.notification.push.device.handler.constant.PushDeviceHandlerConstants.ErrorMessages.ERROR_CODE_DEVICE_EDIT_FAILED; import static org.wso2.carbon.identity.notification.push.device.handler.constant.PushDeviceHandlerConstants.ErrorMessages.ERROR_CODE_DEVICE_NOT_FOUND; import static org.wso2.carbon.identity.notification.push.device.handler.constant.PushDeviceHandlerConstants.ErrorMessages.ERROR_CODE_DEVICE_NOT_FOUND_FOR_USER_ID; import static org.wso2.carbon.identity.notification.push.device.handler.constant.PushDeviceHandlerConstants.ErrorMessages.ERROR_CODE_DEVICE_REGISTRATION_FAILED; @@ -247,6 +251,57 @@ public void editDevice(String deviceId, String path, String value) throws PushDe handleEditDevice(device, path, value); } + @Override + public void editDeviceMobile(String deviceId, String token) throws PushDeviceHandlerException { + + Optional deviceOptional = deviceDAO.getDevice(deviceId); + if (!deviceOptional.isPresent()) { + throw new PushDeviceHandlerClientException(ERROR_CODE_DEVICE_NOT_FOUND.getCode(), + String.format(ERROR_CODE_DEVICE_NOT_FOUND.getMessage(), deviceId)); + } + Device device = deviceOptional.get(); + + JWTClaimsSet claimsSet; + try { + claimsSet = PushChallengeValidator.getValidatedClaimSet(token, device.getPublicKey()); + } catch (PushTokenValidationException e) { + throw new PushDeviceHandlerClientException(ERROR_CODE_TOKEN_CLAIM_VERIFICATION_FAILED.getCode(), + String.format(ERROR_CODE_TOKEN_CLAIM_VERIFICATION_FAILED.getMessage(), deviceId), e); + } + + String deviceToken = null; + String deviceName = null; + + try { + if (claimsSet.getClaims().containsKey(DEVICE_EDIT_REQUEST_DEVICE_TOKEN)) { + deviceToken = PushChallengeValidator + .getClaimFromClaimSet(claimsSet, DEVICE_EDIT_REQUEST_DEVICE_TOKEN, deviceId); + } + + if (claimsSet.getClaims().containsKey(DEVICE_EDIT_REQUEST_DEVICE_NAME)) { + deviceName = PushChallengeValidator + .getClaimFromClaimSet(claimsSet, DEVICE_EDIT_REQUEST_DEVICE_NAME, deviceId); + } + } catch (PushTokenValidationException e) { + throw new PushDeviceHandlerClientException(e.getErrorCode(), e.getMessage(), e); + } + + if (deviceToken == null && deviceName == null) { + throw new PushDeviceHandlerClientException(ERROR_CODE_DEVICE_EDIT_FAILED.getCode(), + String.format(ERROR_CODE_DEVICE_EDIT_FAILED.getMessage(), deviceId)); + } + + if (deviceToken != null) { + device.setDeviceToken(deviceToken); + } + if (deviceName != null) { + device.setDeviceName(deviceName); + } + + handleUpdateDeviceForProvider(device); + deviceDAO.editDevice(device.getDeviceId(), device); + } + @Override public RegistrationDiscoveryData getRegistrationDiscoveryData(String username, String tenantDomain) throws PushDeviceHandlerException { From 1873dd02fa28d1faf29ddb024b1f63ea9cd00417 Mon Sep 17 00:00:00 2001 From: VihangaMunasinghe Date: Wed, 25 Mar 2026 00:19:49 +0530 Subject: [PATCH 02/13] Add unit tests for editDeviceMobile method to validate device updates --- .../impl/DeviceHandlerServiceImplTest.java | 406 ++++++++++++++++++ 1 file changed, 406 insertions(+) diff --git a/components/org.wso2.carbon.identity.notification.push.device.handler/src/test/java/org/wso2/carbon/identity/notification/push/device/handler/impl/DeviceHandlerServiceImplTest.java b/components/org.wso2.carbon.identity.notification.push.device.handler/src/test/java/org/wso2/carbon/identity/notification/push/device/handler/impl/DeviceHandlerServiceImplTest.java index ed63812..554412a 100644 --- a/components/org.wso2.carbon.identity.notification.push.device.handler/src/test/java/org/wso2/carbon/identity/notification/push/device/handler/impl/DeviceHandlerServiceImplTest.java +++ b/components/org.wso2.carbon.identity.notification.push.device.handler/src/test/java/org/wso2/carbon/identity/notification/push/device/handler/impl/DeviceHandlerServiceImplTest.java @@ -1010,6 +1010,412 @@ public void testEditDeviceWhenPushProviderServerExceptionThrown() } } + @Test + public void testEditDeviceMobileWithBothFields() + throws PushDeviceHandlerException, NotificationSenderManagementException, PushProviderException, + JOSEException, ParseException { + + try ( + MockedStatic mockedIdentityTenantUtil = + Mockito.mockStatic(IdentityTenantUtil.class); + MockedStatic mockedPushDeviceHandlerDataHolder = + Mockito.mockStatic(PushDeviceHandlerDataHolder.class); + MockedStatic mockedStatic = Mockito.mockStatic(SignedJWT.class) + ) { + + mockedIdentityTenantUtil.when(() -> IdentityTenantUtil.getTenantId(any())).thenReturn(-1234); + + Device deviceObj = new Device(); + deviceObj.setDeviceId("1234567890"); + deviceObj.setProvider("FCM"); + deviceObj.setDeviceToken(deviceToken); + deviceObj.setPublicKey(publicKey); + Optional device = Optional.of(deviceObj); + when(deviceDAO.getDevice(anyString())).thenReturn(device); + + mockedStatic.when(() -> SignedJWT.parse(validJwt)).thenReturn(mockSignedJWT); + + when(mockSignedJWT.getJWTClaimsSet()).thenReturn(mockClaimsSet); + when(mockClaimsSet.getExpirationTime()).thenReturn(new Date(System.currentTimeMillis() + 3000000)); + when(mockClaimsSet.getNotBeforeTime()).thenReturn(new Date(System.currentTimeMillis() - 3000000)); + when(mockSignedJWT.verify(any())).thenReturn(true); + + Map claims = new HashMap<>(); + claims.put("deviceToken", "newDeviceToken"); + claims.put("name", "newDeviceName"); + when(mockClaimsSet.getClaims()).thenReturn(claims); + when(mockClaimsSet.getStringClaim("deviceToken")).thenReturn("newDeviceToken"); + when(mockClaimsSet.getStringClaim("name")).thenReturn("newDeviceName"); + + PushDeviceHandlerDataHolder pushDeviceHandlerDataHolder = mock(PushDeviceHandlerDataHolder.class); + mockedPushDeviceHandlerDataHolder.when(PushDeviceHandlerDataHolder::getInstance) + .thenReturn(pushDeviceHandlerDataHolder); + + NotificationSenderManagementService notificationSenderManagementService = + mock(NotificationSenderManagementService.class); + when(pushDeviceHandlerDataHolder.getNotificationSenderManagementService()) + .thenReturn(notificationSenderManagementService); + PushSenderDTO pushSenderDTO = new PushSenderDTO(); + pushSenderDTO.setName("FCM_PushPublisher"); + pushSenderDTO.setProvider("FCM"); + pushSenderDTO.setProviderId("fcm-provider-id"); + List pushSenders = new ArrayList<>(); + pushSenders.add(pushSenderDTO); + when(notificationSenderManagementService.getPushSenders(anyBoolean())) + .thenReturn(pushSenders); + + FCMPushProvider fcmPushProvider = mock(FCMPushProvider.class); + when(pushDeviceHandlerDataHolder.getPushProvider(eq("FCM"))).thenReturn(fcmPushProvider); + when(fcmPushProvider.getName()).thenReturn("FCM"); + doNothing().when(fcmPushProvider).updateDevice(any(), any()); + + doNothing().when(deviceDAO).editDevice(anyString(), any()); + Mockito.clearInvocations(deviceDAO); + + deviceHandlerService.editDeviceMobile("1234567890", validJwt); + + verify(fcmPushProvider, times(1)).updateDevice(any(), any()); + verify(deviceDAO, times(1)).editDevice(anyString(), any()); + } + } + + @Test + public void testEditDeviceMobileWithTokenOnly() + throws PushDeviceHandlerException, NotificationSenderManagementException, PushProviderException, + JOSEException, ParseException { + + try ( + MockedStatic mockedIdentityTenantUtil = + Mockito.mockStatic(IdentityTenantUtil.class); + MockedStatic mockedPushDeviceHandlerDataHolder = + Mockito.mockStatic(PushDeviceHandlerDataHolder.class); + MockedStatic mockedStatic = Mockito.mockStatic(SignedJWT.class) + ) { + + mockedIdentityTenantUtil.when(() -> IdentityTenantUtil.getTenantId(any())).thenReturn(-1234); + + Device deviceObj = new Device(); + deviceObj.setDeviceId("1234567890"); + deviceObj.setProvider("FCM"); + deviceObj.setDeviceToken(deviceToken); + deviceObj.setPublicKey(publicKey); + Optional device = Optional.of(deviceObj); + when(deviceDAO.getDevice(anyString())).thenReturn(device); + + mockedStatic.when(() -> SignedJWT.parse(validJwt)).thenReturn(mockSignedJWT); + + when(mockSignedJWT.getJWTClaimsSet()).thenReturn(mockClaimsSet); + when(mockClaimsSet.getExpirationTime()).thenReturn(new Date(System.currentTimeMillis() + 3000000)); + when(mockClaimsSet.getNotBeforeTime()).thenReturn(new Date(System.currentTimeMillis() - 3000000)); + when(mockSignedJWT.verify(any())).thenReturn(true); + + Map claims = new HashMap<>(); + claims.put("deviceToken", "newDeviceToken"); + when(mockClaimsSet.getClaims()).thenReturn(claims); + when(mockClaimsSet.getStringClaim("deviceToken")).thenReturn("newDeviceToken"); + + PushDeviceHandlerDataHolder pushDeviceHandlerDataHolder = mock(PushDeviceHandlerDataHolder.class); + mockedPushDeviceHandlerDataHolder.when(PushDeviceHandlerDataHolder::getInstance) + .thenReturn(pushDeviceHandlerDataHolder); + + NotificationSenderManagementService notificationSenderManagementService = + mock(NotificationSenderManagementService.class); + when(pushDeviceHandlerDataHolder.getNotificationSenderManagementService()) + .thenReturn(notificationSenderManagementService); + PushSenderDTO pushSenderDTO = new PushSenderDTO(); + pushSenderDTO.setName("FCM_PushPublisher"); + pushSenderDTO.setProvider("FCM"); + pushSenderDTO.setProviderId("fcm-provider-id"); + List pushSenders = new ArrayList<>(); + pushSenders.add(pushSenderDTO); + when(notificationSenderManagementService.getPushSenders(anyBoolean())) + .thenReturn(pushSenders); + + FCMPushProvider fcmPushProvider = mock(FCMPushProvider.class); + when(pushDeviceHandlerDataHolder.getPushProvider(eq("FCM"))).thenReturn(fcmPushProvider); + when(fcmPushProvider.getName()).thenReturn("FCM"); + doNothing().when(fcmPushProvider).updateDevice(any(), any()); + + doNothing().when(deviceDAO).editDevice(anyString(), any()); + Mockito.clearInvocations(deviceDAO); + + deviceHandlerService.editDeviceMobile("1234567890", validJwt); + + verify(fcmPushProvider, times(1)).updateDevice(any(), any()); + verify(deviceDAO, times(1)).editDevice(anyString(), any()); + } + } + + @Test + public void testEditDeviceMobileWithNameOnly() + throws PushDeviceHandlerException, NotificationSenderManagementException, PushProviderException, + JOSEException, ParseException { + + try ( + MockedStatic mockedIdentityTenantUtil = + Mockito.mockStatic(IdentityTenantUtil.class); + MockedStatic mockedPushDeviceHandlerDataHolder = + Mockito.mockStatic(PushDeviceHandlerDataHolder.class); + MockedStatic mockedStatic = Mockito.mockStatic(SignedJWT.class) + ) { + + mockedIdentityTenantUtil.when(() -> IdentityTenantUtil.getTenantId(any())).thenReturn(-1234); + + Device deviceObj = new Device(); + deviceObj.setDeviceId("1234567890"); + deviceObj.setProvider("FCM"); + deviceObj.setDeviceToken(deviceToken); + deviceObj.setPublicKey(publicKey); + Optional device = Optional.of(deviceObj); + when(deviceDAO.getDevice(anyString())).thenReturn(device); + + mockedStatic.when(() -> SignedJWT.parse(validJwt)).thenReturn(mockSignedJWT); + + when(mockSignedJWT.getJWTClaimsSet()).thenReturn(mockClaimsSet); + when(mockClaimsSet.getExpirationTime()).thenReturn(new Date(System.currentTimeMillis() + 3000000)); + when(mockClaimsSet.getNotBeforeTime()).thenReturn(new Date(System.currentTimeMillis() - 3000000)); + when(mockSignedJWT.verify(any())).thenReturn(true); + + Map claims = new HashMap<>(); + claims.put("name", "newDeviceName"); + when(mockClaimsSet.getClaims()).thenReturn(claims); + when(mockClaimsSet.getStringClaim("name")).thenReturn("newDeviceName"); + + PushDeviceHandlerDataHolder pushDeviceHandlerDataHolder = mock(PushDeviceHandlerDataHolder.class); + mockedPushDeviceHandlerDataHolder.when(PushDeviceHandlerDataHolder::getInstance) + .thenReturn(pushDeviceHandlerDataHolder); + + NotificationSenderManagementService notificationSenderManagementService = + mock(NotificationSenderManagementService.class); + when(pushDeviceHandlerDataHolder.getNotificationSenderManagementService()) + .thenReturn(notificationSenderManagementService); + PushSenderDTO pushSenderDTO = new PushSenderDTO(); + pushSenderDTO.setName("FCM_PushPublisher"); + pushSenderDTO.setProvider("FCM"); + pushSenderDTO.setProviderId("fcm-provider-id"); + List pushSenders = new ArrayList<>(); + pushSenders.add(pushSenderDTO); + when(notificationSenderManagementService.getPushSenders(anyBoolean())) + .thenReturn(pushSenders); + + FCMPushProvider fcmPushProvider = mock(FCMPushProvider.class); + when(pushDeviceHandlerDataHolder.getPushProvider(eq("FCM"))).thenReturn(fcmPushProvider); + when(fcmPushProvider.getName()).thenReturn("FCM"); + doNothing().when(fcmPushProvider).updateDevice(any(), any()); + + doNothing().when(deviceDAO).editDevice(anyString(), any()); + Mockito.clearInvocations(deviceDAO); + + deviceHandlerService.editDeviceMobile("1234567890", validJwt); + + verify(fcmPushProvider, times(1)).updateDevice(any(), any()); + verify(deviceDAO, times(1)).editDevice(anyString(), any()); + } + } + + @Test + public void testEditDeviceMobileDeviceNotFound() throws PushDeviceHandlerException { + + Optional device = Optional.empty(); + when(deviceDAO.getDevice(anyString())).thenReturn(device); + + Assert.assertThrows(PushDeviceHandlerClientException.class, () -> { + deviceHandlerService.editDeviceMobile("1234567890", validJwt); + }); + } + + @Test + public void testEditDeviceMobileTokenValidationFailed() + throws PushDeviceHandlerException, JOSEException, ParseException { + + try ( + MockedStatic mockedStatic = Mockito.mockStatic(SignedJWT.class) + ) { + + Device deviceObj = new Device(); + deviceObj.setDeviceId("1234567890"); + deviceObj.setProvider("FCM"); + deviceObj.setDeviceToken(deviceToken); + deviceObj.setPublicKey(publicKey); + Optional device = Optional.of(deviceObj); + when(deviceDAO.getDevice(anyString())).thenReturn(device); + + mockedStatic.when(() -> SignedJWT.parse(validJwt)).thenReturn(mockSignedJWT); + + when(mockSignedJWT.getJWTClaimsSet()).thenReturn(mockClaimsSet); + when(mockClaimsSet.getExpirationTime()).thenReturn(new Date(System.currentTimeMillis() + 3000000)); + when(mockClaimsSet.getNotBeforeTime()).thenReturn(new Date(System.currentTimeMillis() - 3000000)); + when(mockSignedJWT.verify(any())).thenReturn(false); + + Assert.assertThrows(PushDeviceHandlerClientException.class, () -> { + deviceHandlerService.editDeviceMobile("1234567890", validJwt); + }); + } + } + + @Test + public void testEditDeviceMobileNoEditableFields() + throws PushDeviceHandlerException, JOSEException, ParseException { + + try ( + MockedStatic mockedStatic = Mockito.mockStatic(SignedJWT.class) + ) { + + Device deviceObj = new Device(); + deviceObj.setDeviceId("1234567890"); + deviceObj.setProvider("FCM"); + deviceObj.setDeviceToken(deviceToken); + deviceObj.setPublicKey(publicKey); + Optional device = Optional.of(deviceObj); + when(deviceDAO.getDevice(anyString())).thenReturn(device); + + mockedStatic.when(() -> SignedJWT.parse(validJwt)).thenReturn(mockSignedJWT); + + when(mockSignedJWT.getJWTClaimsSet()).thenReturn(mockClaimsSet); + when(mockClaimsSet.getExpirationTime()).thenReturn(new Date(System.currentTimeMillis() + 3000000)); + when(mockClaimsSet.getNotBeforeTime()).thenReturn(new Date(System.currentTimeMillis() - 3000000)); + when(mockSignedJWT.verify(any())).thenReturn(true); + + Map claims = new HashMap<>(); + when(mockClaimsSet.getClaims()).thenReturn(claims); + + Assert.assertThrows(PushDeviceHandlerClientException.class, () -> { + deviceHandlerService.editDeviceMobile("1234567890", validJwt); + }); + } + } + + @Test + public void testEditDeviceMobileProviderClientException() + throws PushDeviceHandlerException, NotificationSenderManagementException, PushProviderException, + JOSEException, ParseException { + + try ( + MockedStatic mockedIdentityTenantUtil = + Mockito.mockStatic(IdentityTenantUtil.class); + MockedStatic mockedPushDeviceHandlerDataHolder = + Mockito.mockStatic(PushDeviceHandlerDataHolder.class); + MockedStatic mockedStatic = Mockito.mockStatic(SignedJWT.class) + ) { + + mockedIdentityTenantUtil.when(() -> IdentityTenantUtil.getTenantId(any())).thenReturn(-1234); + + Device deviceObj = new Device(); + deviceObj.setDeviceId("1234567890"); + deviceObj.setProvider("FCM"); + deviceObj.setDeviceToken(deviceToken); + deviceObj.setPublicKey(publicKey); + Optional device = Optional.of(deviceObj); + when(deviceDAO.getDevice(anyString())).thenReturn(device); + + mockedStatic.when(() -> SignedJWT.parse(validJwt)).thenReturn(mockSignedJWT); + + when(mockSignedJWT.getJWTClaimsSet()).thenReturn(mockClaimsSet); + when(mockClaimsSet.getExpirationTime()).thenReturn(new Date(System.currentTimeMillis() + 3000000)); + when(mockClaimsSet.getNotBeforeTime()).thenReturn(new Date(System.currentTimeMillis() - 3000000)); + when(mockSignedJWT.verify(any())).thenReturn(true); + + Map claims = new HashMap<>(); + claims.put("deviceToken", "newDeviceToken"); + when(mockClaimsSet.getClaims()).thenReturn(claims); + when(mockClaimsSet.getStringClaim("deviceToken")).thenReturn("newDeviceToken"); + + PushDeviceHandlerDataHolder pushDeviceHandlerDataHolder = mock(PushDeviceHandlerDataHolder.class); + mockedPushDeviceHandlerDataHolder.when(PushDeviceHandlerDataHolder::getInstance) + .thenReturn(pushDeviceHandlerDataHolder); + + NotificationSenderManagementService notificationSenderManagementService = + mock(NotificationSenderManagementService.class); + when(pushDeviceHandlerDataHolder.getNotificationSenderManagementService()) + .thenReturn(notificationSenderManagementService); + PushSenderDTO pushSenderDTO = new PushSenderDTO(); + pushSenderDTO.setName("FCM_PushPublisher"); + pushSenderDTO.setProvider("FCM"); + pushSenderDTO.setProviderId("fcm-provider-id"); + List pushSenders = new ArrayList<>(); + pushSenders.add(pushSenderDTO); + when(notificationSenderManagementService.getPushSenders(anyBoolean())) + .thenReturn(pushSenders); + + FCMPushProvider fcmPushProvider = mock(FCMPushProvider.class); + when(pushDeviceHandlerDataHolder.getPushProvider(eq("FCM"))).thenReturn(fcmPushProvider); + when(fcmPushProvider.getName()).thenReturn("FCM"); + PushProviderClientException ppce = new PushProviderClientException( + "ERR_DEVICE_UPDATE", "Failed to update device at provider"); + doThrow(ppce).when(fcmPushProvider).updateDevice(any(), any()); + + Assert.assertThrows(PushDeviceHandlerClientException.class, () -> { + deviceHandlerService.editDeviceMobile("1234567890", validJwt); + }); + } + } + + @Test + public void testEditDeviceMobileProviderServerException() + throws PushDeviceHandlerException, NotificationSenderManagementException, PushProviderException, + JOSEException, ParseException { + + try ( + MockedStatic mockedIdentityTenantUtil = + Mockito.mockStatic(IdentityTenantUtil.class); + MockedStatic mockedPushDeviceHandlerDataHolder = + Mockito.mockStatic(PushDeviceHandlerDataHolder.class); + MockedStatic mockedStatic = Mockito.mockStatic(SignedJWT.class) + ) { + + mockedIdentityTenantUtil.when(() -> IdentityTenantUtil.getTenantId(any())).thenReturn(-1234); + + Device deviceObj = new Device(); + deviceObj.setDeviceId("1234567890"); + deviceObj.setProvider("FCM"); + deviceObj.setDeviceToken(deviceToken); + deviceObj.setPublicKey(publicKey); + Optional device = Optional.of(deviceObj); + when(deviceDAO.getDevice(anyString())).thenReturn(device); + + mockedStatic.when(() -> SignedJWT.parse(validJwt)).thenReturn(mockSignedJWT); + + when(mockSignedJWT.getJWTClaimsSet()).thenReturn(mockClaimsSet); + when(mockClaimsSet.getExpirationTime()).thenReturn(new Date(System.currentTimeMillis() + 3000000)); + when(mockClaimsSet.getNotBeforeTime()).thenReturn(new Date(System.currentTimeMillis() - 3000000)); + when(mockSignedJWT.verify(any())).thenReturn(true); + + Map claims = new HashMap<>(); + claims.put("deviceToken", "newDeviceToken"); + when(mockClaimsSet.getClaims()).thenReturn(claims); + when(mockClaimsSet.getStringClaim("deviceToken")).thenReturn("newDeviceToken"); + + PushDeviceHandlerDataHolder pushDeviceHandlerDataHolder = mock(PushDeviceHandlerDataHolder.class); + mockedPushDeviceHandlerDataHolder.when(PushDeviceHandlerDataHolder::getInstance) + .thenReturn(pushDeviceHandlerDataHolder); + + NotificationSenderManagementService notificationSenderManagementService = + mock(NotificationSenderManagementService.class); + when(pushDeviceHandlerDataHolder.getNotificationSenderManagementService()) + .thenReturn(notificationSenderManagementService); + PushSenderDTO pushSenderDTO = new PushSenderDTO(); + pushSenderDTO.setName("FCM_PushPublisher"); + pushSenderDTO.setProvider("FCM"); + pushSenderDTO.setProviderId("fcm-provider-id"); + List pushSenders = new ArrayList<>(); + pushSenders.add(pushSenderDTO); + when(notificationSenderManagementService.getPushSenders(anyBoolean())) + .thenReturn(pushSenders); + + PushProviderServerException ppse = new PushProviderServerException( + "ERR_PROVIDER_SERVER", "Provider service temporarily unavailable"); + org.wso2.carbon.identity.notification.push.provider.PushProvider pushProvider = + mock(org.wso2.carbon.identity.notification.push.provider.PushProvider.class); + when(pushDeviceHandlerDataHolder.getPushProvider(eq("FCM"))).thenReturn(pushProvider); + when(pushProvider.getName()).thenReturn("FCM"); + doThrow(ppse).when(pushProvider).updateDevice(any(), any()); + + Assert.assertThrows(PushDeviceHandlerServerException.class, () -> { + deviceHandlerService.editDeviceMobile("1234567890", validJwt); + }); + } + } + @Test public void testGetRegistrationDiscoveryData() throws PushDeviceHandlerException { From 21e50d844818ff65a49db96bafdf854873badc49 Mon Sep 17 00:00:00 2001 From: VihangaMunasinghe Date: Wed, 25 Mar 2026 18:45:05 +0530 Subject: [PATCH 03/13] Add PushChallengeValidator method to return claims as a Map and update device handler to use new method --- .../push/common/PushChallengeValidator.java | 16 ++++++++++++++ .../impl/DeviceHandlerServiceImpl.java | 21 ++++++++----------- 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/components/org.wso2.carbon.identity.notification.push.common/src/main/java/org/wso2/carbon/identity/notification/push/common/PushChallengeValidator.java b/components/org.wso2.carbon.identity.notification.push.common/src/main/java/org/wso2/carbon/identity/notification/push/common/PushChallengeValidator.java index f680766..e9e1ca7 100644 --- a/components/org.wso2.carbon.identity.notification.push.common/src/main/java/org/wso2/carbon/identity/notification/push/common/PushChallengeValidator.java +++ b/components/org.wso2.carbon.identity.notification.push.common/src/main/java/org/wso2/carbon/identity/notification/push/common/PushChallengeValidator.java @@ -36,6 +36,7 @@ import java.text.ParseException; import java.util.Base64; import java.util.Date; +import java.util.Map; /** * JWT token validator for Push notification scenarios. @@ -81,6 +82,21 @@ public static JWTClaimsSet getValidatedClaimSet(String jwt, String publicKey) th } } + /** + * Validate the JWT token and return the claim values. + * + * @param jwt JWT token to be validated + * @param publicKey Public key used for signing the JWT + * @return Map of claim values + * @throws PushTokenValidationException Error when validating the JWT token + */ + public static Map getValidatedClaims(String jwt, String publicKey) + throws PushTokenValidationException { + + JWTClaimsSet claimsSet = getValidatedClaimSet(jwt, publicKey); + return claimsSet.getClaims(); + } + /** * Validate the legitimacy of JWT token. * diff --git a/components/org.wso2.carbon.identity.notification.push.device.handler/src/main/java/org/wso2/carbon/identity/notification/push/device/handler/impl/DeviceHandlerServiceImpl.java b/components/org.wso2.carbon.identity.notification.push.device.handler/src/main/java/org/wso2/carbon/identity/notification/push/device/handler/impl/DeviceHandlerServiceImpl.java index c2db437..730c330 100644 --- a/components/org.wso2.carbon.identity.notification.push.device.handler/src/main/java/org/wso2/carbon/identity/notification/push/device/handler/impl/DeviceHandlerServiceImpl.java +++ b/components/org.wso2.carbon.identity.notification.push.device.handler/src/main/java/org/wso2/carbon/identity/notification/push/device/handler/impl/DeviceHandlerServiceImpl.java @@ -18,7 +18,6 @@ package org.wso2.carbon.identity.notification.push.device.handler.impl; -import com.nimbusds.jwt.JWTClaimsSet; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -261,9 +260,9 @@ public void editDeviceMobile(String deviceId, String token) throws PushDeviceHan } Device device = deviceOptional.get(); - JWTClaimsSet claimsSet; + Map claims; try { - claimsSet = PushChallengeValidator.getValidatedClaimSet(token, device.getPublicKey()); + claims = PushChallengeValidator.getValidatedClaims(token, device.getPublicKey()); } catch (PushTokenValidationException e) { throw new PushDeviceHandlerClientException(ERROR_CODE_TOKEN_CLAIM_VERIFICATION_FAILED.getCode(), String.format(ERROR_CODE_TOKEN_CLAIM_VERIFICATION_FAILED.getMessage(), deviceId), e); @@ -273,24 +272,22 @@ public void editDeviceMobile(String deviceId, String token) throws PushDeviceHan String deviceName = null; try { - if (claimsSet.getClaims().containsKey(DEVICE_EDIT_REQUEST_DEVICE_TOKEN)) { - deviceToken = PushChallengeValidator - .getClaimFromClaimSet(claimsSet, DEVICE_EDIT_REQUEST_DEVICE_TOKEN, deviceId); + if (claims.containsKey(DEVICE_EDIT_REQUEST_DEVICE_TOKEN)) { + deviceToken = (String) claims.get(DEVICE_EDIT_REQUEST_DEVICE_TOKEN); } - if (claimsSet.getClaims().containsKey(DEVICE_EDIT_REQUEST_DEVICE_NAME)) { - deviceName = PushChallengeValidator - .getClaimFromClaimSet(claimsSet, DEVICE_EDIT_REQUEST_DEVICE_NAME, deviceId); + if (claims.containsKey(DEVICE_EDIT_REQUEST_DEVICE_NAME)) { + deviceName = (String) claims.get(DEVICE_EDIT_REQUEST_DEVICE_NAME); } - } catch (PushTokenValidationException e) { - throw new PushDeviceHandlerClientException(e.getErrorCode(), e.getMessage(), e); + } catch (ClassCastException e) { + throw new PushDeviceHandlerClientException(ERROR_CODE_DEVICE_EDIT_FAILED.getCode(), + String.format(ERROR_CODE_DEVICE_EDIT_FAILED.getMessage(), deviceId), e); } if (deviceToken == null && deviceName == null) { throw new PushDeviceHandlerClientException(ERROR_CODE_DEVICE_EDIT_FAILED.getCode(), String.format(ERROR_CODE_DEVICE_EDIT_FAILED.getMessage(), deviceId)); } - if (deviceToken != null) { device.setDeviceToken(deviceToken); } From 2e2e4cbec6bf0ed919ad5ef9b628c16d0a8e7468 Mon Sep 17 00:00:00 2001 From: VihangaMunasinghe Date: Wed, 25 Mar 2026 18:45:17 +0530 Subject: [PATCH 04/13] Fix syntax error in EDIT_DEVICE SQL query in PushDeviceHandlerConstants --- .../device/handler/constant/PushDeviceHandlerConstants.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/org.wso2.carbon.identity.notification.push.device.handler/src/main/java/org/wso2/carbon/identity/notification/push/device/handler/constant/PushDeviceHandlerConstants.java b/components/org.wso2.carbon.identity.notification.push.device.handler/src/main/java/org/wso2/carbon/identity/notification/push/device/handler/constant/PushDeviceHandlerConstants.java index 55488cd..3e7d8ce 100644 --- a/components/org.wso2.carbon.identity.notification.push.device.handler/src/main/java/org/wso2/carbon/identity/notification/push/device/handler/constant/PushDeviceHandlerConstants.java +++ b/components/org.wso2.carbon.identity.notification.push.device.handler/src/main/java/org/wso2/carbon/identity/notification/push/device/handler/constant/PushDeviceHandlerConstants.java @@ -58,7 +58,7 @@ public static class SQLQueries { public static final String GET_PUBLIC_KEY_BY_ID = "SELECT PUBLIC_KEY FROM IDN_PUSH_DEVICE_STORE " + "WHERE ID = :ID;"; public static final String UNREGISTER_DEVICE = "DELETE FROM IDN_PUSH_DEVICE_STORE WHERE ID = :ID;"; - public static final String EDIT_DEVICE = "UPDATE IDN_PUSH_DEVICE_STORE SET DEVICE_NAME = :DEVICE_NAME; " + + public static final String EDIT_DEVICE = "UPDATE IDN_PUSH_DEVICE_STORE SET DEVICE_NAME = :DEVICE_NAME;, " + "DEVICE_TOKEN = :DEVICE_TOKEN; WHERE ID = :ID;"; } From d496a8b6bfd5a918b6938b01c93252036aa33919 Mon Sep 17 00:00:00 2001 From: VihangaMunasinghe Date: Thu, 26 Mar 2026 02:20:01 +0530 Subject: [PATCH 05/13] Update EDIT_DEVICE_TEST SQL query and add unit tests for PushChallengeValidator claims validation --- .../common/PushChallengeValidatorTest.java | 85 +++++++++++++++++++ .../device/handler/dao/DeviceDAOImplTest.java | 2 +- 2 files changed, 86 insertions(+), 1 deletion(-) diff --git a/components/org.wso2.carbon.identity.notification.push.common/src/test/java/org/wso2/carbon/identity/notification/push/common/PushChallengeValidatorTest.java b/components/org.wso2.carbon.identity.notification.push.common/src/test/java/org/wso2/carbon/identity/notification/push/common/PushChallengeValidatorTest.java index 167ae31..c9aa87c 100644 --- a/components/org.wso2.carbon.identity.notification.push.common/src/test/java/org/wso2/carbon/identity/notification/push/common/PushChallengeValidatorTest.java +++ b/components/org.wso2.carbon.identity.notification.push.common/src/test/java/org/wso2/carbon/identity/notification/push/common/PushChallengeValidatorTest.java @@ -31,6 +31,8 @@ import java.text.ParseException; import java.util.Date; +import java.util.HashMap; +import java.util.Map; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.when; @@ -141,6 +143,89 @@ public void testGetValidatedClaimSetWithExpiredToken() throws Exception { } } + @Test + public void testGetValidatedClaimsWithValidToken() throws Exception { + + try (MockedStatic mockedStatic = Mockito.mockStatic(SignedJWT.class)) { + mockedStatic.when(() -> SignedJWT.parse(validJwt)).thenReturn(mockSignedJWT); + + Map expectedClaims = new HashMap<>(); + expectedClaims.put("chg", "e0c3d04c-750b-4301-8f76-e07ebf02e53a"); + expectedClaims.put("td", "carbon.super"); + + when(mockSignedJWT.getJWTClaimsSet()).thenReturn(mockClaimsSet); + when(mockClaimsSet.getExpirationTime()).thenReturn(new Date(System.currentTimeMillis() + 3000000)); + when(mockClaimsSet.getNotBeforeTime()).thenReturn(new Date(System.currentTimeMillis() - 3000000)); + when(mockSignedJWT.verify(any())).thenReturn(true); + when(mockClaimsSet.getClaims()).thenReturn(expectedClaims); + + Map claims = PushChallengeValidator.getValidatedClaims(validJwt, publicKey); + assertNotNull(claims); + } + } + + @Test(expectedExceptions = PushTokenValidationException.class) + public void testGetValidatedClaimsWithBlankToken() throws Exception { + + PushChallengeValidator.getValidatedClaims("", publicKey); + } + + @Test(expectedExceptions = PushTokenValidationException.class) + public void testGetValidatedClaimsWithInvalidJwtToken() throws Exception { + + PushChallengeValidator.getValidatedClaims(invalidJwt, publicKey); + } + + @Test(expectedExceptions = PushTokenValidationException.class) + public void testGetValidatedClaimsWithExpiredToken() throws Exception { + + try (MockedStatic mockedStatic = Mockito.mockStatic(SignedJWT.class)) { + mockedStatic.when(() -> SignedJWT.parse(validJwt)).thenReturn(mockSignedJWT); + when(mockSignedJWT.getJWTClaimsSet()).thenReturn(mockClaimsSet); + when(mockClaimsSet.getExpirationTime()).thenReturn(new Date(System.currentTimeMillis() - 3000000)); + when(mockSignedJWT.verify(any())).thenReturn(true); + PushChallengeValidator.getValidatedClaims(validJwt, publicKey); + } + } + + @Test(expectedExceptions = PushTokenValidationException.class) + public void testGetValidatedClaimsWithInvalidSignature() throws Exception { + + try (MockedStatic mockedStatic = Mockito.mockStatic(SignedJWT.class)) { + mockedStatic.when(() -> SignedJWT.parse(validJwt)).thenReturn(mockSignedJWT); + when(mockSignedJWT.getJWTClaimsSet()).thenReturn(null); + PushChallengeValidator.getValidatedClaims(validJwt, invalidPublicKey); + } + } + + @Test + public void testGetValidatedClaimsReturnsCorrectClaimValues() throws Exception { + + try (MockedStatic mockedStatic = Mockito.mockStatic(SignedJWT.class)) { + mockedStatic.when(() -> SignedJWT.parse(validJwt)).thenReturn(mockSignedJWT); + + Map expectedClaims = new HashMap<>(); + expectedClaims.put("td", "carbon.super"); + expectedClaims.put("pid", "f5ae6a0d-390a-4eea-a380-8bcc86e4a148"); + expectedClaims.put("chg", "e0c3d04c-750b-4301-8f76-e07ebf02e53a"); + expectedClaims.put("res", "APPROVED"); + + when(mockSignedJWT.getJWTClaimsSet()).thenReturn(mockClaimsSet); + when(mockClaimsSet.getExpirationTime()).thenReturn(new Date(System.currentTimeMillis() + 3000000)); + when(mockClaimsSet.getNotBeforeTime()).thenReturn(new Date(System.currentTimeMillis() - 3000000)); + when(mockSignedJWT.verify(any())).thenReturn(true); + when(mockClaimsSet.getClaims()).thenReturn(expectedClaims); + + Map claims = PushChallengeValidator.getValidatedClaims(validJwt, publicKey); + assertNotNull(claims); + Assert.assertEquals(claims.get("td"), "carbon.super"); + Assert.assertEquals(claims.get("pid"), "f5ae6a0d-390a-4eea-a380-8bcc86e4a148"); + Assert.assertEquals(claims.get("chg"), "e0c3d04c-750b-4301-8f76-e07ebf02e53a"); + Assert.assertEquals(claims.get("res"), "APPROVED"); + Assert.assertEquals(claims.size(), 4); + } + } + @Test public void testValidateChallengeWithEmptyClaimsSet() { diff --git a/components/org.wso2.carbon.identity.notification.push.device.handler/src/test/java/org/wso2/carbon/identity/notification/push/device/handler/dao/DeviceDAOImplTest.java b/components/org.wso2.carbon.identity.notification.push.device.handler/src/test/java/org/wso2/carbon/identity/notification/push/device/handler/dao/DeviceDAOImplTest.java index 8376fbe..f73728a 100644 --- a/components/org.wso2.carbon.identity.notification.push.device.handler/src/test/java/org/wso2/carbon/identity/notification/push/device/handler/dao/DeviceDAOImplTest.java +++ b/components/org.wso2.carbon.identity.notification.push.device.handler/src/test/java/org/wso2/carbon/identity/notification/push/device/handler/dao/DeviceDAOImplTest.java @@ -42,7 +42,7 @@ public class DeviceDAOImplTest { "DEVICE_MODEL, DEVICE_TOKEN, DEVICE_HANDLE, PROVIDER, PUBLIC_KEY, TENANT_ID) VALUES " + "( ? , ? , ? , ? , ? , ? , ? , ? , ? )"; public static final String UNREGISTER_DEVICE_TEST = "DELETE FROM IDN_PUSH_DEVICE_STORE WHERE ID = ? "; - public static final String EDIT_DEVICE_TEST = "UPDATE IDN_PUSH_DEVICE_STORE SET DEVICE_NAME = ? " + + public static final String EDIT_DEVICE_TEST = "UPDATE IDN_PUSH_DEVICE_STORE SET DEVICE_NAME = ? , " + "DEVICE_TOKEN = ? WHERE ID = ? "; private DeviceDAOImpl deviceDAO; From 154729e745dd781efe2fc52109f033b5cc0c027f Mon Sep 17 00:00:00 2001 From: VihangaMunasinghe Date: Thu, 26 Mar 2026 10:10:01 +0530 Subject: [PATCH 06/13] Update copyright year in source files to 2025-2026 --- .../notification/push/common/PushChallengeValidator.java | 2 +- .../notification/push/common/PushChallengeValidatorTest.java | 2 +- .../notification/push/device/handler/dao/DeviceDAOImplTest.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/components/org.wso2.carbon.identity.notification.push.common/src/main/java/org/wso2/carbon/identity/notification/push/common/PushChallengeValidator.java b/components/org.wso2.carbon.identity.notification.push.common/src/main/java/org/wso2/carbon/identity/notification/push/common/PushChallengeValidator.java index e9e1ca7..f8f8b04 100644 --- a/components/org.wso2.carbon.identity.notification.push.common/src/main/java/org/wso2/carbon/identity/notification/push/common/PushChallengeValidator.java +++ b/components/org.wso2.carbon.identity.notification.push.common/src/main/java/org/wso2/carbon/identity/notification/push/common/PushChallengeValidator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, WSO2 LLC. (http://www.wso2.com). + * Copyright (c) 2025-2026, 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 diff --git a/components/org.wso2.carbon.identity.notification.push.common/src/test/java/org/wso2/carbon/identity/notification/push/common/PushChallengeValidatorTest.java b/components/org.wso2.carbon.identity.notification.push.common/src/test/java/org/wso2/carbon/identity/notification/push/common/PushChallengeValidatorTest.java index c9aa87c..229e420 100644 --- a/components/org.wso2.carbon.identity.notification.push.common/src/test/java/org/wso2/carbon/identity/notification/push/common/PushChallengeValidatorTest.java +++ b/components/org.wso2.carbon.identity.notification.push.common/src/test/java/org/wso2/carbon/identity/notification/push/common/PushChallengeValidatorTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, WSO2 LLC. (http://www.wso2.com). + * Copyright (c) 2025-2026, 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 diff --git a/components/org.wso2.carbon.identity.notification.push.device.handler/src/test/java/org/wso2/carbon/identity/notification/push/device/handler/dao/DeviceDAOImplTest.java b/components/org.wso2.carbon.identity.notification.push.device.handler/src/test/java/org/wso2/carbon/identity/notification/push/device/handler/dao/DeviceDAOImplTest.java index f73728a..8dc9a8e 100644 --- a/components/org.wso2.carbon.identity.notification.push.device.handler/src/test/java/org/wso2/carbon/identity/notification/push/device/handler/dao/DeviceDAOImplTest.java +++ b/components/org.wso2.carbon.identity.notification.push.device.handler/src/test/java/org/wso2/carbon/identity/notification/push/device/handler/dao/DeviceDAOImplTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, WSO2 LLC. (http://www.wso2.com). + * Copyright (c) 2025-2026, 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 From 99b5de20815f232bb50493f0c79912e99e8754b5 Mon Sep 17 00:00:00 2001 From: VihangaMunasinghe Date: Thu, 26 Mar 2026 20:39:32 +0530 Subject: [PATCH 07/13] Fix best practices --- .../device/handler/DeviceHandlerService.java | 2 +- .../constant/PushDeviceHandlerConstants.java | 6 +-- .../impl/DeviceHandlerServiceImpl.java | 42 +++++++++++++------ 3 files changed, 34 insertions(+), 16 deletions(-) diff --git a/components/org.wso2.carbon.identity.notification.push.device.handler/src/main/java/org/wso2/carbon/identity/notification/push/device/handler/DeviceHandlerService.java b/components/org.wso2.carbon.identity.notification.push.device.handler/src/main/java/org/wso2/carbon/identity/notification/push/device/handler/DeviceHandlerService.java index 06cf0ae..4d5ce01 100644 --- a/components/org.wso2.carbon.identity.notification.push.device.handler/src/main/java/org/wso2/carbon/identity/notification/push/device/handler/DeviceHandlerService.java +++ b/components/org.wso2.carbon.identity.notification.push.device.handler/src/main/java/org/wso2/carbon/identity/notification/push/device/handler/DeviceHandlerService.java @@ -99,7 +99,7 @@ Device registerDevice(RegistrationRequest registrationRequest, String tenantDoma * @param token Token. * @throws PushDeviceHandlerException Push Device Handler Exception. */ - void editDeviceMobile(String deviceId, String token) throws PushDeviceHandlerException; + default void editDeviceMobile(String deviceId, String token) throws PushDeviceHandlerException{} /** * Get registration discovery data. diff --git a/components/org.wso2.carbon.identity.notification.push.device.handler/src/main/java/org/wso2/carbon/identity/notification/push/device/handler/constant/PushDeviceHandlerConstants.java b/components/org.wso2.carbon.identity.notification.push.device.handler/src/main/java/org/wso2/carbon/identity/notification/push/device/handler/constant/PushDeviceHandlerConstants.java index 3e7d8ce..25d3d00 100644 --- a/components/org.wso2.carbon.identity.notification.push.device.handler/src/main/java/org/wso2/carbon/identity/notification/push/device/handler/constant/PushDeviceHandlerConstants.java +++ b/components/org.wso2.carbon.identity.notification.push.device.handler/src/main/java/org/wso2/carbon/identity/notification/push/device/handler/constant/PushDeviceHandlerConstants.java @@ -30,8 +30,8 @@ public class PushDeviceHandlerConstants { public static final String DEVICE_REGISTRATION_CONTEXT_VALIDITY_PERIOD = "PushAuthenticator.DeviceRegistrationContext.ValidityPeriod"; public static final int DEFAULT_DEVICE_REGISTRATION_CONTEXT_VALIDITY_PERIOD = 180; - public static final String DEVICE_EDIT_REQUEST_DEVICE_NAME = "name"; - public static final String DEVICE_EDIT_REQUEST_DEVICE_TOKEN = "deviceToken"; + public static final String DEVICE_NAME = "name"; + public static final String DEVICE_TOKEN = "deviceToken"; /** * Private constructor to prevent initialization of the class. @@ -141,7 +141,7 @@ public enum ErrorMessages { ), ERROR_CODE_DEVICE_EDIT_FAILED( "PDH-150014", - "Error occurred while editing the device for the device ID: %s." + "Error occurred while updating the device for the device ID: %s." ); private final String code; diff --git a/components/org.wso2.carbon.identity.notification.push.device.handler/src/main/java/org/wso2/carbon/identity/notification/push/device/handler/impl/DeviceHandlerServiceImpl.java b/components/org.wso2.carbon.identity.notification.push.device.handler/src/main/java/org/wso2/carbon/identity/notification/push/device/handler/impl/DeviceHandlerServiceImpl.java index 730c330..0da1bff 100644 --- a/components/org.wso2.carbon.identity.notification.push.device.handler/src/main/java/org/wso2/carbon/identity/notification/push/device/handler/impl/DeviceHandlerServiceImpl.java +++ b/components/org.wso2.carbon.identity.notification.push.device.handler/src/main/java/org/wso2/carbon/identity/notification/push/device/handler/impl/DeviceHandlerServiceImpl.java @@ -71,8 +71,8 @@ import java.util.UUID; import static org.wso2.carbon.identity.notification.push.device.handler.constant.PushDeviceHandlerConstants.DEFAULT_PUSH_PROVIDER; -import static org.wso2.carbon.identity.notification.push.device.handler.constant.PushDeviceHandlerConstants.DEVICE_EDIT_REQUEST_DEVICE_NAME; -import static org.wso2.carbon.identity.notification.push.device.handler.constant.PushDeviceHandlerConstants.DEVICE_EDIT_REQUEST_DEVICE_TOKEN; +import static org.wso2.carbon.identity.notification.push.device.handler.constant.PushDeviceHandlerConstants.DEVICE_NAME; +import static org.wso2.carbon.identity.notification.push.device.handler.constant.PushDeviceHandlerConstants.DEVICE_TOKEN; import static org.wso2.carbon.identity.notification.push.device.handler.constant.PushDeviceHandlerConstants.ErrorMessages.ERROR_CODE_DEVICE_ALREADY_REGISTERED; import static org.wso2.carbon.identity.notification.push.device.handler.constant.PushDeviceHandlerConstants.ErrorMessages.ERROR_CODE_DEVICE_EDIT_FAILED; import static org.wso2.carbon.identity.notification.push.device.handler.constant.PushDeviceHandlerConstants.ErrorMessages.ERROR_CODE_DEVICE_NOT_FOUND; @@ -268,20 +268,17 @@ public void editDeviceMobile(String deviceId, String token) throws PushDeviceHan String.format(ERROR_CODE_TOKEN_CLAIM_VERIFICATION_FAILED.getMessage(), deviceId), e); } + validateDeviceEditClaims(claims, deviceId); + String deviceToken = null; String deviceName = null; - try { - if (claims.containsKey(DEVICE_EDIT_REQUEST_DEVICE_TOKEN)) { - deviceToken = (String) claims.get(DEVICE_EDIT_REQUEST_DEVICE_TOKEN); - } + if (claims.containsKey(DEVICE_TOKEN)) { + deviceToken = (String) claims.get(DEVICE_TOKEN); + } - if (claims.containsKey(DEVICE_EDIT_REQUEST_DEVICE_NAME)) { - deviceName = (String) claims.get(DEVICE_EDIT_REQUEST_DEVICE_NAME); - } - } catch (ClassCastException e) { - throw new PushDeviceHandlerClientException(ERROR_CODE_DEVICE_EDIT_FAILED.getCode(), - String.format(ERROR_CODE_DEVICE_EDIT_FAILED.getMessage(), deviceId), e); + if (claims.containsKey(DEVICE_NAME)) { + deviceName = (String) claims.get(DEVICE_NAME); } if (deviceToken == null && deviceName == null) { @@ -725,4 +722,25 @@ public static PushSenderData buildPushSenderData(PushSenderDTO pushSenderDTO) { pushSenderData.setProviderId(pushSenderDTO.getProviderId()); return pushSenderData; } + + /** + * Validate the claims in the edit device token. + * + * @param claims Claims to validate. + * @param deviceId Device ID for error messages. + * @throws PushDeviceHandlerClientException If the claims are invalid. + */ + private static void validateDeviceEditClaims(Map claims, String deviceId) + throws PushDeviceHandlerClientException { + + if (claims.containsKey(DEVICE_TOKEN) && !(claims.get(DEVICE_TOKEN) instanceof String)) { + throw new PushDeviceHandlerClientException(ERROR_CODE_DEVICE_EDIT_FAILED.getCode(), + String.format(ERROR_CODE_DEVICE_EDIT_FAILED.getMessage(), deviceId)); + } + + if (claims.containsKey(DEVICE_NAME) && !(claims.get(DEVICE_NAME) instanceof String)) { + throw new PushDeviceHandlerClientException(ERROR_CODE_DEVICE_EDIT_FAILED.getCode(), + String.format(ERROR_CODE_DEVICE_EDIT_FAILED.getMessage(), deviceId)); + } + } } From fc813b8b16d7a1840bc8e1ba72082021525bb364 Mon Sep 17 00:00:00 2001 From: VihangaMunasinghe Date: Thu, 26 Mar 2026 20:39:41 +0530 Subject: [PATCH 08/13] Add unit tests for invalid claim types in editDeviceMobile method --- .../impl/DeviceHandlerServiceImplTest.java | 103 ++++++++++++++++++ 1 file changed, 103 insertions(+) diff --git a/components/org.wso2.carbon.identity.notification.push.device.handler/src/test/java/org/wso2/carbon/identity/notification/push/device/handler/impl/DeviceHandlerServiceImplTest.java b/components/org.wso2.carbon.identity.notification.push.device.handler/src/test/java/org/wso2/carbon/identity/notification/push/device/handler/impl/DeviceHandlerServiceImplTest.java index 554412a..98b5d36 100644 --- a/components/org.wso2.carbon.identity.notification.push.device.handler/src/test/java/org/wso2/carbon/identity/notification/push/device/handler/impl/DeviceHandlerServiceImplTest.java +++ b/components/org.wso2.carbon.identity.notification.push.device.handler/src/test/java/org/wso2/carbon/identity/notification/push/device/handler/impl/DeviceHandlerServiceImplTest.java @@ -1224,6 +1224,109 @@ public void testEditDeviceMobileDeviceNotFound() throws PushDeviceHandlerExcepti }); } + @Test + public void testEditDeviceMobileWithInvalidDeviceTokenClaimType() + throws PushDeviceHandlerException, JOSEException, ParseException { + + try ( + MockedStatic mockedStatic = Mockito.mockStatic(SignedJWT.class) + ) { + + Device deviceObj = new Device(); + deviceObj.setDeviceId("1234567890"); + deviceObj.setProvider("FCM"); + deviceObj.setDeviceToken(deviceToken); + deviceObj.setPublicKey(publicKey); + Optional device = Optional.of(deviceObj); + when(deviceDAO.getDevice(anyString())).thenReturn(device); + + mockedStatic.when(() -> SignedJWT.parse(validJwt)).thenReturn(mockSignedJWT); + + when(mockSignedJWT.getJWTClaimsSet()).thenReturn(mockClaimsSet); + when(mockClaimsSet.getExpirationTime()).thenReturn(new Date(System.currentTimeMillis() + 3000000)); + when(mockClaimsSet.getNotBeforeTime()).thenReturn(new Date(System.currentTimeMillis() - 3000000)); + when(mockSignedJWT.verify(any())).thenReturn(true); + + // Set deviceToken claim as a non-String type (Integer) to trigger validation failure. + Map claims = new HashMap<>(); + claims.put("deviceToken", 12345); + when(mockClaimsSet.getClaims()).thenReturn(claims); + + Assert.assertThrows(PushDeviceHandlerClientException.class, () -> { + deviceHandlerService.editDeviceMobile("1234567890", validJwt); + }); + } + } + + @Test + public void testEditDeviceMobileWithInvalidDeviceNameClaimType() + throws PushDeviceHandlerException, JOSEException, ParseException { + + try ( + MockedStatic mockedStatic = Mockito.mockStatic(SignedJWT.class) + ) { + + Device deviceObj = new Device(); + deviceObj.setDeviceId("1234567890"); + deviceObj.setProvider("FCM"); + deviceObj.setDeviceToken(deviceToken); + deviceObj.setPublicKey(publicKey); + Optional device = Optional.of(deviceObj); + when(deviceDAO.getDevice(anyString())).thenReturn(device); + + mockedStatic.when(() -> SignedJWT.parse(validJwt)).thenReturn(mockSignedJWT); + + when(mockSignedJWT.getJWTClaimsSet()).thenReturn(mockClaimsSet); + when(mockClaimsSet.getExpirationTime()).thenReturn(new Date(System.currentTimeMillis() + 3000000)); + when(mockClaimsSet.getNotBeforeTime()).thenReturn(new Date(System.currentTimeMillis() - 3000000)); + when(mockSignedJWT.verify(any())).thenReturn(true); + + // Set name claim as a non-String type (Boolean) to trigger validation failure. + Map claims = new HashMap<>(); + claims.put("name", true); + when(mockClaimsSet.getClaims()).thenReturn(claims); + + Assert.assertThrows(PushDeviceHandlerClientException.class, () -> { + deviceHandlerService.editDeviceMobile("1234567890", validJwt); + }); + } + } + + @Test + public void testEditDeviceMobileWithBothInvalidClaimTypes() + throws PushDeviceHandlerException, JOSEException, ParseException { + + try ( + MockedStatic mockedStatic = Mockito.mockStatic(SignedJWT.class) + ) { + + Device deviceObj = new Device(); + deviceObj.setDeviceId("1234567890"); + deviceObj.setProvider("FCM"); + deviceObj.setDeviceToken(deviceToken); + deviceObj.setPublicKey(publicKey); + Optional device = Optional.of(deviceObj); + when(deviceDAO.getDevice(anyString())).thenReturn(device); + + mockedStatic.when(() -> SignedJWT.parse(validJwt)).thenReturn(mockSignedJWT); + + when(mockSignedJWT.getJWTClaimsSet()).thenReturn(mockClaimsSet); + when(mockClaimsSet.getExpirationTime()).thenReturn(new Date(System.currentTimeMillis() + 3000000)); + when(mockClaimsSet.getNotBeforeTime()).thenReturn(new Date(System.currentTimeMillis() - 3000000)); + when(mockSignedJWT.verify(any())).thenReturn(true); + + // Set both claims as non-String types. The deviceToken check runs first. + Map claims = new HashMap<>(); + claims.put("deviceToken", 12345); + claims.put("name", 67890); + when(mockClaimsSet.getClaims()).thenReturn(claims); + + Assert.assertThrows(PushDeviceHandlerClientException.class, () -> { + deviceHandlerService.editDeviceMobile("1234567890", validJwt); + }); + } + } + @Test public void testEditDeviceMobileTokenValidationFailed() throws PushDeviceHandlerException, JOSEException, ParseException { From 5e6374acf3386349e700dd74043ba73842c44c39 Mon Sep 17 00:00:00 2001 From: VihangaMunasinghe Date: Thu, 26 Mar 2026 21:22:20 +0530 Subject: [PATCH 09/13] Add audit logging to device registration and update --- .../impl/DeviceHandlerServiceImpl.java | 15 ++++++ .../utils/DeviceHandlerAuditLogger.java | 20 ++++++-- .../utils/DeviceHandlerAuditLoggerTest.java | 46 ++++++++++++++++++- 3 files changed, 76 insertions(+), 5 deletions(-) diff --git a/components/org.wso2.carbon.identity.notification.push.device.handler/src/main/java/org/wso2/carbon/identity/notification/push/device/handler/impl/DeviceHandlerServiceImpl.java b/components/org.wso2.carbon.identity.notification.push.device.handler/src/main/java/org/wso2/carbon/identity/notification/push/device/handler/impl/DeviceHandlerServiceImpl.java index 0da1bff..94d68d9 100644 --- a/components/org.wso2.carbon.identity.notification.push.device.handler/src/main/java/org/wso2/carbon/identity/notification/push/device/handler/impl/DeviceHandlerServiceImpl.java +++ b/components/org.wso2.carbon.identity.notification.push.device.handler/src/main/java/org/wso2/carbon/identity/notification/push/device/handler/impl/DeviceHandlerServiceImpl.java @@ -138,6 +138,11 @@ public Device registerDevice(RegistrationRequest registrationRequest, String ten device = handleDeviceRegistration(registrationRequest, context); if (context.isRegistered()) { deviceRegistrationContextManager.clearContext(registrationRequest.getDeviceId(), tenantDomain); + AUDIT_LOGGER.printAuditLog( + DeviceHandlerAuditLogger.Operation.REGISTER_DEVICE, + deviceId, + device.getUserId() + ); } else { throw new PushDeviceHandlerClientException(ERROR_CODE_DEVICE_REGISTRATION_FAILED.getCode(), String.format(ERROR_CODE_DEVICE_REGISTRATION_FAILED.getMessage(), deviceId)); @@ -248,6 +253,11 @@ public void editDevice(String deviceId, String path, String value) throws PushDe Device device = getDevice(deviceId); handleEditDevice(device, path, value); + AUDIT_LOGGER.printAuditLog( + DeviceHandlerAuditLogger.Operation.UPDATE_DEVICE, + deviceId, + device.getUserId() + ); } @Override @@ -294,6 +304,11 @@ public void editDeviceMobile(String deviceId, String token) throws PushDeviceHan handleUpdateDeviceForProvider(device); deviceDAO.editDevice(device.getDeviceId(), device); + AUDIT_LOGGER.printAuditLog( + DeviceHandlerAuditLogger.Operation.UPDATE_DEVICE, + deviceId, + device.getUserId() + ); } @Override diff --git a/components/org.wso2.carbon.identity.notification.push.device.handler/src/main/java/org/wso2/carbon/identity/notification/push/device/handler/utils/DeviceHandlerAuditLogger.java b/components/org.wso2.carbon.identity.notification.push.device.handler/src/main/java/org/wso2/carbon/identity/notification/push/device/handler/utils/DeviceHandlerAuditLogger.java index b3b2d33..d252301 100644 --- a/components/org.wso2.carbon.identity.notification.push.device.handler/src/main/java/org/wso2/carbon/identity/notification/push/device/handler/utils/DeviceHandlerAuditLogger.java +++ b/components/org.wso2.carbon.identity.notification.push.device.handler/src/main/java/org/wso2/carbon/identity/notification/push/device/handler/utils/DeviceHandlerAuditLogger.java @@ -45,7 +45,7 @@ public class DeviceHandlerAuditLogger { */ public void printAuditLog(Operation operation, String deviceId, String userId) { - JSONObject data = createAuditLogEntry(userId); + JSONObject data = createAuditLogEntry(operation, userId); buildAuditLog(operation, deviceId, data); } @@ -72,11 +72,21 @@ private void buildAuditLog(Operation operation, String targetId, JSONObject data * * @return Audit log data. */ - private JSONObject createAuditLogEntry(String userId) { + private JSONObject createAuditLogEntry(Operation operation, String userId) { JSONObject data = new JSONObject(); data.put(LogConstants.END_USER_ID, userId != null ? userId : JSONObject.NULL); - data.put(LogConstants.UNREGISTERED_AT, System.currentTimeMillis()); + switch (operation) { + case REGISTER_DEVICE: + data.put(LogConstants.REGISTERED_AT, System.currentTimeMillis()); + break; + case UPDATE_DEVICE: + data.put(LogConstants.UPDATED_AT, System.currentTimeMillis()); + break; + case UNREGISTER_DEVICE: + data.put(LogConstants.UNREGISTERED_AT, System.currentTimeMillis()); + break; + } return data; } @@ -128,6 +138,8 @@ private String getInitiatorId() { */ public enum Operation { + REGISTER_DEVICE("Register-Push-Auth-Device"), + UPDATE_DEVICE("Update-Push-Auth-Device"), UNREGISTER_DEVICE("Unregister-Push-Auth-Device"); private final String logAction; @@ -150,6 +162,8 @@ private static class LogConstants { public static final String TARGET_TYPE_FIELD = "Push-Auth-Device"; public static final String END_USER_ID = "UserId"; + public static final String REGISTERED_AT = "RegisteredAt"; + public static final String UPDATED_AT = "UpdatedAt"; public static final String UNREGISTERED_AT = "UnregisteredAt"; } } diff --git a/components/org.wso2.carbon.identity.notification.push.device.handler/src/test/java/org/wso2/carbon/identity/notification/push/device/handler/utils/DeviceHandlerAuditLoggerTest.java b/components/org.wso2.carbon.identity.notification.push.device.handler/src/test/java/org/wso2/carbon/identity/notification/push/device/handler/utils/DeviceHandlerAuditLoggerTest.java index 863fd22..a44a72b 100644 --- a/components/org.wso2.carbon.identity.notification.push.device.handler/src/test/java/org/wso2/carbon/identity/notification/push/device/handler/utils/DeviceHandlerAuditLoggerTest.java +++ b/components/org.wso2.carbon.identity.notification.push.device.handler/src/test/java/org/wso2/carbon/identity/notification/push/device/handler/utils/DeviceHandlerAuditLoggerTest.java @@ -130,9 +130,11 @@ public void testGetUserWithSystemUser() throws Exception { public void testCreateAuditLogEntryWithValidData() throws Exception { Method createAuditLogEntryMethod = DeviceHandlerAuditLogger.class - .getDeclaredMethod("createAuditLogEntry", String.class); + .getDeclaredMethod("createAuditLogEntry", + DeviceHandlerAuditLogger.Operation.class, String.class); createAuditLogEntryMethod.setAccessible(true); - JSONObject result = (JSONObject) createAuditLogEntryMethod.invoke(auditLogger, "testUserId"); + JSONObject result = (JSONObject) createAuditLogEntryMethod.invoke( + auditLogger, DeviceHandlerAuditLogger.Operation.UNREGISTER_DEVICE, "testUserId"); Assert.assertNotNull(result); Assert.assertTrue(result.has("UserId")); @@ -141,6 +143,46 @@ public void testCreateAuditLogEntryWithValidData() throws Exception { Assert.assertTrue(result.getLong("UnregisteredAt") > 0); } + /** + * Test the private method 'createAuditLogEntry' with register device operation. + */ + @Test + public void testCreateAuditLogEntryWithRegisterDevice() throws Exception { + + Method createAuditLogEntryMethod = DeviceHandlerAuditLogger.class + .getDeclaredMethod("createAuditLogEntry", + DeviceHandlerAuditLogger.Operation.class, String.class); + createAuditLogEntryMethod.setAccessible(true); + JSONObject result = (JSONObject) createAuditLogEntryMethod.invoke( + auditLogger, DeviceHandlerAuditLogger.Operation.REGISTER_DEVICE, "testUserId"); + + Assert.assertNotNull(result); + Assert.assertTrue(result.has("UserId")); + Assert.assertEquals(result.getString("UserId"), "testUserId"); + Assert.assertTrue(result.has("RegisteredAt")); + Assert.assertTrue(result.getLong("RegisteredAt") > 0); + } + + /** + * Test the private method 'createAuditLogEntry' with update device operation. + */ + @Test + public void testCreateAuditLogEntryWithUpdateDevice() throws Exception { + + Method createAuditLogEntryMethod = DeviceHandlerAuditLogger.class + .getDeclaredMethod("createAuditLogEntry", + DeviceHandlerAuditLogger.Operation.class, String.class); + createAuditLogEntryMethod.setAccessible(true); + JSONObject result = (JSONObject) createAuditLogEntryMethod.invoke( + auditLogger, DeviceHandlerAuditLogger.Operation.UPDATE_DEVICE, "testUserId"); + + Assert.assertNotNull(result); + Assert.assertTrue(result.has("UserId")); + Assert.assertEquals(result.getString("UserId"), "testUserId"); + Assert.assertTrue(result.has("UpdatedAt")); + Assert.assertTrue(result.getLong("UpdatedAt") > 0); + } + /** * Test the private method 'getInitiatorId'. */ From 3226b942008086e4b1f2a3e97ca742bb18a64185 Mon Sep 17 00:00:00 2001 From: WSO2 Builder Date: Tue, 7 Apr 2026 10:52:49 +0000 Subject: [PATCH 10/13] [WSO2 Release] [Jenkins #1] [Release 1.2.0] prepare release v1.2.0 --- .../org.wso2.carbon.identity.notification.push.common/pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- pom.xml | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/components/org.wso2.carbon.identity.notification.push.common/pom.xml b/components/org.wso2.carbon.identity.notification.push.common/pom.xml index d60dce2..e8d1248 100644 --- a/components/org.wso2.carbon.identity.notification.push.common/pom.xml +++ b/components/org.wso2.carbon.identity.notification.push.common/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.notification.push identity-notification-push - 1.1.6-SNAPSHOT + 1.2.0 ../../pom.xml diff --git a/components/org.wso2.carbon.identity.notification.push.device.handler/pom.xml b/components/org.wso2.carbon.identity.notification.push.device.handler/pom.xml index 4943ba1..2c97627 100644 --- a/components/org.wso2.carbon.identity.notification.push.device.handler/pom.xml +++ b/components/org.wso2.carbon.identity.notification.push.device.handler/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.notification.push identity-notification-push - 1.1.6-SNAPSHOT + 1.2.0 ../../pom.xml diff --git a/components/org.wso2.carbon.identity.notification.push.provider/pom.xml b/components/org.wso2.carbon.identity.notification.push.provider/pom.xml index 8db1d11..873adea 100644 --- a/components/org.wso2.carbon.identity.notification.push.provider/pom.xml +++ b/components/org.wso2.carbon.identity.notification.push.provider/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.notification.push identity-notification-push - 1.1.6-SNAPSHOT + 1.2.0 ../../pom.xml diff --git a/features/org.wso2.carbon.identity.notification.push.feature/pom.xml b/features/org.wso2.carbon.identity.notification.push.feature/pom.xml index f226db6..f1f844c 100644 --- a/features/org.wso2.carbon.identity.notification.push.feature/pom.xml +++ b/features/org.wso2.carbon.identity.notification.push.feature/pom.xml @@ -23,7 +23,7 @@ org.wso2.carbon.identity.notification.push identity-notification-push - 1.1.6-SNAPSHOT + 1.2.0 ../../pom.xml diff --git a/pom.xml b/pom.xml index 05b9010..75b29d9 100644 --- a/pom.xml +++ b/pom.xml @@ -26,7 +26,7 @@ org.wso2.carbon.identity.notification.push 4.0.0 - 1.1.6-SNAPSHOT + 1.2.0 identity-notification-push pom WSO2 Carbon - Identity Notification Push @@ -36,7 +36,7 @@ scm:git:https://github.com/wso2-extensions/identity-notification-push.git scm:git:https://github.com/wso2-extensions/identity-notification-push.git - HEAD + v1.2.0 From f09c710b4dcb61f0c0af756e75e0a2962b5a9752 Mon Sep 17 00:00:00 2001 From: WSO2 Builder Date: Tue, 7 Apr 2026 10:52:50 +0000 Subject: [PATCH 11/13] [WSO2 Release] [Jenkins #1] [Release 1.2.0] prepare for next development iteration --- .../org.wso2.carbon.identity.notification.push.common/pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- pom.xml | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/components/org.wso2.carbon.identity.notification.push.common/pom.xml b/components/org.wso2.carbon.identity.notification.push.common/pom.xml index e8d1248..c92bae0 100644 --- a/components/org.wso2.carbon.identity.notification.push.common/pom.xml +++ b/components/org.wso2.carbon.identity.notification.push.common/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.notification.push identity-notification-push - 1.2.0 + 1.2.1-SNAPSHOT ../../pom.xml diff --git a/components/org.wso2.carbon.identity.notification.push.device.handler/pom.xml b/components/org.wso2.carbon.identity.notification.push.device.handler/pom.xml index 2c97627..50691aa 100644 --- a/components/org.wso2.carbon.identity.notification.push.device.handler/pom.xml +++ b/components/org.wso2.carbon.identity.notification.push.device.handler/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.notification.push identity-notification-push - 1.2.0 + 1.2.1-SNAPSHOT ../../pom.xml diff --git a/components/org.wso2.carbon.identity.notification.push.provider/pom.xml b/components/org.wso2.carbon.identity.notification.push.provider/pom.xml index 873adea..74d737a 100644 --- a/components/org.wso2.carbon.identity.notification.push.provider/pom.xml +++ b/components/org.wso2.carbon.identity.notification.push.provider/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.notification.push identity-notification-push - 1.2.0 + 1.2.1-SNAPSHOT ../../pom.xml diff --git a/features/org.wso2.carbon.identity.notification.push.feature/pom.xml b/features/org.wso2.carbon.identity.notification.push.feature/pom.xml index f1f844c..6f6b66a 100644 --- a/features/org.wso2.carbon.identity.notification.push.feature/pom.xml +++ b/features/org.wso2.carbon.identity.notification.push.feature/pom.xml @@ -23,7 +23,7 @@ org.wso2.carbon.identity.notification.push identity-notification-push - 1.2.0 + 1.2.1-SNAPSHOT ../../pom.xml diff --git a/pom.xml b/pom.xml index 75b29d9..8c5d91d 100644 --- a/pom.xml +++ b/pom.xml @@ -26,7 +26,7 @@ org.wso2.carbon.identity.notification.push 4.0.0 - 1.2.0 + 1.2.1-SNAPSHOT identity-notification-push pom WSO2 Carbon - Identity Notification Push @@ -36,7 +36,7 @@ scm:git:https://github.com/wso2-extensions/identity-notification-push.git scm:git:https://github.com/wso2-extensions/identity-notification-push.git - v1.2.0 + HEAD From d58c37e5bc3826a832d431fff9e0e8f94e47b5b8 Mon Sep 17 00:00:00 2001 From: WSO2 Builder Date: Wed, 29 Apr 2026 09:02:31 +0000 Subject: [PATCH 12/13] [WSO2 Release] [Jenkins #38] [Release 1.2.1] prepare release v1.2.1 --- .../org.wso2.carbon.identity.notification.push.common/pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- pom.xml | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/components/org.wso2.carbon.identity.notification.push.common/pom.xml b/components/org.wso2.carbon.identity.notification.push.common/pom.xml index c92bae0..c634663 100644 --- a/components/org.wso2.carbon.identity.notification.push.common/pom.xml +++ b/components/org.wso2.carbon.identity.notification.push.common/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.notification.push identity-notification-push - 1.2.1-SNAPSHOT + 1.2.1 ../../pom.xml diff --git a/components/org.wso2.carbon.identity.notification.push.device.handler/pom.xml b/components/org.wso2.carbon.identity.notification.push.device.handler/pom.xml index 50691aa..dc94eb2 100644 --- a/components/org.wso2.carbon.identity.notification.push.device.handler/pom.xml +++ b/components/org.wso2.carbon.identity.notification.push.device.handler/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.notification.push identity-notification-push - 1.2.1-SNAPSHOT + 1.2.1 ../../pom.xml diff --git a/components/org.wso2.carbon.identity.notification.push.provider/pom.xml b/components/org.wso2.carbon.identity.notification.push.provider/pom.xml index 74d737a..fc3d4a4 100644 --- a/components/org.wso2.carbon.identity.notification.push.provider/pom.xml +++ b/components/org.wso2.carbon.identity.notification.push.provider/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.notification.push identity-notification-push - 1.2.1-SNAPSHOT + 1.2.1 ../../pom.xml diff --git a/features/org.wso2.carbon.identity.notification.push.feature/pom.xml b/features/org.wso2.carbon.identity.notification.push.feature/pom.xml index 6f6b66a..2efc8cd 100644 --- a/features/org.wso2.carbon.identity.notification.push.feature/pom.xml +++ b/features/org.wso2.carbon.identity.notification.push.feature/pom.xml @@ -23,7 +23,7 @@ org.wso2.carbon.identity.notification.push identity-notification-push - 1.2.1-SNAPSHOT + 1.2.1 ../../pom.xml diff --git a/pom.xml b/pom.xml index 8c5d91d..49d71fd 100644 --- a/pom.xml +++ b/pom.xml @@ -26,7 +26,7 @@ org.wso2.carbon.identity.notification.push 4.0.0 - 1.2.1-SNAPSHOT + 1.2.1 identity-notification-push pom WSO2 Carbon - Identity Notification Push @@ -36,7 +36,7 @@ scm:git:https://github.com/wso2-extensions/identity-notification-push.git scm:git:https://github.com/wso2-extensions/identity-notification-push.git - HEAD + v1.2.1 From dd947ffd7683770682cf68c987b6cc3f6090d523 Mon Sep 17 00:00:00 2001 From: WSO2 Builder Date: Wed, 29 Apr 2026 09:02:33 +0000 Subject: [PATCH 13/13] [WSO2 Release] [Jenkins #38] [Release 1.2.1] prepare for next development iteration --- .../org.wso2.carbon.identity.notification.push.common/pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- pom.xml | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/components/org.wso2.carbon.identity.notification.push.common/pom.xml b/components/org.wso2.carbon.identity.notification.push.common/pom.xml index c634663..52e1dbc 100644 --- a/components/org.wso2.carbon.identity.notification.push.common/pom.xml +++ b/components/org.wso2.carbon.identity.notification.push.common/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.notification.push identity-notification-push - 1.2.1 + 1.2.2-SNAPSHOT ../../pom.xml diff --git a/components/org.wso2.carbon.identity.notification.push.device.handler/pom.xml b/components/org.wso2.carbon.identity.notification.push.device.handler/pom.xml index dc94eb2..a992db8 100644 --- a/components/org.wso2.carbon.identity.notification.push.device.handler/pom.xml +++ b/components/org.wso2.carbon.identity.notification.push.device.handler/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.notification.push identity-notification-push - 1.2.1 + 1.2.2-SNAPSHOT ../../pom.xml diff --git a/components/org.wso2.carbon.identity.notification.push.provider/pom.xml b/components/org.wso2.carbon.identity.notification.push.provider/pom.xml index fc3d4a4..79879c5 100644 --- a/components/org.wso2.carbon.identity.notification.push.provider/pom.xml +++ b/components/org.wso2.carbon.identity.notification.push.provider/pom.xml @@ -21,7 +21,7 @@ org.wso2.carbon.identity.notification.push identity-notification-push - 1.2.1 + 1.2.2-SNAPSHOT ../../pom.xml diff --git a/features/org.wso2.carbon.identity.notification.push.feature/pom.xml b/features/org.wso2.carbon.identity.notification.push.feature/pom.xml index 2efc8cd..60dda18 100644 --- a/features/org.wso2.carbon.identity.notification.push.feature/pom.xml +++ b/features/org.wso2.carbon.identity.notification.push.feature/pom.xml @@ -23,7 +23,7 @@ org.wso2.carbon.identity.notification.push identity-notification-push - 1.2.1 + 1.2.2-SNAPSHOT ../../pom.xml diff --git a/pom.xml b/pom.xml index 49d71fd..ba1e571 100644 --- a/pom.xml +++ b/pom.xml @@ -26,7 +26,7 @@ org.wso2.carbon.identity.notification.push 4.0.0 - 1.2.1 + 1.2.2-SNAPSHOT identity-notification-push pom WSO2 Carbon - Identity Notification Push @@ -36,7 +36,7 @@ scm:git:https://github.com/wso2-extensions/identity-notification-push.git scm:git:https://github.com/wso2-extensions/identity-notification-push.git - v1.2.1 + HEAD