Search in sources :

Example 1 with SearchHierarchyConstraints

use of com.evolveum.midpoint.schema.processor.SearchHierarchyConstraints in project midpoint by Evolveum.

the class EntitlementConverter method postProcessEntitlementEntitlementToSubject.

private <S extends ShadowType, T> void postProcessEntitlementEntitlementToSubject(ProvisioningContext subjectCtx, final PrismObject<S> resourceObject, RefinedAssociationDefinition assocDefType, final ProvisioningContext entitlementCtx, ResourceAttributeContainer attributesContainer, final PrismContainer<ShadowAssociationType> associationContainer, OperationResult parentResult) throws SchemaException, CommunicationException, ObjectNotFoundException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException {
    ResourceType resourceType = subjectCtx.getResource();
    final QName associationName = assocDefType.getName();
    final RefinedObjectClassDefinition entitlementDef = entitlementCtx.getObjectClassDefinition();
    if (associationName == null) {
        throw new SchemaException("No name in entitlement association " + assocDefType + " in " + resourceType);
    }
    QName associationAuxiliaryObjectClass = assocDefType.getAuxiliaryObjectClass();
    if (associationAuxiliaryObjectClass != null && associationAuxiliaryObjectClass.getNamespaceURI() != null && !associationAuxiliaryObjectClass.getNamespaceURI().equals(ResourceTypeUtil.getResourceNamespace(resourceType))) {
        LOGGER.warn("Auxiliary object class {} in association {} does not have namespace that matches {}", associationAuxiliaryObjectClass, assocDefType.getName(), resourceType);
    }
    if (associationAuxiliaryObjectClass != null && !subjectCtx.getObjectClassDefinition().hasAuxiliaryObjectClass(associationAuxiliaryObjectClass)) {
        LOGGER.trace("Ignoring association {} because subject does not have auxiliary object class {}, it has {}", associationName, associationAuxiliaryObjectClass, subjectCtx.getObjectClassDefinition().getAuxiliaryObjectClassDefinitions());
        return;
    }
    QName assocAttrName = assocDefType.getResourceObjectAssociationType().getAssociationAttribute();
    if (assocAttrName == null) {
        throw new SchemaException("No association attribute defined in entitlement association '" + associationName + "' in " + resourceType);
    }
    RefinedAttributeDefinition assocAttrDef = entitlementDef.findAttributeDefinition(assocAttrName);
    if (assocAttrDef == null) {
        throw new SchemaException("Association attribute '" + assocAttrName + "'defined in entitlement association '" + associationName + "' was not found in schema for " + resourceType);
    }
    QName valueAttrName = assocDefType.getResourceObjectAssociationType().getValueAttribute();
    if (valueAttrName == null) {
        throw new SchemaException("No value attribute defined in entitlement association '" + associationName + "' in " + resourceType);
    }
    ResourceAttribute<T> valueAttr = attributesContainer.findAttribute(valueAttrName);
    if (valueAttr == null || valueAttr.isEmpty()) {
        LOGGER.trace("Ignoring association {} because subject does not have any value in attribute {}", associationName, valueAttrName);
        return;
    }
    if (valueAttr.size() > 1) {
        throw new SchemaException("Value attribute " + valueAttrName + " has no more than one value; attribute defined in entitlement association '" + associationName + "' in " + resourceType);
    }
    ObjectQuery query = createQuery(assocDefType, assocAttrDef, valueAttr);
    AttributesToReturn attributesToReturn = ProvisioningUtil.createAttributesToReturn(entitlementCtx);
    SearchHierarchyConstraints searchHierarchyConstraints = null;
    ResourceObjectReferenceType baseContextRef = entitlementDef.getBaseContext();
    if (baseContextRef != null) {
        // TODO: this should be done once per search. Not in every run of postProcessEntitlementEntitlementToSubject
        // this has to go outside of this method
        PrismObject<ShadowType> baseContextShadow = resourceObjectReferenceResolver.resolve(subjectCtx, baseContextRef, null, "base context specification in " + entitlementDef, parentResult);
        RefinedObjectClassDefinition baseContextObjectClassDefinition = subjectCtx.getRefinedSchema().determineCompositeObjectClassDefinition(baseContextShadow);
        ResourceObjectIdentification baseContextIdentification = ShadowUtil.getResourceObjectIdentification(baseContextShadow, baseContextObjectClassDefinition);
        searchHierarchyConstraints = new SearchHierarchyConstraints(baseContextIdentification, null);
    }
    ResultHandler<ShadowType> handler = new ResultHandler<ShadowType>() {

        @Override
        public boolean handle(PrismObject<ShadowType> entitlementShadow) {
            PrismContainerValue<ShadowAssociationType> associationCVal = associationContainer.createNewValue();
            associationCVal.asContainerable().setName(associationName);
            Collection<ResourceAttribute<?>> entitlementIdentifiers = ShadowUtil.getAllIdentifiers(entitlementShadow);
            try {
                ResourceAttributeContainer identifiersContainer = new ResourceAttributeContainer(ShadowAssociationType.F_IDENTIFIERS, entitlementDef.toResourceAttributeContainerDefinition(), prismContext);
                associationCVal.add(identifiersContainer);
                identifiersContainer.getValue().addAll(ResourceAttribute.cloneCollection(entitlementIdentifiers));
                // Remember the full shadow in user data. This is used later as an optimization to create the shadow in repo 
                identifiersContainer.setUserData(ResourceObjectConverter.FULL_SHADOW_KEY, entitlementShadow);
                if (LOGGER.isTraceEnabled()) {
                    LOGGER.trace("Processed entitlement-to-subject association for account {} and entitlement {}", ShadowUtil.getHumanReadableName(resourceObject), ShadowUtil.getHumanReadableName(entitlementShadow));
                }
            } catch (SchemaException e) {
                throw new TunnelException(e);
            }
            return true;
        }
    };
    ConnectorInstance connector = subjectCtx.getConnector(ReadCapabilityType.class, parentResult);
    try {
        if (LOGGER.isTraceEnabled()) {
            LOGGER.trace("Processed entitlement-to-subject association for account {}: query {}", ShadowUtil.getHumanReadableName(resourceObject), query);
        }
        try {
            connector.search(entitlementDef, query, handler, attributesToReturn, null, searchHierarchyConstraints, subjectCtx, parentResult);
        } catch (GenericFrameworkException e) {
            throw new GenericConnectorException("Generic error in the connector " + connector + ". Reason: " + e.getMessage(), e);
        }
    } catch (TunnelException e) {
        throw (SchemaException) e.getCause();
    }
}
Also used : AttributesToReturn(com.evolveum.midpoint.provisioning.ucf.api.AttributesToReturn) ResourceAttributeContainer(com.evolveum.midpoint.schema.processor.ResourceAttributeContainer) ResultHandler(com.evolveum.midpoint.provisioning.ucf.api.ResultHandler) PrismObject(com.evolveum.midpoint.prism.PrismObject) TunnelException(com.evolveum.midpoint.util.exception.TunnelException) SearchHierarchyConstraints(com.evolveum.midpoint.schema.processor.SearchHierarchyConstraints) ResourceObjectIdentification(com.evolveum.midpoint.schema.processor.ResourceObjectIdentification) GenericConnectorException(com.evolveum.midpoint.provisioning.api.GenericConnectorException) ResourceObjectReferenceType(com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceObjectReferenceType) ResourceAttribute(com.evolveum.midpoint.schema.processor.ResourceAttribute) ShadowAssociationType(com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowAssociationType) SchemaException(com.evolveum.midpoint.util.exception.SchemaException) GenericFrameworkException(com.evolveum.midpoint.provisioning.ucf.api.GenericFrameworkException) QName(javax.xml.namespace.QName) ShadowType(com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType) ResourceType(com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType) ObjectQuery(com.evolveum.midpoint.prism.query.ObjectQuery) ConnectorInstance(com.evolveum.midpoint.provisioning.ucf.api.ConnectorInstance)

