package org.ovirt.engine.core.sso.search; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.stream.Collectors; import org.ovirt.engine.api.extensions.Base; import org.ovirt.engine.api.extensions.ExtMap; import org.ovirt.engine.api.extensions.aaa.Authz; import org.ovirt.engine.core.extensions.mgr.ExtensionProxy; public class DirectoryUtils { @FunctionalInterface private interface QueryResultHandler { boolean handle(Collection<ExtMap> queryResults); } private static final int QUERIES_RESULTS_LIMIT = 1000; private static final int PAGE_SIZE = 500; public static Collection<ExtMap> findDirectoryUsersByQuery( final ExtensionProxy extension, final String namespace, final String query) { return queryDirectoryUsers( extension, namespace, SearchParsingUtils.generateQueryMap( query, Authz.QueryEntity.PRINCIPAL ), false, false); } public static Collection<ExtMap> findDirectoryGroupsByQuery( final ExtensionProxy extension, final String namespace, final String query) { return queryDirectoryGroups( extension, namespace, SearchParsingUtils.generateQueryMap(query, Authz.QueryEntity.GROUP), false, false); } private static Collection<ExtMap> queryDirectoryUsers( final ExtensionProxy extension, final String namespace, final ExtMap filter, boolean groupsResolving, boolean groupsResolvingRecursive) { return queryPrincipalRecords(extension, namespace, filter, groupsResolving, groupsResolvingRecursive); } private static List<ExtMap> queryDirectoryGroups( final ExtensionProxy extension, final String namespace, final ExtMap filter, boolean groupsResolving, boolean groupsResolvingRecursive) { return queryGroupRecords(extension, namespace, filter, groupsResolving, groupsResolvingRecursive) .stream() .collect(Collectors.toList()); } private static Collection<ExtMap> queryPrincipalRecords( final ExtensionProxy extension, final String namespace, final ExtMap filter, boolean groupsResolving, boolean groupsResolvingRecursive) { ExtMap inputMap = new ExtMap().mput( Authz.InvokeKeys.QUERY_ENTITY, Authz.QueryEntity.PRINCIPAL ).mput( Authz.InvokeKeys.QUERY_FLAGS, queryFlagValue(groupsResolving, groupsResolvingRecursive) ).mput( Authz.InvokeKeys.QUERY_FILTER, filter ).mput( Authz.InvokeKeys.NAMESPACE, namespace ); return populateRecords( extension, namespace, inputMap); } private static Collection<ExtMap> queryGroupRecords( final ExtensionProxy extension, final String namespace, final ExtMap filter, boolean groupsResolving, boolean groupsResolvingRecursive) { ExtMap inputMap = new ExtMap().mput( Authz.InvokeKeys.QUERY_ENTITY, Authz.QueryEntity.GROUP ).mput( Authz.InvokeKeys.QUERY_FLAGS, queryFlagValue(groupsResolving, groupsResolvingRecursive) ).mput( Authz.InvokeKeys.QUERY_FILTER, filter ).mput( Authz.InvokeKeys.NAMESPACE, namespace ); return populateRecords( extension, namespace, inputMap); } private static Collection<ExtMap> populateRecords( final ExtensionProxy extension, final String namespace, final ExtMap input) { final List<ExtMap> records = new ArrayList<>(); queryImpl(extension, namespace, input, (queryResults) -> { boolean result = true; for (ExtMap queryResult : queryResults) { if (records.size() < QUERIES_RESULTS_LIMIT) { records.add(queryResult); } else { result = false; break; } } return result; }); return records; } private static void queryImpl( final ExtensionProxy extension, final String namespace, final ExtMap input, final QueryResultHandler handler) { Object opaque = extension.invoke( new ExtMap().mput( Base.InvokeKeys.COMMAND, Authz.InvokeCommands.QUERY_OPEN ).mput( Authz.InvokeKeys.NAMESPACE, namespace ).mput( input ) ).get(Authz.InvokeKeys.QUERY_OPAQUE); Collection<ExtMap> result = null; try { do { result = extension.invoke( new ExtMap().mput( Base.InvokeKeys.COMMAND, Authz.InvokeCommands.QUERY_EXECUTE ).mput( Authz.InvokeKeys.QUERY_OPAQUE, opaque ).mput( Authz.InvokeKeys.PAGE_SIZE, PAGE_SIZE ) ).get(Authz.InvokeKeys.QUERY_RESULT); } while (result != null && handler.handle(result)); } finally { extension.invoke( new ExtMap().mput( Base.InvokeKeys.COMMAND, Authz.InvokeCommands.QUERY_CLOSE ).mput( Authz.InvokeKeys.QUERY_OPAQUE, opaque ) ); } } private static int queryFlagValue(boolean resolveGroups, boolean resolveGroupsRecursive) { int result = 0; if (resolveGroups) { result |= Authz.QueryFlags.RESOLVE_GROUPS; } if (resolveGroupsRecursive) { result |= Authz.QueryFlags.RESOLVE_GROUPS_RECURSIVE | Authz.QueryFlags.RESOLVE_GROUPS; } return result; } }