Skip to content

Commit

Permalink
Add unit tests for PasswordExpiryEventListener
Browse files Browse the repository at this point in the history
  • Loading branch information
PasinduYeshan committed Dec 9, 2024
1 parent a44564e commit 8e378b5
Show file tree
Hide file tree
Showing 4 changed files with 246 additions and 38 deletions.
5 changes: 5 additions & 0 deletions components/org.wso2.carbon.identity.password.expiry/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@
<artifactId>mockito-inline</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.identity.framework</groupId>
<artifactId>org.wso2.carbon.identity.testutil</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.identity.organization.management.core</groupId>
<artifactId>org.wso2.carbon.identity.organization.management.service</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -288,17 +288,17 @@ public void testIsPasswordExpiredWithoutRules(Integer daysAgo, boolean expectedE
public Object[][] passwordExpiryTestCases() {
return new Object[][] {
// {daysAgo, roles, groups, skipIfNoApplicableRules, expectedExpired, description}.
{55, new String[]{ROLE_MAP.get("employee"), ROLE_MAP.get("manager")}, new String[]{}, false, false,
{55, new String[]{"employee", "manager"}, new String[]{}, false, false,
"Not expired: 3rd rule (60) applies"},
{55, new String[]{ROLE_MAP.get("employee"), ROLE_MAP.get("manager"), ROLE_MAP.get("contractor")},
{55, new String[]{"employee", "manager", "contractor"},
new String[]{}, false, true, "Expired: 2nd rule (40) applies"},
{35, new String[]{ROLE_MAP.get("employee"), ROLE_MAP.get("contractor")}, new String[]{}, false, false,
{35, new String[]{"employee", "contractor"}, new String[]{}, false, false,
"Not expired: 2nd rule (40) applies"},
{35, new String[]{ROLE_MAP.get("employee"), ROLE_MAP.get("contractor")}, new String[]{"admin"}, false,
{35, new String[]{"employee", "contractor"}, new String[]{"admin"}, false,
false, "Not expired: 1st rule (skip) applies."},
{35, new String[]{ROLE_MAP.get("employee")}, new String[]{}, false, true,
{35, new String[]{"employee"}, new String[]{}, false, true,
"Expired: Default expiry policy applies."},
{35, new String[]{ROLE_MAP.get("employee")}, new String[]{}, true, false,
{35, new String[]{"employee"}, new String[]{}, true, false,
"Not expired: Default expiry policy applies - skip if no rules applicable."},
};
}
Expand All @@ -319,13 +319,7 @@ public void testIsPasswordExpiredWithRules(int daysAgo, String[] roles, String[]

mockPasswordExpiryEnabled(identityGovernanceService, PasswordPolicyConstants.TRUE);

List<Group> userGroups = new ArrayList<>();
Arrays.stream(groups).forEach(groupName -> {
Group groupObj = new Group();
groupObj.setGroupID(GROUP_MAP.get(groupName));
userGroups.add(groupObj);
});
when(abstractUserStoreManager.getGroupListOfUser(userId, null, null)).thenReturn(userGroups);
when(abstractUserStoreManager.getGroupListOfUser(userId, null, null)).thenReturn(getGroups(groups));

// Mock last password update time.
Long updateTime = getUpdateTime(daysAgo);
Expand Down Expand Up @@ -363,7 +357,8 @@ public Object[][] passwordExpiryTimeTestCases() {
@Test(dataProvider = "passwordExpiryTimeTestCases")
public void testGetUserPasswordExpiryTime(Integer daysAgo, String[] roles, String[] groups, Integer expiryDays,
String description)
throws IdentityGovernanceException, UserStoreException, PostAuthenticationFailedException {
throws IdentityGovernanceException, UserStoreException, PostAuthenticationFailedException,
IdentityRoleManagementException {

when(IdentityTenantUtil.getTenantId(anyString())).thenReturn(3);
when(realmService.getTenantUserRealm(anyInt())).thenReturn(userRealm);
Expand Down Expand Up @@ -391,8 +386,12 @@ public void testGetUserPasswordExpiryTime(Integer daysAgo, String[] roles, Strin
new String[]{PasswordPolicyConstants.CONNECTOR_CONFIG_SKIP_IF_NO_APPLICABLE_RULES},
tenantDomain)).thenReturn(getSkipIfNoRulesApplicableProperty(PasswordPolicyConstants.FALSE));

List<String> roleIds = Arrays.stream(roles).map(ROLE_MAP::get).collect(Collectors.toList());
List<String> groupIds = Arrays.stream(groups).map(GROUP_MAP::get).collect(Collectors.toList());
// Mock user roles.
when(roleManagementService.getRoleListOfUser(userId, tenantDomain)).thenReturn(getRoles(roles));

// Mock user groups.
when(abstractUserStoreManager.getGroupListOfUser(userId, null, null))
.thenReturn(getGroups(groups));

long testStartTime = System.currentTimeMillis();
Optional<Long> expiryTime =
Expand All @@ -417,9 +416,9 @@ public void testGetUserPasswordExpiryTime()
throws IdentityGovernanceException, UserStoreException, PostAuthenticationFailedException {

// Case 1: Password expiry disabled.
mockPasswordExpiryEnabled(identityGovernanceService, PasswordPolicyConstants.FALSE);
Optional<Long> expiryTime =
PasswordPolicyUtils.getUserPasswordExpiryTime(tenantDomain, tenantAwareUsername);
Optional<Long> expiryTime = PasswordPolicyUtils.getUserPasswordExpiryTime(
tenantDomain, tenantAwareUsername, false, null,
null, null);
Assert.assertFalse(expiryTime.isPresent());

// Case 2: Password expiry enabled, but no rules.
Expand All @@ -435,20 +434,9 @@ public void testGetUserPasswordExpiryTime()
Long updateTime = System.currentTimeMillis() - getDaysTimeInMillis(20);
mockLastPasswordUpdateTime(updateTime, abstractUserStoreManager);

// Mock empty password expiry rules.
ConnectorConfig connectorConfig = new ConnectorConfig();
connectorConfig.setProperties( new Property[0]);
when(identityGovernanceService.getConnectorWithConfigs(tenantDomain,
PasswordPolicyConstants.CONNECTOR_CONFIG_NAME)).thenReturn(connectorConfig);

when(identityGovernanceService.getConfiguration(
new String[]{PasswordPolicyConstants.CONNECTOR_CONFIG_PASSWORD_EXPIRY_IN_DAYS},
tenantDomain)).thenReturn(getPasswordExpiryInDaysProperty());
when(identityGovernanceService.getConfiguration(
new String[]{PasswordPolicyConstants.CONNECTOR_CONFIG_SKIP_IF_NO_APPLICABLE_RULES},
tenantDomain)).thenReturn(getSkipIfNoRulesApplicableProperty(PasswordPolicyConstants.FALSE));

expiryTime = PasswordPolicyUtils.getUserPasswordExpiryTime(tenantDomain, tenantAwareUsername);
expiryTime = PasswordPolicyUtils.getUserPasswordExpiryTime(
tenantDomain, tenantAwareUsername, true, false,
Collections.emptyList(), DEFAULT_EXPIRY_DAYS);

long expectedExpiryTime = updateTime + getDaysTimeInMillis(DEFAULT_EXPIRY_DAYS);
Assert.assertTrue(Math.abs(expiryTime.get() - expectedExpiryTime) <= TIME_TOLERANCE_MS);
Expand All @@ -458,14 +446,18 @@ public void testGetUserPasswordExpiryTime()
new String[]{PasswordPolicyConstants.CONNECTOR_CONFIG_SKIP_IF_NO_APPLICABLE_RULES},
tenantDomain)).thenReturn(getSkipIfNoRulesApplicableProperty(PasswordPolicyConstants.TRUE));

expiryTime = PasswordPolicyUtils.getUserPasswordExpiryTime(tenantDomain, tenantAwareUsername);
expiryTime = PasswordPolicyUtils.getUserPasswordExpiryTime(tenantDomain, tenantAwareUsername,
true, true, Collections.emptyList(),
DEFAULT_EXPIRY_DAYS);
Assert.assertFalse(expiryTime.isPresent());

// Case 4: UserStoreException.
when(abstractUserStoreManager.getUserIDFromUserName(tenantAwareUsername)).thenThrow(
new org.wso2.carbon.user.core.UserStoreException());
try {
PasswordPolicyUtils.getUserPasswordExpiryTime(tenantDomain, tenantAwareUsername);
PasswordPolicyUtils.getUserPasswordExpiryTime(tenantDomain, tenantAwareUsername,
true, true, Collections.emptyList(),
DEFAULT_EXPIRY_DAYS);
Assert.fail("Expected PostAuthenticationFailedException was not thrown");
} catch (Exception e) {
Assert.assertTrue(e instanceof PostAuthenticationFailedException);
Expand Down Expand Up @@ -538,17 +530,28 @@ private static Long getUpdateTime(Integer daysAgo) {
return daysAgo != null ? System.currentTimeMillis() - getDaysTimeInMillis(daysAgo) : null;
}

private List<RoleBasicInfo> getRoles(String[] roleIds) {
private List<RoleBasicInfo> getRoles(String[] roleNames) {

List<RoleBasicInfo> userRoles = new ArrayList<>();
for (String roleId : roleIds) {
for (String roleId : roleNames) {
RoleBasicInfo roleInfo = new RoleBasicInfo();
roleInfo.setId(roleId);
roleInfo.setId(ROLE_MAP.get(roleId));
userRoles.add(roleInfo);
}
return userRoles;
}

private static List<Group> getGroups(String[] groupNames) {

List<Group> userGroups = new ArrayList<>();
Arrays.stream(groupNames).forEach(groupName -> {
Group groupObj = new Group();
groupObj.setGroupID(GROUP_MAP.get(groupName));
userGroups.add(groupObj);
});
return userGroups;
}

private Property[] getPasswordExpiryRulesProperties() {

Property expiryRule1 = new Property();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
/*
* Copyright (c) 2024, 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.password.expiry.listener;

import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.identity.application.authentication.framework.exception.PostAuthenticationFailedException;
import org.wso2.carbon.identity.password.expiry.constants.PasswordPolicyConstants;
import org.wso2.carbon.identity.password.expiry.util.PasswordPolicyUtils;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.MockitoAnnotations;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import org.wso2.carbon.identity.common.testng.WithCarbonHome;
import org.wso2.carbon.user.core.UserStoreException;
import org.wso2.carbon.user.core.UserStoreManager;
import org.wso2.carbon.user.core.model.UserClaimSearchEntry;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.when;

/**
* Unit test cases for PasswordExpiryEventListener.
*/
@WithCarbonHome
public class PasswordExpiryEventListenerTest {

private static final String TENANT_DOMAIN = "test.com";
private PasswordExpiryEventListener passwordExpiryEventListener;

@Mock
PrivilegedCarbonContext privilegedCarbonContext;
@Mock
UserStoreManager userStoreManager;

private MockedStatic<PrivilegedCarbonContext> mockedPrivilegedCarbonContext;
private MockedStatic<PasswordPolicyUtils> mockedPasswordPolicyUtils;

@BeforeMethod
public void setUp() {

MockitoAnnotations.openMocks(this);
passwordExpiryEventListener = new PasswordExpiryEventListener();

mockedPrivilegedCarbonContext.when(PrivilegedCarbonContext::getThreadLocalCarbonContext)
.thenReturn(privilegedCarbonContext);

when(privilegedCarbonContext.getTenantDomain()).thenReturn(TENANT_DOMAIN);
}

@BeforeClass
public void init() {

mockedPrivilegedCarbonContext = mockStatic(PrivilegedCarbonContext.class);
mockedPasswordPolicyUtils = mockStatic(PasswordPolicyUtils.class);
}

@AfterClass
public void close() {

mockedPrivilegedCarbonContext.close();
mockedPasswordPolicyUtils.close();
}

@Test
public void testGetExecutionOrderId() {

Assert.assertEquals(passwordExpiryEventListener.getExecutionOrderId(), 99); // TODO: Change the order id accordingly.
}

@Test
public void testDoPostGetUserClaimValuesWithPasswordExpiryClaim() throws UserStoreException {

String username = "testUser";
String[] claims;
Map<String, String> claimMap = new HashMap<>();
String profileName = "default";

// Case 1: When claims contains PASSWORD_EXPIRY_TIME_CLAIM.
claims = new String[]{PasswordPolicyConstants.PASSWORD_EXPIRY_TIME_CLAIM};

mockedPasswordPolicyUtils.when(() -> PasswordPolicyUtils.getUserPasswordExpiryTime(
eq(TENANT_DOMAIN), eq(username))).thenReturn(Optional.of(1000L));

passwordExpiryEventListener.doPostGetUserClaimValues(username, claims, profileName, claimMap, userStoreManager);
Assert.assertNotNull(claimMap.get(PasswordPolicyConstants.PASSWORD_EXPIRY_TIME_CLAIM));

// Case 2: PostAuthenticationFailedException is thrown.
mockedPasswordPolicyUtils.when(() ->
PasswordPolicyUtils.getUserPasswordExpiryTime(eq(TENANT_DOMAIN), eq(username)))
.thenThrow(new PostAuthenticationFailedException("test-error", "test-error"));
try {
passwordExpiryEventListener.doPostGetUserClaimValues(username, claims, profileName, claimMap, userStoreManager);
} catch (Exception e) {
Assert.assertTrue(e instanceof UserStoreException);
}
}

@Test
public void testDoPostGetUserClaimValuesWithoutPasswordExpiryClaim() throws UserStoreException {

String username = "testUser";
String[] claims;
Map<String, String> claimMap = new HashMap<>();
String profileName = "default";
claims = new String[]{"claim1", "claim2"};

passwordExpiryEventListener.doPostGetUserClaimValues(username, claims, profileName, claimMap, userStoreManager);
Assert.assertFalse(claimMap.containsKey(PasswordPolicyConstants.PASSWORD_EXPIRY_TIME_CLAIM));
}

@Test
public void testDoPostGetUsersClaimValuesWithPasswordExpiryClaim() throws UserStoreException {

String[] userNames = new String[]{"testUser1", "testUser2"};
String[] claims = new String[]{PasswordPolicyConstants.PASSWORD_EXPIRY_TIME_CLAIM};
String profileName = "default";

UserClaimSearchEntry[] userClaimSearchEntries = new UserClaimSearchEntry[2];
userClaimSearchEntries[0] = new UserClaimSearchEntry();
userClaimSearchEntries[0].setUserName("testUser1");
userClaimSearchEntries[1] = new UserClaimSearchEntry();
userClaimSearchEntries[1].setUserName("testUser1");

mockedPasswordPolicyUtils.when(() ->
PasswordPolicyUtils.isPasswordExpiryEnabled(TENANT_DOMAIN)).thenReturn(true);
mockedPasswordPolicyUtils.when(() ->
PasswordPolicyUtils.isSkipIfNoApplicableRulesEnabled(TENANT_DOMAIN)).thenReturn(false);
mockedPasswordPolicyUtils.when(() ->
PasswordPolicyUtils.getPasswordExpiryInDays(TENANT_DOMAIN)).thenReturn(30);
mockedPasswordPolicyUtils.when(() ->
PasswordPolicyUtils.getPasswordExpiryRules(TENANT_DOMAIN)).thenReturn(Collections.emptyList());
mockedPasswordPolicyUtils.when(() -> PasswordPolicyUtils.getUserPasswordExpiryTime(
eq(TENANT_DOMAIN), anyString(), eq(true), eq(false), any(), eq(30)))
.thenReturn(Optional.of(1000L));

passwordExpiryEventListener.doPostGetUsersClaimValues(userNames, claims, profileName, userClaimSearchEntries);
Assert.assertNotNull(
userClaimSearchEntries[0].getClaims().get(PasswordPolicyConstants.PASSWORD_EXPIRY_TIME_CLAIM));
Assert.assertNotNull(
userClaimSearchEntries[1].getClaims().get(PasswordPolicyConstants.PASSWORD_EXPIRY_TIME_CLAIM));

// Case 2: PostAuthenticationFailedException is thrown.
mockedPasswordPolicyUtils.when(() -> PasswordPolicyUtils.getUserPasswordExpiryTime(
eq(TENANT_DOMAIN), anyString(), eq(true), eq(false), any(), eq(30)))
.thenThrow(new PostAuthenticationFailedException("test-error", "test-error"));
try {
passwordExpiryEventListener.doPostGetUsersClaimValues(userNames, claims,
profileName, userClaimSearchEntries);
} catch (Exception e) {
Assert.assertTrue(e instanceof UserStoreException);
}
}

@Test
public void testDoPostGetUsersClaimValuesWithoutPasswordExpiryClaims() throws UserStoreException {

String[] userNames = new String[]{"testUser1", "testUser2"};
String[] claims = new String[]{"claim1", "claim2"};
String profileName = "default";

UserClaimSearchEntry[] userClaimSearchEntries = new UserClaimSearchEntry[2];
userClaimSearchEntries[0] = new UserClaimSearchEntry();
userClaimSearchEntries[0].setUserName("testUser1");
userClaimSearchEntries[1] = new UserClaimSearchEntry();
userClaimSearchEntries[1].setUserName("testUser1");

passwordExpiryEventListener.doPostGetUsersClaimValues(userNames, claims, profileName, userClaimSearchEntries);
Assert.assertNull(userClaimSearchEntries[0].getClaims());
Assert.assertNull(userClaimSearchEntries[1].getClaims());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<classes>
<class name="org.wso2.carbon.identity.password.expiry.PasswordResetEnforcerHandlerTest"/>
<class name="org.wso2.carbon.identity.password.expiry.PasswordPolicyUtilsTest"/>
<class name="org.wso2.carbon.identity.password.expiry.listener.PasswordExpiryEventListenerTest"/>
<class name="org.wso2.carbon.identity.password.expiry.PasswordChangeHandler"/>
<class name="org.wso2.carbon.identity.password.expiry.PasswordExpiryConfigImplTest"/>
</classes>
Expand Down

0 comments on commit 8e378b5

Please sign in to comment.