Skip to content

Commit

Permalink
count/searchReferences added on the ModelService level
Browse files Browse the repository at this point in the history
Currently, security is suggested in the code but not yet implemented.
  • Loading branch information
virgo47 committed Jan 23, 2023
1 parent 4f8f653 commit cdecb17
Show file tree
Hide file tree
Showing 2 changed files with 155 additions and 18 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2010-2017 Evolveum and contributors
* Copyright (C) 2010-2023 Evolveum and contributors
*
* This work is dual-licensed under the Apache License 2.0
* and European Union Public License. See LICENSE file for details.
Expand Down Expand Up @@ -66,7 +66,6 @@
*
* @author lazyman
* @author Radovan Semancik
*
*/
public interface ModelService {

Expand All @@ -78,6 +77,8 @@ public interface ModelService {
String SEARCH_CONTAINERS = CLASS_NAME_WITH_DOT + "searchContainers";
String COUNT_CONTAINERS = CLASS_NAME_WITH_DOT + "countContainers";
String COUNT_OBJECTS = CLASS_NAME_WITH_DOT + "countObjects";
String SEARCH_REFERENCES = CLASS_NAME_WITH_DOT + "searchReferences";
String COUNT_REFERENCES = CLASS_NAME_WITH_DOT + "countReferences";
String EXECUTE_CHANGES = CLASS_NAME_WITH_DOT + "executeChanges";
String EXECUTE_CHANGE = CLASS_NAME_WITH_DOT + "executeChange";
String RECOMPUTE = CLASS_NAME_WITH_DOT + "recompute";
Expand Down Expand Up @@ -337,7 +338,7 @@ <T extends ObjectType> SearchResultList<PrismObject<T>> searchObjects(Class<T> t

/**
* Search for "sub-object" structures, i.e. containers.
* Supported types are: AccessCertificationCaseType, CaseWorkItemType.
* Supported types are: AccessCertificationCaseType, CaseWorkItemType, OperationExecutionType and AssignmentType.
*/
<T extends Containerable> SearchResultList<T> searchContainers(
Class<T> type, ObjectQuery query,
Expand All @@ -348,6 +349,33 @@ <T extends Containerable> Integer countContainers(Class<T> type, ObjectQuery que
Task task, OperationResult parentResult)
throws SchemaException, SecurityViolationException, ObjectNotFoundException, ExpressionEvaluationException, CommunicationException, ConfigurationException;

/**
* Reference search - currently supporting roleMembershipRef and linkRef search.
* This returns reference objects extracted from the actual object(s) that own them,
* but selection of which (and cardinality of the result list) is based on a repository search.
*
* Query must not be null and its filter must be:
*
* * either a OWNER-BY filter,
* * or AND filter containing exactly one OWNER-BY filter and optionally one or more REF filters with empty path (self).
*
* @param query mandatory query with exactly one root OWNER-BY and additional REF filters
*/
SearchResultList<ObjectReferenceType> searchReferences(
ObjectQuery query, Collection<SelectorOptions<GetOperationOptions>> options,
Task task, OperationResult parentResult) throws SchemaException, SecurityViolationException,
ConfigurationException, ObjectNotFoundException, ExpressionEvaluationException, CommunicationException;

/**
* Reference count - currently supporting roleMembershipRef and linkRef search.
* See {@link #searchReferences(ObjectQuery, Collection, Task, OperationResult)} for more details.
*
* @param query mandatory query
*/
Integer countReferences(ObjectQuery query,
Collection<SelectorOptions<GetOperationOptions>> options, Task task, OperationResult parentResult)
throws SchemaException, SecurityViolationException, ObjectNotFoundException,
ExpressionEvaluationException, CommunicationException, ConfigurationException;
/**
* Search for objects in iterative fashion (using callback).
*
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2010-2021 Evolveum and contributors
* Copyright (C) 2010-2023 Evolveum and contributors
*
* This work is dual-licensed under the Apache License 2.0
* and European Union Public License. See LICENSE file for details.
Expand All @@ -13,20 +13,10 @@
import static com.evolveum.midpoint.util.DebugUtil.lazy;

import java.io.*;
import java.util.Objects;
import java.util.*;
import java.util.stream.Collectors;
import javax.xml.namespace.QName;

import com.evolveum.midpoint.cases.api.CaseManager;

import com.evolveum.midpoint.provisioning.api.*;
import com.evolveum.midpoint.schema.constants.ObjectTypes.ObjectManager;
import com.evolveum.midpoint.schema.processor.ResourceSchema;
import com.evolveum.midpoint.schema.util.*;

import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.CapabilityCollectionType;

import org.apache.commons.lang3.Validate;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
Expand All @@ -37,20 +27,20 @@
import com.evolveum.midpoint.audit.api.AuditEventRecord;
import com.evolveum.midpoint.audit.api.AuditEventStage;
import com.evolveum.midpoint.audit.api.AuditEventType;
import com.evolveum.midpoint.cases.api.CaseManager;
import com.evolveum.midpoint.certification.api.CertificationManager;
import com.evolveum.midpoint.common.LocalizationService;
import com.evolveum.midpoint.model.api.*;
import com.evolveum.midpoint.model.api.authentication.GuiProfiledPrincipalManager;
import com.evolveum.midpoint.model.api.hooks.HookRegistry;
import com.evolveum.midpoint.model.api.hooks.ReadHook;
import com.evolveum.midpoint.repo.common.SystemObjectCache;
import com.evolveum.midpoint.model.common.util.AuditHelper;
import com.evolveum.midpoint.model.impl.ModelObjectResolver;
import com.evolveum.midpoint.model.impl.importer.ObjectImporter;
import com.evolveum.midpoint.model.impl.lens.*;
import com.evolveum.midpoint.model.impl.scripting.ExecutionContext;
import com.evolveum.midpoint.model.impl.scripting.ScriptingExpressionEvaluator;
import com.evolveum.midpoint.model.impl.sync.tasks.imp.ImportFromResourceLauncher;
import com.evolveum.midpoint.model.common.util.AuditHelper;
import com.evolveum.midpoint.model.impl.util.ModelImplUtils;
import com.evolveum.midpoint.prism.*;
import com.evolveum.midpoint.prism.crypto.Protector;
Expand All @@ -63,16 +53,27 @@
import com.evolveum.midpoint.prism.polystring.PolyString;
import com.evolveum.midpoint.prism.query.*;
import com.evolveum.midpoint.prism.util.CloneUtil;
import com.evolveum.midpoint.provisioning.api.DiscoveredConfiguration;
import com.evolveum.midpoint.provisioning.api.EventDispatcher;
import com.evolveum.midpoint.provisioning.api.ExternalResourceEvent;
import com.evolveum.midpoint.provisioning.api.ProvisioningService;
import com.evolveum.midpoint.repo.api.RepositoryService;
import com.evolveum.midpoint.repo.common.SystemObjectCache;
import com.evolveum.midpoint.repo.common.activity.TaskActivityManager;
import com.evolveum.midpoint.schema.*;
import com.evolveum.midpoint.schema.constants.ObjectTypes;
import com.evolveum.midpoint.schema.constants.ObjectTypes.ObjectManager;
import com.evolveum.midpoint.schema.constants.SchemaConstants;
import com.evolveum.midpoint.schema.expression.VariablesMap;
import com.evolveum.midpoint.schema.internals.InternalsConfig;
import com.evolveum.midpoint.schema.processor.ResourceSchema;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.schema.result.OperationResultRunner;
import com.evolveum.midpoint.schema.result.OperationResultStatus;
import com.evolveum.midpoint.schema.util.ObjectQueryUtil;
import com.evolveum.midpoint.schema.util.ObjectTypeUtil;
import com.evolveum.midpoint.schema.util.WorkItemId;
import com.evolveum.midpoint.schema.util.cases.ApprovalUtils;
import com.evolveum.midpoint.security.api.AuthorizationConstants;
import com.evolveum.midpoint.security.api.SecurityContextManager;
import com.evolveum.midpoint.security.enforcer.api.AuthorizationParameters;
Expand All @@ -86,11 +87,11 @@
import com.evolveum.midpoint.util.logging.LoggingUtils;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
import com.evolveum.midpoint.schema.util.cases.ApprovalUtils;
import com.evolveum.midpoint.xml.ns._public.common.api_types_3.CompareResultType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;
import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ExecuteScriptType;
import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ScriptingExpressionType;
import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.CapabilityCollectionType;
import com.evolveum.prism.xml.ns._public.types_3.EvaluationTimeType;
import com.evolveum.prism.xml.ns._public.types_3.ObjectDeltaType;
import com.evolveum.prism.xml.ns._public.types_3.PolyStringType;
Expand Down Expand Up @@ -802,6 +803,112 @@ public <T extends Containerable> Integer countContainers(Class<T> type, ObjectQu
return count;
}

@Override
public SearchResultList<ObjectReferenceType> searchReferences(
ObjectQuery query, Collection<SelectorOptions<GetOperationOptions>> options,
Task task, OperationResult parentResult) throws SchemaException, SecurityViolationException,
ConfigurationException, ObjectNotFoundException, ExpressionEvaluationException, CommunicationException {

Objects.requireNonNull(query, "Query must be provided for reference search");
Validate.notNull(parentResult, "Result type must not be null.");

ModelImplUtils.validatePaging(query.getPaging());

final OperationResult operationResult = parentResult.subresult(SEARCH_REFERENCES)
.addParam(OperationResult.PARAM_QUERY, query)
.build();

// TODO try/finally for operationResult should probably start here

options = preProcessOptionsSecurity(options, task, operationResult);
final GetOperationOptions rootOptions = SelectorOptions.findRootOptions(options);

query = preProcessReferenceQuerySecurity(query, task, operationResult); // TODO not implemented yet!

if (isFilterNone(query, operationResult)) {
return new SearchResultList<>(new ArrayList<>());
}

SearchResultList<ObjectReferenceType> list;
enterModelMethod(); // outside try-catch because if this ends with an exception, cache is not entered yet
try {
logQuery(query);

try {
if (GetOperationOptions.isRaw(rootOptions)) { // MID-2218
QNameUtil.setTemporarilyTolerateUndeclaredPrefixes(true);
}
list = cacheRepositoryService.searchReferences(query, options, operationResult);
} catch (SchemaException | RuntimeException e) {
recordSearchException(e, ObjectManager.REPOSITORY, operationResult);
throw e;
} finally {
QNameUtil.setTemporarilyTolerateUndeclaredPrefixes(false);
operationResult.close();
operationResult.cleanup();
}
} finally {
exitModelMethod();
}

// TODO how does schemaTransformer.applySchemasAndSecurityToContainers apply to reference result?
// Also, reconsider the order/nesting of enter/exitModelMethod and operationResult.close().
// Should we do this out of op-result try/finally? How are exceptions handled here?
return list;
}

@Override
public Integer countReferences(ObjectQuery query,
Collection<SelectorOptions<GetOperationOptions>> options, Task task, OperationResult parentResult)
throws SchemaException, SecurityViolationException, ObjectNotFoundException,
ExpressionEvaluationException, CommunicationException, ConfigurationException {

Objects.requireNonNull(query, "Query must be provided for reference search");
Validate.notNull(parentResult, "Result type must not be null.");

final OperationResult operationResult = parentResult.subresult(SEARCH_REFERENCES)
.addParam(OperationResult.PARAM_QUERY, query)
.build();
// TODO try/finally for operationResult should probably start here

options = preProcessOptionsSecurity(options, task, operationResult);
final GetOperationOptions rootOptions = SelectorOptions.findRootOptions(options);

query = preProcessReferenceQuerySecurity(query, task, operationResult); // TODO not implemented yet!

if (isFilterNone(query, operationResult)) {
return 0;
}

enterModelMethod(); // outside try-catch because if this ends with an exception, cache is not entered yet
int count;
try {
logQuery(query);

try {
count = cacheRepositoryService.countReferences(query, options, operationResult);
} catch (RuntimeException e) {
recordSearchException(e, ObjectManager.REPOSITORY, operationResult);
throw e;
} finally {
operationResult.close();
operationResult.cleanup();
}
} finally {
exitModelMethod();
}

return count;
}

private ObjectQuery preProcessReferenceQuerySecurity(ObjectQuery query, Task task, OperationResult options) {
// TODO:
// 1. extract owner object type from OWNED-BY query (if it's a container type, follow up to the object type)
// 2. use it for securityEnforcer.preProcessObjectFilter()
// 3. add filters to the owned-by filter as necessary
return query;
}

// See MID-6323 in Jira

private boolean isFilterNone(ObjectQuery query, OperationResult result) {
Expand Down Expand Up @@ -2173,7 +2280,9 @@ public <O extends ObjectType> Collection<ObjectDeltaOperation<? extends ObjectTy
result.computeStatus();
return deltas;

} catch (ObjectNotFoundException | SchemaException | ConfigurationException | ObjectAlreadyExistsException | ExpressionEvaluationException | CommunicationException | PolicyViolationException | SecurityViolationException | RuntimeException | Error e) {
} catch (ObjectNotFoundException | SchemaException | ConfigurationException | ObjectAlreadyExistsException |
ExpressionEvaluationException | CommunicationException | PolicyViolationException | SecurityViolationException |
RuntimeException | Error e) {
ModelImplUtils.recordFatalError(result, e);
throw e;
} finally {
Expand Down

0 comments on commit cdecb17

Please sign in to comment.