Example 2 with SearchHierarchyConstraints

use of com.evolveum.midpoint.schema.processor.SearchHierarchyConstraints in project midpoint by Evolveum.

the class EntitlementConverter method collectEntitlementsAsObjectOperationDelete.

/////////
// DELETE
/////////
/**
	 * This is somehow different that all the other methods. We are not following the content of a shadow or delta. We are following
	 * the definitions. This is to avoid the need to read the object that is going to be deleted. In fact, the object should not be there
	 * any more, but we still want to clean up entitlement membership based on the information from the shadow.  
	 */
public <T> void collectEntitlementsAsObjectOperationDelete(ProvisioningContext subjectCtx, final Map<ResourceObjectDiscriminator, ResourceObjectOperations> roMap, PrismObject<ShadowType> subjectShadow, OperationResult parentResult) throws SchemaException, CommunicationException, ObjectNotFoundException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException {
    Collection<RefinedAssociationDefinition> entitlementAssociationDefs = subjectCtx.getObjectClassDefinition().getAssociationDefinitions();
    if (entitlementAssociationDefs == null || entitlementAssociationDefs.isEmpty()) {
        // Nothing to do
        LOGGER.trace("No associations in deleted shadow");
        return;
    }
    ResourceAttributeContainer subjectAttributesContainer = ShadowUtil.getAttributesContainer(subjectShadow);
    for (final RefinedAssociationDefinition assocDefType : subjectCtx.getObjectClassDefinition().getAssociationDefinitions()) {
        if (assocDefType.getResourceObjectAssociationType().getDirection() != ResourceObjectAssociationDirectionType.OBJECT_TO_SUBJECT) {
            // We can ignore these. They will die together with the object. No need to explicitly delete them.
            LOGGER.trace("Ignoring subject-to-object association in deleted shadow");
            continue;
        }
        if (!assocDefType.requiresExplicitReferentialIntegrity()) {
            // Referential integrity not required for this one
            LOGGER.trace("Ignoring association in deleted shadow because it does not require explicit referential integrity assurance");
            continue;
        }
        if (assocDefType.getAuxiliaryObjectClass() != null && !subjectCtx.getObjectClassDefinition().hasAuxiliaryObjectClass(assocDefType.getAuxiliaryObjectClass())) {
            LOGGER.trace("Ignoring association in deleted shadow because subject does not have {} auxiliary object class", assocDefType.getAuxiliaryObjectClass());
            continue;
        }
        QName associationName = assocDefType.getName();
        if (associationName == null) {
            throw new SchemaException("No name in entitlement association " + assocDefType + " in " + subjectCtx.getResource());
        }
        ShadowKindType entitlementKind = assocDefType.getKind();
        if (entitlementKind == null) {
            entitlementKind = ShadowKindType.ENTITLEMENT;
        }
        for (String entitlementIntent : assocDefType.getIntents()) {
            final ProvisioningContext entitlementCtx = subjectCtx.spawn(entitlementKind, entitlementIntent);
            final RefinedObjectClassDefinition entitlementOcDef = entitlementCtx.getObjectClassDefinition();
            if (entitlementOcDef == null) {
                throw new SchemaException("No definition for entitlement intent(s) '" + assocDefType.getIntents() + "' defined in entitlement association " + associationName + " in " + subjectCtx.getResource());
            }
            final QName assocAttrName = assocDefType.getResourceObjectAssociationType().getAssociationAttribute();
            if (assocAttrName == null) {
                throw new SchemaException("No association attribute defined in entitlement association '" + associationName + "' in " + subjectCtx.getResource());
            }
            final RefinedAttributeDefinition assocAttrDef = entitlementOcDef.findAttributeDefinition(assocAttrName);
            if (assocAttrDef == null) {
                throw new SchemaException("Association attribute '" + assocAttrName + "'defined in entitlement association '" + associationName + "' was not found in schema for " + subjectCtx.getResource());
            }
            QName valueAttrName = assocDefType.getResourceObjectAssociationType().getValueAttribute();
            if (valueAttrName == null) {
                throw new SchemaException("No value attribute defined in entitlement association '" + associationName + "' in " + subjectCtx.getResource());
            }
            final ResourceAttribute<T> valueAttr = subjectAttributesContainer.findAttribute(valueAttrName);
            if (valueAttr == null || valueAttr.isEmpty()) {
                // Although we cannot really remedy the situation now, we at least throw an error so the problem is detected.
                throw new SchemaException("Value attribute " + valueAttrName + " has no value; attribute defined in entitlement association '" + associationName + "' in " + subjectCtx.getResource());
            }
            if (valueAttr.size() > 1) {
                throw new SchemaException("Value attribute " + valueAttrName + " has no more than one value; attribute defined in entitlement association '" + associationName + "' in " + subjectCtx.getResource());
            }
            ObjectQuery query = createQuery(assocDefType, assocAttrDef, valueAttr);
            AttributesToReturn attributesToReturn = ProvisioningUtil.createAttributesToReturn(entitlementCtx);
            SearchHierarchyConstraints searchHierarchyConstraints = null;
            ResourceObjectReferenceType baseContextRef = entitlementOcDef.getBaseContext();
            if (baseContextRef != null) {
                PrismObject<ShadowType> baseContextShadow = resourceObjectReferenceResolver.resolve(subjectCtx, baseContextRef, null, "base context specification in " + entitlementOcDef, parentResult);
                RefinedObjectClassDefinition baseContextObjectClassDefinition = subjectCtx.getRefinedSchema().determineCompositeObjectClassDefinition(baseContextShadow);
                ResourceObjectIdentification baseContextIdentification = ShadowUtil.getResourceObjectIdentification(baseContextShadow, baseContextObjectClassDefinition);
                searchHierarchyConstraints = new SearchHierarchyConstraints(baseContextIdentification, null);
            }
            ResultHandler<ShadowType> handler = new ResultHandler<ShadowType>() {

                @Override
                public boolean handle(PrismObject<ShadowType> entitlementShadow) {
                    Collection<? extends ResourceAttribute<?>> primaryIdentifiers = ShadowUtil.getPrimaryIdentifiers(entitlementShadow);
                    ResourceObjectDiscriminator disc = new ResourceObjectDiscriminator(entitlementOcDef.getTypeName(), primaryIdentifiers);
                    ResourceObjectOperations operations = roMap.get(disc);
                    if (operations == null) {
                        operations = new ResourceObjectOperations();
                        roMap.put(disc, operations);
                        operations.setResourceObjectContext(entitlementCtx);
                        Collection<? extends ResourceAttribute<?>> allIdentifiers = ShadowUtil.getAllIdentifiers(entitlementShadow);
                        operations.setAllIdentifiers(allIdentifiers);
                    }
                    PropertyDelta<T> attributeDelta = null;
                    for (Operation operation : operations.getOperations()) {
                        if (operation instanceof PropertyModificationOperation) {
                            PropertyModificationOperation propOp = (PropertyModificationOperation) operation;
                            if (propOp.getPropertyDelta().getElementName().equals(assocAttrName)) {
                                attributeDelta = propOp.getPropertyDelta();
                            }
                        }
                    }
                    if (attributeDelta == null) {
                        attributeDelta = assocAttrDef.createEmptyDelta(new ItemPath(ShadowType.F_ATTRIBUTES, assocAttrName));
                        PropertyModificationOperation attributeModification = new PropertyModificationOperation(attributeDelta);
                        attributeModification.setMatchingRuleQName(assocDefType.getMatchingRule());
                        operations.add(attributeModification);
                    }
                    attributeDelta.addValuesToDelete(valueAttr.getClonedValues());
                    if (LOGGER.isTraceEnabled()) {
                        LOGGER.trace("Association in deleted shadow delta:\n{}", attributeDelta.debugDump());
                    }
                    return true;
                }
            };
            try {
                LOGGER.trace("Searching for associations in deleted shadow, query: {}", query);
                ConnectorInstance connector = subjectCtx.getConnector(ReadCapabilityType.class, parentResult);
                connector.search(entitlementOcDef, query, handler, attributesToReturn, null, searchHierarchyConstraints, subjectCtx, parentResult);
            } catch (TunnelException e) {
                throw (SchemaException) e.getCause();
            } catch (GenericFrameworkException e) {
                throw new GenericConnectorException(e.getMessage(), e);
            }
        }
    }
}
Also used : AttributesToReturn(com.evolveum.midpoint.provisioning.ucf.api.AttributesToReturn) ResourceAttributeContainer(com.evolveum.midpoint.schema.processor.ResourceAttributeContainer) ResultHandler(com.evolveum.midpoint.provisioning.ucf.api.ResultHandler) Operation(com.evolveum.midpoint.provisioning.ucf.api.Operation) PropertyModificationOperation(com.evolveum.midpoint.provisioning.ucf.api.PropertyModificationOperation) PrismObject(com.evolveum.midpoint.prism.PrismObject) TunnelException(com.evolveum.midpoint.util.exception.TunnelException) SearchHierarchyConstraints(com.evolveum.midpoint.schema.processor.SearchHierarchyConstraints) ResourceObjectIdentification(com.evolveum.midpoint.schema.processor.ResourceObjectIdentification) GenericConnectorException(com.evolveum.midpoint.provisioning.api.GenericConnectorException) PropertyModificationOperation(com.evolveum.midpoint.provisioning.ucf.api.PropertyModificationOperation) ResourceObjectReferenceType(com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceObjectReferenceType) SchemaException(com.evolveum.midpoint.util.exception.SchemaException) GenericFrameworkException(com.evolveum.midpoint.provisioning.ucf.api.GenericFrameworkException) QName(javax.xml.namespace.QName) ShadowType(com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType) ObjectQuery(com.evolveum.midpoint.prism.query.ObjectQuery) ConnectorInstance(com.evolveum.midpoint.provisioning.ucf.api.ConnectorInstance) ShadowKindType(com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowKindType) ItemPath(com.evolveum.midpoint.prism.path.ItemPath)

