/*
* Copyright (c) 2010-2017 Evolveum
*
* Licensed 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 com.evolveum.midpoint.model.impl.controller;
import java.util.*;
import javax.xml.namespace.QName;
import com.evolveum.midpoint.common.refinery.*;
import com.evolveum.midpoint.model.api.*;
import com.evolveum.midpoint.model.api.visualizer.Scene;
import com.evolveum.midpoint.model.common.SystemObjectCache;
import com.evolveum.midpoint.model.common.stringpolicy.ValuePolicyProcessor;
import com.evolveum.midpoint.model.impl.visualizer.Visualizer;
import com.evolveum.midpoint.prism.*;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;
import org.apache.commons.lang.Validate;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import com.evolveum.midpoint.model.api.context.ModelContext;
import com.evolveum.midpoint.model.api.util.MergeDeltas;
import com.evolveum.midpoint.model.impl.ModelObjectResolver;
import com.evolveum.midpoint.model.impl.lens.ContextFactory;
import com.evolveum.midpoint.model.impl.lens.LensContext;
import com.evolveum.midpoint.model.impl.lens.projector.Projector;
import com.evolveum.midpoint.prism.crypto.EncryptionException;
import com.evolveum.midpoint.prism.crypto.Protector;
import com.evolveum.midpoint.prism.delta.ObjectDelta;
import com.evolveum.midpoint.prism.path.ItemPath;
import com.evolveum.midpoint.prism.query.AllFilter;
import com.evolveum.midpoint.prism.query.AndFilter;
import com.evolveum.midpoint.prism.query.EqualFilter;
import com.evolveum.midpoint.prism.query.NoneFilter;
import com.evolveum.midpoint.prism.query.NotFilter;
import com.evolveum.midpoint.prism.query.ObjectFilter;
import com.evolveum.midpoint.prism.query.OrFilter;
import com.evolveum.midpoint.prism.query.RefFilter;
import com.evolveum.midpoint.prism.query.TypeFilter;
import com.evolveum.midpoint.provisioning.api.ProvisioningService;
import com.evolveum.midpoint.repo.api.RepositoryService;
import com.evolveum.midpoint.schema.GetOperationOptions;
import com.evolveum.midpoint.schema.ResourceShadowDiscriminator;
import com.evolveum.midpoint.schema.RetrieveOption;
import com.evolveum.midpoint.schema.SelectorOptions;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.schema.result.OperationResultStatus;
import com.evolveum.midpoint.schema.statistics.ConnectorOperationalStatus;
import com.evolveum.midpoint.schema.util.ShadowUtil;
import com.evolveum.midpoint.security.api.Authorization;
import com.evolveum.midpoint.security.api.AuthorizationConstants;
import com.evolveum.midpoint.security.api.ItemSecurityDecisions;
import com.evolveum.midpoint.security.api.MidPointPrincipal;
import com.evolveum.midpoint.security.api.ObjectSecurityConstraints;
import com.evolveum.midpoint.security.api.SecurityEnforcer;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.util.DebugUtil;
import com.evolveum.midpoint.util.DisplayableValue;
import com.evolveum.midpoint.util.QNameUtil;
import com.evolveum.midpoint.util.exception.CommunicationException;
import com.evolveum.midpoint.util.exception.ConfigurationException;
import com.evolveum.midpoint.util.exception.ExpressionEvaluationException;
import com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException;
import com.evolveum.midpoint.util.exception.ObjectNotFoundException;
import com.evolveum.midpoint.util.exception.PolicyViolationException;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.util.exception.SecurityViolationException;
import com.evolveum.midpoint.util.exception.SystemException;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
import com.evolveum.prism.xml.ns._public.types_3.ItemPathType;
import com.evolveum.prism.xml.ns._public.types_3.PolyStringType;
import com.evolveum.prism.xml.ns._public.types_3.ProtectedStringType;
/**
* @author semancik
*
*/
@Component("modelInteractionService")
public class ModelInteractionServiceImpl implements ModelInteractionService {
private static final Trace LOGGER = TraceManager.getTrace(ModelInteractionServiceImpl.class);
@Autowired(required = true)
private ContextFactory contextFactory;
@Autowired(required = true)
private Projector projector;
@Autowired(required = true)
private SecurityEnforcer securityEnforcer;
@Autowired(required = true)
private SchemaTransformer schemaTransformer;
@Autowired(required = true)
private ProvisioningService provisioning;
@Autowired(required = true)
private ModelObjectResolver objectResolver;
@Autowired(required = true)
private ObjectMerger objectMerger;
@Autowired(required = true)
@Qualifier("cacheRepositoryService")
private transient RepositoryService cacheRepositoryService;
@Autowired(required = true)
private SystemObjectCache systemObjectCache;
@Autowired(required = true)
private ValuePolicyProcessor valuePolicyGenerator;
@Autowired(required = true)
private Protector protector;
@Autowired(required = true)
private PrismContext prismContext;
@Autowired
private Visualizer visualizer;
/* (non-Javadoc)
* @see com.evolveum.midpoint.model.api.ModelInteractionService#previewChanges(com.evolveum.midpoint.prism.delta.ObjectDelta, com.evolveum.midpoint.schema.result.OperationResult)
*/
@Override
public <F extends ObjectType> ModelContext<F> previewChanges(
Collection<ObjectDelta<? extends ObjectType>> deltas, ModelExecuteOptions options, Task task, OperationResult parentResult)
throws SchemaException, PolicyViolationException, ExpressionEvaluationException, ObjectNotFoundException, ObjectAlreadyExistsException, CommunicationException, ConfigurationException, SecurityViolationException {
return previewChanges(deltas, options, task, Collections.<ProgressListener>emptyList(), parentResult);
}
@Override
public <F extends ObjectType> ModelContext<F> previewChanges(
Collection<ObjectDelta<? extends ObjectType>> deltas, ModelExecuteOptions options, Task task,
Collection<ProgressListener> listeners, OperationResult parentResult)
throws SchemaException, PolicyViolationException, ExpressionEvaluationException, ObjectNotFoundException, ObjectAlreadyExistsException, CommunicationException, ConfigurationException, SecurityViolationException {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Preview changes input:\n{}", DebugUtil.debugDump(deltas));
}
int size = 0;
if (deltas != null) {
size = deltas.size();
}
Collection<ObjectDelta<? extends ObjectType>> clonedDeltas = new ArrayList<ObjectDelta<? extends ObjectType>>(size);
if (deltas != null) {
for (ObjectDelta delta : deltas){
clonedDeltas.add(delta.clone());
}
}
OperationResult result = parentResult.createSubresult(PREVIEW_CHANGES);
LensContext<F> context = null;
try {
//used cloned deltas instead of origin deltas, because some of the values should be lost later..
context = contextFactory.createContext(clonedDeltas, options, task, result);
// context.setOptions(options);
if (LOGGER.isDebugEnabled()) {
LOGGER.trace("Preview changes context:\n{}", context.debugDump());
}
context.setProgressListeners(listeners);
projector.projectAllWaves(context, "preview", task, result);
context.distributeResource();
} catch (ConfigurationException e) {
ModelUtils.recordFatalError(result, e);
throw e;
} catch (SecurityViolationException e) {
ModelUtils.recordFatalError(result, e);
throw e;
} catch (CommunicationException e) {
ModelUtils.recordFatalError(result, e);
throw e;
} catch (ObjectNotFoundException e) {
ModelUtils.recordFatalError(result, e);
throw e;
} catch (SchemaException e) {
ModelUtils.recordFatalError(result, e);
throw e;
} catch (ObjectAlreadyExistsException e) {
ModelUtils.recordFatalError(result, e);
throw e;
} catch (ExpressionEvaluationException e) {
ModelUtils.recordFatalError(result, e);
throw e;
} catch (PolicyViolationException e) {
ModelUtils.recordFatalError(result, e);
throw e;
} catch (RuntimeException e) {
ModelUtils.recordFatalError(result, e);
throw e;
}
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Preview changes output:\n{}", context.debugDump());
}
result.computeStatus();
result.cleanupResult();
return context;
}
@Override
public <F extends ObjectType> ModelContext<F> unwrapModelContext(LensContextType wrappedContext, OperationResult result) throws SchemaException, ConfigurationException, ObjectNotFoundException, CommunicationException {
return LensContext.fromLensContextType(wrappedContext, prismContext, provisioning, result);
}
@Override
public <O extends ObjectType> PrismObjectDefinition<O> getEditObjectDefinition(PrismObject<O> object, AuthorizationPhaseType phase, OperationResult parentResult) throws SchemaException, ConfigurationException, ObjectNotFoundException {
OperationResult result = parentResult.createMinorSubresult(GET_EDIT_OBJECT_DEFINITION);
PrismObjectDefinition<O> objectDefinition = object.getDefinition().deepClone(true);
PrismObject<O> baseObject = object;
if (object.getOid() != null) {
// Re-read the object from the repository to make sure we have all the properties.
// the object from method parameters may be already processed by the security code
// and properties needed to evaluate authorizations may not be there
// MID-3126, see also MID-3435
baseObject = cacheRepositoryService.getObject(object.getCompileTimeClass(), object.getOid(), null, result);
}
// TODO: maybe we need to expose owner resolver in the interface?
ObjectSecurityConstraints securityConstraints = securityEnforcer.compileSecurityConstraints(baseObject, null);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Security constrains for {}:\n{}", object, securityConstraints==null?"null":securityConstraints.debugDump());
}
if (securityConstraints == null) {
// Nothing allowed => everything denied
result.setStatus(OperationResultStatus.NOT_APPLICABLE);
return null;
}
ObjectTemplateType objectTemplateType;
try {
objectTemplateType = schemaTransformer.determineObjectTemplate(object, phase, result);
} catch (ConfigurationException | ObjectNotFoundException e) {
result.recordFatalError(e);
throw e;
}
schemaTransformer.applyObjectTemplateToDefinition(objectDefinition, objectTemplateType, result);
schemaTransformer.applySecurityConstraints(objectDefinition, securityConstraints, phase);
if (object.canRepresent(ShadowType.class)) {
PrismObject<ShadowType> shadow = (PrismObject<ShadowType>)object;
String resourceOid = ShadowUtil.getResourceOid(shadow);
if (resourceOid != null) {
Collection<SelectorOptions<GetOperationOptions>> options = SelectorOptions.createCollection(GetOperationOptions.createReadOnly());
PrismObject<ResourceType> resource;
try {
resource = provisioning.getObject(ResourceType.class, resourceOid, options, null, result); // TODO include task here
} catch (CommunicationException | SecurityViolationException e) {
throw new ConfigurationException(e.getMessage(), e);
}
RefinedObjectClassDefinition refinedObjectClassDefinition = getEditObjectClassDefinition(shadow, resource, phase);
if (refinedObjectClassDefinition != null) {
((ComplexTypeDefinitionImpl) objectDefinition.getComplexTypeDefinition()).replaceDefinition(ShadowType.F_ATTRIBUTES,
refinedObjectClassDefinition.toResourceAttributeContainerDefinition());
}
}
}
result.computeStatus();
return objectDefinition;
}
@Override
public PrismObjectDefinition<ShadowType> getEditShadowDefinition(ResourceShadowDiscriminator discr, AuthorizationPhaseType phase, OperationResult parentResult) throws SchemaException, ConfigurationException, ObjectNotFoundException {
// HACK hack hack
// Make a dummy shadow instance here and evaluate the schema for that. It is not 100% correct. But good enough for now.
// TODO: refactor when we add better support for multi-tenancy
PrismObject<ShadowType> shadow = prismContext.createObject(ShadowType.class);
ShadowType shadowType = shadow.asObjectable();
ObjectReferenceType resourceRef = new ObjectReferenceType();
if (discr != null) {
resourceRef.setOid(discr.getResourceOid());
shadowType.setResourceRef(resourceRef);
shadowType.setKind(discr.getKind());
shadowType.setIntent(discr.getIntent());
shadowType.setObjectClass(discr.getObjectClass());
}
return getEditObjectDefinition(shadow, phase, parentResult);
}
@Override
public RefinedObjectClassDefinition getEditObjectClassDefinition(PrismObject<ShadowType> shadow, PrismObject<ResourceType> resource, AuthorizationPhaseType phase)
throws SchemaException {
Validate.notNull(resource, "Resource must not be null");
RefinedResourceSchema refinedSchema = RefinedResourceSchemaImpl.getRefinedSchema(resource);
CompositeRefinedObjectClassDefinition rocd = refinedSchema.determineCompositeObjectClassDefinition(shadow);
if (rocd == null) {
LOGGER.debug("No object class definition for shadow {}, returning null");
return null;
}
LayerRefinedObjectClassDefinition layeredROCD = rocd.forLayer(LayerType.PRESENTATION);
// TODO: maybe we need to expose owner resolver in the interface?
ObjectSecurityConstraints securityConstraints = securityEnforcer.compileSecurityConstraints(shadow, null);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Security constrains for {}:\n{}", shadow, securityConstraints==null?"null":securityConstraints.debugDump());
}
if (securityConstraints == null) {
return null;
}
ItemPath attributesPath = new ItemPath(ShadowType.F_ATTRIBUTES);
AuthorizationDecisionType attributesReadDecision = schemaTransformer.computeItemDecision(securityConstraints, attributesPath, ModelAuthorizationAction.READ.getUrl(),
securityConstraints.getActionDecision(ModelAuthorizationAction.READ.getUrl(), phase), phase);
AuthorizationDecisionType attributesAddDecision = schemaTransformer.computeItemDecision(securityConstraints, attributesPath, ModelAuthorizationAction.ADD.getUrl(),
securityConstraints.getActionDecision(ModelAuthorizationAction.ADD.getUrl(), phase), phase);
AuthorizationDecisionType attributesModifyDecision = schemaTransformer.computeItemDecision(securityConstraints, attributesPath, ModelAuthorizationAction.MODIFY.getUrl(),
securityConstraints.getActionDecision(ModelAuthorizationAction.MODIFY.getUrl(), phase), phase);
LOGGER.trace("Attributes container access read:{}, add:{}, modify:{}", new Object[]{attributesReadDecision, attributesAddDecision, attributesModifyDecision});
/*
* We are going to modify attribute definitions list.
* So let's make a (shallow) clone here, although it is probably not strictly necessary.
*/
layeredROCD = layeredROCD.clone();
for (LayerRefinedAttributeDefinition rAttrDef: layeredROCD.getAttributeDefinitions()) {
ItemPath attributePath = new ItemPath(ShadowType.F_ATTRIBUTES, rAttrDef.getName());
AuthorizationDecisionType attributeReadDecision = schemaTransformer.computeItemDecision(securityConstraints, attributePath, ModelAuthorizationAction.READ.getUrl(), attributesReadDecision, phase);
AuthorizationDecisionType attributeAddDecision = schemaTransformer.computeItemDecision(securityConstraints, attributePath, ModelAuthorizationAction.ADD.getUrl(), attributesAddDecision, phase);
AuthorizationDecisionType attributeModifyDecision = schemaTransformer.computeItemDecision(securityConstraints, attributePath, ModelAuthorizationAction.MODIFY.getUrl(), attributesModifyDecision, phase);
LOGGER.trace("Attribute {} access read:{}, add:{}, modify:{}", new Object[]{rAttrDef.getName(), attributeReadDecision, attributeAddDecision, attributeModifyDecision});
if (attributeReadDecision != AuthorizationDecisionType.ALLOW) {
((LayerRefinedAttributeDefinitionImpl) rAttrDef).setOverrideCanRead(false);
}
if (attributeAddDecision != AuthorizationDecisionType.ALLOW) {
((LayerRefinedAttributeDefinitionImpl) rAttrDef).setOverrideCanAdd(false);
}
if (attributeModifyDecision != AuthorizationDecisionType.ALLOW) {
((LayerRefinedAttributeDefinitionImpl) rAttrDef).setOverrideCanModify(false);
}
}
// TODO what about activation and credentials?
return layeredROCD;
}
public <O extends ObjectType,R extends AbstractRoleType> ItemSecurityDecisions getAllowedRequestAssignmentItems(PrismObject<O> object, PrismObject<R> target) throws SchemaException, SecurityViolationException {
return securityEnforcer.getAllowedRequestAssignmentItems(securityEnforcer.getPrincipal(), object, target, null);
}
@Override
public Collection<? extends DisplayableValue<String>> getActionUrls() {
return Arrays.asList(ModelAuthorizationAction.values());
}
@Override
public <F extends FocusType> RoleSelectionSpecification getAssignableRoleSpecification(PrismObject<F> focus, OperationResult parentResult)
throws ObjectNotFoundException, SchemaException, ConfigurationException {
OperationResult result = parentResult.createMinorSubresult(GET_ASSIGNABLE_ROLE_SPECIFICATION);
RoleSelectionSpecification spec = new RoleSelectionSpecification();
ObjectSecurityConstraints securityConstraints = securityEnforcer.compileSecurityConstraints(focus, null);
if (securityConstraints == null) {
return null;
}
AuthorizationDecisionType decision = securityConstraints.findItemDecision(new ItemPath(FocusType.F_ASSIGNMENT),
ModelAuthorizationAction.MODIFY.getUrl(), AuthorizationPhaseType.REQUEST);
if (decision == AuthorizationDecisionType.ALLOW) {
getAllRoleTypesSpec(spec, result);
result.recordSuccess();
return spec;
}
if (decision == AuthorizationDecisionType.DENY) {
result.recordSuccess();
spec.setNoRoleTypes();
spec.setFilter(NoneFilter.createNone());
return spec;
}
decision = securityConstraints.getActionDecision(ModelAuthorizationAction.MODIFY.getUrl(), AuthorizationPhaseType.REQUEST);
if (decision == AuthorizationDecisionType.ALLOW) {
getAllRoleTypesSpec(spec, result);
result.recordSuccess();
return spec;
}
if (decision == AuthorizationDecisionType.DENY) {
result.recordSuccess();
spec.setNoRoleTypes();
spec.setFilter(NoneFilter.createNone());
return spec;
}
try {
ObjectFilter filter = securityEnforcer.preProcessObjectFilter(ModelAuthorizationAction.ASSIGN.getUrl(),
AuthorizationPhaseType.REQUEST, AbstractRoleType.class, focus, AllFilter.createAll());
LOGGER.trace("assignableRoleSpec filter: {}", filter);
spec.setFilter(filter);
if (filter instanceof NoneFilter) {
result.recordSuccess();
spec.setNoRoleTypes();
return spec;
} else if (filter == null || filter instanceof AllFilter) {
getAllRoleTypesSpec(spec, result);
result.recordSuccess();
return spec;
} else if (filter instanceof OrFilter) {
Collection<RoleSelectionSpecEntry> allRoleTypeDvals = new ArrayList<>();
for (ObjectFilter subfilter: ((OrFilter)filter).getConditions()) {
Collection<RoleSelectionSpecEntry> roleTypeDvals = getRoleSelectionSpecEntries(subfilter);
if (roleTypeDvals == null || roleTypeDvals.isEmpty()) {
// This branch of the OR clause does not have any constraint for roleType
// therefore all role types are possible (regardless of other branches, this is OR)
spec = new RoleSelectionSpecification();
spec.setFilter(filter);
getAllRoleTypesSpec(spec, result);
result.recordSuccess();
return spec;
} else {
allRoleTypeDvals.addAll(roleTypeDvals);
}
}
addRoleTypeSpecEntries(spec, allRoleTypeDvals, result);
} else {
Collection<RoleSelectionSpecEntry> roleTypeDvals = getRoleSelectionSpecEntries(filter);
if (roleTypeDvals == null || roleTypeDvals.isEmpty()) {
getAllRoleTypesSpec(spec, result);
result.recordSuccess();
return spec;
} else {
addRoleTypeSpecEntries(spec, roleTypeDvals, result);
}
}
result.recordSuccess();
return spec;
} catch (SchemaException | ConfigurationException | ObjectNotFoundException e) {
result.recordFatalError(e);
throw e;
}
}
private void addRoleTypeSpecEntries(RoleSelectionSpecification spec,
Collection<RoleSelectionSpecEntry> roleTypeDvals, OperationResult result) throws ObjectNotFoundException, SchemaException, ConfigurationException {
if (roleTypeDvals == null || roleTypeDvals.isEmpty()) {
getAllRoleTypesSpec(spec, result);
} else {
if (RoleSelectionSpecEntry.hasNegative(roleTypeDvals)) {
Collection<RoleSelectionSpecEntry> positiveList = RoleSelectionSpecEntry.getPositive(roleTypeDvals);
if (positiveList == null || positiveList.isEmpty()) {
positiveList = getRoleSpecEntriesForAllRoles(result);
}
if (positiveList == null || positiveList.isEmpty()) {
return;
}
for (RoleSelectionSpecEntry positiveEntry: positiveList) {
if (!RoleSelectionSpecEntry.hasNegativeValue(roleTypeDvals,positiveEntry.getValue())) {
spec.addRoleType(positiveEntry);
}
}
} else {
spec.addRoleTypes(roleTypeDvals);
}
}
}
private RoleSelectionSpecification getAllRoleTypesSpec(RoleSelectionSpecification spec, OperationResult result)
throws ObjectNotFoundException, SchemaException, ConfigurationException {
Collection<RoleSelectionSpecEntry> allEntries = getRoleSpecEntriesForAllRoles(result);
if (allEntries == null || allEntries.isEmpty()) {
return spec;
}
spec.addRoleTypes(allEntries);
return spec;
}
private Collection<RoleSelectionSpecEntry> getRoleSpecEntriesForAllRoles(OperationResult result)
throws ObjectNotFoundException, SchemaException, ConfigurationException {
ObjectTemplateType objectTemplateType = schemaTransformer.determineObjectTemplate(RoleType.class, AuthorizationPhaseType.REQUEST, result);
if (objectTemplateType == null) {
return null;
}
Collection<RoleSelectionSpecEntry> allEntries = new ArrayList();
for(ObjectTemplateItemDefinitionType itemDef: objectTemplateType.getItem()) {
ItemPathType ref = itemDef.getRef();
if (ref == null) {
continue;
}
ItemPath itemPath = ref.getItemPath();
QName itemName = ItemPath.getName(itemPath.first());
if (itemName == null) {
continue;
}
if (QNameUtil.match(RoleType.F_ROLE_TYPE, itemName)) {
ObjectReferenceType valueEnumerationRef = itemDef.getValueEnumerationRef();
if (valueEnumerationRef == null || valueEnumerationRef.getOid() == null) {
return allEntries;
}
Collection<SelectorOptions<GetOperationOptions>> options = SelectorOptions.createCollection(LookupTableType.F_ROW,
GetOperationOptions.createRetrieve(RetrieveOption.INCLUDE));
PrismObject<LookupTableType> lookup = cacheRepositoryService.getObject(LookupTableType.class, valueEnumerationRef.getOid(),
options, result);
for (LookupTableRowType row: lookup.asObjectable().getRow()) {
PolyStringType polyLabel = row.getLabel();
String key = row.getKey();
String label = key;
if (polyLabel != null) {
label = polyLabel.getOrig();
}
RoleSelectionSpecEntry roleTypeDval = new RoleSelectionSpecEntry(key, label, null);
allEntries.add(roleTypeDval);
}
return allEntries;
}
}
return allEntries;
}
private Collection<RoleSelectionSpecEntry> getRoleSelectionSpecEntries(ObjectFilter filter) throws SchemaException {
LOGGER.trace("getRoleSelectionSpec({})", filter);
if (filter == null || filter instanceof AllFilter) {
return null;
} else if (filter instanceof EqualFilter<?>) {
return createSingleDisplayableValueCollection(getRoleSelectionSpecEq((EqualFilter)filter));
} else if (filter instanceof AndFilter) {
for (ObjectFilter subfilter: ((AndFilter)filter).getConditions()) {
if (subfilter instanceof EqualFilter<?>) {
RoleSelectionSpecEntry roleTypeDval = getRoleSelectionSpecEq((EqualFilter)subfilter);
if (roleTypeDval != null) {
return createSingleDisplayableValueCollection(roleTypeDval);
}
}
}
return null;
} else if (filter instanceof OrFilter) {
Collection<RoleSelectionSpecEntry> col = new ArrayList<>(((OrFilter)filter).getConditions().size());
for (ObjectFilter subfilter: ((OrFilter)filter).getConditions()) {
if (subfilter instanceof EqualFilter<?>) {
RoleSelectionSpecEntry roleTypeDval = getRoleSelectionSpecEq((EqualFilter)subfilter);
if (roleTypeDval != null) {
col.add(roleTypeDval);
}
}
}
return col;
} else if (filter instanceof TypeFilter) {
return getRoleSelectionSpecEntries(((TypeFilter)filter).getFilter());
} else if (filter instanceof NotFilter) {
Collection<RoleSelectionSpecEntry> subRoleSelectionSpec = getRoleSelectionSpecEntries(((NotFilter)filter).getFilter());
RoleSelectionSpecEntry.negate(subRoleSelectionSpec);
return subRoleSelectionSpec;
} else if (filter instanceof RefFilter) {
return null;
} else {
throw new UnsupportedOperationException("Unexpected filter "+filter);
}
}
private Collection<RoleSelectionSpecEntry> createSingleDisplayableValueCollection(
RoleSelectionSpecEntry dval) {
if (dval == null) {
return null;
}
Collection<RoleSelectionSpecEntry> col = new ArrayList<>(1);
col.add(dval);
return col;
}
private RoleSelectionSpecEntry getRoleSelectionSpecEq(EqualFilter<String> eqFilter) throws SchemaException {
if (QNameUtil.match(RoleType.F_ROLE_TYPE, eqFilter.getElementName())) {
List<PrismPropertyValue<String>> ppvs = eqFilter.getValues();
if (ppvs.size() > 1) {
throw new SchemaException("More than one value in roleType search filter");
}
String roleType = ppvs.get(0).getValue();
RoleSelectionSpecEntry roleTypeDval = new RoleSelectionSpecEntry(roleType, roleType, null);
return roleTypeDval;
}
return null;
}
@Override
public AuthenticationsPolicyType getAuthenticationPolicy(PrismObject<UserType> user, Task task,
OperationResult parentResult) throws ObjectNotFoundException, SchemaException {
// TODO: check for user membership in an organization (later versions)
OperationResult result = parentResult.createMinorSubresult(GET_AUTHENTICATIONS_POLICY);
return resolvePolicyTypeFromSecurityPolicy(AuthenticationsPolicyType.class, SecurityPolicyType.F_AUTHENTICATION, user, task, result);
}
@Override
public RegistrationsPolicyType getRegistrationPolicy(PrismObject<UserType> user, Task task,
OperationResult parentResult) throws ObjectNotFoundException, SchemaException {
// TODO: check for user membership in an organization (later versions)
OperationResult result = parentResult.createMinorSubresult(GET_REGISTRATIONS_POLICY);
return resolvePolicyTypeFromSecurityPolicy(RegistrationsPolicyType.class, SecurityPolicyType.F_REGISTRATION, user, task, result);
}
@Override
public CredentialsPolicyType getCredentialsPolicy(PrismObject<UserType> user, Task task, OperationResult parentResult) throws ObjectNotFoundException, SchemaException {
// TODO: check for user membership in an organization (later versions)
OperationResult result = parentResult.createMinorSubresult(GET_CREDENTIALS_POLICY);
return resolvePolicyTypeFromSecurityPolicy(CredentialsPolicyType.class, SecurityPolicyType.F_CREDENTIALS, user, task, result);
}
private <C extends Containerable> C resolvePolicyTypeFromSecurityPolicy(Class<C> type, QName path, PrismObject<UserType> user, Task task, OperationResult parentResult) throws ObjectNotFoundException, SchemaException {
SecurityPolicyType securityPolicyType = getSecurityPolicy(user, task, parentResult);
if (securityPolicyType == null) {
return null;
}
PrismContainer<C> container = securityPolicyType.asPrismObject().findContainer(path);
if (container == null) {
return null;
}
PrismContainerValue<C> containerValue = container.getValue();
parentResult.recordSuccess();
return containerValue.asContainerable();
}
@Override
public SecurityPolicyType getSecurityPolicy(PrismObject<UserType> user, Task task, OperationResult parentResult) throws ObjectNotFoundException, SchemaException {
OperationResult result = parentResult.createMinorSubresult(GET_SECURITY_POLICY);
try {
PrismObject<SystemConfigurationType> systemConfiguration = systemObjectCache.getSystemConfiguration(result);
if (systemConfiguration == null) {
result.recordNotApplicableIfUnknown();
return null;
}
ObjectReferenceType secPolicyRef = systemConfiguration.asObjectable().getGlobalSecurityPolicyRef();
if (secPolicyRef == null) {
result.recordNotApplicableIfUnknown();
return null;
}
SecurityPolicyType securityPolicyType = objectResolver.resolve(secPolicyRef, SecurityPolicyType.class, null, "security policy referred from system configuration", task, result);
if (securityPolicyType == null) {
result.recordNotApplicableIfUnknown();
return null;
}
return securityPolicyType;
}catch (ObjectNotFoundException | SchemaException e) {
result.recordFatalError(e);
throw e;
}
}
@Override
public AdminGuiConfigurationType getAdminGuiConfiguration(Task task, OperationResult parentResult) throws ObjectNotFoundException, SchemaException {
MidPointPrincipal principal = null;
try {
principal = securityEnforcer.getPrincipal();
} catch (SecurityViolationException e) {
LOGGER.warn("Security violation while getting principlal to get GUI config: {}", e.getMessage(), e);
}
if (principal == null) {
PrismObject<SystemConfigurationType> systemConfiguration = systemObjectCache.getSystemConfiguration(parentResult);
if (systemConfiguration == null) {
return null;
}
return systemConfiguration.asObjectable().getAdminGuiConfiguration();
} else {
return principal.getAdminGuiConfiguration();
}
}
@Override
public SystemConfigurationType getSystemConfiguration(OperationResult parentResult) throws ObjectNotFoundException, SchemaException {
PrismObject<SystemConfigurationType> systemConfiguration = systemObjectCache.getSystemConfiguration(parentResult);
if (systemConfiguration == null) {
return null;
}
return systemConfiguration.asObjectable();
}
@Override
public DeploymentInformationType getDeploymentInformationConfiguration(OperationResult parentResult) throws ObjectNotFoundException, SchemaException {
PrismObject<SystemConfigurationType> systemConfiguration = systemObjectCache.getSystemConfiguration(parentResult);
if (systemConfiguration == null) {
return null;
}
return systemConfiguration.asObjectable().getDeploymentInformation();
}
@Override
public AccessCertificationConfigurationType getCertificationConfiguration(OperationResult parentResult) throws ObjectNotFoundException, SchemaException {
PrismObject<SystemConfigurationType> systemConfiguration = systemObjectCache.getSystemConfiguration(parentResult);
if (systemConfiguration == null) {
return null;
}
return systemConfiguration.asObjectable().getAccessCertification();
}
@Override
public boolean checkPassword(String userOid, ProtectedStringType password, Task task, OperationResult parentResult)
throws ObjectNotFoundException, SchemaException {
OperationResult result = parentResult.createMinorSubresult(CHECK_PASSWORD);
UserType userType;
try {
userType = objectResolver.getObjectSimple(UserType.class, userOid, null, task, result);
} catch (ObjectNotFoundException e) {
result.recordFatalError(e);
throw e;
}
if (userType.getCredentials() == null || userType.getCredentials().getPassword() == null
|| userType.getCredentials().getPassword().getValue() == null) {
return password == null;
}
ProtectedStringType currentPassword = userType.getCredentials().getPassword().getValue();
boolean cmp;
try {
cmp = protector.compare(password, currentPassword);
} catch (EncryptionException e) {
result.recordFatalError(e);
throw new SystemException(e.getMessage(),e);
}
result.recordSuccess();
return cmp;
}
@Override
public List<? extends Scene> visualizeDeltas(List<ObjectDelta<? extends ObjectType>> deltas, Task task, OperationResult result) throws SchemaException {
return visualizer.visualizeDeltas(deltas, task, result);
}
@Override
@NotNull
public Scene visualizeDelta(ObjectDelta<? extends ObjectType> delta, Task task, OperationResult result) throws SchemaException {
return visualizer.visualizeDelta(delta, task, result);
}
@Override
public List<ConnectorOperationalStatus> getConnectorOperationalStatus(String resourceOid, OperationResult parentResult)
throws SchemaException, ObjectNotFoundException, CommunicationException, ConfigurationException {
OperationResult result = parentResult.createMinorSubresult(GET_CONNECTOR_OPERATIONAL_STATUS);
List<ConnectorOperationalStatus> status;
try {
status = provisioning.getConnectorOperationalStatus(resourceOid, result);
} catch (SchemaException | ObjectNotFoundException | CommunicationException | ConfigurationException e) {
result.recordFatalError(e);
throw e;
}
result.computeStatus();
return status;
}
@Override
public <O extends ObjectType> MergeDeltas<O> mergeObjectsPreviewDeltas(Class<O> type, String leftOid,
String rightOid, String mergeConfigurationName, Task task, OperationResult parentResult)
throws ObjectNotFoundException, SchemaException, ConfigurationException, ExpressionEvaluationException, CommunicationException, SecurityViolationException {
OperationResult result = parentResult.createMinorSubresult(MERGE_OBJECTS_PREVIEW_DELTA);
try {
MergeDeltas<O> mergeDeltas = objectMerger.computeMergeDeltas(type, leftOid, rightOid, mergeConfigurationName, task, result);
result.computeStatus();
return mergeDeltas;
} catch (ObjectNotFoundException | SchemaException | ConfigurationException | ExpressionEvaluationException |
CommunicationException | SecurityViolationException | RuntimeException | Error e) {
result.recordFatalError(e);
throw e;
}
}
@Override
public <O extends ObjectType> PrismObject<O> mergeObjectsPreviewObject(Class<O> type, String leftOid,
String rightOid, String mergeConfigurationName, Task task, OperationResult parentResult)
throws ObjectNotFoundException, SchemaException, ConfigurationException, ExpressionEvaluationException, CommunicationException, SecurityViolationException {
OperationResult result = parentResult.createMinorSubresult(MERGE_OBJECTS_PREVIEW_OBJECT);
try {
MergeDeltas<O> mergeDeltas = objectMerger.computeMergeDeltas(type, leftOid, rightOid, mergeConfigurationName, task, result);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Merge preview {} + {} deltas:\n{}", leftOid, rightOid, mergeDeltas.debugDump(1));
}
final PrismObject<O> objectLeft = (PrismObject<O>) objectResolver.getObjectSimple(type, leftOid, null, task, result).asPrismObject();
if (mergeDeltas == null) {
result.computeStatus();
return objectLeft;
}
mergeDeltas.getLeftObjectDelta().applyTo(objectLeft);
mergeDeltas.getLeftLinkDelta().applyTo(objectLeft);
result.computeStatus();
return objectLeft;
} catch (ObjectNotFoundException | SchemaException | ConfigurationException | ExpressionEvaluationException |
CommunicationException | SecurityViolationException | RuntimeException | Error e) {
result.recordFatalError(e);
throw e;
}
}
@Override
public <O extends ObjectType> String generateValue(StringPolicyType policy, int defaultLength, boolean generateMinimalSize,
PrismObject<O> object, String shortDesc, Task task, OperationResult parentResult) throws ExpressionEvaluationException, SchemaException, ObjectNotFoundException {
return valuePolicyGenerator.generate(null, policy, defaultLength, generateMinimalSize, object, shortDesc, task, parentResult);
}
}