Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve getUserCountByRole() Method #3951

Merged
merged 13 commits into from
Apr 5, 2024
Merged
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
/*
* Copyright (c) (2005-2021), WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
* Copyright (c) 2005-2024, WSO2 LLC. (http://www.wso2.com).
*
* WSO2 Inc. 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
* 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
* 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
Expand Down Expand Up @@ -9479,14 +9479,13 @@ protected List<User> doGetUserListOfRoleWithID(String roleName, String filter) t
}

/**
* Return the count of users belong to the given role for the given filter.
* Return the count of users belong to the given role for the given filter when unique id feature is not enabled.
*
* @param roleName role name.
* @param filter filter.
* @return user count for the given role.
* @throws UserStoreException Thrown by the underlying UserStoreManager.
*/
protected int doGetUserCountOfRole(String roleName, String filter) throws UserStoreException {
protected int doGetUserCountOfRole(String roleName) throws UserStoreException {
dhaura marked this conversation as resolved.
Show resolved Hide resolved

if (log.isDebugEnabled()) {
log.debug("doGetUserCountOfRole operation is not implemented in: " + this.getClass());
Expand All @@ -9495,6 +9494,22 @@ protected int doGetUserCountOfRole(String roleName, String filter) throws UserSt
"doGetUserCountOfRole operation is not implemented in: " + this.getClass());
}

/**
* Return the count of users belong to the given role for the given filter.
dhaura marked this conversation as resolved.
Show resolved Hide resolved
*
* @param roleName role name.
* @return user count for the given role.
* @throws UserStoreException Thrown by the underlying UserStoreManager.
*/
protected int doGetUserCountOfRoleWithID(String roleName) throws UserStoreException {

if (log.isDebugEnabled()) {
log.debug("doGetUserCountOfRoleWithID operation is not implemented in: " + this.getClass());
}
throw new NotImplementedException(
"doGetUserCountOfRoleWithID operation is not implemented in: " + this.getClass());
}

/**
* Return the list of users belong to the given role for the given filter.
*
Expand Down Expand Up @@ -19198,33 +19213,69 @@ public UserUniqueIDDomainResolver getUserUniqueIDDomainResolver() {
return userUniqueIDDomainResolver;
}

public int getUserCountForRole(String roleName) throws UserStoreException {
/**
* Retrieves the user count that belongs to a given role.
*
* @param roleName Name of the role.
* @return User count of the given role.
* @throws UserStoreException If an unexpected error occurs while accessing user store.
*/
public int getUserCountForRole(String roleName) throws UserStoreException {

int count = 0;
if (!isSecureCall.get()) {
Class argTypes[] = new Class[] { String.class, String.class };
Object object = callSecure("getUserCountByRole", new Object[] { roleName, QUERY_FILTER_STRING_ANY }, argTypes);
Class argTypes[] = new Class[] { String.class };
Object object = callSecure("getUserCountForRole", new Object[] { roleName }, argTypes);
return (int) object;
}

return getUserCountByRole(roleName, QUERY_FILTER_STRING_ANY);
}
// If role does not exit, just return.
if (!isExistingRole(roleName)) {
return count;
}

public int getUserCountByRole(String roleName, String filter) throws UserStoreException {
UserStore userStore = getUserStoreOfRoles(roleName);

int count = 0;
if (!isSecureCall.get()) {
Class argTypes[] = new Class[] { String.class, String.class };
Object object = callSecure("getUserCountByRole", new Object[] { roleName, filter }, argTypes);
return (int) object;
if (userStore.isRecurssive()) {
UserStoreManager resolvedUserStoreManager = userStore.getUserStoreManager();
if (resolvedUserStoreManager instanceof AbstractUserStoreManager) {
return ((AbstractUserStoreManager) resolvedUserStoreManager)
.getUserCountForRole(userStore.getDomainFreeName());
}
}

// If role does not exit, just return.
if (!isExistingRole(roleName)) {
// #################### Domain Name Free Zone Starts Here ################################

if (userStore.isHybridRole()) {
if (UserCoreConstants.INTERNAL_DOMAIN.equalsIgnoreCase(userStore.getDomainName())) {
count += hybridRoleManager.getUserCountOfHybridRole(userStore.getDomainFreeName());
} else {
count += hybridRoleManager.getUserCountOfHybridRole(userStore.getDomainAwareName());
}

// Get the user count of associated groups of the role.
if (isRoleAndGroupSeparationEnabled()) {
String[] groupsOfRole;
if (UserCoreConstants.INTERNAL_DOMAIN.equalsIgnoreCase(userStore.getDomainName())) {
groupsOfRole = hybridRoleManager.getGroupListOfHybridRole(userStore.getDomainFreeName());
} else {
groupsOfRole = hybridRoleManager.getGroupListOfHybridRole(userStore.getDomainAwareName());
}
for (String group : groupsOfRole) {
count += getUserCountForRole(group);
}
}

return count;
}

if (readGroupsEnabled) {
count += doGetUserCountOfRole(roleName, filter);
// If unique id feature is not enabled, we have to call the legacy methods.
if (!isUniqueUserIdEnabledInUserStore(userStore)) {
count += doGetUserCountOfRole(roleName);
} else {
count += doGetUserCountOfRoleWithID(roleName);
}
}

return count;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,9 @@ public class HybridJDBCConstants {
public static final String GET_USER_LIST_OF_ROLE_SQL = "SELECT UM_USER_NAME, UM_DOMAIN_NAME FROM UM_HYBRID_USER_ROLE, UM_DOMAIN WHERE " +
"UM_ROLE_ID=(SELECT UM_ID FROM UM_HYBRID_ROLE WHERE UM_ROLE_NAME=? AND UM_TENANT_ID=?) AND UM_HYBRID_USER_ROLE.UM_TENANT_ID=? " +
"AND UM_HYBRID_USER_ROLE.UM_DOMAIN_ID=UM_DOMAIN.UM_DOMAIN_ID";
public static final String GET_USER_COUNT_OF_ROLE_SQL = "SELECT COUNT(UM_ID) FROM UM_HYBRID_USER_ROLE, UM_DOMAIN "
+ "WHERE UM_ROLE_ID=(SELECT UM_ID FROM UM_HYBRID_ROLE WHERE UM_ROLE_NAME=? AND UM_TENANT_ID=?) "
+ "AND UM_HYBRID_USER_ROLE.UM_TENANT_ID=? AND UM_HYBRID_USER_ROLE.UM_DOMAIN_ID=UM_DOMAIN.UM_DOMAIN_ID";

public static final String GET_GROUP_LIST_OF_ROLE_SQL =
"SELECT UM_GROUP_NAME, UM_DOMAIN_NAME FROM UM_HYBRID_GROUP_ROLE, UM_DOMAIN WHERE "
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1551,4 +1551,35 @@ private boolean isTableExists(String tableName) {
}
return false;
}

/**
* Retrieve the number of users assigned to a role.
*
* @param roleName Given role.
* @return Number of users assigned to the given role.
* @throws UserStoreException An unexpected exception has occurred.
*/
public int getUserCountOfHybridRole(String roleName) throws UserStoreException {

if (UserCoreUtil.isEveryoneRole(roleName, realmConfig)) {
return userRealm.getUserStoreManager().listUsers("*", -1).length;
}

// ########### Domain-less Roles and Domain-aware Users from here onwards #############

String sqlStmt = HybridJDBCConstants.GET_USER_COUNT_OF_ROLE_SQL;
Connection dbConnection = null;
try {
dbConnection = DatabaseUtil.getDBConnection(dataSource);
return DatabaseUtil.getIntegerValueFromDatabase(dbConnection, sqlStmt, roleName, tenantId, tenantId);
} catch (SQLException e) {
String errorMessage = "Error occurred while getting user count from hybrid role : " + roleName;
if (log.isDebugEnabled()) {
log.debug(errorMessage, e);
}
throw new UserStoreException(errorMessage, e);
} finally {
DatabaseUtil.closeAllConnections(dbConnection);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
/*
* Copyright (c) 2005-2010, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
* Copyright (c) 2005-2024, WSO2 LLC. (http://www.wso2.com).
*
* WSO2 Inc. 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
* 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
* 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
Expand Down Expand Up @@ -57,6 +57,7 @@ public final class JDBCRealmConstants {
public static final String GET_USERS_IN_ROLE_FILTER = "GetUserListOfRoleFilterSQL";
public static final String GET_USERS_IN_ROLE_FILTER_WITH_ID = "GetUserListOfRoleFilterWithIDSQL";
public static final String GET_USERS_COUNT_WITH_FILTER_ROLE = "GetUserCountWithFilterRoleSQL";
public static final String GET_USERS_COUNT_WITH_FILTER_ROLE_WITH_ID = "GetUserCountWithFilterRoleWithIDSQL";
public static final String GET_USERS_IN_SHARED_ROLE = "GetUserListOfSharedRoleSQL";
public static final String GET_USERS_IN_SHARED_ROLE_FILTER = "GetUserListOfSharedRoleFilterSQL";
public static final String GET_USERS_IN_SHARED_ROLE_FILTER_WITH_ID = "GetUserListOfSharedRoleFilterWithIDSQL";
Expand Down Expand Up @@ -270,7 +271,11 @@ public final class JDBCRealmConstants {
+ "UM_ROLE.UM_ID=UM_USER_ROLE.UM_ROLE_ID AND UM_USER_ROLE.UM_TENANT_ID=? AND UM_ROLE"
+ ".UM_TENANT_ID=? AND UM_USER.UM_TENANT_ID=?";

public static final String GET_USERS_COUNT_WITH_FILTER_ROLE_SQL = "SELECT count(UM_ID) FROM UM_USER_ROLE " +
public static final String GET_USERS_COUNT_WITH_FILTER_ROLE_SQL = "SELECT COUNT(UM_USER_NAME) FROM " +
"UM_USER_ROLE, UM_ROLE, UM_USER WHERE UM_ROLE.UM_ROLE_NAME=? AND UM_USER.UM_ID=UM_USER_ROLE.UM_USER_ID " +
"AND UM_ROLE.UM_ID=UM_USER_ROLE.UM_ROLE_ID AND UM_USER_ROLE.UM_TENANT_ID=? AND UM_ROLE.UM_TENANT_ID=? " +
"AND UM_USER.UM_TENANT_ID=?";
public static final String GET_USERS_COUNT_WITH_FILTER_ROLE_SQL_WITH_ID = "SELECT COUNT(UM_ID) FROM UM_USER_ROLE " +
"WHERE UM_ROLE_ID = ? AND UM_TENANT_ID = ?";

public static final String GET_ROLE_ID_BY_NAME_SQL = "SELECT UM_ID FROM UM_ROLE " +
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
/*
z * Copyright 2005-2007 WSO2, Inc. (http://wso2.com)
* Copyright (c) 2005-2024, WSO2 LLC. (http://www.wso2.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the 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
*
* 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"//also need to clear role authorization
userRealm.getAuthorizationManager().cle 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.
* 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.user.core.jdbc;
Expand Down Expand Up @@ -851,6 +852,13 @@ public String[] doGetUserListOfRole(String roleName, String filter) throws UserS
return getUserListOfJDBCRole(roleContext, filter);
}

@Override
public int doGetUserCountOfRole(String roleName) throws UserStoreException {

RoleContext roleContext = createRoleContext(roleName);
return getUserCountByRole(roleContext);
}

/**
*
*/
Expand Down Expand Up @@ -934,6 +942,33 @@ public String[] getUserListOfJDBCRole(RoleContext ctx, String filter, int maxIte
return names;
}

/**
* Return the count of users belong to the given role for the given {@link RoleContext} and filter.
*
* @param ctx {@link RoleContext} corresponding to the role.
* @throws UserStoreException If an unexpected error occurs.
*/
public int getUserCountByRole(RoleContext ctx) throws UserStoreException {

String roleName = ctx.getRoleName();
Connection dbConnection = null;
String sqlStmt = realmConfig.getUserStoreProperty(JDBCRealmConstants.GET_USERS_COUNT_WITH_FILTER_ROLE);
try {
dhaura marked this conversation as resolved.
Show resolved Hide resolved
dbConnection = getDBConnection();
return DatabaseUtil.getIntegerValueFromDatabase(
dbConnection, sqlStmt, roleName,tenantId, tenantId, tenantId);
} catch (SQLException e) {
String errorMessage =
"Error occurred while getting the count of users in the role : " + roleName;
if (log.isDebugEnabled()) {
log.debug(errorMessage, e);
}
throw new UserStoreException(errorMessage, e);
} finally {
DatabaseUtil.closeAllConnections(dbConnection);
}
}

/**
*
*/
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-2024, 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 @@ -11,7 +11,7 @@
* 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
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
Expand Down Expand Up @@ -352,11 +352,17 @@ public List<User> doGetUserListOfRoleWithID(String roleName, String filter) thro
}

@Override
public int doGetUserCountOfRole(String roleName, String filter)
public int doGetUserCountOfRole(String roleName) throws UserStoreException {

throw new UserStoreException("Operation is not supported.");
}

@Override
public int doGetUserCountOfRoleWithID(String roleName)
throws UserStoreException {

RoleContext roleContext = createRoleContext(roleName);
return getUserCountByRole(roleContext, filter);
return getUserCountByRole(roleContext);
}

public List<User> getUserListOfJDBCRoleWithID(RoleContext ctx, String filter) throws UserStoreException {
Expand Down Expand Up @@ -429,39 +435,17 @@ public List<User> getUserListOfJDBCRoleWithID(RoleContext ctx, String filter, in
* Return the count of users belong to the given role for the given {@link RoleContext} and filter.
*
* @param ctx {@link RoleContext} corresponding to the role.
* @param filter String filter for the users.
* @throws UserStoreException If an unexpected error occurs while accessing user store.
*/
public int getUserCountByRole(RoleContext ctx, String filter) throws UserStoreException {
public int getUserCountByRole(RoleContext ctx) throws UserStoreException {

String roleName = ctx.getRoleName();

if (StringUtils.isNotEmpty(filter)) {
filter = filter.trim();
filter = filter.replace("*", "%");
filter = filter.replace("?", "_");
} else {
filter = "%";
}
return getUserCountByRoleFromDatabase(roleName, filter);
}

/**
* Return the count of users belong to the given role for the given {@link RoleContext} and filter.
*
* @param roleName Name of the role.
* @param filter String filter for the users.
* @return The count of users matching the provided constraints.
* @throws UserStoreException
*/
public int getUserCountByRoleFromDatabase(String roleName, String filter)
throws UserStoreException {

String roleId = getRoleIdByName(roleName, tenantId);
String roleId = getRoleIdByName(ctx.getRoleName(), tenantId);
Connection dbConnection = null;
PreparedStatement prepStmt = null;
ResultSet rs = null;
int count = 0 ;
String sqlStmt = realmConfig.getUserStoreProperty(JDBCRealmConstants.GET_USERS_COUNT_WITH_FILTER_ROLE);
String sqlStmt = realmConfig.getUserStoreProperty(JDBCRealmConstants.GET_USERS_COUNT_WITH_FILTER_ROLE_WITH_ID);
try {
dbConnection = getDBConnection();
prepStmt = dbConnection.prepareStatement(sqlStmt);
Expand Down
Loading