Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
package org.wso2.carbon.identity.event.handler.notification;

import org.apache.commons.lang.StringUtils;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.identity.base.IdentityRuntimeException;
import org.wso2.carbon.identity.core.bean.context.MessageContext;
import org.wso2.carbon.identity.event.IdentityEventConstants;
Expand Down Expand Up @@ -266,15 +267,32 @@ private PushNotificationData buildPushNotificationData(Event event) throws Ident
placeholderValues.put(ORGANIZATION_NAME_PLACEHOLDER, organizationName);
}

/*
* If the tenant domain is different from the organization name, then it is an organization user. Hence,
* the organization ID is the tenant domain.
*/
String organizationId = null;
if (!tenantDomain.equals(organizationName)) {
organizationId = tenantDomain;
String primaryTenantDomain = null;

if (NotificationUtil.isOrganization(tenantDomain)) {
LOG.debug("Tenant domain is an organization.");
try {
organizationId = NotificationHandlerDataHolder.getInstance()
.getOrganizationManager().resolveOrganizationId(tenantDomain);
} catch (OrganizationManagementException e) {
if (LOG.isDebugEnabled()) {
LOG.debug("Error while resolving organization ID for tenant domain: " + tenantDomain, e);
}
throw new IdentityEventException(e.getMessage(), e);
}

/* If an accessing organization ID is present, this flow is for a tenant organization path
* (/t/{tenant-domain}/o/{org-id}).
* Therefore, include the primary tenant domain in the PushNotificationData. */
if (StringUtils.isNotEmpty(PrivilegedCarbonContext.getThreadLocalCarbonContext()
.getAccessingOrganizationId())) {
LOG.debug("Adding primary tenant domain to the push notification data.");
primaryTenantDomain = NotificationUtil.getPrimaryTenantDomain(organizationId);
}
} else {
// If tenant user, organizationName is null.
LOG.debug("Tenant domain is not an organization.");
organizationName = null;
}

Expand All @@ -289,6 +307,7 @@ private PushNotificationData buildPushNotificationData(Event event) throws Ident
.setTenantDomain(tenantDomain)
.setOrganizationId(organizationId)
.setOrganizationName(organizationName)
.setPrimaryTenantDomain(primaryTenantDomain)
.setUserStoreDomain((String) eventProperties.get(
IdentityEventConstants.EventProperty.USER_STORE_DOMAIN))
.setApplicationName((String) eventProperties.get(IdentityEventConstants.EventProperty.APPLICATION_NAME))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2024, WSO2 LLC. (http://www.wso2.org) All Rights Reserved.
* Copyright (c) 2016-2026, WSO2 LLC. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 LLC. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
Expand Down Expand Up @@ -869,6 +869,41 @@ public static String resolveHumanReadableOrganizationName(String tenantDomain) t
return organizationName;
}

/**
* Check whether the given tenant domain belongs to an organization.
*
* @param tenantDomain Tenant domain.
* @return true if the tenant domain belongs to an organization, false otherwise.
* @throws IdentityEventException Error while checking whether the tenant domain belongs to an organization.
*/
public static boolean isOrganization(String tenantDomain) throws IdentityEventException {

try {
return OrganizationManagementUtil.isOrganization(tenantDomain);
} catch (OrganizationManagementException e) {
throw new IdentityEventException(e.getMessage(), e);
}
}

/**
* Get the primary tenant domain of the given organization ID.
*
* @param organizationId Organization ID.
* @return Primary tenant domain.
* @throws IdentityEventException If an error occurred while getting the primary tenant domain.
*/
public static String getPrimaryTenantDomain(String organizationId) throws IdentityEventException {

Comment on lines +894 to +896

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Log Improvement Suggestion No: 4

Suggested change
*/
public static String getOrganizationUUID(String tenantDomain) throws IdentityEventException {
public static String getOrganizationUUID(String tenantDomain) throws IdentityEventException {
if (log.isDebugEnabled()) {
log.debug("Retrieving organization UUID for tenant domain: " + tenantDomain);
}
String organizationUUID = null;

try {
OrganizationManager organizationManager = NotificationHandlerDataHolder.getInstance()
.getOrganizationManager();
String primaryOrgId = organizationManager.getPrimaryOrganizationId(organizationId);
return organizationManager.resolveTenantDomain(primaryOrgId);
} catch (OrganizationManagementException e) {
throw new IdentityEventException(e.getMessage(), e);
}
}

/**
* Get the notification locale.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,17 @@
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.mockito.ArgumentCaptor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.MockitoAnnotations;
import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import org.wso2.carbon.context.CarbonContext;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.identity.central.log.mgt.utils.LoggerUtils;
import org.wso2.carbon.identity.core.util.IdentityUtil;
import org.wso2.carbon.identity.event.IdentityEventException;
Expand Down Expand Up @@ -757,6 +760,159 @@ public void testHandleEventWithProviderNameVariations() throws Exception {
eq("carbon.super"));
}

@Test
public void testHandleEventOrganizationTenantWithAccessingOrgId() throws Exception {

String orgTenantDomain = "org-tenant";
String orgId = "org-uuid-123";
String primaryOrgTenantDomain = "primary-tenant";

Event event = createPushNotificationEvent("FCM", orgTenantDomain);

try (MockedStatic<NotificationHandlerDataHolder> mockedDataHolder = mockStatic(
NotificationHandlerDataHolder.class);
MockedStatic<NotificationUtil> mockedNotificationUtil = mockStatic(NotificationUtil.class);
MockedStatic<PrivilegedCarbonContext> mockedPrivilegedCarbonContext =
mockStatic(PrivilegedCarbonContext.class)) {

mockedDataHolder.when(NotificationHandlerDataHolder::getInstance)
.thenReturn(notificationHandlerDataHolder);
when(notificationHandlerDataHolder.getOrganizationManager()).thenReturn(organizationManager);
when(organizationManager.resolveOrganizationId(orgTenantDomain)).thenReturn(orgId);

mockedNotificationUtil.when(() -> NotificationUtil.resolveHumanReadableOrganizationName(anyString()))
.thenReturn(SAMPLE_ORGANIZATION_NAME);
mockedNotificationUtil.when(() -> NotificationUtil.isOrganization(orgTenantDomain))
.thenReturn(true);
mockedNotificationUtil.when(() -> NotificationUtil.getPrimaryTenantDomain(orgId))
.thenReturn(primaryOrgTenantDomain);

PrivilegedCarbonContext mockPrivilegedContext = mock(PrivilegedCarbonContext.class);
mockedPrivilegedCarbonContext.when(PrivilegedCarbonContext::getThreadLocalCarbonContext)
.thenReturn(mockPrivilegedContext);
when(mockPrivilegedContext.getAccessingOrganizationId()).thenReturn("accessing-org-id");

when(notificationHandlerDataHolder.getNotificationSenderManagementService())
.thenReturn(notificationSenderManagementService);
PushSenderDTO sender = new PushSenderDTO();
sender.setName("PushPublisher");
sender.setProvider("FCM");
sender.setProviderId("fcm-provider-id");
List<PushSenderDTO> pushSenders = new ArrayList<>();
pushSenders.add(sender);
when(notificationSenderManagementService.getPushSenders(true)).thenReturn(pushSenders);
when(notificationHandlerDataHolder.getPushProvider("FCM")).thenReturn(pushProvider);

pushNotificationHandler.handleEvent(event);

ArgumentCaptor<PushNotificationData> captor = ArgumentCaptor.forClass(PushNotificationData.class);
verify(pushProvider).sendNotification(captor.capture(), any(PushSenderData.class),
eq(orgTenantDomain));
PushNotificationData data = captor.getValue();
Assert.assertEquals(data.getOrganizationId(), orgId);
Assert.assertEquals(data.getPrimaryTenantDomain(), primaryOrgTenantDomain);
Assert.assertEquals(data.getOrganizationName(), SAMPLE_ORGANIZATION_NAME);
}
}

@Test
public void testHandleEventOrganizationTenantWithoutAccessingOrgId() throws Exception {

String orgTenantDomain = "org-tenant";
String orgId = "org-uuid-123";

Event event = createPushNotificationEvent("FCM", orgTenantDomain);

try (MockedStatic<NotificationHandlerDataHolder> mockedDataHolder = mockStatic(
NotificationHandlerDataHolder.class);
MockedStatic<NotificationUtil> mockedNotificationUtil = mockStatic(NotificationUtil.class);
MockedStatic<PrivilegedCarbonContext> mockedPrivilegedCarbonContext =
mockStatic(PrivilegedCarbonContext.class)) {

mockedDataHolder.when(NotificationHandlerDataHolder::getInstance)
.thenReturn(notificationHandlerDataHolder);
when(notificationHandlerDataHolder.getOrganizationManager()).thenReturn(organizationManager);
when(organizationManager.resolveOrganizationId(orgTenantDomain)).thenReturn(orgId);

mockedNotificationUtil.when(() -> NotificationUtil.resolveHumanReadableOrganizationName(anyString()))
.thenReturn(SAMPLE_ORGANIZATION_NAME);
mockedNotificationUtil.when(() -> NotificationUtil.isOrganization(orgTenantDomain))
.thenReturn(true);

PrivilegedCarbonContext mockPrivilegedContext = mock(PrivilegedCarbonContext.class);
mockedPrivilegedCarbonContext.when(PrivilegedCarbonContext::getThreadLocalCarbonContext)
.thenReturn(mockPrivilegedContext);
when(mockPrivilegedContext.getAccessingOrganizationId()).thenReturn(null);

when(notificationHandlerDataHolder.getNotificationSenderManagementService())
.thenReturn(notificationSenderManagementService);
PushSenderDTO sender = new PushSenderDTO();
sender.setName("PushPublisher");
sender.setProvider("FCM");
sender.setProviderId("fcm-provider-id");
List<PushSenderDTO> pushSenders = new ArrayList<>();
pushSenders.add(sender);
when(notificationSenderManagementService.getPushSenders(true)).thenReturn(pushSenders);
when(notificationHandlerDataHolder.getPushProvider("FCM")).thenReturn(pushProvider);

pushNotificationHandler.handleEvent(event);

ArgumentCaptor<PushNotificationData> captor = ArgumentCaptor.forClass(PushNotificationData.class);
verify(pushProvider).sendNotification(captor.capture(), any(PushSenderData.class),
eq(orgTenantDomain));
PushNotificationData data = captor.getValue();
Assert.assertEquals(data.getOrganizationId(), orgId);
Assert.assertNull(data.getPrimaryTenantDomain());
Assert.assertEquals(data.getOrganizationName(), SAMPLE_ORGANIZATION_NAME);
}
}

/**
* Test that when the tenant domain is not an organization, the built PushNotificationData has
* null organizationId, organizationName, and primaryTenantDomain.
*/
@Test
public void testHandleEventNonOrganizationTenant() throws Exception {

Event event = createPushNotificationEvent("FCM", "carbon.super");

try (MockedStatic<NotificationHandlerDataHolder> mockedDataHolder = mockStatic(
NotificationHandlerDataHolder.class);
MockedStatic<NotificationUtil> mockedNotificationUtil = mockStatic(NotificationUtil.class)) {

mockedDataHolder.when(NotificationHandlerDataHolder::getInstance)
.thenReturn(notificationHandlerDataHolder);
when(notificationHandlerDataHolder.getOrganizationManager()).thenReturn(organizationManager);
when(organizationManager.resolveOrganizationId(anyString())).thenReturn("orgId");

mockedNotificationUtil.when(() -> NotificationUtil.resolveHumanReadableOrganizationName(anyString()))
.thenReturn(SAMPLE_ORGANIZATION_NAME);
mockedNotificationUtil.when(() -> NotificationUtil.isOrganization("carbon.super"))
.thenReturn(false);

when(notificationHandlerDataHolder.getNotificationSenderManagementService())
.thenReturn(notificationSenderManagementService);
PushSenderDTO sender = new PushSenderDTO();
sender.setName("PushPublisher");
sender.setProvider("FCM");
sender.setProviderId("fcm-provider-id");
List<PushSenderDTO> pushSenders = new ArrayList<>();
pushSenders.add(sender);
when(notificationSenderManagementService.getPushSenders(true)).thenReturn(pushSenders);
when(notificationHandlerDataHolder.getPushProvider("FCM")).thenReturn(pushProvider);

pushNotificationHandler.handleEvent(event);

ArgumentCaptor<PushNotificationData> captor = ArgumentCaptor.forClass(PushNotificationData.class);
verify(pushProvider).sendNotification(captor.capture(), any(PushSenderData.class),
eq("carbon.super"));
PushNotificationData data = captor.getValue();
Assert.assertNull(data.getOrganizationId());
Assert.assertNull(data.getOrganizationName());
Assert.assertNull(data.getPrimaryTenantDomain());
}
}

// ==================== Helper Methods ====================

/**
Expand Down
Loading
Loading