use of org.ocpsoft.common.util.Strings in project dataverse by IQSS.
the class UserServiceBean method retrieveRolesForUsers.
/**
* Attempt to retrieve all the user roles in 1 query
* Consider putting limits on this -- e.g. no more than 1,000 user identifiers or something similar
*
* @param userIdentifierList
* @return
*/
private HashMap<String, List<String>> retrieveRolesForUsers(List<Object[]> userObjectList) {
// Iterate through results, retrieving only the assignee identifiers
// Note: userInfo[1], the assigneeIdentifier, cannot be null in the database
//
List<String> userIdentifierList = userObjectList.stream().map(userInfo -> (String) userInfo[1]).collect(Collectors.toList());
List<Integer> databaseIds = userObjectList.stream().map(userInfo -> (Integer) userInfo[0]).collect(Collectors.toList());
if ((userIdentifierList == null) || (userIdentifierList.isEmpty())) {
return null;
}
// -------------------------------------------------
// Prepare a string to use within the SQL "a.assigneeidentifier IN (....)" clause
//
// Note: This is not ideal but .setParameter was failing with attempts using:
//
// Collection<String>, List<String>, String[]
//
// This appears to be due to the JDBC driver or Postgres. In this case SQL
// injection isn't possible b/c the list of assigneeidentifier strings comes
// from a previous query
//
// Add '@' to each identifier and delimit the list by ","
// -------------------------------------------------
String identifierListString = userIdentifierList.stream().filter(x -> !Strings.isNullOrEmpty(x)).map(x -> "'@" + x + "'").collect(Collectors.joining(", "));
// -------------------------------------------------
// Create/Run the query to find directly assigned roles
// -------------------------------------------------
String qstr = "SELECT distinct a.assigneeidentifier,";
qstr += " d.name";
qstr += " FROM roleassignment a,";
qstr += " dataverserole d";
qstr += " WHERE d.id = a.role_id";
qstr += " AND a.assigneeidentifier IN (" + identifierListString + ")";
qstr += " ORDER by a.assigneeidentifier, d.name;";
Query nativeQuery = em.createNativeQuery(qstr);
List<Object[]> dbRoleResults = nativeQuery.getResultList();
if (dbRoleResults == null) {
return null;
}
HashMap<String, List<String>> userRoleLookup = new HashMap<>();
String userIdentifier;
String userRole;
for (Object[] dbResultRow : dbRoleResults) {
userIdentifier = UserUtil.getStringOrNull(dbResultRow[0]);
userRole = UserUtil.getStringOrNull(dbResultRow[1]);
if ((userIdentifier != null) && (userRole != null)) {
// should never be null
List<String> userRoleList = userRoleLookup.getOrDefault(userIdentifier, new ArrayList<String>());
if (!userRoleList.contains(userRole)) {
userRoleList.add(userRole);
userRoleLookup.put(userIdentifier, userRoleList);
}
}
}
// And now the roles assigned via groups:
// 1. One query for selecting all the groups to which these users may belong:
HashMap<String, List<String>> groupsLookup = new HashMap<>();
String idListString = StringUtils.join(databaseIds, ",");
// A *RECURSIVE* native query, that finds all the groups that the specified
// users are part of, BOTH by direct inclusion, AND via parent groups:
qstr = "WITH RECURSIVE group_user AS ((" + " SELECT distinct g.groupalias, g.id, u.useridentifier" + " FROM explicitgroup g, explicitgroup_authenticateduser e, authenticateduser u" + " WHERE e.explicitgroup_id = g.id " + " AND u.id IN (" + idListString + ")" + " AND u.id = e.containedauthenticatedusers_id)" + " UNION\n" + " SELECT p.groupalias, p.id, c.useridentifier" + " FROM group_user c, explicitgroup p, explicitgroup_explicitgroup e" + " WHERE e.explicitgroup_id = p.id" + " AND e.containedexplicitgroups_id = c.id)" + "SELECT distinct groupalias, useridentifier FROM group_user;";
// System.out.println("qstr: " + qstr);
nativeQuery = em.createNativeQuery(qstr);
List<Object[]> groupResults = nativeQuery.getResultList();
if (groupResults == null) {
return userRoleLookup;
}
String groupIdentifiers = null;
for (Object[] group : groupResults) {
String alias = UserUtil.getStringOrNull(group[0]);
String user = UserUtil.getStringOrNull(group[1]);
if (alias != null) {
alias = "&explicit/" + alias;
if (groupIdentifiers == null) {
groupIdentifiers = "'" + alias + "'";
} else {
groupIdentifiers += ", '" + alias + "'";
}
List<String> groupUserList = groupsLookup.getOrDefault(alias, new ArrayList<String>());
if (!groupUserList.contains(user)) {
groupUserList.add(user);
groupsLookup.put(alias, groupUserList);
}
}
}
if (groupIdentifiers == null) {
return userRoleLookup;
}
qstr = "SELECT distinct a.assigneeidentifier,";
qstr += " d.name";
qstr += " FROM roleassignment a,";
qstr += " dataverserole d";
qstr += " WHERE d.id = a.role_id";
qstr += " AND a.assigneeidentifier IN (";
qstr += groupIdentifiers;
qstr += ") ORDER by a.assigneeidentifier, d.name;";
// System.out.println("qstr: " + qstr);
nativeQuery = em.createNativeQuery(qstr);
dbRoleResults = nativeQuery.getResultList();
if (dbRoleResults == null) {
return userRoleLookup;
}
for (Object[] dbResultRow : dbRoleResults) {
String groupIdentifier = UserUtil.getStringOrNull(dbResultRow[0]);
String groupRole = UserUtil.getStringOrNull(dbResultRow[1]);
if ((groupIdentifier != null) && (groupRole != null)) {
// should never be null
List<String> groupUserList = groupsLookup.get(groupIdentifier);
if (groupUserList != null) {
for (String groupUserIdentifier : groupUserList) {
groupUserIdentifier = "@" + groupUserIdentifier;
// System.out.println("Group user: "+groupUserIdentifier);
List<String> userRoleList = userRoleLookup.getOrDefault(groupUserIdentifier, new ArrayList<String>());
if (!userRoleList.contains(groupRole)) {
// System.out.println("User Role: "+groupRole);
userRoleList.add(groupRole);
userRoleLookup.put(groupUserIdentifier, userRoleList);
}
}
}
}
}
return userRoleLookup;
}
Aggregations