use of com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType in project midpoint by Evolveum.
the class ActivationProcessor method processActivationUserCurrent.
public <F extends FocusType> void processActivationUserCurrent(LensContext<F> context, LensProjectionContext projCtx, XMLGregorianCalendar now, Task task, OperationResult result) throws ExpressionEvaluationException, ObjectNotFoundException, SchemaException, PolicyViolationException, CommunicationException, ConfigurationException, SecurityViolationException {
String projCtxDesc = projCtx.toHumanReadableString();
SynchronizationPolicyDecision decision = projCtx.getSynchronizationPolicyDecision();
SynchronizationIntent synchronizationIntent = projCtx.getSynchronizationIntent();
if (decision == SynchronizationPolicyDecision.BROKEN) {
LOGGER.trace("Broken projection {}, skipping further activation processing", projCtxDesc);
return;
}
if (decision != null) {
throw new IllegalStateException("Decision " + decision + " already present for projection " + projCtxDesc);
}
if (synchronizationIntent == SynchronizationIntent.UNLINK) {
projCtx.setSynchronizationPolicyDecision(SynchronizationPolicyDecision.UNLINK);
LOGGER.trace("Evaluated decision for {} to {} because of unlink synchronization intent, skipping further activation processing", projCtxDesc, SynchronizationPolicyDecision.UNLINK);
return;
}
if (projCtx.isThombstone()) {
if (shouldKeepThombstone(projCtx)) {
// Let's keep thombstones linked until they expire. So we do not have shadows without owners.
// This is also needed for async delete operations.
projCtx.setSynchronizationPolicyDecision(SynchronizationPolicyDecision.KEEP);
LOGGER.trace("Evaluated decision for {} to {} because it is thombstone, skipping further activation processing", projCtxDesc, SynchronizationPolicyDecision.KEEP);
} else {
projCtx.setSynchronizationPolicyDecision(SynchronizationPolicyDecision.UNLINK);
LOGGER.trace("Evaluated decision for {} to {} because it is thombstone, skipping further activation processing", projCtxDesc, SynchronizationPolicyDecision.UNLINK);
}
return;
}
if (synchronizationIntent == SynchronizationIntent.DELETE || projCtx.isDelete()) {
// TODO: is this OK?
projCtx.setSynchronizationPolicyDecision(SynchronizationPolicyDecision.DELETE);
LOGGER.trace("Evaluated decision for {} to {}, skipping further activation processing", projCtxDesc, SynchronizationPolicyDecision.DELETE);
return;
}
boolean shadowShouldExist = evaluateExistenceMapping(context, projCtx, now, true, task, result);
LOGGER.trace("Evaluated intended existence of projection {} to {}", projCtxDesc, shadowShouldExist);
// Let's reconcile the existence intent (shadowShouldExist) and the synchronization intent in the context
LensProjectionContext lowerOrderContext = LensUtil.findLowerOrderContext(context, projCtx);
if (synchronizationIntent == null || synchronizationIntent == SynchronizationIntent.SYNCHRONIZE) {
if (shadowShouldExist) {
projCtx.setActive(true);
if (projCtx.isExists()) {
if (lowerOrderContext != null && lowerOrderContext.isDelete()) {
// HACK HACK HACK
decision = SynchronizationPolicyDecision.DELETE;
} else {
decision = SynchronizationPolicyDecision.KEEP;
}
} else {
if (lowerOrderContext != null) {
if (lowerOrderContext.isDelete()) {
// HACK HACK HACK
decision = SynchronizationPolicyDecision.DELETE;
} else {
// If there is a lower-order context then that one will be ADD
// and this one is KEEP. When the execution comes to this context
// then the projection already exists
decision = SynchronizationPolicyDecision.KEEP;
}
} else {
decision = SynchronizationPolicyDecision.ADD;
}
}
} else {
// Delete
if (projCtx.isExists()) {
decision = SynchronizationPolicyDecision.DELETE;
} else {
// we should delete the entire context, but then we will lost track of what
// happened. So just ignore it.
decision = SynchronizationPolicyDecision.IGNORE;
// if there are any triggers then move them to focus. We may still need them.
LensUtil.moveTriggers(projCtx, context.getFocusContext());
}
}
} else if (synchronizationIntent == SynchronizationIntent.ADD) {
if (shadowShouldExist) {
projCtx.setActive(true);
if (projCtx.isExists()) {
// Attempt to add something that is already there, but should be OK
decision = SynchronizationPolicyDecision.KEEP;
} else {
decision = SynchronizationPolicyDecision.ADD;
}
} else {
throw new PolicyViolationException("Request to add projection " + projCtxDesc + " but the activation policy decided that it should not exist");
}
} else if (synchronizationIntent == SynchronizationIntent.KEEP) {
if (shadowShouldExist) {
projCtx.setActive(true);
if (projCtx.isExists()) {
decision = SynchronizationPolicyDecision.KEEP;
} else {
decision = SynchronizationPolicyDecision.ADD;
}
} else {
throw new PolicyViolationException("Request to keep projection " + projCtxDesc + " but the activation policy decided that it should not exist");
}
} else {
throw new IllegalStateException("Unknown sync intent " + synchronizationIntent);
}
LOGGER.trace("Evaluated decision for projection {} to {}", projCtxDesc, decision);
projCtx.setSynchronizationPolicyDecision(decision);
PrismObject<F> focusNew = context.getFocusContext().getObjectNew();
if (focusNew == null) {
// This must be a user delete or something similar. No point in proceeding
LOGGER.trace("focusNew is null, skipping activation processing of {}", projCtxDesc);
return;
}
if (decision == SynchronizationPolicyDecision.UNLINK || decision == SynchronizationPolicyDecision.DELETE) {
LOGGER.trace("Decision is {}, skipping activation properties processing for {}", decision, projCtxDesc);
return;
}
ResourceObjectTypeDefinitionType resourceAccountDefType = projCtx.getResourceObjectTypeDefinitionType();
if (resourceAccountDefType == null) {
LOGGER.trace("No refined object definition, therefore also no activation outbound definition, skipping activation processing for account " + projCtxDesc);
return;
}
ResourceActivationDefinitionType activationType = resourceAccountDefType.getActivation();
if (activationType == null) {
LOGGER.trace("No activation definition in projection {}, skipping activation properties processing", projCtxDesc);
return;
}
ActivationCapabilityType capActivation = ResourceTypeUtil.getEffectiveCapability(projCtx.getResource(), ActivationCapabilityType.class);
if (capActivation == null) {
LOGGER.trace("Skipping activation status and validity processing because {} has no activation capability", projCtx.getResource());
return;
}
ActivationStatusCapabilityType capStatus = CapabilityUtil.getEffectiveActivationStatus(capActivation);
ActivationValidityCapabilityType capValidFrom = CapabilityUtil.getEffectiveActivationValidFrom(capActivation);
ActivationValidityCapabilityType capValidTo = CapabilityUtil.getEffectiveActivationValidTo(capActivation);
ActivationLockoutStatusCapabilityType capLockoutStatus = CapabilityUtil.getEffectiveActivationLockoutStatus(capActivation);
if (capStatus != null) {
evaluateActivationMapping(context, projCtx, activationType.getAdministrativeStatus(), SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS, SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS, capActivation, now, true, ActivationType.F_ADMINISTRATIVE_STATUS.getLocalPart(), task, result);
} else {
LOGGER.trace("Skipping activation administrative status processing because {} does not have activation administrative status capability", projCtx.getResource());
}
ResourceBidirectionalMappingType validFromMappingType = activationType.getValidFrom();
if (validFromMappingType == null || validFromMappingType.getOutbound() == null) {
LOGGER.trace("Skipping activation validFrom processing because {} does not have appropriate outbound mapping", projCtx.getResource());
} else if (capValidFrom == null && !ExpressionUtil.hasExplicitTarget(validFromMappingType.getOutbound())) {
LOGGER.trace("Skipping activation validFrom processing because {} does not have activation validFrom capability nor outbound mapping with explicit target", projCtx.getResource());
} else {
evaluateActivationMapping(context, projCtx, activationType.getValidFrom(), SchemaConstants.PATH_ACTIVATION_VALID_FROM, SchemaConstants.PATH_ACTIVATION_VALID_FROM, null, now, true, ActivationType.F_VALID_FROM.getLocalPart(), task, result);
}
ResourceBidirectionalMappingType validToMappingType = activationType.getValidTo();
if (validToMappingType == null || validToMappingType.getOutbound() == null) {
LOGGER.trace("Skipping activation validTo processing because {} does not have appropriate outbound mapping", projCtx.getResource());
} else if (capValidTo == null && !ExpressionUtil.hasExplicitTarget(validToMappingType.getOutbound())) {
LOGGER.trace("Skipping activation validTo processing because {} does not have activation validTo capability nor outbound mapping with explicit target", projCtx.getResource());
} else {
evaluateActivationMapping(context, projCtx, activationType.getValidTo(), SchemaConstants.PATH_ACTIVATION_VALID_TO, SchemaConstants.PATH_ACTIVATION_VALID_TO, null, now, true, ActivationType.F_VALID_TO.getLocalPart(), task, result);
}
if (capLockoutStatus != null) {
evaluateActivationMapping(context, projCtx, activationType.getLockoutStatus(), SchemaConstants.PATH_ACTIVATION_LOCKOUT_STATUS, SchemaConstants.PATH_ACTIVATION_LOCKOUT_STATUS, capActivation, now, true, ActivationType.F_LOCKOUT_STATUS.getLocalPart(), task, result);
} else {
LOGGER.trace("Skipping activation lockout status processing because {} does not have activation lockout status capability", projCtx.getResource());
}
}
use of com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType in project midpoint by Evolveum.
the class PageAccounts method loadShadowOwner.
private <F extends FocusType> F loadShadowOwner(IModel<SelectableBean> model) {
F owner = null;
ShadowType shadow = getShadow(model);
String shadowOid;
if (shadow != null) {
shadowOid = shadow.getOid();
} else {
return null;
}
Task task = createSimpleTask(OPERATION_LOAD_ACCOUNT_OWNER);
OperationResult result = new OperationResult(OPERATION_LOAD_ACCOUNT_OWNER);
try {
PrismObject prismOwner = getModelService().searchShadowOwner(shadowOid, null, task, result);
if (prismOwner != null) {
owner = (F) prismOwner.asObjectable();
}
} catch (ObjectNotFoundException exception) {
//owner was not found, it's possible and it's ok on unlinked accounts
} catch (Exception ex) {
result.recordFatalError(getString("PageAccounts.message.ownerNotFound", shadowOid), ex);
LoggingUtils.logUnexpectedException(LOGGER, "Could not load owner of account with oid: " + shadowOid, ex);
} finally {
result.computeStatusIfUnknown();
}
if (WebComponentUtil.showResultInPage(result)) {
showResult(result, false);
}
return owner;
}
use of com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType in project midpoint by Evolveum.
the class PageAccounts method ownerDetailsPerformed.
private <F extends FocusType> void ownerDetailsPerformed(AjaxRequestTarget target, IModel<SelectableBean> model) {
F focus = loadShadowOwner(model);
if (focus == null) {
error(getString("PageAccounts.message.cantShowOwner"));
target.add(getFeedbackPanel());
return;
}
PageParameters parameters = new PageParameters();
parameters.add(OnePageParameterEncoder.PARAMETER, focus.getOid());
if (focus instanceof UserType) {
navigateToNext(PageUser.class, parameters);
} else if (focus instanceof RoleType) {
navigateToNext(PageRole.class, parameters);
} else if (focus instanceof OrgType) {
navigateToNext(PageOrgUnit.class, parameters);
} else {
error(getString("PageAccounts.message.unsupportedOwnerType"));
target.add(getFeedbackPanel());
return;
}
}
use of com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType in project midpoint by Evolveum.
the class ShadowIntegrityCheckResultHandler method checkShadow.
private void checkShadow(ShadowCheckResult checkResult, PrismObject<ShadowType> shadow, Task workerTask, OperationResult result) throws SchemaException {
ShadowType shadowType = shadow.asObjectable();
ObjectReferenceType resourceRef = shadowType.getResourceRef();
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Checking shadow {} (resource {})", ObjectTypeUtil.toShortString(shadowType), resourceRef != null ? resourceRef.getOid() : "(null)");
}
statistics.incrementShadows();
if (resourceRef == null) {
checkResult.recordError(Statistics.NO_RESOURCE_OID, new SchemaException("No resourceRef"));
fixNoResourceIfRequested(checkResult, Statistics.NO_RESOURCE_OID);
applyFixes(checkResult, shadow, workerTask, result);
return;
}
String resourceOid = resourceRef.getOid();
if (resourceOid == null) {
checkResult.recordError(Statistics.NO_RESOURCE_OID, new SchemaException("Null resource OID"));
fixNoResourceIfRequested(checkResult, Statistics.NO_RESOURCE_OID);
applyFixes(checkResult, shadow, workerTask, result);
return;
}
PrismObject<ResourceType> resource = resources.get(resourceOid);
if (resource == null) {
statistics.incrementResources();
try {
resource = provisioningService.getObject(ResourceType.class, resourceOid, null, workerTask, result);
} catch (ObjectNotFoundException e) {
checkResult.recordError(Statistics.NO_RESOURCE, new ObjectNotFoundException("Resource object does not exist: " + e.getMessage(), e));
fixNoResourceIfRequested(checkResult, Statistics.NO_RESOURCE);
applyFixes(checkResult, shadow, workerTask, result);
return;
} catch (SchemaException e) {
checkResult.recordError(Statistics.CANNOT_GET_RESOURCE, new SchemaException("Resource object has schema problems: " + e.getMessage(), e));
return;
} catch (CommonException | RuntimeException e) {
checkResult.recordError(Statistics.CANNOT_GET_RESOURCE, new SystemException("Resource object cannot be fetched for some reason: " + e.getMessage(), e));
return;
}
resources.put(resourceOid, resource);
}
checkResult.setResource(resource);
ShadowKindType kind = shadowType.getKind();
if (kind == null) {
// TODO or simply assume account?
checkResult.recordError(Statistics.NO_KIND_SPECIFIED, new SchemaException("No kind specified"));
return;
}
if (checkExtraData) {
checkOrFixShadowActivationConsistency(checkResult, shadow, fixExtraData);
}
PrismObject<ShadowType> fetchedShadow = null;
if (checkFetch) {
fetchedShadow = fetchShadow(checkResult, shadow, resource, workerTask, result);
if (fetchedShadow != null) {
shadow.setUserData(KEY_EXISTS_ON_RESOURCE, "true");
}
}
if (checkOwners) {
List<PrismObject<FocusType>> owners = searchOwners(shadow, result);
if (owners != null) {
shadow.setUserData(KEY_OWNERS, owners);
if (owners.size() > 1) {
checkResult.recordError(Statistics.MULTIPLE_OWNERS, new SchemaException("Multiple owners: " + owners));
}
}
if (shadowType.getSynchronizationSituation() == SynchronizationSituationType.LINKED && (owners == null || owners.isEmpty())) {
checkResult.recordError(Statistics.LINKED_WITH_NO_OWNER, new SchemaException("Linked shadow with no owner"));
}
if (shadowType.getSynchronizationSituation() != SynchronizationSituationType.LINKED && owners != null && !owners.isEmpty()) {
checkResult.recordError(Statistics.NOT_LINKED_WITH_OWNER, new SchemaException("Shadow with an owner but not marked as linked (marked as " + shadowType.getSynchronizationSituation() + ")"));
}
}
String intent = shadowType.getIntent();
if (checkIntents && (intent == null || intent.isEmpty())) {
checkResult.recordWarning(Statistics.NO_INTENT_SPECIFIED, "None or empty intent");
}
if (fixIntents && (intent == null || intent.isEmpty())) {
doFixIntent(checkResult, fetchedShadow, shadow, resource, workerTask, result);
}
Pair<String, ShadowKindType> key = new ImmutablePair<>(resourceOid, kind);
ObjectTypeContext context = contextMap.get(key);
if (context == null) {
context = new ObjectTypeContext();
context.setResource(resource);
RefinedResourceSchema resourceSchema;
try {
resourceSchema = RefinedResourceSchemaImpl.getRefinedSchema(context.getResource(), LayerType.MODEL, prismContext);
} catch (SchemaException e) {
checkResult.recordError(Statistics.CANNOT_GET_REFINED_SCHEMA, new SchemaException("Couldn't derive resource schema: " + e.getMessage(), e));
return;
}
if (resourceSchema == null) {
checkResult.recordError(Statistics.NO_RESOURCE_REFINED_SCHEMA, new SchemaException("No resource schema"));
return;
}
context.setObjectClassDefinition(resourceSchema.getRefinedDefinition(kind, shadowType));
if (context.getObjectClassDefinition() == null) {
// TODO or warning only?
checkResult.recordError(Statistics.NO_OBJECT_CLASS_REFINED_SCHEMA, new SchemaException("No refined object class definition for kind=" + kind + ", intent=" + intent));
return;
}
contextMap.put(key, context);
}
try {
provisioningService.applyDefinition(shadow, workerTask, result);
} catch (SchemaException | ObjectNotFoundException | CommunicationException | ConfigurationException | ExpressionEvaluationException e) {
checkResult.recordError(Statistics.OTHER_FAILURE, new SystemException("Couldn't apply definition to shadow from repo", e));
return;
}
Set<RefinedAttributeDefinition<?>> identifiers = new HashSet<>();
Collection<? extends RefinedAttributeDefinition<?>> primaryIdentifiers = context.getObjectClassDefinition().getPrimaryIdentifiers();
identifiers.addAll(primaryIdentifiers);
identifiers.addAll(context.getObjectClassDefinition().getSecondaryIdentifiers());
PrismContainer<ShadowAttributesType> attributesContainer = shadow.findContainer(ShadowType.F_ATTRIBUTES);
if (attributesContainer == null) {
// might happen on unfinished shadows?
checkResult.recordError(Statistics.OTHER_FAILURE, new SchemaException("No attributes container"));
return;
}
for (RefinedAttributeDefinition<?> identifier : identifiers) {
PrismProperty property = attributesContainer.getValue().findProperty(identifier.getName());
if (property == null || property.size() == 0) {
checkResult.recordWarning(Statistics.OTHER_FAILURE, "No value for identifier " + identifier.getName());
continue;
}
if (property.size() > 1) {
// we don't expect multi-valued identifiers
checkResult.recordError(Statistics.OTHER_FAILURE, new SchemaException("Multi-valued identifier " + identifier.getName() + " with values " + property.getValues()));
continue;
}
// size == 1
String value = (String) property.getValue().getValue();
if (value == null) {
checkResult.recordWarning(Statistics.OTHER_FAILURE, "Null value for identifier " + identifier.getName());
continue;
}
if (checkUniqueness) {
if (!checkDuplicatesOnPrimaryIdentifiersOnly || primaryIdentifiers.contains(identifier)) {
addIdentifierValue(checkResult, context, identifier.getName(), value, shadow);
}
}
if (checkNormalization) {
doCheckNormalization(checkResult, identifier, value, context);
}
}
applyFixes(checkResult, shadow, workerTask, result);
}
use of com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType in project midpoint by Evolveum.
the class ShadowIntegrityCheckResultHandler method deleteShadows.
// shadowsToDelete do not contain 'already deleted shadows'
private void deleteShadows(DuplicateShadowsTreatmentInstruction instruction, StringBuilder sb, Task task, OperationResult result) {
LOGGER.trace("Going to delete shadows:\n{}", instruction);
if (instruction == null || instruction.getShadowsToDelete() == null) {
return;
}
Collection<PrismObject<ShadowType>> shadowsToDelete = instruction.getShadowsToDelete();
String shadowOidToReplaceDeleted = instruction.getShadowOidToReplaceDeletedOnes();
for (PrismObject<ShadowType> shadowToDelete : shadowsToDelete) {
LOGGER.info("Deleting redundant shadow{} {}", skippedForDryRun(), ObjectTypeUtil.toShortString(shadowToDelete));
sb.append(" --> deleted redundant shadow").append(skippedForDryRun()).append(" ").append(ObjectTypeUtil.toShortString(shadowToDelete)).append("\n");
String oid = shadowToDelete.getOid();
List<PrismObject<FocusType>> owners;
if (checkOwners) {
owners = (List) shadowToDelete.getUserData(KEY_OWNERS);
} else {
owners = searchOwners(shadowToDelete, result);
}
if (!dryRun) {
try {
repositoryService.deleteObject(ShadowType.class, oid, result);
task.recordObjectActionExecuted(shadowToDelete, ChangeType.DELETE, null);
duplicateShadowsDeleted.add(oid);
} catch (ObjectNotFoundException e) {
// suspicious, but not a big deal
task.recordObjectActionExecuted(shadowToDelete, ChangeType.DELETE, e);
LoggingUtils.logExceptionAsWarning(LOGGER, "Shadow {} couldn't be deleted, because it does not exist anymore", e, ObjectTypeUtil.toShortString(shadowToDelete));
continue;
} catch (RuntimeException e) {
task.recordObjectActionExecuted(shadowToDelete, ChangeType.DELETE, e);
LoggingUtils.logUnexpectedException(LOGGER, "Shadow {} couldn't be deleted because of an unexpected exception", e, ObjectTypeUtil.toShortString(shadowToDelete));
continue;
}
}
if (owners == null || owners.isEmpty()) {
continue;
}
for (PrismObject owner : owners) {
List<ItemDelta> modifications = new ArrayList<>(2);
ReferenceDelta deleteDelta = ReferenceDelta.createModificationDelete(FocusType.F_LINK_REF, owner.getDefinition(), new PrismReferenceValue(oid, ShadowType.COMPLEX_TYPE));
modifications.add(deleteDelta);
if (shadowOidToReplaceDeleted != null) {
ReferenceDelta addDelta = ReferenceDelta.createModificationAdd(FocusType.F_LINK_REF, owner.getDefinition(), new PrismReferenceValue(shadowOidToReplaceDeleted, ShadowType.COMPLEX_TYPE));
modifications.add(addDelta);
}
LOGGER.info("Executing modify delta{} for owner {}:\n{}", skippedForDryRun(), ObjectTypeUtil.toShortString(owner), DebugUtil.debugDump(modifications));
if (!dryRun) {
try {
repositoryService.modifyObject((Class) owner.getClass(), owner.getOid(), modifications, result);
task.recordObjectActionExecuted(owner, ChangeType.MODIFY, null);
} catch (ObjectNotFoundException | SchemaException | ObjectAlreadyExistsException | RuntimeException e) {
task.recordObjectActionExecuted(owner, ChangeType.MODIFY, e);
LoggingUtils.logUnexpectedException(LOGGER, "Focal object {} (owner of {}) couldn't be updated", e, ObjectTypeUtil.toShortString(owner), ObjectTypeUtil.toShortString(shadowToDelete));
}
}
}
}
}
Aggregations