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 @@ -238,7 +238,9 @@
net.minidev.json; version="${net.minidev.json.imp.pkg.version.range}",
org.wso2.carbon.identity.central.log.mgt.utils; version="${carbon.identity.package.import.version.range}",
org.wso2.carbon.identity.conditional.auth.functions.common.utils,
org.wso2.carbon.utils*;version="${carbon.kernel.package.import.version.range}"
org.wso2.carbon.utils*;version="${carbon.kernel.package.import.version.range}",
org.wso2.carbon.identity.organization.management.service;version="${org.wso2.carbon.identity.organization.management.core.version.range}",
org.wso2.carbon.identity.organization.management.service.exception;version="${org.wso2.carbon.identity.organization.management.core.version.range}"
</Import-Package>
<DynamicImport-Package>
org.graalvm.polyglot,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
* Copyright (c) 2019-2025, WSO2 LLC. (http://www.wso2.com).
*
* WSO2 Inc. licenses this file to you under the Apache License,
* 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
Expand All @@ -18,6 +18,7 @@

package org.wso2.carbon.identity.conditional.auth.functions.user;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.graalvm.polyglot.HostAccess;
Expand All @@ -31,6 +32,7 @@
import org.wso2.carbon.identity.conditional.auth.functions.user.internal.UserFunctionsServiceHolder;
import org.wso2.carbon.identity.conditional.auth.functions.user.model.JsUserSession;
import org.wso2.carbon.identity.conditional.auth.functions.user.model.JsWrapperFactoryProvider;
import org.wso2.carbon.identity.organization.management.service.exception.OrganizationManagementException;
import org.wso2.carbon.user.core.UserRealm;

import java.util.List;
Expand Down Expand Up @@ -62,14 +64,14 @@ private List<UserSession> getUserSessions(AuthenticatedUser authenticatedUser)
throws UserSessionRetrievalException {

List<UserSession> userSessions = null;
String tenantDomain = authenticatedUser.getTenantDomain();
String tenantDomain = getUserTenantDomain(authenticatedUser);

try {
UserRealm userRealm = Utils.getUserRealm(tenantDomain);
if (userRealm != null) {
String userId = authenticatedUser.getUserId();
userSessions = UserFunctionsServiceHolder.getInstance()
.getUserSessionManagementService().getSessionsByUserId(userId);
.getUserSessionManagementService().getSessionsByUserId(userId, tenantDomain);
}
} catch (SessionManagementException e) {
throw new UserSessionRetrievalException("Error occurred while retrieving sessions: ", e);
Expand All @@ -81,4 +83,20 @@ private List<UserSession> getUserSessions(AuthenticatedUser authenticatedUser)
return userSessions;
}

private String getUserTenantDomain(AuthenticatedUser authenticatedUser) throws UserSessionRetrievalException {

String tenantDomain = authenticatedUser.getTenantDomain();
String userAccessingOrganization = authenticatedUser.getAccessingOrganization();
if (StringUtils.isNotBlank(userAccessingOrganization)) {
try {
tenantDomain = UserFunctionsServiceHolder.getInstance().getOrganizationManager()
.resolveTenantDomain(userAccessingOrganization);
} catch (OrganizationManagementException e) {
Comment on lines +91 to +94

Choose a reason for hiding this comment

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

Log Improvement Suggestion No: 2

Suggested change
try {
tenantDomain = UserFunctionsServiceHolder.getInstance().getOrganizationManager()
.resolveTenantDomain(userAccessingOrganization);
} catch (OrganizationManagementException e) {
try {
tenantDomain = UserFunctionsServiceHolder.getInstance().getOrganizationManager()
.resolveTenantDomain(userAccessingOrganization);
if (LOG.isDebugEnabled()) {
LOG.debug("Resolved tenant domain: " + tenantDomain + " for organization: " + userAccessingOrganization);
}
} catch (OrganizationManagementException e) {

throw new UserSessionRetrievalException(
"Error occurred while resolving tenant domain of user accessing organization: " +
userAccessingOrganization, e);
}
}
return tenantDomain;
}
Comment on lines +86 to +101
Copy link

Copilot AI Oct 27, 2025

Choose a reason for hiding this comment

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

[nitpick] The method concatenates the organization ID directly into the error message on line 96-97. Consider using String.format() or structured logging to improve readability and maintainability of the error message.

Copilot uses AI. Check for mistakes.
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
import org.wso2.carbon.identity.conditional.auth.functions.user.SetAccountAssociationToLocalUser;
import org.wso2.carbon.identity.conditional.auth.functions.user.UpdateUserPasswordFunction;
import org.wso2.carbon.identity.conditional.auth.functions.user.UpdateUserPasswordFunctionImpl;
import org.wso2.carbon.identity.organization.management.service.OrganizationManager;
import org.wso2.carbon.identity.role.v2.mgt.core.RoleManagementService;
import org.wso2.carbon.idp.mgt.IdpManager;
import org.wso2.carbon.user.core.service.RealmService;
Expand Down Expand Up @@ -290,4 +291,21 @@ protected void unsetRoleManagementService(RoleManagementService roleManagementSe
LOG.debug("Role management service is unset in the conditional authentication user functions bundle");
}
}

@Reference(name = "identity.organization.management.component",
service = OrganizationManager.class,
cardinality = ReferenceCardinality.MANDATORY,
policy = ReferencePolicy.DYNAMIC,
unbind = "unsetOrganizationManager")
protected void setOrganizationManager(OrganizationManager organizationManager) {

UserFunctionsServiceHolder.getInstance().setOrganizationManager(organizationManager);
LOG.debug("Organization manager service is set in the conditional authentication user functions bundle.");
Comment on lines +300 to +303

Choose a reason for hiding this comment

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

Log Improvement Suggestion No: 3

Suggested change
protected void setOrganizationManager(OrganizationManager organizationManager) {
UserFunctionsServiceHolder.getInstance().setOrganizationManager(organizationManager);
LOG.debug("Organization manager service is set in the conditional authentication user functions bundle.");
protected void setOrganizationManager(OrganizationManager organizationManager) {
UserFunctionsServiceHolder.getInstance().setOrganizationManager(organizationManager);
if (LOG.isDebugEnabled()) {
LOG.debug("Organization manager service is set in the conditional authentication user functions bundle.");
}

Copy link

Copilot AI Oct 27, 2025

Choose a reason for hiding this comment

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

Corrected inconsistent punctuation in debug message: removed period to match the style of the unset method on line 309.

Suggested change
LOG.debug("Organization manager service is set in the conditional authentication user functions bundle.");
LOG.debug("Organization manager service is set in the conditional authentication user functions bundle");

Copilot uses AI. Check for mistakes.
}

protected void unsetOrganizationManager(OrganizationManager organizationManager) {

UserFunctionsServiceHolder.getInstance().setOrganizationManager(null);
LOG.debug("Organization manager service is unset in the conditional authentication user functions bundle.");
Comment on lines +306 to +309

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
protected void unsetOrganizationManager(OrganizationManager organizationManager) {
UserFunctionsServiceHolder.getInstance().setOrganizationManager(null);
LOG.debug("Organization manager service is unset in the conditional authentication user functions bundle.");
protected void unsetOrganizationManager(OrganizationManager organizationManager) {
UserFunctionsServiceHolder.getInstance().setOrganizationManager(null);
if (LOG.isDebugEnabled()) {
LOG.debug("Organization manager service is unset in the conditional authentication user functions bundle.");
}

Copy link

Copilot AI Oct 27, 2025

Choose a reason for hiding this comment

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

Corrected inconsistent punctuation in debug message: removed period to match the style used in other unset methods (e.g., line 291).

Suggested change
LOG.debug("Organization manager service is unset in the conditional authentication user functions bundle.");
LOG.debug("Organization manager service is unset in the conditional authentication user functions bundle");

Copilot uses AI. Check for mistakes.
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.wso2.carbon.identity.application.authentication.framework.JsFunctionRegistry;
import org.wso2.carbon.identity.application.authentication.framework.UserSessionManagementService;
import org.wso2.carbon.identity.application.mgt.ApplicationManagementService;
import org.wso2.carbon.identity.organization.management.service.OrganizationManager;
import org.wso2.carbon.identity.role.v2.mgt.core.RoleManagementService;
import org.wso2.carbon.idp.mgt.IdpManager;
import org.wso2.carbon.user.core.service.RealmService;
Expand All @@ -35,6 +36,7 @@ public class UserFunctionsServiceHolder {
private ApplicationManagementService applicationManagementService;
private RoleManagementService roleManagementService;
private JsFunctionRegistry jsFunctionRegistry;
private OrganizationManager organizationManager;

private UserFunctionsServiceHolder() {

Expand Down Expand Up @@ -106,4 +108,14 @@ public void setJsFunctionRegistry(JsFunctionRegistry jsFunctionRegistry) {

this.jsFunctionRegistry = jsFunctionRegistry;
}

public OrganizationManager getOrganizationManager() {

return organizationManager;
}

public void setOrganizationManager(OrganizationManager organizationManager) {

this.organizationManager = organizationManager;
}
Comment on lines +117 to +120

Choose a reason for hiding this comment

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

Log Improvement Suggestion No: 5

Suggested change
public void setOrganizationManager(OrganizationManager organizationManager) {
this.organizationManager = organizationManager;
}
public void setOrganizationManager(OrganizationManager organizationManager) {
if (organizationManager != null) {
log.debug("OrganizationManager service is set in UserFunctionsServiceHolder.");
}
this.organizationManager = organizationManager;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
/*
* 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.conditional.auth.functions.user;

import org.mockito.Mock;
import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.identity.application.authentication.framework.UserSessionManagementService;
import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js.JsAuthenticatedUser;
import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js.graaljs.JsGraalAuthenticatedUser;
import org.wso2.carbon.identity.application.authentication.framework.internal.FrameworkServiceDataHolder;
import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser;
import org.wso2.carbon.identity.application.authentication.framework.model.UserSession;
import org.wso2.carbon.identity.common.testng.WithCarbonHome;
import org.wso2.carbon.identity.common.testng.WithRealmService;
import org.wso2.carbon.identity.conditional.auth.functions.user.internal.UserFunctionsServiceHolder;
import org.wso2.carbon.identity.conditional.auth.functions.user.model.JsUserSession;
import org.wso2.carbon.identity.core.util.IdentityTenantUtil;
import org.wso2.carbon.identity.organization.management.service.OrganizationManager;
import org.wso2.carbon.identity.organization.management.service.exception.OrganizationManagementException;

import java.util.ArrayList;
import java.util.List;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;

/**
* Unit tests for GetUserSessionsFunctionImpl class.
*/
@WithCarbonHome
@WithRealmService(injectToSingletons = {UserFunctionsServiceHolder.class, IdentityTenantUtil.class,
FrameworkServiceDataHolder.class})
public class GetUserSessionsFunctionImplTest {

private static final String TEST_USER_NAME = "testUser";
private static final String TENANT_DOMAIN_CARBON_SUPER = "carbon.super";
private static final String USER_STORE_DOMAIN_PRIMARY = "PRIMARY";
private static final String TEST_USER_ID_123 = "test-user-id-123";
private static final String TEST_USER_ID_456 = "test-user-id-456";
private static final String TEST_USER_ID_ORG_123 = "test-user-id-org-123";
private static final String TEST_USER_ID_ORG_456 = "test-user-id-org-456";
private static final String ORG_ID_123 = "org123";
private static final String ORG_TENANT_DOMAIN = "org.tenant.com";
private static final String INVALID_ORG = "invalidOrg";
private static final String ORG_NOT_FOUND_MESSAGE = "Organization not found";

@Mock
private UserSessionManagementService userSessionManagementService;
@Mock
private OrganizationManager organizationManager;
private GetUserSessionsFunctionImpl getUserSessionsFunction;

@BeforeMethod
public void setUp() {

initMocks(this);
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(TENANT_DOMAIN_CARBON_SUPER, true);

getUserSessionsFunction = new GetUserSessionsFunctionImpl();
UserFunctionsServiceHolder.getInstance().setUserSessionManagementService(userSessionManagementService);
UserFunctionsServiceHolder.getInstance().setOrganizationManager(organizationManager);
}

@AfterMethod
public void tearDown() {

PrivilegedCarbonContext.destroyCurrentContext();
}

@Test
public void testGetUserSessionsSuccess() throws Exception {

// Create test user.
AuthenticatedUser authenticatedUser = new AuthenticatedUser();
authenticatedUser.setUserName(TEST_USER_NAME);
authenticatedUser.setTenantDomain(TENANT_DOMAIN_CARBON_SUPER);
authenticatedUser.setUserStoreDomain(USER_STORE_DOMAIN_PRIMARY);
authenticatedUser.setUserId(TEST_USER_ID_123);

JsAuthenticatedUser jsUser = new JsGraalAuthenticatedUser(authenticatedUser);

// Create mock user sessions.
List<UserSession> mockSessions = new ArrayList<>();
UserSession session1 = mock(UserSession.class);
UserSession session2 = mock(UserSession.class);
mockSessions.add(session1);
mockSessions.add(session2);

// Mock the session management service.
when(userSessionManagementService.getSessionsByUserId(TEST_USER_ID_123, TENANT_DOMAIN_CARBON_SUPER))
.thenReturn(mockSessions);

// Execute the function.
List<JsUserSession> result = getUserSessionsFunction.getUserSessions(jsUser);

// Verify results.
Assert.assertNotNull(result);
Assert.assertEquals(result.size(), 2);
}

@Test
public void testGetUserSessionsWithEmptyResult() throws Exception {

// Create test user.
AuthenticatedUser authenticatedUser = new AuthenticatedUser();
authenticatedUser.setUserName(TEST_USER_NAME);
authenticatedUser.setTenantDomain(TENANT_DOMAIN_CARBON_SUPER);
authenticatedUser.setUserStoreDomain(USER_STORE_DOMAIN_PRIMARY);
authenticatedUser.setUserId(TEST_USER_ID_456);

JsAuthenticatedUser jsUser = new JsGraalAuthenticatedUser(authenticatedUser);

// Mock empty session list.
when(userSessionManagementService.getSessionsByUserId(TEST_USER_ID_456, TENANT_DOMAIN_CARBON_SUPER))
.thenReturn(new ArrayList<>());

// Execute the function.
List<JsUserSession> result = getUserSessionsFunction.getUserSessions(jsUser);

// Verify results.
Assert.assertNotNull(result);
Assert.assertEquals(result.size(), 0);
}

@Test
public void testGetUserSessionsWithOrganization() throws Exception {

// Create test user with accessing organization.
AuthenticatedUser authenticatedUser = new AuthenticatedUser();
authenticatedUser.setUserName(TEST_USER_NAME);
authenticatedUser.setTenantDomain(TENANT_DOMAIN_CARBON_SUPER);
authenticatedUser.setUserStoreDomain(USER_STORE_DOMAIN_PRIMARY);
authenticatedUser.setUserId(TEST_USER_ID_ORG_123);
authenticatedUser.setAccessingOrganization(ORG_ID_123);

JsAuthenticatedUser jsUser = new JsGraalAuthenticatedUser(authenticatedUser);

// Mock organization manager.
when(organizationManager.resolveTenantDomain(ORG_ID_123)).thenReturn(ORG_TENANT_DOMAIN);

// Create mock user sessions
List<UserSession> mockSessions = new ArrayList<>();
UserSession session = mock(UserSession.class);
mockSessions.add(session);

// Mock the session management service with resolved tenant domain.
when(userSessionManagementService.getSessionsByUserId(TEST_USER_ID_ORG_123, ORG_TENANT_DOMAIN))
.thenReturn(mockSessions);

// Execute the function.
List<JsUserSession> result = getUserSessionsFunction.getUserSessions(jsUser);

// Verify results.
Assert.assertNotNull(result);
Assert.assertEquals(result.size(), 1);
}

@Test
public void testGetUserSessionsWithOrganizationManagementException() throws Exception {

// Create test user with accessing organization.
AuthenticatedUser authenticatedUser = new AuthenticatedUser();
authenticatedUser.setUserName(TEST_USER_NAME);
authenticatedUser.setTenantDomain(TENANT_DOMAIN_CARBON_SUPER);
authenticatedUser.setUserStoreDomain(USER_STORE_DOMAIN_PRIMARY);
authenticatedUser.setUserId(TEST_USER_ID_ORG_456);
authenticatedUser.setAccessingOrganization(INVALID_ORG);

JsAuthenticatedUser jsUser = new JsGraalAuthenticatedUser(authenticatedUser);

// Mock organization manager to throw exception.
when(organizationManager.resolveTenantDomain(INVALID_ORG))
.thenThrow(new OrganizationManagementException(ORG_NOT_FOUND_MESSAGE));

// Execute the function.
List<JsUserSession> result = getUserSessionsFunction.getUserSessions(jsUser);
Assert.assertNull(result);
}
}
13 changes: 7 additions & 6 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,11 @@
<artifactId>nimbus-jose-jwt</artifactId>
<version>${nimbusds.version}</version>
</dependency>
<dependency>
<groupId>org.wso2.carbon.identity.organization.management.core</groupId>
<artifactId>org.wso2.carbon.identity.organization.management.service</artifactId>
<version>${identity.organization.management.core.version}</version>
</dependency>

<dependency>
<groupId>org.jacoco</groupId>
Expand Down Expand Up @@ -321,12 +326,6 @@
<artifactId>org.wso2.carbon.crypto.impl</artifactId>
<version>${carbon.crypto.version}</version>
</dependency>
<dependency>
<groupId>org.wso2.carbon.identity.organization.management.core</groupId>
<artifactId>org.wso2.carbon.identity.organization.management.service</artifactId>
<version>${identity.organization.management.core.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
Expand Down Expand Up @@ -530,6 +529,8 @@
<carbon.user.package.import.version.range>[1.0.1, 2.0.0)</carbon.user.package.import.version.range>
<carbon.identity.framework.version>7.7.34</carbon.identity.framework.version>
<identity.organization.management.core.version>1.0.89</identity.organization.management.core.version>
<org.wso2.carbon.identity.organization.management.core.version.range>[1.0.0, 2.0.0)
</org.wso2.carbon.identity.organization.management.core.version.range>
<carbon.identity.framework.testutils.version>5.20.447</carbon.identity.framework.testutils.version>
<carbon.identity.package.import.version.range>[5.14.0, 8.0.0)</carbon.identity.package.import.version.range>
<identity.governance.version>1.1.17</identity.governance.version>
Expand Down