Aggregations

PrismObject (com.evolveum.midpoint.prism.PrismObject)2 ObjectQuery (com.evolveum.midpoint.prism.query.ObjectQuery)2 GenericConnectorException (com.evolveum.midpoint.provisioning.api.GenericConnectorException)2 AttributesToReturn (com.evolveum.midpoint.provisioning.ucf.api.AttributesToReturn)2 ConnectorInstance (com.evolveum.midpoint.provisioning.ucf.api.ConnectorInstance)2 GenericFrameworkException (com.evolveum.midpoint.provisioning.ucf.api.GenericFrameworkException)2 ResultHandler (com.evolveum.midpoint.provisioning.ucf.api.ResultHandler)2 ResourceAttributeContainer (com.evolveum.midpoint.schema.processor.ResourceAttributeContainer)2 ResourceObjectIdentification (com.evolveum.midpoint.schema.processor.ResourceObjectIdentification)2 SearchHierarchyConstraints (com.evolveum.midpoint.schema.processor.SearchHierarchyConstraints)2 SchemaException (com.evolveum.midpoint.util.exception.SchemaException)2 TunnelException (com.evolveum.midpoint.util.exception.TunnelException)2 ResourceObjectReferenceType (com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceObjectReferenceType)2 ShadowType (com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType)2 QName (javax.xml.namespace.QName)2 ItemPath (com.evolveum.midpoint.prism.path.ItemPath)1 Operation (com.evolveum.midpoint.provisioning.ucf.api.Operation)1 PropertyModificationOperation (com.evolveum.midpoint.provisioning.ucf.api.PropertyModificationOperation)1 ResourceAttribute (com.evolveum.midpoint.schema.processor.ResourceAttribute)1 ResourceType (com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType)1