diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/util/WebModelServiceUtils.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/util/WebModelServiceUtils.java index ff721c90bbc..72f8f7e0879 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/util/WebModelServiceUtils.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/api/util/WebModelServiceUtils.java @@ -1,844 +1,848 @@ -/* - * Copyright (c) 2010-2019 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.gui.api.util; - -import static com.evolveum.midpoint.schema.GetOperationOptions.createNoFetchCollection; - -import java.util.*; - -import com.evolveum.midpoint.prism.PrismReferenceValue; -import com.evolveum.midpoint.util.QNameUtil; -import com.evolveum.midpoint.xml.ns._public.common.common_3.*; -import org.apache.commons.lang.BooleanUtils; -import org.apache.commons.lang.LocaleUtils; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang.Validate; -import org.apache.wicket.RestartResponseException; -import org.apache.wicket.Session; -import org.apache.wicket.ThreadContext; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import com.evolveum.midpoint.common.LocalizationService; -import com.evolveum.midpoint.gui.api.page.PageBase; -import com.evolveum.midpoint.model.api.ModelExecuteOptions; -import com.evolveum.midpoint.model.api.ModelInteractionService; -import com.evolveum.midpoint.model.api.authentication.CompiledGuiProfile; -import com.evolveum.midpoint.model.api.authentication.GuiProfiledPrincipal; -import com.evolveum.midpoint.prism.PrismContext; -import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.prism.PrismObjectDefinition; -import com.evolveum.midpoint.prism.delta.ChangeType; -import com.evolveum.midpoint.prism.delta.DeltaFactory; -import com.evolveum.midpoint.prism.delta.ObjectDelta; -import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.prism.query.ObjectQuery; -import com.evolveum.midpoint.schema.GetOperationOptions; -import com.evolveum.midpoint.schema.GetOperationOptionsBuilder; -import com.evolveum.midpoint.schema.SchemaHelper; -import com.evolveum.midpoint.schema.SelectorOptions; -import com.evolveum.midpoint.schema.constants.SchemaConstants; -import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.schema.util.ObjectTypeUtil; -import com.evolveum.midpoint.security.api.MidPointPrincipal; -import com.evolveum.midpoint.task.api.Task; -import com.evolveum.midpoint.task.api.TaskManager; -import com.evolveum.midpoint.util.exception.AuthorizationException; -import com.evolveum.midpoint.util.exception.CommonException; -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.logging.LoggingUtils; -import com.evolveum.midpoint.util.logging.Trace; -import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.web.page.login.PageLogin; -import com.evolveum.midpoint.web.security.MidPointApplication; -import com.evolveum.midpoint.web.security.util.SecurityUtils; -import com.evolveum.prism.xml.ns._public.types_3.EvaluationTimeType; - -import javax.xml.namespace.QName; - -/** - * Utility class that contains methods that interact with ModelService and other - * midPoint components. - * - * @author lazyman - */ -public class WebModelServiceUtils { - - private static final Trace LOGGER = TraceManager.getTrace(WebModelServiceUtils.class); - - private static final String DOT_CLASS = WebModelServiceUtils.class.getName() + "."; - private static final String OPERATION_LOAD_OBJECT = DOT_CLASS + "loadObject"; - private static final String OPERATION_DELETE_OBJECT = DOT_CLASS + "deleteObject"; - private static final String OPERATION_SEARCH_OBJECTS = DOT_CLASS + "searchObjects"; - private static final String OPERATION_SAVE_OBJECT = DOT_CLASS + "saveObject"; - private static final String OPERATION_LOAD_OBJECT_REFS = DOT_CLASS + "loadObjectReferences"; - private static final String OPERATION_COUNT_OBJECT = DOT_CLASS + "countObjects"; - private static final String OPERATION_ASSUME_POWER_OF_ATTORNEY = DOT_CLASS + "assumePowerOfAttorney"; - private static final String OPERATION_DROP_POWER_OF_ATTORNEY = DOT_CLASS + "dropPowerOfAttorney"; - private static final String OPERATION_GET_SYSTEM_CONFIG = DOT_CLASS + "getSystemConfiguration"; - private static final String OPERATION_LOAD_FLOW_POLICY = DOT_CLASS + "loadFlowPolicy"; - - public static String resolveReferenceName(ObjectReferenceType ref, PageBase page) { - return resolveReferenceName(ref, page, false); - } - - public static String resolveReferenceName(ObjectReferenceType ref, PageBase page, boolean translate) { - Task task = page.createSimpleTask(WebModelServiceUtils.class.getName() + ".resolveReferenceName"); - return resolveReferenceName(ref, page, task, task.getResult(), translate); - } - - public static String resolveReferenceName(ObjectReferenceType ref, PageBase page, Task task, OperationResult result) { - return resolveReferenceName(ref, page, task, result, false); - } - - public static String resolveReferenceName(ObjectReferenceType ref, PageBase page, Task task, OperationResult result, boolean translate) { - if (ref == null) { - return null; - } - if (ref.getTargetName() != null) { - return translate ? page.getLocalizationService().translate(ref.getTargetName().toPolyString(), page.getLocale(), true) - : ref.getTargetName().getOrig(); - } - if (StringUtils.isEmpty(ref.getOid()) || ref.getType() == null){ - return null; - } - PrismObject object = resolveReferenceNoFetch(ref, page, task, result); - if (object == null) { - return ref.getOid(); - } else { - ref.asReferenceValue().setObject(object); - return WebComponentUtil.getName(object, translate); - } - } - - public static PrismObject resolveReferenceNoFetch(ObjectReferenceType reference, PageBase page, Task task, OperationResult result) { - if (reference == null) { - return null; - } - if (reference.asReferenceValue().getObject() != null) { - return reference.asReferenceValue().getObject(); - } - PrismContext prismContext = page.getPrismContext(); - if (reference.getType() == null) { - LOGGER.error("No type in {}", reference); - return null; - } - PrismObjectDefinition definition = prismContext.getSchemaRegistry().findObjectDefinitionByType(reference.getType()); - if (definition == null) { - LOGGER.error("No definition for {} was found", reference.getType()); - return null; - } - if (reference.getOid() == null) { - if (reference.getResolutionTime() == EvaluationTimeType.RUN) { - // Runtime reference resolution. Ignore it for now. Later we maybe would want to resolve it here. - // But it may resolve to several objects .... - return null; - } else { - LOGGER.error("Null OID in reference {}", reference); - // Throw an exception instead? Maybe not. We want GUI to be robust. - return null; - } - } - return loadObject(definition.getCompileTimeClass(), reference.getOid(), createNoFetchCollection(), page, task, result); - } - - public static List createObjectReferenceList(Class type, PageBase page, Map referenceMap){ - referenceMap.clear(); - - OperationResult result = new OperationResult(OPERATION_LOAD_OBJECT_REFS); -// Task task = page.createSimpleTask(OPERATION_LOAD_PASSWORD_POLICIES); - - try { - List> objects = searchObjects(type, null, result, page); - result.recomputeStatus(); - List references = new ArrayList<>(); - - for(PrismObject object: objects){ - referenceMap.put(object.getOid(), WebComponentUtil.getName(object)); - references.add(ObjectTypeUtil.createObjectRef(object, page.getPrismContext())); - - } - return references; - } catch (Exception e){ - result.recordFatalError(page.createStringResource("WebModelUtils.couldntLoadPasswordPolicies").getString(), e); - LoggingUtils.logUnexpectedException(LOGGER, "Couldn't load password policies", e); - } - - // TODO - show error somehow - // if(!result.isSuccess()){ - // getPageBase().showResult(result); - // } - - return null; - } - - public static String runTask(TaskType taskToRun, Task operationalTask, OperationResult parentResult, PageBase pageBase){ - try { - ObjectDelta delta = DeltaFactory.Object.createAddDelta(taskToRun.asPrismObject()); - pageBase.getPrismContext().adopt(delta); - pageBase.getModelService().executeChanges(WebComponentUtil.createDeltaCollection(delta), null, - operationalTask, parentResult); - parentResult.recordInProgress(); - parentResult.setBackgroundTaskOid(delta.getOid()); - pageBase.showResult(parentResult); - return delta.getOid(); - } catch (ObjectAlreadyExistsException | ObjectNotFoundException | SchemaException - | ExpressionEvaluationException | CommunicationException | ConfigurationException - | PolicyViolationException | SecurityViolationException e) { - // TODO Auto-generated catch block -// error(pageBase.getString("pageUsers.message.nothingSelected") + e.getMessage()); - parentResult.recordFatalError(pageBase.createStringResource("WebModelUtils.couldntRunTask", e.getMessage()).getString(), e); - LoggingUtils.logUnexpectedException(LOGGER, "Couldn't run task " + e.getMessage(), e); - return null; - } - - } - - public static void runTask(Collection tasksToRun, Task operationalTask, OperationResult parentResult, PageBase pageBase){ -// try { - - for (TaskType taskToRun : tasksToRun){ - runTask(tasksToRun, operationalTask, parentResult, pageBase); - } - -// } -// ObjectDelta delta = ObjectDelta.createAddDelta(taskToRun.asPrismObject()); -// pageBase.getPrismContext().adopt(delta); -// pageBase.getModelService().executeChanges(WebComponentUtil.createDeltaCollection(delta), null, -// operationalTask, parentResult); -// parentResult.recordInProgress(); -// parentResult.setBackgroundTaskOid(delta.getOid()); -// pageBase.showResult(parentResult); -// return delta.getOid(); -// } catch (ObjectAlreadyExistsException | ObjectNotFoundException | SchemaException -// | ExpressionEvaluationException | CommunicationException | ConfigurationException -// | PolicyViolationException | SecurityViolationException e) { -// // TODO Auto-generated catch block -//// error(pageBase.getString("pageUsers.message.nothingSelected") + e.getMessage()); -// parentResult.recordFatalError(pageBase.createStringResource("WebModelUtils.couldntRunTask", e.getMessage()).getString(), e); -// LoggingUtils.logUnexpectedException(LOGGER, "Couldn't run task " + e.getMessage(), e); -// return null; -// } - - } - - public static PrismObject loadObject(PrismReferenceValue objectRef, QName expectedTargetType, PageBase pageBase, Task task, OperationResult result) { - if (objectRef == null) { - return null; - } - - if (QNameUtil.match(expectedTargetType, objectRef.getTargetType())) { - Class type = pageBase.getPrismContext().getSchemaRegistry().determineClassForType(objectRef.getTargetType()); - PrismObject resourceType = WebModelServiceUtils.loadObject(type, objectRef.getOid(), GetOperationOptions.createNoFetchCollection(), pageBase, task, result); - return resourceType; - } - - return null; - } - - @Nullable - public static PrismObject loadObject(ObjectReferenceType objectReference, - PageBase page, Task task, OperationResult result) { - Class type = page.getPrismContext().getSchemaRegistry().determineClassForType(objectReference.getType()); - return loadObject(type, objectReference.getOid(), null, page, task, result); - } - - @Nullable - public static PrismObject loadObject(Class type, String oid, - PageBase page, Task task, OperationResult result) { - return loadObject(type, oid, null, page, task, result); - } - - @Nullable - public static PrismObject loadObject(Class type, String oid, - Collection> options, - PageBase page, Task task, OperationResult result) { - return loadObject(type, oid, options, true, page, task, result); - } - - @Nullable - public static PrismObject loadObject(Class type, String oid, - Collection> options, boolean allowNotFound, - PageBase page, Task task, OperationResult result) { - LOGGER.debug("Loading {} with oid {}, options {}", type.getSimpleName(), oid, options); - - OperationResult subResult; - if (result != null) { - subResult = result.createMinorSubresult(OPERATION_LOAD_OBJECT); - } else { - subResult = new OperationResult(OPERATION_LOAD_OBJECT); - } - PrismObject object = null; - try { - if (options == null) { - options = SelectorOptions.createCollection(GetOperationOptions.createResolveNames()); - } else { - GetOperationOptions getOpts = SelectorOptions.findRootOptions(options); - if (getOpts == null) { - options.add(new SelectorOptions<>(GetOperationOptions.createResolveNames())); - } else { - getOpts.setResolveNames(Boolean.TRUE); - } - } - object = page.getModelService().getObject(type, oid, options, task, subResult); - } catch (AuthorizationException e) { - // Not authorized to access the object. This is probably caused by a reference that - // point to an object that the current user cannot read. This is no big deal. - // Just do not display that object. - subResult.recordHandledError(e); - LOGGER.debug("User {} is not authorized to read {} {}", - task.getOwner() != null ? task.getOwner().getName() : null, type.getSimpleName(), oid); - return null; - } catch (ObjectNotFoundException e) { - if (allowNotFound) { - // Object does not exist. It was deleted in the meanwhile, or not created yet. This could happen quite often. - subResult.recordHandledError(e); - LOGGER.debug("{} {} does not exist", type.getSimpleName(), oid, e); - return null; - } else { - subResult.recordFatalError(page.createStringResource("WebModelUtils.couldntLoadObject").getString(), e); - LoggingUtils.logUnexpectedException(LOGGER, "Couldn't load object", e); - } - } catch (Exception ex) { - subResult.recordFatalError(page.createStringResource("WebModelUtils.couldntLoadObject").getString(), ex); - LoggingUtils.logUnexpectedException(LOGGER, "Couldn't load object", ex); - } finally { - subResult.computeStatus(); - } - // TODO reconsider this part: until recently, the condition was always 'false' - if (WebComponentUtil.showResultInPage(subResult)) { - page.showResult(subResult); - } - - LOGGER.debug("Loaded {} with result {}", object, subResult); - - return object; - } - - //TODO consider using modelServiceLocator instead of PageBase in other methods.. Do we even need it? What about showResult? Should it be - // here or directly in the page? Consider usability and readabiltiy - @Nullable - public static PrismObject loadObject(ObjectReferenceType objectReference, - ModelServiceLocator page, Task task, OperationResult result) { - Class type = page.getPrismContext().getSchemaRegistry().determineClassForType(objectReference.getType()); - String oid = objectReference.getOid(); - Collection> options = null; - LOGGER.debug("Loading {} with oid {}, options {}", type.getSimpleName(), oid, options); - - OperationResult subResult; - if (result != null) { - subResult = result.createMinorSubresult(OPERATION_LOAD_OBJECT); - } else { - subResult = new OperationResult(OPERATION_LOAD_OBJECT); - } - PrismObject object = null; - try { - if (options == null) { - options = SelectorOptions.createCollection(GetOperationOptions.createResolveNames()); - } else { - GetOperationOptions getOpts = SelectorOptions.findRootOptions(options); - if (getOpts == null) { - options.add(new SelectorOptions<>(GetOperationOptions.createResolveNames())); - } else { - getOpts.setResolveNames(Boolean.TRUE); - } - } - object = page.getModelService().getObject(type, oid, options, task, subResult); - } catch (AuthorizationException e) { - // Not authorized to access the object. This is probably caused by a reference that - // point to an object that the current user cannot read. This is no big deal. - // Just do not display that object. - subResult.recordHandledError(e); - LOGGER.debug("User {} is not authorized to read {} {}", - task.getOwner() != null ? task.getOwner().getName() : null, type.getSimpleName(), oid); - return null; - } catch (ObjectNotFoundException e) { - // Object does not exist. It was deleted in the meanwhile, or not created yet. This could happen quite often. - subResult.recordHandledError(e); - LOGGER.debug("{} {} does not exist", type.getSimpleName(), oid, e); - return null; - - } catch (Exception ex) { - subResult.recordFatalError("WebModelUtils.couldntLoadObject", ex); - LoggingUtils.logUnexpectedException(LOGGER, "Couldn't load object", ex); - } finally { - subResult.computeStatus(); - } - // TODO reconsider this part: until recently, the condition was always 'false' - if (WebComponentUtil.showResultInPage(subResult)) { - if (page instanceof PageBase) { - ((PageBase)page).showResult(subResult); - } - } - - LOGGER.debug("Loaded {} with result {}", object, subResult); - - return object; - } - - public static boolean isNoFetch(Collection> options) { - if (options == null) { - return false; - } - GetOperationOptions rootOptions = SelectorOptions.findRootOptions(options); - if (rootOptions == null) { - return false; - } - return GetOperationOptions.isNoFetch(rootOptions); - } - - @NotNull - public static List> searchObjects( - Class type, ObjectQuery query, OperationResult result, PageBase page) { - return searchObjects(type, query, null, result, page, null); - } - - @NotNull - public static List> searchObjects(Class type, ObjectQuery query, - Collection> options, - OperationResult result, PageBase page) { - return searchObjects(type, query, options, result, page, null); - } - - @NotNull - public static List> searchObjects( - Class type, ObjectQuery query, Collection> options, - OperationResult result, PageBase page, PrismObject principal) { - LOGGER.debug("Searching {} with oid {}, options {}", type.getSimpleName(), query, options); - - OperationResult subResult; - if (result != null) { - subResult = result.createMinorSubresult(OPERATION_SEARCH_OBJECTS); - } else { - subResult = new OperationResult(OPERATION_SEARCH_OBJECTS); - } - List> objects = new ArrayList<>(); - try { - Task task = createSimpleTask(subResult.getOperation(), principal, page.getTaskManager()); - List> list = page.getModelService().searchObjects(type, query, options, task, subResult); - if (list != null) { - objects.addAll(list); - } - } catch (Exception ex) { - subResult.recordFatalError(page.createStringResource("WebModelUtils.couldntSearchObjects").getString(), ex); - LoggingUtils.logUnexpectedException(LOGGER, "Couldn't search objects", ex); - } finally { - subResult.computeStatus(); - } - - if (result == null && WebComponentUtil.showResultInPage(subResult)) { - page.showResult(subResult); - } - - LOGGER.debug("Loaded ({}) with result {}", objects.size(), subResult); - - return objects; - } - - public static int countObjects(Class type, ObjectQuery query, PageBase page) { - LOGGER.debug("Count object: type => {}, query => {}", type, query); - Task task = page.createSimpleTask(OPERATION_COUNT_OBJECT); - OperationResult parentResult = new OperationResult(OPERATION_COUNT_OBJECT); - int count = 0; - try { - count = page.getModelService().countObjects(type, query, null, task, parentResult); - } catch (SchemaException | ObjectNotFoundException | SecurityViolationException - | ConfigurationException | CommunicationException | ExpressionEvaluationException ex) { - parentResult.recordFatalError(page.createStringResource("WebModelUtils.couldntCountObjects").getString(), ex); - LoggingUtils.logUnexpectedException(LOGGER, "Couldn't count objects", ex); - } - - LOGGER.debug("Count objects with result {}", parentResult); - return count; - } - - public static void deleteObject(Class type, String oid, OperationResult result, - PageBase page) { - deleteObject(type, oid, null, result, page, null); - } - - public static void deleteObject(Class type, String oid, ModelExecuteOptions options, - OperationResult result, PageBase page) { - deleteObject(type, oid, options, result, page, null); - } - - public static void deleteObject(Class type, String oid, ModelExecuteOptions options, - OperationResult result, PageBase page, - PrismObject principal) { - LOGGER.debug("Deleting {} with oid {}, options {}", type.getSimpleName(), oid, options); - - OperationResult subResult; - if (result != null) { - subResult = result.createMinorSubresult(OPERATION_DELETE_OBJECT); - } else { - subResult = new OperationResult(OPERATION_DELETE_OBJECT); - } - try { - Task task = createSimpleTask(result.getOperation(), principal, page.getTaskManager()); - - ObjectDelta delta = page.getPrismContext().deltaFactory().object().create(type, ChangeType.DELETE); - delta.setOid(oid); - - page.getModelService().executeChanges(WebComponentUtil.createDeltaCollection(delta), options, task, subResult); - } catch (Exception ex) { - subResult.recordFatalError(page.createStringResource("WebModelUtils.couldntDeleteObject").getString(), ex); - LoggingUtils.logUnexpectedException(LOGGER, "Couldn't delete object", ex); - } finally { - subResult.computeStatus(); - } - - if (result == null && WebComponentUtil.showResultInPage(subResult)) { - page.showResult(subResult); - } - - LOGGER.debug("Deleted with result {}", result); - } - - public static Collection> createOptionsForParentOrgRefs(GetOperationOptionsBuilder builder) { - return builder - .item(ObjectType.F_PARENT_ORG_REF).retrieve() - .build(); - } - - public static void save(ObjectDelta delta, OperationResult result, PageBase page) { - save(delta, result, null, page); - } - - public static void save(ObjectDelta delta, OperationResult result, Task task, PageBase page) { - save(delta, null, result, task, page); - } - - public static void save(ObjectDelta delta, ModelExecuteOptions options, OperationResult result, Task task, PageBase page) { - save(WebComponentUtil.createDeltaCollection(delta), options, result, task, page); - } - - - public static void save(Collection> deltas, ModelExecuteOptions options, - OperationResult result, Task task, PageBase page) { - LOGGER.debug("Saving deltas {}, options {}", deltas, options); - - OperationResult subResult; - if (result != null) { - subResult = result.createMinorSubresult(OPERATION_SAVE_OBJECT); - } else { - subResult = new OperationResult(OPERATION_SAVE_OBJECT); - } - - try { - if (task == null) { - task = page.createSimpleTask(result.getOperation()); - } - - page.getModelService().executeChanges(deltas, options, task, result); - } catch (Exception ex) { - subResult.recordFatalError(ex.getMessage()); - LoggingUtils.logUnexpectedException(LOGGER, "Couldn't save object", ex); - } finally { - subResult.computeStatus(); - } - - if (result == null && WebComponentUtil.showResultInPage(subResult)) { - page.showResult(subResult); - } - - LOGGER.debug("Saved with result {}", subResult); - } - - public static ObjectDelta createActivationAdminStatusDelta( - Class type, String oid, boolean enabled, PrismContext context) { - - ItemPath path = SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS; - ActivationStatusType status = enabled ? ActivationStatusType.ENABLED : ActivationStatusType.DISABLED; - ObjectDelta objectDelta = context.deltaFactory().object().createModificationReplaceProperty(type, oid, path, - status); - - return objectDelta; - } - - public static FocusType getLoggedInFocus() { - MidPointPrincipal principal = SecurityUtils.getPrincipalUser(); - Validate.notNull(principal, "No principal"); - if (principal.getFocus() == null) { - throw new IllegalArgumentException("No focus in principal: " + principal); - } - return principal.getFocus(); - } - - public static String getLoggedInFocusOid() { - MidPointPrincipal principal = SecurityUtils.getPrincipalUser(); - Validate.notNull(principal, "No principal"); - if (principal.getOid() == null) { - throw new IllegalArgumentException("No OID in principal: "+principal); - } - return principal.getOid(); - } - - public static Locale getLocale() { - return getLocale(null); - } - - public static Locale getLocale(FocusType focus) { - MidPointPrincipal principal = SecurityUtils.getPrincipalUser(); - Locale locale = null; - if (principal != null) { - if (focus == null) { - PrismObject focusPrismObject = principal.getFocus().asPrismObject(); - focus = focusPrismObject == null ? null : focusPrismObject.asObjectable(); - } - if (focus != null && focus.getPreferredLanguage() != null && - !focus.getPreferredLanguage().trim().equals("")) { - try { - locale = LocaleUtils.toLocale(focus.getPreferredLanguage()); - } catch (Exception ex) { - LOGGER.debug("Error occurred while getting user locale, " + ex.getMessage()); - } - } - if (locale != null && MidPointApplication.containsLocale(locale)) { - return locale; - } else { - String userLocale = focus != null ? focus.getLocale() : null; - try { - locale = userLocale == null ? null : LocaleUtils.toLocale(userLocale); - } catch (Exception ex) { - LOGGER.debug("Error occurred while getting user locale, " + ex.getMessage()); - } - if (locale != null && MidPointApplication.containsLocale(locale)) { - return locale; - } else { - //session in tests is null - if (ThreadContext.getSession() == null) { - return MidPointApplication.getDefaultLocale(); - } - - locale = Session.get().getLocale(); - if (locale == null || !MidPointApplication.containsLocale(locale)) { - //default locale for web application - return MidPointApplication.getDefaultLocale(); - } - return locale; - } - } - } - return MidPointApplication.getDefaultLocale(); - } - - public static TimeZone getTimezone() { - return getTimezone(null); - } - - public static TimeZone getTimezone(FocusType focus) { - GuiProfiledPrincipal principal = SecurityUtils.getPrincipalUser(); - if (principal != null && focus == null) { - focus = principal.getFocus(); - } - String timeZone; - - if (focus != null && StringUtils.isNotEmpty(focus.getTimezone())) { - timeZone = focus.getTimezone(); - } else { - timeZone = principal != null && principal.getCompiledGuiProfile() != null ? - principal.getCompiledGuiProfile().getDefaultTimezone() : ""; - } - try { - if (timeZone != null) { - return TimeZone.getTimeZone(timeZone); - } - } catch (Exception ex){ - LOGGER.debug("Error occurred while getting user time zone, " + ex.getMessage()); - } - return null; - } - - public static Task createSimpleTask(String operation, PrismObject owner, TaskManager manager) { - return createSimpleTask(operation, null, owner, manager); - } - - public static Task createSimpleTask(String operation, String channel, PrismObject owner, TaskManager manager) { - Task task = manager.createTaskInstance(operation); - - if (owner == null) { - MidPointPrincipal user = SecurityUtils.getPrincipalUser(); - if (user == null) { - throw new RestartResponseException(PageLogin.class); - } else { - owner = user.getFocus().asPrismObject(); - } - } - - task.setOwner(owner); - if (channel == null) { - task.setChannel(SchemaConstants.CHANNEL_GUI_USER_URI); - } else { - task.setChannel(channel); - } - - return task; - } - - public static PrismObject reconstructObject(Class type, - String oid, String eventIdentifier, Task task, OperationResult result){ - try { - MidPointApplication application = (MidPointApplication) MidPointApplication.get(); - return application.getAuditService().reconstructObject(type, oid, eventIdentifier, task, result); - } catch (Exception ex){ - LOGGER.debug("Error occurred while reconsructing the object, " + ex.getMessage()); - } - return null; - } - - public static Collection> createLookupTableRetrieveOptions(SchemaHelper schemaHelper) { - return schemaHelper.getOperationOptionsBuilder() - .item(LookupTableType.F_ROW) - .retrieveQuery() - .asc(LookupTableRowType.F_LABEL) - .end() - .build(); - } - - public static ActivationStatusType getAssignmentEffectiveStatus(String lifecycleStatus, ActivationType activationType, PageBase pageBase){ - return pageBase.getModelInteractionService().getAssignmentEffectiveStatus(lifecycleStatus, activationType); - } - - public static void assumePowerOfAttorney(PrismObject donor, - ModelInteractionService modelInteractionService, TaskManager taskManager, OperationResult parentResult) { - Task task = taskManager.createTaskInstance(); - OperationResult result = OperationResult.createSubResultOrNewResult(parentResult, OPERATION_ASSUME_POWER_OF_ATTORNEY); - - try { - modelInteractionService.assumePowerOfAttorney(donor, task, result); - } catch (CommonException ex) { - LoggingUtils.logUnexpectedException(LOGGER, "Couldn't assume power of attorney", ex); - result.recordFatalError("WebModelUtils.couldntAssumePowerAttorney", ex); - } finally { - result.computeStatusIfUnknown(); - } - } - - public static void dropPowerOfAttorney(ModelInteractionService modelInteractionService, TaskManager taskManager, OperationResult parentResult) { - Task task = taskManager.createTaskInstance(); - OperationResult result = OperationResult.createSubResultOrNewResult(parentResult, OPERATION_DROP_POWER_OF_ATTORNEY); - - try { - modelInteractionService.dropPowerOfAttorney(task, result); - } catch (CommonException ex) { - LoggingUtils.logUnexpectedException(LOGGER, "Couldn't drop power of attorney", ex); - result.recordFatalError("WebModelUtils.couldntDropPowerAttorney", ex); - } finally { - result.computeStatusIfUnknown(); - } - } - - public static boolean isEnableExperimentalFeature(Task task, ModelServiceLocator pageBase) { - OperationResult result = task.getResult(); - - ModelInteractionService mInteractionService = pageBase.getModelInteractionService(); - - CompiledGuiProfile adminGuiConfig = null; - try { - adminGuiConfig = mInteractionService.getCompiledGuiProfile(task, result); - result.recomputeStatus(); - result.recordSuccessIfUnknown(); - } catch (Exception e) { - LoggingUtils.logException(LOGGER, "Cannot load admin gui config", e); - result.recordPartialError("Cannot load admin gui config. Reason: " + e.getLocalizedMessage()); - - } - - if (adminGuiConfig == null) { - return false; - } - - return BooleanUtils.isTrue(adminGuiConfig.isEnableExperimentalFeatures()); - - } - - public static boolean isEnableExperimentalFeature(ModelInteractionService modelInteractionService, Task task, OperationResult result) { - CompiledGuiProfile adminGuiConfig = null; - try { - adminGuiConfig = modelInteractionService.getCompiledGuiProfile(task, result); - result.recomputeStatus(); - result.recordSuccessIfUnknown(); - } catch (Exception e) { - LoggingUtils.logException(LOGGER, "Cannot load admin gui config", e); - result.recordPartialError("Cannot load admin gui config. Reason: " + e.getLocalizedMessage()); - - } - - if (adminGuiConfig == null) { - return false; - } - - return BooleanUtils.isTrue(adminGuiConfig.isEnableExperimentalFeatures()); - - } - - public static boolean isEnableExperimentalFeature(ModelServiceLocator pageBase) { - Task task = pageBase.createSimpleTask("Load admin gui config"); - return isEnableExperimentalFeature(task, pageBase); - - } - - public static AccessCertificationConfigurationType getCertificationConfiguration(PageBase pageBase) { - OperationResult result = new OperationResult(WebModelServiceUtils.class.getName() + ".getCertificationConfiguration"); - try { - return pageBase.getModelInteractionService().getCertificationConfiguration(result); - } catch (Throwable t) { - LoggingUtils.logUnexpectedException(LOGGER, "Cannot load certification configuration", t); - return null; - } - } - - public static String translateMessage(OperationResult result, ModelServiceLocator page) { - LocalizationService service = page.getLocalizationService(); - Locale locale = page.getLocale(); - - return service.translate(result.getUserFriendlyMessage(), locale); - } - - public static boolean isPostAuthenticationEnabled(TaskManager taskManager, ModelInteractionService modelInteractionService) { - MidPointPrincipal midpointPrincipal = SecurityUtils.getPrincipalUser(); - if (midpointPrincipal != null) { - FocusType focus = midpointPrincipal.getFocus(); - Task task = taskManager.createTaskInstance(OPERATION_LOAD_FLOW_POLICY); - OperationResult parentResult = new OperationResult(OPERATION_LOAD_FLOW_POLICY); - RegistrationsPolicyType registrationPolicyType; - try { - registrationPolicyType = modelInteractionService.getFlowPolicy(focus.asPrismObject(), task, parentResult); - if (registrationPolicyType == null) { - return false; - } - SelfRegistrationPolicyType postAuthenticationPolicy = registrationPolicyType.getPostAuthentication(); - if (postAuthenticationPolicy == null) { - return false; - } - String requiredLifecycleState = postAuthenticationPolicy.getRequiredLifecycleState(); - if (StringUtils.isNotBlank(requiredLifecycleState) && requiredLifecycleState.equals(focus.getLifecycleState())) { - return true; - } - } catch (CommonException e) { - LoggingUtils.logException(LOGGER, "Cannot determine post authentication policies", e); - } - } - return false; - } - - public static PrismObject loadSystemConfigurationAsPrismObject(PageBase pageBase, Task task, OperationResult result) { - PrismObject systemConfig = loadObject( - SystemConfigurationType.class, SystemObjectsType.SYSTEM_CONFIGURATION.value(), null, - pageBase, task, result); - - return systemConfig; - } - -} +/* + * Copyright (c) 2010-2019 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.gui.api.util; + +import static com.evolveum.midpoint.schema.GetOperationOptions.createNoFetchCollection; + +import java.util.*; + +import com.evolveum.midpoint.prism.PrismReferenceValue; +import com.evolveum.midpoint.util.QNameUtil; +import com.evolveum.midpoint.xml.ns._public.common.common_3.*; +import org.apache.commons.lang.BooleanUtils; +import org.apache.commons.lang.LocaleUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.Validate; +import org.apache.wicket.RestartResponseException; +import org.apache.wicket.Session; +import org.apache.wicket.ThreadContext; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import com.evolveum.midpoint.common.LocalizationService; +import com.evolveum.midpoint.gui.api.page.PageBase; +import com.evolveum.midpoint.model.api.ModelExecuteOptions; +import com.evolveum.midpoint.model.api.ModelInteractionService; +import com.evolveum.midpoint.model.api.authentication.CompiledGuiProfile; +import com.evolveum.midpoint.model.api.authentication.GuiProfiledPrincipal; +import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.PrismObjectDefinition; +import com.evolveum.midpoint.prism.delta.ChangeType; +import com.evolveum.midpoint.prism.delta.DeltaFactory; +import com.evolveum.midpoint.prism.delta.ObjectDelta; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.prism.query.ObjectQuery; +import com.evolveum.midpoint.schema.GetOperationOptions; +import com.evolveum.midpoint.schema.GetOperationOptionsBuilder; +import com.evolveum.midpoint.schema.SchemaHelper; +import com.evolveum.midpoint.schema.SelectorOptions; +import com.evolveum.midpoint.schema.constants.SchemaConstants; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.schema.util.ObjectTypeUtil; +import com.evolveum.midpoint.security.api.MidPointPrincipal; +import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.task.api.TaskManager; +import com.evolveum.midpoint.util.exception.AuthorizationException; +import com.evolveum.midpoint.util.exception.CommonException; +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.logging.LoggingUtils; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.web.page.login.PageLogin; +import com.evolveum.midpoint.web.security.MidPointApplication; +import com.evolveum.midpoint.web.security.util.SecurityUtils; +import com.evolveum.prism.xml.ns._public.types_3.EvaluationTimeType; + +import javax.xml.namespace.QName; + +/** + * Utility class that contains methods that interact with ModelService and other + * midPoint components. + * + * @author lazyman + */ +public class WebModelServiceUtils { + + private static final Trace LOGGER = TraceManager.getTrace(WebModelServiceUtils.class); + + private static final String DOT_CLASS = WebModelServiceUtils.class.getName() + "."; + private static final String OPERATION_LOAD_OBJECT = DOT_CLASS + "loadObject"; + private static final String OPERATION_DELETE_OBJECT = DOT_CLASS + "deleteObject"; + private static final String OPERATION_SEARCH_OBJECTS = DOT_CLASS + "searchObjects"; + private static final String OPERATION_SAVE_OBJECT = DOT_CLASS + "saveObject"; + private static final String OPERATION_LOAD_OBJECT_REFS = DOT_CLASS + "loadObjectReferences"; + private static final String OPERATION_COUNT_OBJECT = DOT_CLASS + "countObjects"; + private static final String OPERATION_ASSUME_POWER_OF_ATTORNEY = DOT_CLASS + "assumePowerOfAttorney"; + private static final String OPERATION_DROP_POWER_OF_ATTORNEY = DOT_CLASS + "dropPowerOfAttorney"; + private static final String OPERATION_GET_SYSTEM_CONFIG = DOT_CLASS + "getSystemConfiguration"; + private static final String OPERATION_LOAD_FLOW_POLICY = DOT_CLASS + "loadFlowPolicy"; + + public static String resolveReferenceName(ObjectReferenceType ref, PageBase page) { + return resolveReferenceName(ref, page, false); + } + + public static String resolveReferenceName(ObjectReferenceType ref, PageBase page, boolean translate) { + Task task = page.createSimpleTask(WebModelServiceUtils.class.getName() + ".resolveReferenceName"); + return resolveReferenceName(ref, page, task, task.getResult(), translate); + } + + public static String resolveReferenceName(ObjectReferenceType ref, PageBase page, Task task, OperationResult result) { + return resolveReferenceName(ref, page, task, result, false); + } + + public static String resolveReferenceName(ObjectReferenceType ref, PageBase page, Task task, OperationResult result, boolean translate) { + if (ref == null) { + return null; + } + if (ref.getTargetName() != null) { + return translate ? page.getLocalizationService().translate(ref.getTargetName().toPolyString(), page.getLocale(), true) + : ref.getTargetName().getOrig(); + } + if (StringUtils.isEmpty(ref.getOid()) || ref.getType() == null){ + return null; + } + PrismObject object = resolveReferenceNoFetch(ref, page, task, result); + if (object == null) { + return ref.getOid(); + } else { + ref.asReferenceValue().setObject(object); + return WebComponentUtil.getName(object, translate); + } + } + + public static PrismObject resolveReferenceNoFetch(ObjectReferenceType reference, PageBase page, Task task, OperationResult result) { + if (reference == null) { + return null; + } + if (reference.asReferenceValue().getObject() != null) { + return reference.asReferenceValue().getObject(); + } + PrismContext prismContext = page.getPrismContext(); + if (reference.getType() == null) { + LOGGER.error("No type in {}", reference); + return null; + } + PrismObjectDefinition definition = prismContext.getSchemaRegistry().findObjectDefinitionByType(reference.getType()); + if (definition == null) { + LOGGER.error("No definition for {} was found", reference.getType()); + return null; + } + if (reference.getOid() == null) { + if (reference.getResolutionTime() == EvaluationTimeType.RUN) { + // Runtime reference resolution. Ignore it for now. Later we maybe would want to resolve it here. + // But it may resolve to several objects .... + return null; + } else { + LOGGER.error("Null OID in reference {}", reference); + // Throw an exception instead? Maybe not. We want GUI to be robust. + return null; + } + } + return loadObject(definition.getCompileTimeClass(), reference.getOid(), createNoFetchCollection(), page, task, result); + } + + public static List createObjectReferenceList(Class type, PageBase page, Map referenceMap){ + referenceMap.clear(); + + OperationResult result = new OperationResult(OPERATION_LOAD_OBJECT_REFS); +// Task task = page.createSimpleTask(OPERATION_LOAD_PASSWORD_POLICIES); + + try { + List> objects = searchObjects(type, null, result, page); + result.recomputeStatus(); + List references = new ArrayList<>(); + + for(PrismObject object: objects){ + referenceMap.put(object.getOid(), WebComponentUtil.getName(object)); + references.add(ObjectTypeUtil.createObjectRef(object, page.getPrismContext())); + + } + return references; + } catch (Exception e){ + result.recordFatalError(page.createStringResource("WebModelUtils.couldntLoadPasswordPolicies").getString(), e); + LoggingUtils.logUnexpectedException(LOGGER, "Couldn't load password policies", e); + } + + // TODO - show error somehow + // if(!result.isSuccess()){ + // getPageBase().showResult(result); + // } + + return null; + } + + public static String runTask(TaskType taskToRun, Task operationalTask, OperationResult parentResult, PageBase pageBase){ + try { + ObjectDelta delta = DeltaFactory.Object.createAddDelta(taskToRun.asPrismObject()); + pageBase.getPrismContext().adopt(delta); + pageBase.getModelService().executeChanges(WebComponentUtil.createDeltaCollection(delta), null, + operationalTask, parentResult); + parentResult.recordInProgress(); + parentResult.setBackgroundTaskOid(delta.getOid()); + pageBase.showResult(parentResult); + return delta.getOid(); + } catch (ObjectAlreadyExistsException | ObjectNotFoundException | SchemaException + | ExpressionEvaluationException | CommunicationException | ConfigurationException + | PolicyViolationException | SecurityViolationException e) { + // TODO Auto-generated catch block +// error(pageBase.getString("pageUsers.message.nothingSelected") + e.getMessage()); + parentResult.recordFatalError(pageBase.createStringResource("WebModelUtils.couldntRunTask", e.getMessage()).getString(), e); + LoggingUtils.logUnexpectedException(LOGGER, "Couldn't run task " + e.getMessage(), e); + return null; + } + + } + + public static void runTask(Collection tasksToRun, Task operationalTask, OperationResult parentResult, PageBase pageBase){ +// try { + + for (TaskType taskToRun : tasksToRun){ + runTask(tasksToRun, operationalTask, parentResult, pageBase); + } + +// } +// ObjectDelta delta = ObjectDelta.createAddDelta(taskToRun.asPrismObject()); +// pageBase.getPrismContext().adopt(delta); +// pageBase.getModelService().executeChanges(WebComponentUtil.createDeltaCollection(delta), null, +// operationalTask, parentResult); +// parentResult.recordInProgress(); +// parentResult.setBackgroundTaskOid(delta.getOid()); +// pageBase.showResult(parentResult); +// return delta.getOid(); +// } catch (ObjectAlreadyExistsException | ObjectNotFoundException | SchemaException +// | ExpressionEvaluationException | CommunicationException | ConfigurationException +// | PolicyViolationException | SecurityViolationException e) { +// // TODO Auto-generated catch block +//// error(pageBase.getString("pageUsers.message.nothingSelected") + e.getMessage()); +// parentResult.recordFatalError(pageBase.createStringResource("WebModelUtils.couldntRunTask", e.getMessage()).getString(), e); +// LoggingUtils.logUnexpectedException(LOGGER, "Couldn't run task " + e.getMessage(), e); +// return null; +// } + + } + + public static PrismObject loadObject(PrismReferenceValue objectRef, QName expectedTargetType, PageBase pageBase, Task task, OperationResult result) { + if (objectRef == null) { + return null; + } + + if (QNameUtil.match(expectedTargetType, objectRef.getTargetType())) { + Class type = pageBase.getPrismContext().getSchemaRegistry().determineClassForType(objectRef.getTargetType()); + PrismObject resourceType = WebModelServiceUtils.loadObject(type, objectRef.getOid(), GetOperationOptions.createNoFetchCollection(), pageBase, task, result); + return resourceType; + } + + return null; + } + + @Nullable + public static PrismObject loadObject(ObjectReferenceType objectReference, + PageBase page, Task task, OperationResult result) { + Class type = page.getPrismContext().getSchemaRegistry().determineClassForType(objectReference.getType()); + return loadObject(type, objectReference.getOid(), null, page, task, result); + } + + @Nullable + public static PrismObject loadObject(Class type, String oid, + PageBase page, Task task, OperationResult result) { + return loadObject(type, oid, null, page, task, result); + } + + @Nullable + public static PrismObject loadObject(Class type, String oid, + Collection> options, + PageBase page, Task task, OperationResult result) { + return loadObject(type, oid, options, true, page, task, result); + } + + @Nullable + public static PrismObject loadObject(Class type, String oid, + Collection> options, boolean allowNotFound, + PageBase page, Task task, OperationResult result) { + LOGGER.debug("Loading {} with oid {}, options {}", type.getSimpleName(), oid, options); + + OperationResult subResult; + if (result != null) { + subResult = result.createMinorSubresult(OPERATION_LOAD_OBJECT); + } else { + subResult = new OperationResult(OPERATION_LOAD_OBJECT); + } + PrismObject object = null; + try { + if (options == null) { + options = SelectorOptions.createCollection(GetOperationOptions.createResolveNames()); + } else { + GetOperationOptions getOpts = SelectorOptions.findRootOptions(options); + if (getOpts == null) { + options.add(new SelectorOptions<>(GetOperationOptions.createResolveNames())); + } else { + getOpts.setResolveNames(Boolean.TRUE); + } + } + object = page.getModelService().getObject(type, oid, options, task, subResult); + } catch (AuthorizationException e) { + // Not authorized to access the object. This is probably caused by a reference that + // point to an object that the current user cannot read. This is no big deal. + // Just do not display that object. + subResult.recordHandledError(e); + LOGGER.debug("User {} is not authorized to read {} {}", + task.getOwner() != null ? task.getOwner().getName() : null, type.getSimpleName(), oid); + return null; + } catch (ObjectNotFoundException e) { + if (allowNotFound) { + // Object does not exist. It was deleted in the meanwhile, or not created yet. This could happen quite often. + subResult.recordHandledError(e); + LOGGER.debug("{} {} does not exist", type.getSimpleName(), oid, e); + return null; + } else { + subResult.recordFatalError(page.createStringResource("WebModelUtils.couldntLoadObject").getString(), e); + LoggingUtils.logUnexpectedException(LOGGER, "Couldn't load object", e); + } + } catch (Exception ex) { + subResult.recordFatalError(page.createStringResource("WebModelUtils.couldntLoadObject").getString(), ex); + LoggingUtils.logUnexpectedException(LOGGER, "Couldn't load object", ex); + } finally { + subResult.computeStatus(); + } + // TODO reconsider this part: until recently, the condition was always 'false' + if (WebComponentUtil.showResultInPage(subResult)) { + page.showResult(subResult); + } + + LOGGER.debug("Loaded {} with result {}", object, subResult); + + return object; + } + + //TODO consider using modelServiceLocator instead of PageBase in other methods.. Do we even need it? What about showResult? Should it be + // here or directly in the page? Consider usability and readabiltiy + @Nullable + public static PrismObject loadObject(ObjectReferenceType objectReference, + ModelServiceLocator page, Task task, OperationResult result) { + Class type = page.getPrismContext().getSchemaRegistry().determineClassForType(objectReference.getType()); + String oid = objectReference.getOid(); + Collection> options = null; + LOGGER.debug("Loading {} with oid {}, options {}", type.getSimpleName(), oid, options); + + OperationResult subResult; + if (result != null) { + subResult = result.createMinorSubresult(OPERATION_LOAD_OBJECT); + } else { + subResult = new OperationResult(OPERATION_LOAD_OBJECT); + } + PrismObject object = null; + try { + if (options == null) { + options = SelectorOptions.createCollection(GetOperationOptions.createResolveNames()); + } else { + GetOperationOptions getOpts = SelectorOptions.findRootOptions(options); + if (getOpts == null) { + options.add(new SelectorOptions<>(GetOperationOptions.createResolveNames())); + } else { + getOpts.setResolveNames(Boolean.TRUE); + } + } + object = page.getModelService().getObject(type, oid, options, task, subResult); + } catch (AuthorizationException e) { + // Not authorized to access the object. This is probably caused by a reference that + // point to an object that the current user cannot read. This is no big deal. + // Just do not display that object. + subResult.recordHandledError(e); + LOGGER.debug("User {} is not authorized to read {} {}", + task.getOwner() != null ? task.getOwner().getName() : null, type.getSimpleName(), oid); + return null; + } catch (ObjectNotFoundException e) { + // Object does not exist. It was deleted in the meanwhile, or not created yet. This could happen quite often. + subResult.recordHandledError(e); + LOGGER.debug("{} {} does not exist", type.getSimpleName(), oid, e); + return null; + + } catch (Exception ex) { + subResult.recordFatalError("WebModelUtils.couldntLoadObject", ex); + LoggingUtils.logUnexpectedException(LOGGER, "Couldn't load object", ex); + } finally { + subResult.computeStatus(); + } + // TODO reconsider this part: until recently, the condition was always 'false' + if (WebComponentUtil.showResultInPage(subResult)) { + if (page instanceof PageBase) { + ((PageBase)page).showResult(subResult); + } + } + + LOGGER.debug("Loaded {} with result {}", object, subResult); + + return object; + } + + public static boolean isNoFetch(Collection> options) { + if (options == null) { + return false; + } + GetOperationOptions rootOptions = SelectorOptions.findRootOptions(options); + if (rootOptions == null) { + return false; + } + return GetOperationOptions.isNoFetch(rootOptions); + } + + @NotNull + public static List> searchObjects( + Class type, ObjectQuery query, OperationResult result, PageBase page) { + return searchObjects(type, query, null, result, page, null); + } + + @NotNull + public static List> searchObjects(Class type, ObjectQuery query, + Collection> options, + OperationResult result, PageBase page) { + return searchObjects(type, query, options, result, page, null); + } + + @NotNull + public static List> searchObjects( + Class type, ObjectQuery query, Collection> options, + OperationResult result, PageBase page, PrismObject principal) { + LOGGER.debug("Searching {} with oid {}, options {}", type.getSimpleName(), query, options); + + OperationResult subResult; + if (result != null) { + subResult = result.createMinorSubresult(OPERATION_SEARCH_OBJECTS); + } else { + subResult = new OperationResult(OPERATION_SEARCH_OBJECTS); + } + List> objects = new ArrayList<>(); + try { + Task task = createSimpleTask(subResult.getOperation(), principal, page.getTaskManager()); + List> list = page.getModelService().searchObjects(type, query, options, task, subResult); + if (list != null) { + objects.addAll(list); + } + } catch (Exception ex) { + subResult.recordFatalError(page.createStringResource("WebModelUtils.couldntSearchObjects").getString(), ex); + LoggingUtils.logUnexpectedException(LOGGER, "Couldn't search objects", ex); + } finally { + subResult.computeStatus(); + } + + if (result == null && WebComponentUtil.showResultInPage(subResult)) { + page.showResult(subResult); + } + + LOGGER.debug("Loaded ({}) with result {}", objects.size(), subResult); + + return objects; + } + + public static int countObjects(Class type, ObjectQuery query, PageBase page) { + LOGGER.debug("Count object: type => {}, query => {}", type, query); + Task task = page.createSimpleTask(OPERATION_COUNT_OBJECT); + OperationResult parentResult = new OperationResult(OPERATION_COUNT_OBJECT); + int count = 0; + try { + count = page.getModelService().countObjects(type, query, null, task, parentResult); + } catch (SchemaException | ObjectNotFoundException | SecurityViolationException + | ConfigurationException | CommunicationException | ExpressionEvaluationException ex) { + parentResult.recordFatalError(page.createStringResource("WebModelUtils.couldntCountObjects").getString(), ex); + LoggingUtils.logUnexpectedException(LOGGER, "Couldn't count objects", ex); + } + + LOGGER.debug("Count objects with result {}", parentResult); + return count; + } + + public static void deleteObject(Class type, String oid, OperationResult result, + PageBase page) { + deleteObject(type, oid, null, result, page, null); + } + + public static void deleteObject(Class type, String oid, ModelExecuteOptions options, + OperationResult result, PageBase page) { + deleteObject(type, oid, options, result, page, null); + } + + public static void deleteObject(Class type, String oid, ModelExecuteOptions options, + OperationResult result, PageBase page, + PrismObject principal) { + LOGGER.debug("Deleting {} with oid {}, options {}", type.getSimpleName(), oid, options); + + OperationResult subResult; + if (result != null) { + subResult = result.createMinorSubresult(OPERATION_DELETE_OBJECT); + } else { + subResult = new OperationResult(OPERATION_DELETE_OBJECT); + } + try { + Task task = createSimpleTask(result.getOperation(), principal, page.getTaskManager()); + + ObjectDelta delta = page.getPrismContext().deltaFactory().object().create(type, ChangeType.DELETE); + delta.setOid(oid); + + page.getModelService().executeChanges(WebComponentUtil.createDeltaCollection(delta), options, task, subResult); + } catch (Exception ex) { + subResult.recordFatalError(page.createStringResource("WebModelUtils.couldntDeleteObject").getString(), ex); + LoggingUtils.logUnexpectedException(LOGGER, "Couldn't delete object", ex); + } finally { + subResult.computeStatus(); + } + + if (result == null && WebComponentUtil.showResultInPage(subResult)) { + page.showResult(subResult); + } + + LOGGER.debug("Deleted with result {}", result); + } + + public static Collection> createOptionsForParentOrgRefs(GetOperationOptionsBuilder builder) { + return builder + .item(ObjectType.F_PARENT_ORG_REF).retrieve() + .build(); + } + + public static void save(ObjectDelta delta, OperationResult result, PageBase page) { + save(delta, result, null, page); + } + + public static void save(ObjectDelta delta, OperationResult result, Task task, PageBase page) { + save(delta, null, result, task, page); + } + + public static void save(ObjectDelta delta, ModelExecuteOptions options, OperationResult result, Task task, PageBase page) { + save(WebComponentUtil.createDeltaCollection(delta), options, result, task, page); + } + + + public static void save(Collection> deltas, ModelExecuteOptions options, + OperationResult result, Task task, PageBase page) { + LOGGER.debug("Saving deltas {}, options {}", deltas, options); + + OperationResult subResult; + if (result != null) { + subResult = result.createMinorSubresult(OPERATION_SAVE_OBJECT); + } else { + subResult = new OperationResult(OPERATION_SAVE_OBJECT); + } + + try { + if (task == null) { + task = page.createSimpleTask(result.getOperation()); + } + + page.getModelService().executeChanges(deltas, options, task, result); + } catch (Exception ex) { + subResult.recordFatalError(ex.getMessage()); + LoggingUtils.logUnexpectedException(LOGGER, "Couldn't save object", ex); + } finally { + subResult.computeStatus(); + } + + if (result == null && WebComponentUtil.showResultInPage(subResult)) { + page.showResult(subResult); + } + + LOGGER.debug("Saved with result {}", subResult); + } + + public static ObjectDelta createActivationAdminStatusDelta( + Class type, String oid, boolean enabled, PrismContext context) { + + ItemPath path = SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS; + ActivationStatusType status = enabled ? ActivationStatusType.ENABLED : ActivationStatusType.DISABLED; + ObjectDelta objectDelta = context.deltaFactory().object().createModificationReplaceProperty(type, oid, path, + status); + + return objectDelta; + } + + public static FocusType getLoggedInFocus() { + MidPointPrincipal principal = SecurityUtils.getPrincipalUser(); + Validate.notNull(principal, "No principal"); + if (principal.getFocus() == null) { + throw new IllegalArgumentException("No focus in principal: " + principal); + } + return principal.getFocus(); + } + + public static String getLoggedInFocusOid() { + MidPointPrincipal principal = SecurityUtils.getPrincipalUser(); + Validate.notNull(principal, "No principal"); + if (principal.getOid() == null) { + throw new IllegalArgumentException("No OID in principal: "+principal); + } + return principal.getOid(); + } + +// public static Locale getLocale() { +// return getLocale(null); +// } + + public static Locale getLocale() { + MidPointPrincipal principal = SecurityUtils.getPrincipalUser(); + if (principal == null) { + return MidPointApplication.getDefaultLocale(); + } + + Locale locale = null; + + F focus = (F) principal.getFocus(); + if (focus == null) { + return MidPointApplication.getDefaultLocale(); + } +// if (principal != null) { +//// if (focus == null) { +// PrismObject focusPrismObject = principal.getFocus().asPrismObject(); +// FocusType focus = focusPrismObject == null ? null : focusPrismObject.asObjectable(); +//// } + String prefLang = focus.getPreferredLanguage(); + if (StringUtils.isBlank(prefLang)) { + prefLang = focus.getLocale(); + } + + try { + locale = LocaleUtils.toLocale(prefLang); + } catch (Exception ex) { + LOGGER.debug("Error occurred while getting user locale, " + ex.getMessage()); + } + + if (locale == null) { + if (ThreadContext.getSession() == null) { + return MidPointApplication.getDefaultLocale(); + } + + locale = Session.get().getLocale(); + } + + if (MidPointApplication.containsLocale(locale)) { + return locale; + } + + return MidPointApplication.getDefaultLocale(); + } + +// public static TimeZone getTimezone() { +// return getTimezone(null); +// } + + public static TimeZone getTimezone() { + GuiProfiledPrincipal principal = SecurityUtils.getPrincipalUser(); + + if (principal == null) { + return null; + } + + FocusType focus = principal.getFocus(); + + String timeZone; + if (focus == null || StringUtils.isEmpty(focus.getTimezone())) { + timeZone = principal.getCompiledGuiProfile().getDefaultTimezone(); + } else { + timeZone = focus.getTimezone(); + } + + if (timeZone == null) { + return null; + } + + try { + return TimeZone.getTimeZone(timeZone); + } catch (Exception ex){ + LOGGER.debug("Error occurred while getting user time zone, " + ex.getMessage()); + return null; + } + + } + + public static Task createSimpleTask(String operation, PrismObject owner, TaskManager manager) { + return createSimpleTask(operation, null, owner, manager); + } + + public static Task createSimpleTask(String operation, String channel, PrismObject owner, TaskManager manager) { + Task task = manager.createTaskInstance(operation); + + if (owner == null) { + MidPointPrincipal user = SecurityUtils.getPrincipalUser(); + if (user == null) { + throw new RestartResponseException(PageLogin.class); + } else { + owner = user.getFocus().asPrismObject(); + } + } + + task.setOwner(owner); + if (channel == null) { + task.setChannel(SchemaConstants.CHANNEL_GUI_USER_URI); + } else { + task.setChannel(channel); + } + + return task; + } + + public static PrismObject reconstructObject(Class type, + String oid, String eventIdentifier, Task task, OperationResult result){ + try { + MidPointApplication application = (MidPointApplication) MidPointApplication.get(); + return application.getAuditService().reconstructObject(type, oid, eventIdentifier, task, result); + } catch (Exception ex){ + LOGGER.debug("Error occurred while reconsructing the object, " + ex.getMessage()); + } + return null; + } + + public static Collection> createLookupTableRetrieveOptions(SchemaHelper schemaHelper) { + return schemaHelper.getOperationOptionsBuilder() + .item(LookupTableType.F_ROW) + .retrieveQuery() + .asc(LookupTableRowType.F_LABEL) + .end() + .build(); + } + + public static ActivationStatusType getAssignmentEffectiveStatus(String lifecycleStatus, ActivationType activationType, PageBase pageBase){ + return pageBase.getModelInteractionService().getAssignmentEffectiveStatus(lifecycleStatus, activationType); + } + + public static void assumePowerOfAttorney(PrismObject donor, + ModelInteractionService modelInteractionService, TaskManager taskManager, OperationResult parentResult) { + Task task = taskManager.createTaskInstance(); + OperationResult result = OperationResult.createSubResultOrNewResult(parentResult, OPERATION_ASSUME_POWER_OF_ATTORNEY); + + try { + modelInteractionService.assumePowerOfAttorney(donor, task, result); + } catch (CommonException ex) { + LoggingUtils.logUnexpectedException(LOGGER, "Couldn't assume power of attorney", ex); + result.recordFatalError("WebModelUtils.couldntAssumePowerAttorney", ex); + } finally { + result.computeStatusIfUnknown(); + } + } + + public static void dropPowerOfAttorney(ModelInteractionService modelInteractionService, TaskManager taskManager, OperationResult parentResult) { + Task task = taskManager.createTaskInstance(); + OperationResult result = OperationResult.createSubResultOrNewResult(parentResult, OPERATION_DROP_POWER_OF_ATTORNEY); + + try { + modelInteractionService.dropPowerOfAttorney(task, result); + } catch (CommonException ex) { + LoggingUtils.logUnexpectedException(LOGGER, "Couldn't drop power of attorney", ex); + result.recordFatalError("WebModelUtils.couldntDropPowerAttorney", ex); + } finally { + result.computeStatusIfUnknown(); + } + } + + public static boolean isEnableExperimentalFeature(Task task, ModelServiceLocator pageBase) { + OperationResult result = task.getResult(); + + ModelInteractionService mInteractionService = pageBase.getModelInteractionService(); + + CompiledGuiProfile adminGuiConfig = null; + try { + adminGuiConfig = mInteractionService.getCompiledGuiProfile(task, result); + result.recomputeStatus(); + result.recordSuccessIfUnknown(); + } catch (Exception e) { + LoggingUtils.logException(LOGGER, "Cannot load admin gui config", e); + result.recordPartialError("Cannot load admin gui config. Reason: " + e.getLocalizedMessage()); + + } + + if (adminGuiConfig == null) { + return false; + } + + return BooleanUtils.isTrue(adminGuiConfig.isEnableExperimentalFeatures()); + + } + + public static boolean isEnableExperimentalFeature(ModelInteractionService modelInteractionService, Task task, OperationResult result) { + CompiledGuiProfile adminGuiConfig = null; + try { + adminGuiConfig = modelInteractionService.getCompiledGuiProfile(task, result); + result.recomputeStatus(); + result.recordSuccessIfUnknown(); + } catch (Exception e) { + LoggingUtils.logException(LOGGER, "Cannot load admin gui config", e); + result.recordPartialError("Cannot load admin gui config. Reason: " + e.getLocalizedMessage()); + + } + + if (adminGuiConfig == null) { + return false; + } + + return BooleanUtils.isTrue(adminGuiConfig.isEnableExperimentalFeatures()); + + } + + public static boolean isEnableExperimentalFeature(ModelServiceLocator pageBase) { + Task task = pageBase.createSimpleTask("Load admin gui config"); + return isEnableExperimentalFeature(task, pageBase); + + } + + public static AccessCertificationConfigurationType getCertificationConfiguration(PageBase pageBase) { + OperationResult result = new OperationResult(WebModelServiceUtils.class.getName() + ".getCertificationConfiguration"); + try { + return pageBase.getModelInteractionService().getCertificationConfiguration(result); + } catch (Throwable t) { + LoggingUtils.logUnexpectedException(LOGGER, "Cannot load certification configuration", t); + return null; + } + } + + public static String translateMessage(OperationResult result, ModelServiceLocator page) { + LocalizationService service = page.getLocalizationService(); + Locale locale = page.getLocale(); + + return service.translate(result.getUserFriendlyMessage(), locale); + } + + public static boolean isPostAuthenticationEnabled(TaskManager taskManager, ModelInteractionService modelInteractionService) { + MidPointPrincipal midpointPrincipal = SecurityUtils.getPrincipalUser(); + if (midpointPrincipal != null) { + FocusType focus = midpointPrincipal.getFocus(); + Task task = taskManager.createTaskInstance(OPERATION_LOAD_FLOW_POLICY); + OperationResult parentResult = new OperationResult(OPERATION_LOAD_FLOW_POLICY); + RegistrationsPolicyType registrationPolicyType; + try { + registrationPolicyType = modelInteractionService.getFlowPolicy(focus.asPrismObject(), task, parentResult); + if (registrationPolicyType == null) { + return false; + } + SelfRegistrationPolicyType postAuthenticationPolicy = registrationPolicyType.getPostAuthentication(); + if (postAuthenticationPolicy == null) { + return false; + } + String requiredLifecycleState = postAuthenticationPolicy.getRequiredLifecycleState(); + if (StringUtils.isNotBlank(requiredLifecycleState) && requiredLifecycleState.equals(focus.getLifecycleState())) { + return true; + } + } catch (CommonException e) { + LoggingUtils.logException(LOGGER, "Cannot determine post authentication policies", e); + } + } + return false; + } + + public static PrismObject loadSystemConfigurationAsPrismObject(PageBase pageBase, Task task, OperationResult result) { + PrismObject systemConfig = loadObject( + SystemConfigurationType.class, SystemObjectsType.SYSTEM_CONFIGURATION.value(), null, + pageBase, task, result); + + return systemConfig; + } + +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/assignment/AssignmentPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/assignment/AssignmentPanel.java index be0bee01bd3..35a41e5fea7 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/assignment/AssignmentPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/assignment/AssignmentPanel.java @@ -897,7 +897,7 @@ public void onClick(AjaxRequestTarget target) { if (targetRef != null && targetRef.getValues() != null && targetRef.getValues().size() > 0) { PrismReferenceValueWrapperImpl refWrapper = targetRef.getValues().get(0); if (!StringUtils.isEmpty(refWrapper.getNewValue().getOid())) { - Class targetClass = ObjectTypes.getObjectTypeFromTypeQName(refWrapper.getRealValue().getType()).getClassDefinition(); + Class targetClass = ObjectTypes.getObjectTypeFromTypeQName(refWrapper.getRealValue().getType()).getClassDefinition(); WebComponentUtil.dispatchToObjectDetailsPage(targetClass, refWrapper.getNewValue().getOid(), AssignmentPanel.this, false); } } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/PageAdminFocus.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/PageAdminFocus.java index 99c619975b9..4be3e81c3fa 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/PageAdminFocus.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/PageAdminFocus.java @@ -1,1027 +1,956 @@ -/* - * Copyright (c) 2010-2019 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.web.page.admin; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeSet; - -import com.evolveum.midpoint.xml.ns._public.common.common_3.*; -import org.apache.commons.lang.StringUtils; -import org.apache.wicket.Session; -import org.apache.wicket.ajax.AjaxRequestTarget; -import org.apache.wicket.protocol.http.WebSession; -import org.apache.wicket.request.mapper.parameter.PageParameters; - -import com.evolveum.midpoint.gui.api.model.LoadableModel; -import com.evolveum.midpoint.gui.api.prism.ItemStatus; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; -import com.evolveum.midpoint.gui.api.prism.ShadowWrapper; -import com.evolveum.midpoint.gui.api.util.WebComponentUtil; -import com.evolveum.midpoint.gui.api.util.WebModelServiceUtils; -import com.evolveum.midpoint.gui.impl.factory.PrismObjectWrapperFactory; -import com.evolveum.midpoint.gui.impl.factory.WrapperContext; -import com.evolveum.midpoint.gui.impl.prism.PrismObjectValueWrapper; -import com.evolveum.midpoint.model.api.ModelExecuteOptions; -import com.evolveum.midpoint.model.api.context.AssignmentPath; -import com.evolveum.midpoint.model.api.context.EvaluatedAssignment; -import com.evolveum.midpoint.model.api.context.EvaluatedAssignmentTarget; -import com.evolveum.midpoint.model.api.context.EvaluatedConstruction; -import com.evolveum.midpoint.model.api.context.ModelContext; -import com.evolveum.midpoint.prism.ItemDefinition; -import com.evolveum.midpoint.prism.OriginType; -import com.evolveum.midpoint.prism.PrismContainerDefinition; -import com.evolveum.midpoint.prism.PrismContainerValue; -import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.prism.PrismObjectDefinition; -import com.evolveum.midpoint.prism.PrismReference; -import com.evolveum.midpoint.prism.PrismReferenceDefinition; -import com.evolveum.midpoint.prism.PrismReferenceValue; -import com.evolveum.midpoint.prism.PrismValue; -import com.evolveum.midpoint.prism.delta.ContainerDelta; -import com.evolveum.midpoint.prism.delta.DeltaSetTriple; -import com.evolveum.midpoint.prism.delta.ItemDelta; -import com.evolveum.midpoint.prism.delta.ObjectDelta; -import com.evolveum.midpoint.prism.delta.ReferenceDelta; -import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.prism.polystring.PolyString; -import com.evolveum.midpoint.prism.schema.SchemaRegistry; -import com.evolveum.midpoint.schema.GetOperationOptions; -import com.evolveum.midpoint.schema.SelectorOptions; -import com.evolveum.midpoint.schema.constants.SchemaConstants; -import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.task.api.Task; -import com.evolveum.midpoint.util.exception.NoFocusNameSchemaException; -import com.evolveum.midpoint.util.exception.SchemaException; -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.web.component.assignment.AssignmentEditorDto; -import com.evolveum.midpoint.web.component.assignment.AssignmentsUtil; -import com.evolveum.midpoint.web.component.prism.show.PagePreviewChanges; -import com.evolveum.midpoint.web.component.progress.ProgressReportingAwarePage; -import com.evolveum.midpoint.web.page.admin.users.component.AssignmentInfoDto; -import com.evolveum.midpoint.web.page.admin.users.dto.UserDtoStatus; -import com.evolveum.midpoint.web.security.util.SecurityUtils; -import com.evolveum.midpoint.web.util.validation.MidpointFormValidator; -import com.evolveum.midpoint.web.util.validation.SimpleValidationError; - -public abstract class PageAdminFocus extends PageAdminObjectDetails - implements ProgressReportingAwarePage { - private static final long serialVersionUID = 1L; - - private LoadableModel> projectionModel; - private LoadableModel> delegatedToMeModel; - - private static final String DOT_CLASS = PageAdminFocus.class.getName() + "."; - private static final String OPERATION_RECOMPUTE_ASSIGNMENTS = DOT_CLASS + "recomputeAssignments"; - - private static final String OPERATION_LOAD_SHADOW = DOT_CLASS + "loadShadow"; - - private static final Trace LOGGER = TraceManager.getTrace(PageAdminFocus.class); - - public PageAdminFocus() { - initialize(null); - } - - public PageAdminFocus(PageParameters parameters) { - getPageParameters().overwriteWith(parameters); - initialize(null); - } - - public PageAdminFocus(final PrismObject userToEdit) { - initialize(userToEdit); - } - - public PageAdminFocus(final PrismObject unitToEdit, boolean isNewObject) { - initialize(unitToEdit, isNewObject); - } - - public PageAdminFocus(final PrismObject unitToEdit, boolean isNewObject, boolean isReadonly) { - initialize(unitToEdit, isNewObject, isReadonly); - } - - - @Override - protected void initializeModel(final PrismObject objectToEdit, boolean isNewObject, boolean isReadonly) { - super.initializeModel(objectToEdit, isNewObject, isReadonly); - - projectionModel = new LoadableModel>(false) { - private static final long serialVersionUID = 1L; - - @Override - protected List load() { - return loadShadowWrappers(true); - } - }; - - delegatedToMeModel= new LoadableModel>(false) { - - private static final long serialVersionUID = 1L; - @Override - protected List load() { - return loadDelegatedToMe(); - } - }; - - } - - public LoadableModel> getProjectionModel() { - return projectionModel; - } - - public LoadableModel> getDelegatedToMeModel() { - return delegatedToMeModel; - } - - public List getFocusShadows() { - return projectionModel.getObject(); - } - - protected void reviveModels() throws SchemaException { - super.reviveModels(); - WebComponentUtil.revive(projectionModel, getPrismContext()); - } - - @Override - public void finishProcessing(AjaxRequestTarget target, OperationResult result, boolean returningFromAsync) { - - if (previewRequested) { - finishPreviewProcessing(target, result); - return; - } - if (result.isSuccess() && getDelta() != null && SecurityUtils.getPrincipalUser().getOid().equals(getDelta().getOid())) { - FocusType focus = null; - if (getObjectWrapper().getObject().asObjectable() instanceof UserType){ - focus = getObjectWrapper().getObject().asObjectable(); - } - Session.get().setLocale(WebModelServiceUtils.getLocale(focus)); - LOGGER.debug("Using {} as locale", getLocale()); - WebSession.get().getClientInfo().getProperties(). - setTimeZone(WebModelServiceUtils.getTimezone(focus)); - LOGGER.debug("Using {} as time zone", WebSession.get().getClientInfo().getProperties().getTimeZone()); - } - boolean focusAddAttempted = getDelta() != null && getDelta().isAdd(); - boolean focusAddSucceeded = focusAddAttempted && StringUtils.isNotEmpty(getDelta().getOid()); - - // we don't want to allow resuming editing if a new focal object was created (on second 'save' there would be a conflict with itself) - // and also in case of partial errors, like those related to projections (many deltas would be already executed, and this could cause problems on second 'save'). - boolean canContinueEditing = !focusAddSucceeded && result.isFatalError(); - - boolean canExitPage; - if (returningFromAsync) { - canExitPage = getProgressPanel().isAllSuccess() || result.isInProgress() || result.isHandledError(); // if there's at least a warning in the progress table, we would like to keep the table open - } else { - canExitPage = !canContinueEditing; // no point in staying on page if we cannot continue editing (in synchronous case i.e. no progress table present) - } - - if (!isKeepDisplayingResults() && canExitPage) { - showResult(result); - redirectBack(); - } else { - if (returningFromAsync) { - getProgressPanel().showBackButton(target); - getProgressPanel().hideAbortButton(target); - } - showResult(result); - target.add(getFeedbackPanel()); - - if (canContinueEditing) { - getProgressPanel().hideBackButton(target); - getProgressPanel().showContinueEditingButton(target); - } - } - } - - private void finishPreviewProcessing(AjaxRequestTarget target, OperationResult result) { - getMainPanel().setVisible(true); - getProgressPanel().hide(); - getProgressPanel().hideAbortButton(target); - getProgressPanel().hideBackButton(target); - getProgressPanel().hideContinueEditingButton(target); - - showResult(result); - target.add(getFeedbackPanel()); - - Map, ModelContext> modelContextMap = new LinkedHashMap<>(); - modelContextMap.put(getObjectWrapper().getObject(), getProgressPanel().getPreviewResult()); - - processAdditionalFocalObjectsForPreview(modelContextMap); - - navigateToNext(new PagePreviewChanges(modelContextMap, getModelInteractionService())); - } - - protected void processAdditionalFocalObjectsForPreview(Map, ModelContext> modelContextMap){ - } - - @Override - public void continueEditing(AjaxRequestTarget target) { - getMainPanel().setVisible(true); - getProgressPanel().hide(); - getProgressPanel().hideAbortButton(target); - getProgressPanel().hideBackButton(target); - getProgressPanel().hideContinueEditingButton(target); - target.add(this); - } - - private List loadShadowWrappers(boolean noFetch) { - List list = new ArrayList<>(); - - PrismObjectWrapper focusWrapper = getObjectModel().getObject(); - PrismObject focus = focusWrapper.getObject(); - PrismReference prismReference = focus.findReference(UserType.F_LINK_REF); - if (prismReference == null || prismReference.isEmpty()) { - return new ArrayList<>(); - } - List references = prismReference.getValues(); - - Task task = createSimpleTask(OPERATION_LOAD_SHADOW); - for (PrismReferenceValue reference : references) { - if(reference == null || (reference.getOid() == null && reference.getTargetType() == null)) { - LOGGER.trace("Skiping reference for shadow with null oid"); - continue; // default value - } - OperationResult subResult = task.getResult().createMinorSubresult(OPERATION_LOAD_SHADOW); - PrismObject projection = getPrismObjectForWrapper(ShadowType.class, reference.getOid(), - noFetch, task, subResult, createLoadOptionForShadowWrapper()); - - if(projection == null) { -// showResult(subResult, "pageAdminFocus.message.couldntLoadShadowProjection"); - LOGGER.error("Couldn't load shadow projection"); - continue; - } - - try { - ShadowWrapper wrapper = loadShadowWrapper(projection, task, subResult); - wrapper.setLoadWithNoFetch(noFetch); - - if (wrapper != null) { - list.add((ShadowWrapper)wrapper); - } else { - showResult(subResult, "pageAdminFocus.message.shadowWrapperIsNull"); - LOGGER.error("ShadowWrapper is null"); - } - - //TODO catch Exception/Runtim,eException, Throwable - } catch (SchemaException e) { - showResult(subResult, "pageAdminFocus.message.couldntCreateShadowWrapper"); - LoggingUtils.logUnexpectedException(LOGGER, "Couldn't create shadow wrapper", e); - } - } - return list; - } - - private Collection> createLoadOptionForShadowWrapper(){ - return getSchemaHelper().getOperationOptionsBuilder() - .item(ShadowType.F_RESOURCE_REF).resolve().readOnly() - .build(); - } - - public ShadowWrapper loadShadowWrapper(PrismObject projection, Task task, OperationResult result) throws SchemaException{ - PrismObjectWrapperFactory factory = getRegistry().getObjectWrapperFactory(projection.getDefinition()); - WrapperContext context = new WrapperContext(task, result); - context.setCreateIfEmpty(false); - ShadowWrapper wrapper = (ShadowWrapper) factory.createObjectWrapper(projection, ItemStatus.NOT_CHANGED, context); - wrapper.setProjectionStatus(UserDtoStatus.MODIFY); - return wrapper; - } - - public void loadFullShadow(PrismObjectValueWrapper shadowWrapperValue, AjaxRequestTarget target) { - if(shadowWrapperValue.getRealValue() == null) { - error(getString("pageAdminFocus.message.couldntCreateShadowWrapper")); - LOGGER.error("Couldn't create shadow wrapper, because RealValue is null in " + shadowWrapperValue); - return; - } - String oid = shadowWrapperValue.getRealValue().getOid(); - Task task = createSimpleTask(OPERATION_LOAD_SHADOW); - OperationResult result = task.getResult(); - PrismObject projection = getPrismObjectForWrapper(ShadowType.class, oid, false, task, - result, createLoadOptionForShadowWrapper()); - - if (projection == null) { - result.recordFatalError(getString("PageAdminFocus.message.loadFullShadow.fatalError", shadowWrapperValue.getRealValue())); - showResult(result); - target.add(getFeedbackPanel()); - return; - } - - ShadowWrapper shadowWrapperNew; - try { - shadowWrapperNew = loadShadowWrapper(projection, task, result); - - if (shadowWrapperNew == null) { - error(getString("pageAdminFocus.message.shadowWrapperIsNull")); - LOGGER.error("ShadowWrapper is null"); - return; - } - - shadowWrapperValue.getItems().clear(); - shadowWrapperValue.getItems().addAll((Collection) shadowWrapperNew.getValue().getItems()); - ((ShadowWrapper)shadowWrapperValue.getParent()).setLoadWithNoFetch(false); - } catch (SchemaException e) { - error(getString("pageAdminFocus.message.couldntCreateShadowWrapper")); - LOGGER.error("Couldn't create shadow wrapper", e); - } - } - -// @Override -// protected List> loadOrgWrappers() { -// return loadSubwrappers(OrgType.class, UserType.F_PARENT_ORG_REF, false); -// } - -// private List> loadSubwrappers(Class type, -// ItemName propertyToLoad, boolean noFetch) { -// List> list = new ArrayList<>(); -// -// PrismObjectWrapper focusWrapper = getObjectModel().getObject(); -// PrismObject focus = focusWrapper.getObject(); -// PrismReference prismReference = focus.findReference(propertyToLoad); -// if (prismReference == null) { -// return new ArrayList<>(); -// } -// List references = prismReference.getValues(); -// -// Task task = createSimpleTask(OPERATION_LOAD_SHADOW); -// for (PrismReferenceValue reference : references) { -// FocusSubwrapperDto subWrapper = loadSubWrapperDto(type, reference.getOid(), noFetch, task); -// if (subWrapper != null) { -// list.add(subWrapper); -// } -// } -// -// return list; -// } - - private PrismObject getPrismObjectForWrapper(Class type, String oid, boolean noFetch, - Task task, OperationResult subResult, Collection> loadOptions){ - if (oid == null) { - return null; - } - - if (noFetch) { - GetOperationOptions rootOptions = SelectorOptions.findRootOptions(loadOptions); - if (rootOptions == null) { - loadOptions.add(new SelectorOptions<>(GetOperationOptions.createNoFetch())); - } else { - rootOptions.setNoFetch(true); - } - } - - PrismObject projection = WebModelServiceUtils.loadObject(type, oid, loadOptions, this, task, subResult); - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Loaded projection {} ({}):\n{}", oid, loadOptions, projection==null?null:projection.debugDump()); - } - - return projection; - } - -// private FocusSubwrapperDto loadSubWrapperDto(Class type, String oid, boolean noFetch, Task task) { -// OperationResult subResult = task.getResult().createMinorSubresult(OPERATION_LOAD_SHADOW); -// Collection> loadOptions = new ArrayList<>(); -// PrismObject projection = getPrismObjectForWrapper(type, oid, noFetch, task, subResult, loadOptions); -// if (projection == null) { -// // No access or error -// // TODO actually it would be nice to show an error if the shadow repo object does not exist -// return null; -// } -// String resourceName = null; -// try { -// S projectionType = projection.asObjectable(); -// -// OperationResultType fetchResult = projectionType.getFetchResult(); -// StringBuilder description = new StringBuilder(); -// if (ShadowType.class.equals(type)) { -// ShadowType shadowType = (ShadowType) projectionType; -// ResourceType resource = shadowType.getResource(); -// resourceName = WebComponentUtil.getName(resource); -// -// if (shadowType.getIntent() != null) { -// description.append(shadowType.getIntent()).append(", "); -// } -// } else if (OrgType.class.equals(type)) { -// OrgType orgType = (OrgType) projectionType; -// resourceName = orgType.getDisplayName() != null -// ? WebComponentUtil.getOrigStringFromPoly(orgType.getDisplayName()) : ""; -// } -// description.append(WebComponentUtil.getOrigStringFromPoly(projectionType.getName())); -// -// ObjectWrapperOld wrapper = ObjectWrapperUtil.createObjectWrapper(resourceName, -// description.toString(), projection, ContainerStatus.MODIFYING, task, this); -// wrapper.setLoadOptions(loadOptions); -// wrapper.setFetchResult(OperationResult.createOperationResult(fetchResult)); -// wrapper.setSelectable(true); -// wrapper.setMinimalized(true); -// -//// wrapper.initializeContainers(this); -// -// subResult.computeStatus(); -// FocusSubwrapperDto ret = new FocusSubwrapperDto<>(wrapper, UserDtoStatus.MODIFY); -// return ret; -// -// } catch (Exception ex) { -// subResult.recordFatalError("Couldn't load account." + ex.getMessage(), ex); -// LoggingUtils.logUnexpectedException(LOGGER, "Couldn't load account", ex); -// subResult.computeStatus(); -// return new FocusSubwrapperDto<>(false, resourceName, subResult); -// } -// } - - private List loadDelegatedToMe() { - List list = new ArrayList<>(); - - PrismObjectWrapper focusWrapper = getObjectModel().getObject(); - PrismObject focus = focusWrapper.getObject(); - List assignments = focus.asObjectable().getAssignment(); - for (AssignmentType assignment : assignments) { - if (assignment.getTargetRef() != null && - UserType.COMPLEX_TYPE.equals(assignment.getTargetRef().getType())) { - AssignmentEditorDto dto = new AssignmentEditorDto(UserDtoStatus.MODIFY, assignment, this); - dto.setSimpleView(true); - dto.setEditable(false); - list.add(dto); - } - } - - Collections.sort(list); - - return list; - } - - protected List getPolicyRulesList(List assignments, UserDtoStatus status){ - List list = new ArrayList<>(); - for (AssignmentType assignment : assignments) { - if (AssignmentsUtil.isPolicyRuleAssignment(assignment)) { - //TODO set status - list.add(assignment); - } - } - return list; - } - - @Override - protected void prepareObjectForAdd(PrismObject focus) throws SchemaException { - super.prepareObjectForAdd(focus); - F focusType = focus.asObjectable(); - // handle added accounts - - List shadowsToAdd = prepareShadowObject(getFocusShadows()); - for (ShadowType shadowToAdd : shadowsToAdd) { - addDefaultKindAndIntent(shadowToAdd.asPrismObject()); - ObjectReferenceType linkRef = new ObjectReferenceType(); - linkRef.asReferenceValue().setObject(shadowToAdd.asPrismObject()); - focusType.getLinkRef().add(linkRef); - } - -// List orgsToAdd = prepareSubobject(getParentOrgs()); -// if (!orgsToAdd.isEmpty()){ -// focusType.getParentOrg().addAll(orgsToAdd); -// } - - } - - @Override - protected void prepareObjectDeltaForModify(ObjectDelta focusDelta) throws SchemaException { - super.prepareObjectDeltaForModify(focusDelta); - // handle accounts - PrismObjectDefinition objectDefinition = getObjectDefinition(); - PrismReferenceDefinition refDef = objectDefinition.findReferenceDefinition(FocusType.F_LINK_REF); - ReferenceDelta refDelta = prepareUserAccountsDeltaForModify(refDef); - if (!refDelta.isEmpty()) { - focusDelta.addModification(refDelta); - } - -// refDef = objectDefinition.findReferenceDefinition(FocusType.F_PARENT_ORG_REF); -// refDelta = prepareUserOrgsDeltaForModify(refDef); -// if (!refDelta.isEmpty()) { -// focusDelta.addModification(refDelta); -// } - } - - protected PrismObjectDefinition getObjectDefinition() { - SchemaRegistry registry = getPrismContext().getSchemaRegistry(); - return registry - .findObjectDefinitionByCompileTimeClass(getCompileTimeClass()); - } - - protected ContainerDelta handleAssignmentDeltas(ObjectDelta focusDelta, - List assignments, PrismContainerDefinition def, - boolean isDelegation) throws SchemaException { - ContainerDelta assDelta = getPrismContext().deltaFactory().container().create(ItemPath.EMPTY_PATH, def.getItemName(), def); - - for (AssignmentEditorDto assDto : assignments) { - PrismContainerValue newValue = assDto.getNewValue(getPrismContext()); - - switch (assDto.getStatus()) { - case ADD: - newValue.applyDefinition(def, false); - assDelta.addValueToAdd(newValue.clone()); - break; - case DELETE: - PrismContainerValue oldValue = assDto.getOldValue(); - if (isDelegation){ - oldValue.applyDefinition(def, false); - } else { - oldValue.applyDefinition(def); - } - assDelta.addValueToDelete(oldValue.clone()); - break; - case MODIFY: - if (!assDto.isModified(getPrismContext())) { - LOGGER.trace("Assignment '{}' not modified.", new Object[] { assDto.getName() }); - continue; - } - - handleModifyAssignmentDelta(assDto, def, newValue, focusDelta); - break; - default: - warn(getString("pageAdminUser.message.illegalAssignmentState", assDto.getStatus())); - } - } - - if (!assDelta.isEmpty()) { - assDelta = focusDelta.addModification(assDelta); - } - - return assDelta; - } - - private void handleModifyAssignmentDelta(AssignmentEditorDto assDto, - PrismContainerDefinition assignmentDef, PrismContainerValue newValue, ObjectDelta focusDelta) - throws SchemaException { - LOGGER.debug("Handling modified assignment '{}', computing delta.", - new Object[] { assDto.getName() }); - - PrismValue oldValue = assDto.getOldValue(); - Collection deltas = oldValue.diff(newValue); - - for (ItemDelta delta : deltas) { - ItemPath deltaPath = delta.getPath().rest(); - ItemDefinition deltaDef = assignmentDef.findItemDefinition(deltaPath); - - delta.setParentPath(WebComponentUtil.joinPath(oldValue.getPath(), delta.getPath().allExceptLast())); - delta.applyDefinition(deltaDef); - - focusDelta.addModification(delta); - } - } - - @Override - protected boolean executeForceDelete(PrismObjectWrapper userWrapper, Task task, ModelExecuteOptions options, - OperationResult parentResult) { - if (isForce()) { - OperationResult result = parentResult.createSubresult("Force delete operation"); - - try { - ObjectDelta forceDeleteDelta = getForceDeleteDelta(userWrapper); - forceDeleteDelta.revive(getPrismContext()); - - if (forceDeleteDelta != null && !forceDeleteDelta.isEmpty()) { - getModelService().executeChanges(WebComponentUtil.createDeltaCollection(forceDeleteDelta), - options, task, result); - } - } catch (Exception ex) { - result.recordFatalError(getString("PageAdminFocus.message.executeForceDelete.fatalError")); - LoggingUtils.logUnexpectedException(LOGGER, "Failed to execute delete operation with force", ex); - return false; - } - - result.recomputeStatus(); - result.recordSuccessIfUnknown(); - return true; - } - return false; - } - - private ObjectDelta getForceDeleteDelta(PrismObjectWrapper focusWrapper) throws SchemaException { - - List accounts = getFocusShadows(); - List refDeltas = new ArrayList<>(); - ObjectDelta forceDeleteDelta = null; - for (ShadowWrapper account : accounts) { -// if (!accDto.isLoadedOK()) { -// continue; -// } - if (account.getProjectionStatus() == UserDtoStatus.DELETE) { -// ObjectWrapperOld accWrapper = accDto.getObjectOld(); - ReferenceDelta refDelta = getPrismContext().deltaFactory().reference().createModificationDelete(UserType.F_LINK_REF, - focusWrapper.getObject().getDefinition(), account.getObject()); - refDeltas.add(refDelta); - } else if (account.getProjectionStatus() == UserDtoStatus.UNLINK) { -// ObjectWrapperOld accWrapper = accDto.getObjectOld(); - ReferenceDelta refDelta = getPrismContext().deltaFactory().reference().createModificationDelete(UserType.F_LINK_REF, - focusWrapper.getObject().getDefinition(), account.getObject().getOid()); - refDeltas.add(refDelta); - } - } - if (!refDeltas.isEmpty()) { - forceDeleteDelta = getPrismContext().deltaFactory().object() - .createModifyDelta(focusWrapper.getObject().getOid(), refDeltas, - getCompileTimeClass()); - } - PrismContainerDefinition def = focusWrapper.getObject().findContainer(UserType.F_ASSIGNMENT) - .getDefinition(); - if (forceDeleteDelta == null) { - forceDeleteDelta = getPrismContext().deltaFactory().object().createEmptyModifyDelta(getCompileTimeClass(), - focusWrapper.getObject().getOid()); - } - return forceDeleteDelta; - } - -// private

List

prepareSubobject(List> projections) throws SchemaException{ -// List

projectionsToAdd = new ArrayList<>(); -// for (FocusSubwrapperDto

projection : projections) { -// if (!projection.isLoadedOK()) { -// continue; -// } -// -// if (UserDtoStatus.MODIFY.equals(projection.getStatus())) { -// // this is legal e.g. when child org is being create (one assignment comes pre-created) -// // TODO do we need more specific checks here? -// continue; -// } -// -// if (!UserDtoStatus.ADD.equals(projection.getStatus())) { -// warn(getString("pageAdminFocus.message.illegalAccountState", projection.getStatus())); -// continue; -// } -// -// ObjectWrapperOld

projectionWrapper = projection.getObjectOld(); -// ObjectDelta

delta = projectionWrapper.getObjectDelta(); -// PrismObject

proj = delta.getObjectToAdd(); -// WebComponentUtil.encryptCredentials(proj, true, getMidpointApplication()); -// -// projectionsToAdd.add(proj.asObjectable()); -// } -// return projectionsToAdd; -// } - - private List prepareShadowObject(List projections) throws SchemaException{ - List projectionsToAdd = new ArrayList<>(); - for (ShadowWrapper projection : projections) { -// if (!projection.isLoadedOK()) { -// continue; -// } - if (UserDtoStatus.MODIFY.equals(projection.getProjectionStatus())) { - // this is legal e.g. when child org is being create (one assignment comes pre-created) - // TODO do we need more specific checks here? - continue; - } - - if (!UserDtoStatus.ADD.equals(projection.getProjectionStatus())) { - warn(getString("pageAdminFocus.message.illegalAccountState", projection.getStatus())); - continue; - } - - ObjectDelta delta = projection.getObjectDelta(); - PrismObject proj = delta.getObjectToAdd(); - WebComponentUtil.encryptCredentials(proj, true, getMidpointApplication()); - - projectionsToAdd.add(proj.asObjectable()); - } - return projectionsToAdd; - } - - - @Override - protected List> getAdditionalModifyDeltas(OperationResult result) { - return getShadowModifyDeltas(result); - } - - private List> getShadowModifyDeltas(OperationResult result) { - List> deltas = new ArrayList<>(); - - List accounts = getFocusShadows(); - for (ShadowWrapper account : accounts) { -// if (!account.isLoadedOK()) { -// continue; -// } - try { - ObjectDelta delta = account.getObjectDelta(); - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Account delta computed from {} as:\n{}", - new Object[] { account, delta.debugDump(3) }); - } - - if (!UserDtoStatus.MODIFY.equals(account.getProjectionStatus())) { - continue; - } - - if (delta == null || delta.isEmpty()) { -// && (accountWrapper.getOldDelta() == null || accountWrapper.getOldDelta().isEmpty())) { - continue; - } - -// if (accountWrapper.getOldDelta() != null) { -// delta = ObjectDeltaCollectionsUtil.summarize(delta, accountWrapper.getOldDelta()); -// } - - - WebComponentUtil.encryptCredentials(delta, true, getMidpointApplication()); - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Modifying account:\n{}", new Object[] { delta.debugDump(3) }); - } - - deltas.add(delta); - - } catch (Exception ex) { - result.recordFatalError(getString("PageAdminFocus.message.getShadowModifyDeltas.fatalError"), ex); - LoggingUtils.logUnexpectedException(LOGGER, "Couldn't compute account delta", ex); - } - } - - return deltas; - } - - /** - * remove this method after model is updated - it has to remove resource - * from accountConstruction - */ - @Deprecated - private void removeResourceFromAccConstruction(AssignmentType assignment) { - ConstructionType accConstruction = assignment.getConstruction(); - if (accConstruction == null || accConstruction.getResourceRef() == null || accConstruction.getResourceRef().asReferenceValue().getObject() == null) { - return; - } - - ObjectReferenceType ref = new ObjectReferenceType(); - ref.setOid(assignment.getConstruction().getResourceRef().getOid()); - ref.setType(ResourceType.COMPLEX_TYPE); - assignment.getConstruction().setResourceRef(ref); - } - - private ReferenceDelta prepareUserAccountsDeltaForModify(PrismReferenceDefinition refDef) - throws SchemaException { - ReferenceDelta refDelta = getPrismContext().deltaFactory().reference().create(refDef); - - List accounts = getFocusShadows(); - for (ShadowWrapper accountWrapper : accounts) { -// if (accDto.isLoadedOK()) { -// ObjectWrapperOld accountWrapper = accDto.getObjectOld(); - accountWrapper.revive(getPrismContext()); - ObjectDelta delta = accountWrapper.getObjectDelta(); - PrismReferenceValue refValue = getPrismContext().itemFactory().createReferenceValue(null, OriginType.USER_ACTION, null); - - PrismObject account; - switch (accountWrapper.getProjectionStatus()) { - case ADD: - account = delta.getObjectToAdd(); - addDefaultKindAndIntent(account); - WebComponentUtil.encryptCredentials(account, true, getMidpointApplication()); - refValue.setObject(account); - refDelta.addValueToAdd(refValue); - break; - case DELETE: - account = accountWrapper.getObject(); - refValue.setObject(account); - refDelta.addValueToDelete(refValue); - break; - case MODIFY: - // nothing to do, account modifications were applied - // before - continue; - case UNLINK: - refValue.setOid(delta.getOid()); - refValue.setTargetType(ShadowType.COMPLEX_TYPE); - refDelta.addValueToDelete(refValue); - break; - default: - warn(getString("pageAdminFocus.message.illegalAccountState", accountWrapper.getProjectionStatus())); - } -// } - } - - return refDelta; - } - - private void addDefaultKindAndIntent(PrismObject account) { - if (account.asObjectable().getKind() == null) { - account.asObjectable().setKind(ShadowKindType.ACCOUNT); - } - if (account.asObjectable().getIntent() == null) { - account.asObjectable().setIntent(SchemaConstants.INTENT_DEFAULT); - } - } - - public List showAllAssignmentsPerformed(AjaxRequestTarget ajaxRequestTarget) { - LOGGER.debug("Recompute user assignments"); - Task task = createSimpleTask(OPERATION_RECOMPUTE_ASSIGNMENTS); - OperationResult result = new OperationResult(OPERATION_RECOMPUTE_ASSIGNMENTS); - ObjectDelta delta; - Set assignmentInfoDtoSet = new TreeSet<>(); - - try { - reviveModels(); - - PrismObjectWrapper focusWrapper = getObjectWrapper(); - delta = focusWrapper.getObjectDelta(); -// if (focusWrapper.getOldDelta() != null) { -// delta = ObjectDeltaCollectionsUtil.summarize(focusWrapper.getOldDelta(), delta); -// } - - switch (focusWrapper.getStatus()) { - case ADDED: - PrismObject focus = delta.getObjectToAdd(); - prepareObjectForAdd(focus); - getPrismContext().adopt(focus, getCompileTimeClass()); - - LOGGER.trace("Delta before add focus:\n{}", delta.debugDumpLazily(3)); - if (!delta.isEmpty()) { - delta.revive(getPrismContext()); - } else { - result.recordSuccess(); - } - break; - case NOT_CHANGED: - prepareObjectDeltaForModify(delta); - LOGGER.trace("Delta before modify user:\n{}", delta.debugDumpLazily(3)); - - List> accountDeltas = getShadowModifyDeltas(result); - if (!delta.isEmpty()) { - delta.revive(getPrismContext()); - } - for (ObjectDelta accDelta : accountDeltas) { - if (!accDelta.isEmpty()) { - accDelta.revive(getPrismContext()); - } - } - break; - default: - error(getString("pageAdminFocus.message.unsupportedState", focusWrapper.getStatus())); - } - - ModelContext modelContext; - try { - ModelExecuteOptions options = ModelExecuteOptions.createEvaluateAllAssignmentRelationsOnRecompute(); - modelContext = getModelInteractionService().previewChanges(Collections.singleton(delta), options, task, result); - } catch (NoFocusNameSchemaException e) { - info(getString("pageAdminFocus.message.noUserName")); - ajaxRequestTarget.add(getFeedbackPanel()); - return null; - } - - DeltaSetTriple> evaluatedAssignmentTriple = modelContext.getEvaluatedAssignmentTriple(); - Collection> evaluatedAssignments = null; - if (evaluatedAssignmentTriple != null) { - evaluatedAssignments = evaluatedAssignmentTriple.getNonNegativeValues(); - } - if (evaluatedAssignments == null || evaluatedAssignments.isEmpty()) { - info(getString("pageAdminFocus.message.noAssignmentsAvailable")); - ajaxRequestTarget.add(getFeedbackPanel()); - return null; - } - - for (EvaluatedAssignment evaluatedAssignment : evaluatedAssignments) { - if (!evaluatedAssignment.isValid()) { - continue; - } - // roles and orgs - DeltaSetTriple targetsTriple = evaluatedAssignment.getRoles(); - Collection targets = targetsTriple.getNonNegativeValues(); - for (EvaluatedAssignmentTarget target : targets) { - if (target.getTarget() != null && ArchetypeType.class.equals(target.getTarget().getCompileTimeClass())){ - continue; - } - if (target.appliesToFocusWithAnyRelation(getRelationRegistry())) { - assignmentInfoDtoSet.add(createAssignmentsPreviewDto(target, task, result)); - } - } - - // all resources - DeltaSetTriple evaluatedConstructionsTriple = evaluatedAssignment - .getEvaluatedConstructions(task, result); - Collection evaluatedConstructions = evaluatedConstructionsTriple - .getNonNegativeValues(); - for (EvaluatedConstruction construction : evaluatedConstructions) { - if (!construction.isWeak()) { - assignmentInfoDtoSet.add(createAssignmentsPreviewDto(construction)); - } - } - } - - return new ArrayList<>(assignmentInfoDtoSet); - - } catch (Exception e) { - LoggingUtils.logUnexpectedException(LOGGER, "Could not create assignments preview.", e); - error("Could not create assignments preview. Reason: " + e); - ajaxRequestTarget.add(getFeedbackPanel()); - } - return null; - } - - private AssignmentInfoDto createAssignmentsPreviewDto(EvaluatedAssignmentTarget evaluatedAbstractRole, - Task task, OperationResult result) { - return createAssignmentsPreviewDto(evaluatedAbstractRole.getTarget(), evaluatedAbstractRole.isDirectlyAssigned(), - evaluatedAbstractRole.getAssignmentPath(), evaluatedAbstractRole.getAssignment(), task, result); - } - - protected AssignmentInfoDto createAssignmentsPreviewDto(ObjectReferenceType reference, Task task, OperationResult result) { - PrismObject targetObject = WebModelServiceUtils.resolveReferenceNoFetch(reference, - PageAdminFocus.this, task, result); - return createAssignmentsPreviewDto(targetObject, true, null, null, task, result); - } - - protected AssignmentInfoDto createDelegableAssignmentsPreviewDto(AssignmentType assignment, Task task, OperationResult result) { - if (assignment.getTargetRef() != null) { - if (RoleType.COMPLEX_TYPE.equals(assignment.getTargetRef().getType()) - || OrgType.COMPLEX_TYPE.equals(assignment.getTargetRef().getType()) - || ServiceType.COMPLEX_TYPE.equals(assignment.getTargetRef().getType())) { - PrismObject targetObject = WebModelServiceUtils.resolveReferenceNoFetch(assignment.getTargetRef(), - PageAdminFocus.this, task, result); - Boolean isDelegable = false; - if (targetObject != null) { - isDelegable = targetObject.asObjectable().isDelegable(); - } - if (Boolean.TRUE.equals(isDelegable)) { - return createAssignmentsPreviewDto(targetObject, true, null, assignment, task, result); - } - } - } - return null; - } - - private AssignmentInfoDto createAssignmentsPreviewDto(PrismObject targetObject, - boolean isDirectlyAssigned, AssignmentPath assignmentPath, AssignmentType assignment, - Task task, OperationResult result) { - AssignmentInfoDto dto = new AssignmentInfoDto(); - dto.setTargetOid(targetObject.getOid()); - dto.setTargetName(getNameToDisplay(targetObject)); - dto.setTargetDescription(targetObject.asObjectable().getDescription()); - dto.setTargetClass(targetObject.getCompileTimeClass()); - dto.setTargetType(WebComponentUtil.classToQName(getPrismContext(), targetObject.getCompileTimeClass())); - dto.setDirect(isDirectlyAssigned); - dto.setAssignmentParent(assignmentPath); - if (assignment != null) { - if (assignment.getTenantRef() != null) { - dto.setTenantName(WebModelServiceUtils.resolveReferenceName(assignment.getTenantRef(), PageAdminFocus.this)); - dto.setTenantRef(assignment.getTenantRef()); - } - if (assignment.getOrgRef() != null) { - dto.setOrgRefName(WebModelServiceUtils.resolveReferenceName(assignment.getOrgRef(), PageAdminFocus.this)); - dto.setOrgRef(assignment.getOrgRef()); - } - if (assignment.getTargetRef() != null){ - dto.setRelation(assignment.getTargetRef().getRelation()); - } - } - return dto; - } - - private String getNameToDisplay(PrismObject target) { - if (target.canRepresent(AbstractRoleType.class)) { - String n = PolyString.getOrig(((AbstractRoleType)target.asObjectable()).getDisplayName()); - if (StringUtils.isNotBlank(n)) { - return n; - } - } - return PolyString.getOrig(target.asObjectable().getName()); - } - - private AssignmentInfoDto createAssignmentsPreviewDto(EvaluatedConstruction evaluatedConstruction) { - AssignmentInfoDto dto = new AssignmentInfoDto(); - PrismObject resource = evaluatedConstruction.getResource(); - dto.setTargetOid(resource.getOid()); - dto.setTargetName(PolyString.getOrig(resource.asObjectable().getName())); - dto.setTargetDescription(resource.asObjectable().getDescription()); - dto.setTargetClass(resource.getCompileTimeClass()); - dto.setDirect(evaluatedConstruction.isDirectlyAssigned()); - dto.setAssignmentParent(evaluatedConstruction.getAssignmentPath()); - dto.setKind(evaluatedConstruction.getKind()); - dto.setIntent(evaluatedConstruction.getIntent()); - return dto; - } - - @Override - protected void performAdditionalValidation(PrismObject object, - Collection> deltas, Collection errors) throws SchemaException { - - if (object != null && object.asObjectable() != null) { - for (AssignmentType assignment : object.asObjectable().getAssignment()) { - for (MidpointFormValidator validator : getFormValidatorRegistry().getValidators()) { - if (errors == null) { - errors = validator.validateAssignment(assignment); - } else { - errors.addAll(validator.validateAssignment(assignment)); - } - } - } - } - - } - - protected boolean isFocusHistoryPage(){ - return false; - } - - protected boolean isSelfProfile(){ - return false; - } -} +/* + * Copyright (c) 2010-2019 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.web.page.admin; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; + +import com.evolveum.midpoint.xml.ns._public.common.common_3.*; +import org.apache.commons.lang.StringUtils; +import org.apache.wicket.Session; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.protocol.http.WebSession; +import org.apache.wicket.request.mapper.parameter.PageParameters; + +import com.evolveum.midpoint.gui.api.model.LoadableModel; +import com.evolveum.midpoint.gui.api.prism.ItemStatus; +import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.prism.ShadowWrapper; +import com.evolveum.midpoint.gui.api.util.WebComponentUtil; +import com.evolveum.midpoint.gui.api.util.WebModelServiceUtils; +import com.evolveum.midpoint.gui.impl.factory.PrismObjectWrapperFactory; +import com.evolveum.midpoint.gui.impl.factory.WrapperContext; +import com.evolveum.midpoint.gui.impl.prism.PrismObjectValueWrapper; +import com.evolveum.midpoint.model.api.ModelExecuteOptions; +import com.evolveum.midpoint.model.api.context.AssignmentPath; +import com.evolveum.midpoint.model.api.context.EvaluatedAssignment; +import com.evolveum.midpoint.model.api.context.EvaluatedAssignmentTarget; +import com.evolveum.midpoint.model.api.context.EvaluatedConstruction; +import com.evolveum.midpoint.model.api.context.ModelContext; +import com.evolveum.midpoint.prism.ItemDefinition; +import com.evolveum.midpoint.prism.OriginType; +import com.evolveum.midpoint.prism.PrismContainerDefinition; +import com.evolveum.midpoint.prism.PrismContainerValue; +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.PrismObjectDefinition; +import com.evolveum.midpoint.prism.PrismReference; +import com.evolveum.midpoint.prism.PrismReferenceDefinition; +import com.evolveum.midpoint.prism.PrismReferenceValue; +import com.evolveum.midpoint.prism.PrismValue; +import com.evolveum.midpoint.prism.delta.ContainerDelta; +import com.evolveum.midpoint.prism.delta.DeltaSetTriple; +import com.evolveum.midpoint.prism.delta.ItemDelta; +import com.evolveum.midpoint.prism.delta.ObjectDelta; +import com.evolveum.midpoint.prism.delta.ReferenceDelta; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.prism.polystring.PolyString; +import com.evolveum.midpoint.prism.schema.SchemaRegistry; +import com.evolveum.midpoint.schema.GetOperationOptions; +import com.evolveum.midpoint.schema.SelectorOptions; +import com.evolveum.midpoint.schema.constants.SchemaConstants; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.util.exception.NoFocusNameSchemaException; +import com.evolveum.midpoint.util.exception.SchemaException; +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.web.component.assignment.AssignmentEditorDto; +import com.evolveum.midpoint.web.component.assignment.AssignmentsUtil; +import com.evolveum.midpoint.web.component.prism.show.PagePreviewChanges; +import com.evolveum.midpoint.web.component.progress.ProgressReportingAwarePage; +import com.evolveum.midpoint.web.page.admin.users.component.AssignmentInfoDto; +import com.evolveum.midpoint.web.page.admin.users.dto.UserDtoStatus; +import com.evolveum.midpoint.web.security.util.SecurityUtils; +import com.evolveum.midpoint.web.util.validation.MidpointFormValidator; +import com.evolveum.midpoint.web.util.validation.SimpleValidationError; + +public abstract class PageAdminFocus extends PageAdminObjectDetails + implements ProgressReportingAwarePage { + private static final long serialVersionUID = 1L; + + private LoadableModel> projectionModel; + private LoadableModel> delegatedToMeModel; + + private static final String DOT_CLASS = PageAdminFocus.class.getName() + "."; + private static final String OPERATION_RECOMPUTE_ASSIGNMENTS = DOT_CLASS + "recomputeAssignments"; + + private static final String OPERATION_LOAD_SHADOW = DOT_CLASS + "loadShadow"; + + private static final Trace LOGGER = TraceManager.getTrace(PageAdminFocus.class); + + public PageAdminFocus() { + initialize(null); + } + + public PageAdminFocus(PageParameters parameters) { + getPageParameters().overwriteWith(parameters); + initialize(null); + } + + public PageAdminFocus(final PrismObject userToEdit) { + initialize(userToEdit); + } + + public PageAdminFocus(final PrismObject unitToEdit, boolean isNewObject) { + initialize(unitToEdit, isNewObject); + } + + public PageAdminFocus(final PrismObject unitToEdit, boolean isNewObject, boolean isReadonly) { + initialize(unitToEdit, isNewObject, isReadonly); + } + + + @Override + protected void initializeModel(final PrismObject objectToEdit, boolean isNewObject, boolean isReadonly) { + super.initializeModel(objectToEdit, isNewObject, isReadonly); + + projectionModel = new LoadableModel>(false) { + private static final long serialVersionUID = 1L; + + @Override + protected List load() { + return loadShadowWrappers(true); + } + }; + + delegatedToMeModel= new LoadableModel>(false) { + + private static final long serialVersionUID = 1L; + @Override + protected List load() { + return loadDelegatedToMe(); + } + }; + + } + + public LoadableModel> getProjectionModel() { + return projectionModel; + } + + public LoadableModel> getDelegatedToMeModel() { + return delegatedToMeModel; + } + + public List getFocusShadows() { + return projectionModel.getObject(); + } + + protected void reviveModels() throws SchemaException { + super.reviveModels(); + WebComponentUtil.revive(projectionModel, getPrismContext()); + } + + @Override + public void continueEditing(AjaxRequestTarget target) { + getMainPanel().setVisible(true); + getProgressPanel().hide(); + getProgressPanel().hideAbortButton(target); + getProgressPanel().hideBackButton(target); + getProgressPanel().hideContinueEditingButton(target); + target.add(this); + } + + private List loadShadowWrappers(boolean noFetch) { + List list = new ArrayList<>(); + + PrismObjectWrapper focusWrapper = getObjectModel().getObject(); + PrismObject focus = focusWrapper.getObject(); + PrismReference prismReference = focus.findReference(UserType.F_LINK_REF); + if (prismReference == null || prismReference.isEmpty()) { + return new ArrayList<>(); + } + List references = prismReference.getValues(); + + Task task = createSimpleTask(OPERATION_LOAD_SHADOW); + for (PrismReferenceValue reference : references) { + if(reference == null || (reference.getOid() == null && reference.getTargetType() == null)) { + LOGGER.trace("Skiping reference for shadow with null oid"); + continue; // default value + } + OperationResult subResult = task.getResult().createMinorSubresult(OPERATION_LOAD_SHADOW); + PrismObject projection = getPrismObjectForWrapper(ShadowType.class, reference.getOid(), + noFetch, task, subResult, createLoadOptionForShadowWrapper()); + + if(projection == null) { +// showResult(subResult, "pageAdminFocus.message.couldntLoadShadowProjection"); + LOGGER.error("Couldn't load shadow projection"); + continue; + } + + try { + ShadowWrapper wrapper = loadShadowWrapper(projection, task, subResult); + wrapper.setLoadWithNoFetch(noFetch); + + if (wrapper != null) { + list.add((ShadowWrapper)wrapper); + } else { + showResult(subResult, "pageAdminFocus.message.shadowWrapperIsNull"); + LOGGER.error("ShadowWrapper is null"); + } + + //TODO catch Exception/Runtim,eException, Throwable + } catch (SchemaException e) { + showResult(subResult, "pageAdminFocus.message.couldntCreateShadowWrapper"); + LoggingUtils.logUnexpectedException(LOGGER, "Couldn't create shadow wrapper", e); + } + } + return list; + } + + private Collection> createLoadOptionForShadowWrapper(){ + return getSchemaHelper().getOperationOptionsBuilder() + .item(ShadowType.F_RESOURCE_REF).resolve().readOnly() + .build(); + } + + public ShadowWrapper loadShadowWrapper(PrismObject projection, Task task, OperationResult result) throws SchemaException{ + PrismObjectWrapperFactory factory = getRegistry().getObjectWrapperFactory(projection.getDefinition()); + WrapperContext context = new WrapperContext(task, result); + context.setCreateIfEmpty(false); + ShadowWrapper wrapper = (ShadowWrapper) factory.createObjectWrapper(projection, ItemStatus.NOT_CHANGED, context); + wrapper.setProjectionStatus(UserDtoStatus.MODIFY); + return wrapper; + } + + public void loadFullShadow(PrismObjectValueWrapper shadowWrapperValue, AjaxRequestTarget target) { + if(shadowWrapperValue.getRealValue() == null) { + error(getString("pageAdminFocus.message.couldntCreateShadowWrapper")); + LOGGER.error("Couldn't create shadow wrapper, because RealValue is null in " + shadowWrapperValue); + return; + } + String oid = shadowWrapperValue.getRealValue().getOid(); + Task task = createSimpleTask(OPERATION_LOAD_SHADOW); + OperationResult result = task.getResult(); + PrismObject projection = getPrismObjectForWrapper(ShadowType.class, oid, false, task, + result, createLoadOptionForShadowWrapper()); + + if (projection == null) { + result.recordFatalError(getString("PageAdminFocus.message.loadFullShadow.fatalError", shadowWrapperValue.getRealValue())); + showResult(result); + target.add(getFeedbackPanel()); + return; + } + + ShadowWrapper shadowWrapperNew; + try { + shadowWrapperNew = loadShadowWrapper(projection, task, result); + + if (shadowWrapperNew == null) { + error(getString("pageAdminFocus.message.shadowWrapperIsNull")); + LOGGER.error("ShadowWrapper is null"); + return; + } + + shadowWrapperValue.getItems().clear(); + shadowWrapperValue.getItems().addAll((Collection) shadowWrapperNew.getValue().getItems()); + ((ShadowWrapper)shadowWrapperValue.getParent()).setLoadWithNoFetch(false); + } catch (SchemaException e) { + error(getString("pageAdminFocus.message.couldntCreateShadowWrapper")); + LOGGER.error("Couldn't create shadow wrapper", e); + } + } + +// @Override +// protected List> loadOrgWrappers() { +// return loadSubwrappers(OrgType.class, UserType.F_PARENT_ORG_REF, false); +// } + +// private List> loadSubwrappers(Class type, +// ItemName propertyToLoad, boolean noFetch) { +// List> list = new ArrayList<>(); +// +// PrismObjectWrapper focusWrapper = getObjectModel().getObject(); +// PrismObject focus = focusWrapper.getObject(); +// PrismReference prismReference = focus.findReference(propertyToLoad); +// if (prismReference == null) { +// return new ArrayList<>(); +// } +// List references = prismReference.getValues(); +// +// Task task = createSimpleTask(OPERATION_LOAD_SHADOW); +// for (PrismReferenceValue reference : references) { +// FocusSubwrapperDto subWrapper = loadSubWrapperDto(type, reference.getOid(), noFetch, task); +// if (subWrapper != null) { +// list.add(subWrapper); +// } +// } +// +// return list; +// } + + private PrismObject getPrismObjectForWrapper(Class type, String oid, boolean noFetch, + Task task, OperationResult subResult, Collection> loadOptions){ + if (oid == null) { + return null; + } + + if (noFetch) { + GetOperationOptions rootOptions = SelectorOptions.findRootOptions(loadOptions); + if (rootOptions == null) { + loadOptions.add(new SelectorOptions<>(GetOperationOptions.createNoFetch())); + } else { + rootOptions.setNoFetch(true); + } + } + + PrismObject projection = WebModelServiceUtils.loadObject(type, oid, loadOptions, this, task, subResult); + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Loaded projection {} ({}):\n{}", oid, loadOptions, projection==null?null:projection.debugDump()); + } + + return projection; + } + +// private FocusSubwrapperDto loadSubWrapperDto(Class type, String oid, boolean noFetch, Task task) { +// OperationResult subResult = task.getResult().createMinorSubresult(OPERATION_LOAD_SHADOW); +// Collection> loadOptions = new ArrayList<>(); +// PrismObject projection = getPrismObjectForWrapper(type, oid, noFetch, task, subResult, loadOptions); +// if (projection == null) { +// // No access or error +// // TODO actually it would be nice to show an error if the shadow repo object does not exist +// return null; +// } +// String resourceName = null; +// try { +// S projectionType = projection.asObjectable(); +// +// OperationResultType fetchResult = projectionType.getFetchResult(); +// StringBuilder description = new StringBuilder(); +// if (ShadowType.class.equals(type)) { +// ShadowType shadowType = (ShadowType) projectionType; +// ResourceType resource = shadowType.getResource(); +// resourceName = WebComponentUtil.getName(resource); +// +// if (shadowType.getIntent() != null) { +// description.append(shadowType.getIntent()).append(", "); +// } +// } else if (OrgType.class.equals(type)) { +// OrgType orgType = (OrgType) projectionType; +// resourceName = orgType.getDisplayName() != null +// ? WebComponentUtil.getOrigStringFromPoly(orgType.getDisplayName()) : ""; +// } +// description.append(WebComponentUtil.getOrigStringFromPoly(projectionType.getName())); +// +// ObjectWrapperOld wrapper = ObjectWrapperUtil.createObjectWrapper(resourceName, +// description.toString(), projection, ContainerStatus.MODIFYING, task, this); +// wrapper.setLoadOptions(loadOptions); +// wrapper.setFetchResult(OperationResult.createOperationResult(fetchResult)); +// wrapper.setSelectable(true); +// wrapper.setMinimalized(true); +// +//// wrapper.initializeContainers(this); +// +// subResult.computeStatus(); +// FocusSubwrapperDto ret = new FocusSubwrapperDto<>(wrapper, UserDtoStatus.MODIFY); +// return ret; +// +// } catch (Exception ex) { +// subResult.recordFatalError("Couldn't load account." + ex.getMessage(), ex); +// LoggingUtils.logUnexpectedException(LOGGER, "Couldn't load account", ex); +// subResult.computeStatus(); +// return new FocusSubwrapperDto<>(false, resourceName, subResult); +// } +// } + + private List loadDelegatedToMe() { + List list = new ArrayList<>(); + + PrismObjectWrapper focusWrapper = getObjectModel().getObject(); + PrismObject focus = focusWrapper.getObject(); + List assignments = focus.asObjectable().getAssignment(); + for (AssignmentType assignment : assignments) { + if (assignment.getTargetRef() != null && + UserType.COMPLEX_TYPE.equals(assignment.getTargetRef().getType())) { + AssignmentEditorDto dto = new AssignmentEditorDto(UserDtoStatus.MODIFY, assignment, this); + dto.setSimpleView(true); + dto.setEditable(false); + list.add(dto); + } + } + + Collections.sort(list); + + return list; + } + + protected List getPolicyRulesList(List assignments, UserDtoStatus status){ + List list = new ArrayList<>(); + for (AssignmentType assignment : assignments) { + if (AssignmentsUtil.isPolicyRuleAssignment(assignment)) { + //TODO set status + list.add(assignment); + } + } + return list; + } + + @Override + protected void prepareObjectForAdd(PrismObject focus) throws SchemaException { + super.prepareObjectForAdd(focus); + F focusType = focus.asObjectable(); + // handle added accounts + + List shadowsToAdd = prepareShadowObject(getFocusShadows()); + for (ShadowType shadowToAdd : shadowsToAdd) { + addDefaultKindAndIntent(shadowToAdd.asPrismObject()); + ObjectReferenceType linkRef = new ObjectReferenceType(); + linkRef.asReferenceValue().setObject(shadowToAdd.asPrismObject()); + focusType.getLinkRef().add(linkRef); + } + +// List orgsToAdd = prepareSubobject(getParentOrgs()); +// if (!orgsToAdd.isEmpty()){ +// focusType.getParentOrg().addAll(orgsToAdd); +// } + + } + + @Override + protected void prepareObjectDeltaForModify(ObjectDelta focusDelta) throws SchemaException { + super.prepareObjectDeltaForModify(focusDelta); + // handle accounts + PrismObjectDefinition objectDefinition = getObjectDefinition(); + PrismReferenceDefinition refDef = objectDefinition.findReferenceDefinition(FocusType.F_LINK_REF); + ReferenceDelta refDelta = prepareUserAccountsDeltaForModify(refDef); + if (!refDelta.isEmpty()) { + focusDelta.addModification(refDelta); + } + +// refDef = objectDefinition.findReferenceDefinition(FocusType.F_PARENT_ORG_REF); +// refDelta = prepareUserOrgsDeltaForModify(refDef); +// if (!refDelta.isEmpty()) { +// focusDelta.addModification(refDelta); +// } + } + + protected PrismObjectDefinition getObjectDefinition() { + SchemaRegistry registry = getPrismContext().getSchemaRegistry(); + return registry + .findObjectDefinitionByCompileTimeClass(getCompileTimeClass()); + } + + protected ContainerDelta handleAssignmentDeltas(ObjectDelta focusDelta, + List assignments, PrismContainerDefinition def, + boolean isDelegation) throws SchemaException { + ContainerDelta assDelta = getPrismContext().deltaFactory().container().create(ItemPath.EMPTY_PATH, def.getItemName(), def); + + for (AssignmentEditorDto assDto : assignments) { + PrismContainerValue newValue = assDto.getNewValue(getPrismContext()); + + switch (assDto.getStatus()) { + case ADD: + newValue.applyDefinition(def, false); + assDelta.addValueToAdd(newValue.clone()); + break; + case DELETE: + PrismContainerValue oldValue = assDto.getOldValue(); + if (isDelegation){ + oldValue.applyDefinition(def, false); + } else { + oldValue.applyDefinition(def); + } + assDelta.addValueToDelete(oldValue.clone()); + break; + case MODIFY: + if (!assDto.isModified(getPrismContext())) { + LOGGER.trace("Assignment '{}' not modified.", new Object[] { assDto.getName() }); + continue; + } + + handleModifyAssignmentDelta(assDto, def, newValue, focusDelta); + break; + default: + warn(getString("pageAdminUser.message.illegalAssignmentState", assDto.getStatus())); + } + } + + if (!assDelta.isEmpty()) { + assDelta = focusDelta.addModification(assDelta); + } + + return assDelta; + } + + private void handleModifyAssignmentDelta(AssignmentEditorDto assDto, + PrismContainerDefinition assignmentDef, PrismContainerValue newValue, ObjectDelta focusDelta) + throws SchemaException { + LOGGER.debug("Handling modified assignment '{}', computing delta.", + new Object[] { assDto.getName() }); + + PrismValue oldValue = assDto.getOldValue(); + Collection deltas = oldValue.diff(newValue); + + for (ItemDelta delta : deltas) { + ItemPath deltaPath = delta.getPath().rest(); + ItemDefinition deltaDef = assignmentDef.findItemDefinition(deltaPath); + + delta.setParentPath(WebComponentUtil.joinPath(oldValue.getPath(), delta.getPath().allExceptLast())); + delta.applyDefinition(deltaDef); + + focusDelta.addModification(delta); + } + } + + @Override + protected boolean executeForceDelete(PrismObjectWrapper userWrapper, Task task, ModelExecuteOptions options, + OperationResult parentResult) { + if (isForce()) { + OperationResult result = parentResult.createSubresult("Force delete operation"); + + try { + ObjectDelta forceDeleteDelta = getForceDeleteDelta(userWrapper); + forceDeleteDelta.revive(getPrismContext()); + + if (forceDeleteDelta != null && !forceDeleteDelta.isEmpty()) { + getModelService().executeChanges(WebComponentUtil.createDeltaCollection(forceDeleteDelta), + options, task, result); + } + } catch (Exception ex) { + result.recordFatalError(getString("PageAdminFocus.message.executeForceDelete.fatalError")); + LoggingUtils.logUnexpectedException(LOGGER, "Failed to execute delete operation with force", ex); + return false; + } + + result.recomputeStatus(); + result.recordSuccessIfUnknown(); + return true; + } + return false; + } + + private ObjectDelta getForceDeleteDelta(PrismObjectWrapper focusWrapper) throws SchemaException { + + List accounts = getFocusShadows(); + List refDeltas = new ArrayList<>(); + ObjectDelta forceDeleteDelta = null; + for (ShadowWrapper account : accounts) { +// if (!accDto.isLoadedOK()) { +// continue; +// } + if (account.getProjectionStatus() == UserDtoStatus.DELETE) { +// ObjectWrapperOld accWrapper = accDto.getObjectOld(); + ReferenceDelta refDelta = getPrismContext().deltaFactory().reference().createModificationDelete(UserType.F_LINK_REF, + focusWrapper.getObject().getDefinition(), account.getObject()); + refDeltas.add(refDelta); + } else if (account.getProjectionStatus() == UserDtoStatus.UNLINK) { +// ObjectWrapperOld accWrapper = accDto.getObjectOld(); + ReferenceDelta refDelta = getPrismContext().deltaFactory().reference().createModificationDelete(UserType.F_LINK_REF, + focusWrapper.getObject().getDefinition(), account.getObject().getOid()); + refDeltas.add(refDelta); + } + } + if (!refDeltas.isEmpty()) { + forceDeleteDelta = getPrismContext().deltaFactory().object() + .createModifyDelta(focusWrapper.getObject().getOid(), refDeltas, + getCompileTimeClass()); + } + PrismContainerDefinition def = focusWrapper.getObject().findContainer(UserType.F_ASSIGNMENT) + .getDefinition(); + if (forceDeleteDelta == null) { + forceDeleteDelta = getPrismContext().deltaFactory().object().createEmptyModifyDelta(getCompileTimeClass(), + focusWrapper.getObject().getOid()); + } + return forceDeleteDelta; + } + +// private

List

prepareSubobject(List> projections) throws SchemaException{ +// List

projectionsToAdd = new ArrayList<>(); +// for (FocusSubwrapperDto

projection : projections) { +// if (!projection.isLoadedOK()) { +// continue; +// } +// +// if (UserDtoStatus.MODIFY.equals(projection.getStatus())) { +// // this is legal e.g. when child org is being create (one assignment comes pre-created) +// // TODO do we need more specific checks here? +// continue; +// } +// +// if (!UserDtoStatus.ADD.equals(projection.getStatus())) { +// warn(getString("pageAdminFocus.message.illegalAccountState", projection.getStatus())); +// continue; +// } +// +// ObjectWrapperOld

projectionWrapper = projection.getObjectOld(); +// ObjectDelta

delta = projectionWrapper.getObjectDelta(); +// PrismObject

proj = delta.getObjectToAdd(); +// WebComponentUtil.encryptCredentials(proj, true, getMidpointApplication()); +// +// projectionsToAdd.add(proj.asObjectable()); +// } +// return projectionsToAdd; +// } + + private List prepareShadowObject(List projections) throws SchemaException{ + List projectionsToAdd = new ArrayList<>(); + for (ShadowWrapper projection : projections) { +// if (!projection.isLoadedOK()) { +// continue; +// } + if (UserDtoStatus.MODIFY.equals(projection.getProjectionStatus())) { + // this is legal e.g. when child org is being create (one assignment comes pre-created) + // TODO do we need more specific checks here? + continue; + } + + if (!UserDtoStatus.ADD.equals(projection.getProjectionStatus())) { + warn(getString("pageAdminFocus.message.illegalAccountState", projection.getStatus())); + continue; + } + + ObjectDelta delta = projection.getObjectDelta(); + PrismObject proj = delta.getObjectToAdd(); + WebComponentUtil.encryptCredentials(proj, true, getMidpointApplication()); + + projectionsToAdd.add(proj.asObjectable()); + } + return projectionsToAdd; + } + + + @Override + protected List> getAdditionalModifyDeltas(OperationResult result) { + return getShadowModifyDeltas(result); + } + + private List> getShadowModifyDeltas(OperationResult result) { + List> deltas = new ArrayList<>(); + + List accounts = getFocusShadows(); + for (ShadowWrapper account : accounts) { +// if (!account.isLoadedOK()) { +// continue; +// } + try { + ObjectDelta delta = account.getObjectDelta(); + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Account delta computed from {} as:\n{}", + new Object[] { account, delta.debugDump(3) }); + } + + if (!UserDtoStatus.MODIFY.equals(account.getProjectionStatus())) { + continue; + } + + if (delta == null || delta.isEmpty()) { +// && (accountWrapper.getOldDelta() == null || accountWrapper.getOldDelta().isEmpty())) { + continue; + } + +// if (accountWrapper.getOldDelta() != null) { +// delta = ObjectDeltaCollectionsUtil.summarize(delta, accountWrapper.getOldDelta()); +// } + + + WebComponentUtil.encryptCredentials(delta, true, getMidpointApplication()); + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Modifying account:\n{}", new Object[] { delta.debugDump(3) }); + } + + deltas.add(delta); + + } catch (Exception ex) { + result.recordFatalError(getString("PageAdminFocus.message.getShadowModifyDeltas.fatalError"), ex); + LoggingUtils.logUnexpectedException(LOGGER, "Couldn't compute account delta", ex); + } + } + + return deltas; + } + + /** + * remove this method after model is updated - it has to remove resource + * from accountConstruction + */ + @Deprecated + private void removeResourceFromAccConstruction(AssignmentType assignment) { + ConstructionType accConstruction = assignment.getConstruction(); + if (accConstruction == null || accConstruction.getResourceRef() == null || accConstruction.getResourceRef().asReferenceValue().getObject() == null) { + return; + } + + ObjectReferenceType ref = new ObjectReferenceType(); + ref.setOid(assignment.getConstruction().getResourceRef().getOid()); + ref.setType(ResourceType.COMPLEX_TYPE); + assignment.getConstruction().setResourceRef(ref); + } + + private ReferenceDelta prepareUserAccountsDeltaForModify(PrismReferenceDefinition refDef) + throws SchemaException { + ReferenceDelta refDelta = getPrismContext().deltaFactory().reference().create(refDef); + + List accounts = getFocusShadows(); + for (ShadowWrapper accountWrapper : accounts) { +// if (accDto.isLoadedOK()) { +// ObjectWrapperOld accountWrapper = accDto.getObjectOld(); + accountWrapper.revive(getPrismContext()); + ObjectDelta delta = accountWrapper.getObjectDelta(); + PrismReferenceValue refValue = getPrismContext().itemFactory().createReferenceValue(null, OriginType.USER_ACTION, null); + + PrismObject account; + switch (accountWrapper.getProjectionStatus()) { + case ADD: + account = delta.getObjectToAdd(); + addDefaultKindAndIntent(account); + WebComponentUtil.encryptCredentials(account, true, getMidpointApplication()); + refValue.setObject(account); + refDelta.addValueToAdd(refValue); + break; + case DELETE: + account = accountWrapper.getObject(); + refValue.setObject(account); + refDelta.addValueToDelete(refValue); + break; + case MODIFY: + // nothing to do, account modifications were applied + // before + continue; + case UNLINK: + refValue.setOid(delta.getOid()); + refValue.setTargetType(ShadowType.COMPLEX_TYPE); + refDelta.addValueToDelete(refValue); + break; + default: + warn(getString("pageAdminFocus.message.illegalAccountState", accountWrapper.getProjectionStatus())); + } +// } + } + + return refDelta; + } + + private void addDefaultKindAndIntent(PrismObject account) { + if (account.asObjectable().getKind() == null) { + account.asObjectable().setKind(ShadowKindType.ACCOUNT); + } + if (account.asObjectable().getIntent() == null) { + account.asObjectable().setIntent(SchemaConstants.INTENT_DEFAULT); + } + } + + public List showAllAssignmentsPerformed(AjaxRequestTarget ajaxRequestTarget) { + LOGGER.debug("Recompute user assignments"); + Task task = createSimpleTask(OPERATION_RECOMPUTE_ASSIGNMENTS); + OperationResult result = new OperationResult(OPERATION_RECOMPUTE_ASSIGNMENTS); + ObjectDelta delta; + Set assignmentInfoDtoSet = new TreeSet<>(); + + try { + reviveModels(); + + PrismObjectWrapper focusWrapper = getObjectWrapper(); + delta = focusWrapper.getObjectDelta(); +// if (focusWrapper.getOldDelta() != null) { +// delta = ObjectDeltaCollectionsUtil.summarize(focusWrapper.getOldDelta(), delta); +// } + + switch (focusWrapper.getStatus()) { + case ADDED: + PrismObject focus = delta.getObjectToAdd(); + prepareObjectForAdd(focus); + getPrismContext().adopt(focus, getCompileTimeClass()); + + LOGGER.trace("Delta before add focus:\n{}", delta.debugDumpLazily(3)); + if (!delta.isEmpty()) { + delta.revive(getPrismContext()); + } else { + result.recordSuccess(); + } + break; + case NOT_CHANGED: + prepareObjectDeltaForModify(delta); + LOGGER.trace("Delta before modify user:\n{}", delta.debugDumpLazily(3)); + + List> accountDeltas = getShadowModifyDeltas(result); + if (!delta.isEmpty()) { + delta.revive(getPrismContext()); + } + for (ObjectDelta accDelta : accountDeltas) { + if (!accDelta.isEmpty()) { + accDelta.revive(getPrismContext()); + } + } + break; + default: + error(getString("pageAdminFocus.message.unsupportedState", focusWrapper.getStatus())); + } + + ModelContext modelContext; + try { + ModelExecuteOptions options = ModelExecuteOptions.createEvaluateAllAssignmentRelationsOnRecompute(); + modelContext = getModelInteractionService().previewChanges(Collections.singleton(delta), options, task, result); + } catch (NoFocusNameSchemaException e) { + info(getString("pageAdminFocus.message.noUserName")); + ajaxRequestTarget.add(getFeedbackPanel()); + return null; + } + + DeltaSetTriple> evaluatedAssignmentTriple = modelContext.getEvaluatedAssignmentTriple(); + Collection> evaluatedAssignments = null; + if (evaluatedAssignmentTriple != null) { + evaluatedAssignments = evaluatedAssignmentTriple.getNonNegativeValues(); + } + if (evaluatedAssignments == null || evaluatedAssignments.isEmpty()) { + info(getString("pageAdminFocus.message.noAssignmentsAvailable")); + ajaxRequestTarget.add(getFeedbackPanel()); + return null; + } + + for (EvaluatedAssignment evaluatedAssignment : evaluatedAssignments) { + if (!evaluatedAssignment.isValid()) { + continue; + } + // roles and orgs + DeltaSetTriple targetsTriple = evaluatedAssignment.getRoles(); + Collection targets = targetsTriple.getNonNegativeValues(); + for (EvaluatedAssignmentTarget target : targets) { + if (target.getTarget() != null && ArchetypeType.class.equals(target.getTarget().getCompileTimeClass())){ + continue; + } + if (target.appliesToFocusWithAnyRelation(getRelationRegistry())) { + assignmentInfoDtoSet.add(createAssignmentsPreviewDto(target, task, result)); + } + } + + // all resources + DeltaSetTriple evaluatedConstructionsTriple = evaluatedAssignment + .getEvaluatedConstructions(task, result); + Collection evaluatedConstructions = evaluatedConstructionsTriple + .getNonNegativeValues(); + for (EvaluatedConstruction construction : evaluatedConstructions) { + if (!construction.isWeak()) { + assignmentInfoDtoSet.add(createAssignmentsPreviewDto(construction)); + } + } + } + + return new ArrayList<>(assignmentInfoDtoSet); + + } catch (Exception e) { + LoggingUtils.logUnexpectedException(LOGGER, "Could not create assignments preview.", e); + error("Could not create assignments preview. Reason: " + e); + ajaxRequestTarget.add(getFeedbackPanel()); + } + return null; + } + + private AssignmentInfoDto createAssignmentsPreviewDto(EvaluatedAssignmentTarget evaluatedAbstractRole, + Task task, OperationResult result) { + return createAssignmentsPreviewDto(evaluatedAbstractRole.getTarget(), evaluatedAbstractRole.isDirectlyAssigned(), + evaluatedAbstractRole.getAssignmentPath(), evaluatedAbstractRole.getAssignment(), task, result); + } + + protected AssignmentInfoDto createAssignmentsPreviewDto(ObjectReferenceType reference, Task task, OperationResult result) { + PrismObject targetObject = WebModelServiceUtils.resolveReferenceNoFetch(reference, + PageAdminFocus.this, task, result); + return createAssignmentsPreviewDto(targetObject, true, null, null, task, result); + } + + protected AssignmentInfoDto createDelegableAssignmentsPreviewDto(AssignmentType assignment, Task task, OperationResult result) { + if (assignment.getTargetRef() != null) { + if (RoleType.COMPLEX_TYPE.equals(assignment.getTargetRef().getType()) + || OrgType.COMPLEX_TYPE.equals(assignment.getTargetRef().getType()) + || ServiceType.COMPLEX_TYPE.equals(assignment.getTargetRef().getType())) { + PrismObject targetObject = WebModelServiceUtils.resolveReferenceNoFetch(assignment.getTargetRef(), + PageAdminFocus.this, task, result); + Boolean isDelegable = false; + if (targetObject != null) { + isDelegable = targetObject.asObjectable().isDelegable(); + } + if (Boolean.TRUE.equals(isDelegable)) { + return createAssignmentsPreviewDto(targetObject, true, null, assignment, task, result); + } + } + } + return null; + } + + private AssignmentInfoDto createAssignmentsPreviewDto(PrismObject targetObject, + boolean isDirectlyAssigned, AssignmentPath assignmentPath, AssignmentType assignment, + Task task, OperationResult result) { + AssignmentInfoDto dto = new AssignmentInfoDto(); + dto.setTargetOid(targetObject.getOid()); + dto.setTargetName(getNameToDisplay(targetObject)); + dto.setTargetDescription(targetObject.asObjectable().getDescription()); + dto.setTargetClass(targetObject.getCompileTimeClass()); + dto.setTargetType(WebComponentUtil.classToQName(getPrismContext(), targetObject.getCompileTimeClass())); + dto.setDirect(isDirectlyAssigned); + dto.setAssignmentParent(assignmentPath); + if (assignment != null) { + if (assignment.getTenantRef() != null) { + dto.setTenantName(WebModelServiceUtils.resolveReferenceName(assignment.getTenantRef(), PageAdminFocus.this)); + dto.setTenantRef(assignment.getTenantRef()); + } + if (assignment.getOrgRef() != null) { + dto.setOrgRefName(WebModelServiceUtils.resolveReferenceName(assignment.getOrgRef(), PageAdminFocus.this)); + dto.setOrgRef(assignment.getOrgRef()); + } + if (assignment.getTargetRef() != null){ + dto.setRelation(assignment.getTargetRef().getRelation()); + } + } + return dto; + } + + private String getNameToDisplay(PrismObject target) { + if (target.canRepresent(AbstractRoleType.class)) { + String n = PolyString.getOrig(((AbstractRoleType)target.asObjectable()).getDisplayName()); + if (StringUtils.isNotBlank(n)) { + return n; + } + } + return PolyString.getOrig(target.asObjectable().getName()); + } + + private AssignmentInfoDto createAssignmentsPreviewDto(EvaluatedConstruction evaluatedConstruction) { + AssignmentInfoDto dto = new AssignmentInfoDto(); + PrismObject resource = evaluatedConstruction.getResource(); + dto.setTargetOid(resource.getOid()); + dto.setTargetName(PolyString.getOrig(resource.asObjectable().getName())); + dto.setTargetDescription(resource.asObjectable().getDescription()); + dto.setTargetClass(resource.getCompileTimeClass()); + dto.setDirect(evaluatedConstruction.isDirectlyAssigned()); + dto.setAssignmentParent(evaluatedConstruction.getAssignmentPath()); + dto.setKind(evaluatedConstruction.getKind()); + dto.setIntent(evaluatedConstruction.getIntent()); + return dto; + } + + @Override + protected void performAdditionalValidation(PrismObject object, + Collection> deltas, Collection errors) throws SchemaException { + + if (object != null && object.asObjectable() != null) { + for (AssignmentType assignment : object.asObjectable().getAssignment()) { + for (MidpointFormValidator validator : getFormValidatorRegistry().getValidators()) { + if (errors == null) { + errors = validator.validateAssignment(assignment); + } else { + errors.addAll(validator.validateAssignment(assignment)); + } + } + } + } + + } + + protected boolean isFocusHistoryPage(){ + return false; + } + + protected boolean isSelfProfile(){ + return false; + } +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/PageAdminObjectDetails.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/PageAdminObjectDetails.java index f82fe7ca9e9..e90588c4372 100755 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/PageAdminObjectDetails.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/PageAdminObjectDetails.java @@ -1,1016 +1,1085 @@ -/* - * Copyright (c) 2010-2018 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.web.page.admin; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; - -import javax.xml.namespace.QName; - -import com.evolveum.midpoint.gui.api.component.*; -import com.evolveum.midpoint.gui.api.component.tabs.PanelTab; -import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; -import com.evolveum.midpoint.gui.api.util.WebPrismUtil; -import com.evolveum.midpoint.model.api.AssignmentCandidatesSpecification; -import com.evolveum.midpoint.prism.PrismContainerValue; -import com.evolveum.midpoint.prism.query.ObjectFilter; -import com.evolveum.midpoint.prism.query.ObjectQuery; -import com.evolveum.midpoint.schema.constants.SchemaConstants; -import com.evolveum.midpoint.util.exception.*; -import com.evolveum.midpoint.web.component.AjaxButton; -import com.evolveum.midpoint.web.component.prism.ValueStatus; -import com.evolveum.midpoint.web.component.util.SelectableBean; -import com.evolveum.midpoint.web.component.util.VisibleBehaviour; -import com.evolveum.midpoint.web.page.admin.configuration.PageSystemConfiguration; -import com.evolveum.midpoint.web.page.admin.server.OperationalButtonsPanel; -import com.evolveum.midpoint.xml.ns._public.common.common_3.*; - -import org.apache.commons.lang.StringUtils; -import org.apache.wicket.Page; -import org.apache.wicket.RestartResponseException; -import org.apache.wicket.ajax.AbstractAjaxTimerBehavior; -import org.apache.wicket.ajax.AjaxRequestTarget; -import org.apache.wicket.behavior.AttributeAppender; -import org.apache.wicket.behavior.Behavior; -import org.apache.wicket.extensions.markup.html.tabs.ITab; -import org.apache.wicket.markup.html.WebMarkupContainer; -import org.apache.wicket.markup.repeater.RepeatingView; -import org.apache.wicket.model.IModel; -import org.apache.wicket.model.Model; -import org.apache.wicket.model.StringResourceModel; -import org.apache.wicket.request.mapper.parameter.PageParameters; -import org.apache.wicket.util.string.StringValue; -import org.apache.wicket.util.time.Duration; -import org.jetbrains.annotations.NotNull; - -import com.evolveum.midpoint.gui.api.model.LoadableModel; -import com.evolveum.midpoint.gui.api.prism.ItemStatus; -import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; -import com.evolveum.midpoint.gui.api.util.WebComponentUtil; -import com.evolveum.midpoint.gui.api.util.WebModelServiceUtils; -import com.evolveum.midpoint.gui.impl.factory.PrismObjectWrapperFactory; -import com.evolveum.midpoint.gui.impl.factory.WrapperContext; -import com.evolveum.midpoint.model.api.ModelExecuteOptions; -import com.evolveum.midpoint.model.api.authentication.CompiledGuiProfile; -import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.prism.delta.ObjectDelta; -import com.evolveum.midpoint.schema.GetOperationOptions; -import com.evolveum.midpoint.schema.SelectorOptions; -import com.evolveum.midpoint.schema.constants.ObjectTypes; -import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.task.api.Task; -import com.evolveum.midpoint.util.QNameUtil; -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.web.component.ObjectSummaryPanel; -import com.evolveum.midpoint.web.component.objectdetails.AbstractObjectMainPanel; -import com.evolveum.midpoint.web.component.progress.ProgressPanel; -import com.evolveum.midpoint.web.component.progress.ProgressReportingAwarePage; -import com.evolveum.midpoint.web.component.util.VisibleEnableBehaviour; -import com.evolveum.midpoint.web.page.admin.users.dto.FocusSubwrapperDto; -import com.evolveum.midpoint.web.util.OnePageParameterEncoder; -import com.evolveum.midpoint.web.util.validation.MidpointFormValidator; -import com.evolveum.midpoint.web.util.validation.SimpleValidationError; - -/** - * @author semancik - */ -public abstract class PageAdminObjectDetails extends PageAdmin - implements ProgressReportingAwarePage { - private static final long serialVersionUID = 1L; - - private static final String DOT_CLASS = PageAdminObjectDetails.class.getName() + "."; - - public static final String PARAM_RETURN_PAGE = "returnPage"; - - private static final String OPERATION_LOAD_OBJECT = DOT_CLASS + "loadObject"; - private static final String OPERATION_LOAD_PARENT_ORGS = DOT_CLASS + "loadParentOrgs"; - private static final String OPERATION_LOAD_GUI_CONFIGURATION = DOT_CLASS + "loadGuiConfiguration"; - protected static final String OPERATION_SAVE = DOT_CLASS + "save"; - protected static final String OPERATION_PREVIEW_CHANGES = DOT_CLASS + "previewChanges"; - protected static final String OPERATION_SEND_TO_SUBMIT = DOT_CLASS + "sendToSubmit"; - protected static final String OPERATION_LOAD_ARCHETYPE_REF = DOT_CLASS + "loadArchetypeRef"; - protected static final String OPERATION_EXECUTE_CHANGES = DOT_CLASS + "executeChangesTask"; - protected static final String OPERATION_EXECUTE_ARCHETYPE_CHANGES = DOT_CLASS + "executeArchetypeChanges"; - protected static final String OPERATION_LOAD_FILTERED_ARCHETYPES = DOT_CLASS + "loadFilteredArchetypes"; - - protected static final String ID_SUMMARY_PANEL = "summaryPanel"; - protected static final String ID_MAIN_PANEL = "mainPanel"; - private static final String ID_PROGRESS_PANEL = "progressPanel"; - private static final String ID_BUTTONS = "buttons"; - - private static final Trace LOGGER = TraceManager.getTrace(PageAdminObjectDetails.class); - - private LoadableModel> objectModel; - private LoadableModel>> parentOrgModel; - - private ProgressPanel progressPanel; - - // used to determine whether to leave this page or stay on it (after - // operation finishing) - private ObjectDelta delta; - - private AbstractObjectMainPanel mainPanel; - private boolean saveOnConfigure; // ugly hack - whether to invoke 'Save' when returning to this page - - private boolean editingFocus = false; //before we got isOidParameterExists status depending only on oid parameter existence - //we should set editingFocus=true not only when oid parameter exists but also - //when object is given as a constructor parameter - - public boolean isEditingFocus() { - return editingFocus; - } - - @Override - protected void createBreadcrumb() { - createInstanceBreadcrumb(); - } - - @Override - protected void onConfigure() { - super.onConfigure(); - if (saveOnConfigure) { - saveOnConfigure = false; - add(new AbstractAjaxTimerBehavior(Duration.milliseconds(100)) { - @Override - protected void onTimer(AjaxRequestTarget target) { - stop(target); - savePerformed(target); - } - }); - } - } - - @Override - protected IModel createPageTitleModel() { - if (PageAdminObjectDetails.this instanceof PageSystemConfiguration){ - return super.createPageTitleModel(); - } - String simpleName = getObjectSimpleName(); - String lokalizedSimpleName = new StringResourceModel("ObjectType." + simpleName).setDefaultValue(simpleName).getString(); - if (isAdd()) { - return createStringResource("PageAdminObjectDetails.title.new", lokalizedSimpleName); - } - - String name = null; - if (getObjectWrapper() != null && getObjectWrapper().getObject() != null) { - name = WebComponentUtil.getName(getObjectWrapper().getObject()); - } - - return createStringResource("PageAdminObjectDetails.title.edit.readonly.${readOnly}", getObjectModel(), lokalizedSimpleName, name); - } - - private String getObjectSimpleName(){ - if (getObjectWrapper() != null && getObjectWrapper().getObject() != null - && getObjectWrapper().getObject().asObjectable() instanceof AssignmentHolderType){ - AssignmentHolderType assignmentHolderObj = (AssignmentHolderType) getObjectWrapper().getObject().asObjectable(); - DisplayType displayType = WebComponentUtil - .getArchetypePolicyDisplayType(assignmentHolderObj, PageAdminObjectDetails.this); - if (displayType == null){ - ObjectReferenceType archetypeReference = getObjectArchetypeRef(); - if (archetypeReference != null){ - OperationResult result = new OperationResult(OPERATION_LOAD_ARCHETYPE_REF); - Task task = createSimpleTask(OPERATION_LOAD_ARCHETYPE_REF); - PrismObject archetypeObj = WebModelServiceUtils.resolveReferenceNoFetch(archetypeReference, - this, task, result); - displayType = archetypeObj != null && archetypeObj.asObjectable().getArchetypePolicy() != null ? - archetypeObj.asObjectable().getArchetypePolicy().getDisplay() : null; - } - } - if (displayType != null && displayType.getLabel() != null) { - String archetypeLocalizedName = getLocalizationService() - .translate(displayType.getLabel().toPolyString(), WebComponentUtil.getCurrentLocale(), true); - if (StringUtils.isNotEmpty(archetypeLocalizedName)) { - return archetypeLocalizedName; - } - } - } - return getCompileTimeClass().getSimpleName(); - } - - public boolean isAdd() { - return !isOidParameterExists() && !editingFocus; - } - - public LoadableModel> getObjectModel() { - return objectModel; - } - - protected AbstractObjectMainPanel getMainPanel() { - return mainPanel; - } - - public PrismObjectWrapper getObjectWrapper() { - return objectModel.getObject(); - } - - public List> getParentOrgs() { - return parentOrgModel.getObject(); - } - - public ObjectDelta getDelta() { - return delta; - } - - public void setDelta(ObjectDelta delta) { - this.delta = delta; - } - - public ProgressPanel getProgressPanel() { - return progressPanel; - } - - protected void reviveModels() throws SchemaException { - WebComponentUtil.revive(objectModel, getPrismContext()); - WebComponentUtil.revive(parentOrgModel, getPrismContext()); - } - - public abstract Class getCompileTimeClass(); - - - public void initialize(final PrismObject objectToEdit) { - boolean isNewObject = objectToEdit == null && StringUtils.isEmpty(getObjectOidParameter()); - - initialize(objectToEdit, isNewObject, false); - } - - public void initialize(final PrismObject objectToEdit, boolean isNewObject) { - initialize(objectToEdit, isNewObject, false); - } - - public void initialize(final PrismObject objectToEdit, boolean isNewObject, boolean isReadonly) { - initializeModel(objectToEdit, isNewObject, isReadonly); -// initLayout(); - } - - protected void initializeModel(final PrismObject objectToEdit, boolean isNewObject, boolean isReadonly) { - editingFocus = !isNewObject; - - objectModel = new LoadableModel>(false) { - private static final long serialVersionUID = 1L; - - @Override - protected PrismObjectWrapper load() { - PrismObjectWrapper wrapper = loadObjectWrapper(objectToEdit, isReadonly); -// wrapper.sort(); - return wrapper; - } - }; - - parentOrgModel = new LoadableModel>>(false) { - private static final long serialVersionUID = 1L; - - @Override - protected List> load() { - return loadOrgWrappers(); - } - }; - } - - private ObjectReferenceType getObjectArchetypeRef() { - ObjectReferenceType archetypeReference = null; - if (getObjectWrapper() != null && getObjectWrapper().getObject() != null - && getObjectWrapper().getObject().asObjectable() instanceof AssignmentHolderType) { - AssignmentHolderType assignmentHolderObj = (AssignmentHolderType) getObjectWrapper().getObject().asObjectable(); - if (assignmentHolderObj.getAssignment() != null) { - for (AssignmentType assignment : assignmentHolderObj.getAssignment()) { - if (assignment.getTargetRef() != null && assignment.getTargetRef().getType() != null - && QNameUtil.match(assignment.getTargetRef().getType(), ArchetypeType.COMPLEX_TYPE)) { - archetypeReference = assignment.getTargetRef(); - break; - } - } - } - } - return archetypeReference; - } - - protected List> loadOrgWrappers() { - // WRONG!! TODO: fix - return null; - } - - protected abstract O createNewObject(); - - @Override - protected void onInitialize() { - super.onInitialize(); - initLayout(); - } - - protected void initLayout() { - initLayoutSummaryPanel(); - initOperationalButtonsPanel(); - - mainPanel = createMainPanel(ID_MAIN_PANEL); - mainPanel.setOutputMarkupId(true); - add(mainPanel); - - progressPanel = new ProgressPanel(ID_PROGRESS_PANEL); - add(progressPanel); - } - - protected abstract ObjectSummaryPanel createSummaryPanel(); - - protected void initLayoutSummaryPanel() { - - ObjectSummaryPanel summaryPanel = createSummaryPanel(); - summaryPanel.setOutputMarkupId(true); - - setSummaryPanelVisibility(summaryPanel); - add(summaryPanel); - } - - protected void setSummaryPanelVisibility(ObjectSummaryPanel summaryPanel){ - summaryPanel.add(new VisibleEnableBehaviour() { - private static final long serialVersionUID = 1L; - - @Override - public boolean isVisible() { - return isOidParameterExists() || editingFocus; - } - }); - } - - private void initOperationalButtonsPanel(){ - OperationalButtonsPanel opButtonPanel = new OperationalButtonsPanel(ID_BUTTONS) { - private static final long serialVersionUID = 1L; - - @Override - protected void addButtons(RepeatingView repeatingView) { - initOperationalButtons(repeatingView); - } - }; - if (getAdditionalOperationalButtonPanelBehaviors() != null && !getAdditionalOperationalButtonPanelBehaviors().isEmpty()){ - getAdditionalOperationalButtonPanelBehaviors().forEach(this::add); - } - opButtonPanel.setOutputMarkupId(true); - opButtonPanel.add(new VisibleBehaviour(() -> isEditingFocus() && opButtonPanel.buttonsExist())); - add(opButtonPanel); - } - - protected List getAdditionalOperationalButtonPanelBehaviors(){ - return new ArrayList<>(); - } - - protected void initOperationalButtons(RepeatingView repeatingView){ - if (getObjectArchetypeRef() != null) { - AjaxButton changeArchetype = new AjaxButton(repeatingView.newChildId(), createStringResource("PageAdminObjectDetails.button.changeArchetype")) { - @Override - public void onClick(AjaxRequestTarget target) { - changeArchetypeButtonClicked(target); - } - }; - changeArchetype.add(new VisibleBehaviour(() -> getObjectArchetypeRef() != null)); - changeArchetype.add(AttributeAppender.append("class", "btn-default")); - repeatingView.add(changeArchetype); - } - } - - protected OperationalButtonsPanel getOperationalButtonsPanel(){ - return (OperationalButtonsPanel) get(ID_BUTTONS); - } - - private void changeArchetypeButtonClicked(AjaxRequestTarget target){ - - AssignmentPopup changeArchetypePopup = new AssignmentPopup(getMainPopupBodyId()) { - - private static final long serialVersionUID = 1L; - - @Override - protected void addPerformed(AjaxRequestTarget target, List newAssignmentsList) { - super.addPerformed(target, newAssignmentsList); - try { - PrismContainerWrapper assignmentsWrapper = getObjectWrapper().findContainer(FocusType.F_ASSIGNMENT); - ((List) newAssignmentsList).forEach(assignment -> { - PrismContainerValue newAssignment = assignmentsWrapper.getItem().createNewValue(); - assignmentsWrapper.getValues().forEach(assignmentValue -> { - if (assignmentValue.getRealValue().getTargetRef() != null - && assignmentValue.getRealValue().getTargetRef().getType() != null - && QNameUtil.match(assignmentValue.getRealValue().getTargetRef().getType(), ArchetypeType.COMPLEX_TYPE)){ - assignmentValue.setStatus(ValueStatus.DELETED); - } - }); - AssignmentType assignmentType = newAssignment.asContainerable(); - assignmentType.setTargetRef(assignment.getTargetRef()); - WebPrismUtil.createNewValueWrapper(assignmentsWrapper, newAssignment, PageAdminObjectDetails.this, target); - OperationResult result = new OperationResult(OPERATION_EXECUTE_ARCHETYPE_CHANGES); - Task task = createSimpleTask(OPERATION_EXECUTE_ARCHETYPE_CHANGES); - try { - ObjectDelta archetypeDelta = getObjectWrapper().getObjectDelta(); - if (!archetypeDelta.isEmpty()) { - archetypeDelta.revive(getPrismContext()); - getModelService().executeChanges(WebComponentUtil.createDeltaCollection(archetypeDelta), null, task, result); - result.computeStatus(); - } - } catch (Exception e) { - LOGGER.error("Cannot save archetype assignment changes: {}", e.getMessage()); - } - showResult(result); - }); - } catch (SchemaException e) { - LOGGER.error("Cannot find assignment wrapper: {}", e.getMessage()); - } - target.add(PageAdminObjectDetails.this.getFeedbackPanel()); - } - - @Override - protected List createAssignmentTabs() { - List tabs = new ArrayList<>(); - - tabs.add(new PanelTab(getPageBase().createStringResource("ObjectTypes.ARCHETYPE"), - new VisibleBehaviour(() -> true)) { - - private static final long serialVersionUID = 1L; - - @Override - public WebMarkupContainer createPanel(String panelId) { - return new FocusTypeAssignmentPopupTabPanel(panelId, ObjectTypes.ARCHETYPE) { - private static final long serialVersionUID = 1L; - - @Override - protected PrismContainerWrapper getAssignmentWrapperModel() { - PrismContainerWrapper assignmentsWrapper = null; - try { - assignmentsWrapper = getObjectWrapper().findContainer(FocusType.F_ASSIGNMENT); - } catch (SchemaException e) { - LOGGER.error("Cannot find assignment wrapper: {}", e.getMessage()); - } - return assignmentsWrapper; - } - - @Override - protected List getSupportedRelations() { - return Collections.singletonList(SchemaConstants.ORG_DEFAULT); - } - - @Override - protected void onSelectionPerformed(AjaxRequestTarget target, IModel> rowModel) { - target.add(getObjectListPanel()); - tabLabelPanelUpdate(target); - } - - @Override - protected IModel getObjectSelectCheckBoxEnableModel(IModel> rowModel){ - if (rowModel == null){ - return Model.of(false); - } - List selectedObjects = getSelectedObjectsList(); - return Model.of(selectedObjects == null || selectedObjects.size() == 0 - || (rowModel.getObject() != null && rowModel.getObject().isSelected())); - } - - - @Override - protected ObjectTypes getObjectType() { - return ObjectTypes.ARCHETYPE; - } - - @Override - protected ObjectQuery addFilterToContentQuery(ObjectQuery query){ - super.addFilterToContentQuery(query); - if (query == null) { - query = getPrismContext().queryFactory().createQuery(); - } - List archetypeOidsList = getFilteredArchetypeOidsList(); - ObjectFilter filter = getPrismContext().queryFor(ArchetypeType.class) - .id(archetypeOidsList.toArray(new String[0])) - .buildFilter(); - query.addFilter(filter); - return query; - } - }; - } - }); - return tabs; - } - }; - - changeArchetypePopup.setOutputMarkupPlaceholderTag(true); - showMainPopup(changeArchetypePopup, target); - - } - - private List getFilteredArchetypeOidsList(){ - OperationResult result = new OperationResult(OPERATION_LOAD_FILTERED_ARCHETYPES); - PrismObject obj = getObjectWrapper().getObject(); - List oidsList = new ArrayList<>(); - try { - List filteredArchetypes = getModelInteractionService().getFilteredArchetypesByHolderType(obj, result); - if (filteredArchetypes != null){ - filteredArchetypes.forEach(archetype -> oidsList.add(archetype.getOid())); - } - } catch (SchemaException ex){ - result.recordPartialError(ex.getLocalizedMessage()); - LOGGER.error("Couldn't load assignment target specification for the object {} , {}", obj.getName(), ex.getLocalizedMessage()); - } - return oidsList; - } - - protected abstract AbstractObjectMainPanel createMainPanel(String id); - - protected String getObjectOidParameter() { - PageParameters parameters = getPageParameters(); - LOGGER.trace("Page parameters: {}", parameters); - StringValue oidValue = parameters.get(OnePageParameterEncoder.PARAMETER); - LOGGER.trace("OID parameter: {}", oidValue); - if (oidValue == null) { - return null; - } - String oid = oidValue.toString(); - if (StringUtils.isBlank(oid)) { - return null; - } - return oid; - } - - protected ObjectSummaryPanel getSummaryPanel() { - return (ObjectSummaryPanel) get(ID_SUMMARY_PANEL); - } - - public boolean isOidParameterExists() { - return getObjectOidParameter() != null; - } - - protected PrismObjectWrapper loadObjectWrapper(PrismObject objectToEdit, boolean isReadonly) { - Task task = createSimpleTask(OPERATION_LOAD_OBJECT); - OperationResult result = task.getResult(); - PrismObject object = null; - try { - if (!isOidParameterExists()) { - if (objectToEdit == null) { - LOGGER.trace("Loading object: New object (creating)"); - O focusType = createNewObject(); - - // Apply subtype using page parameters - List subtypes = getPageParameters().getValues(ObjectType.F_SUBTYPE.getLocalPart()); - subtypes.stream().filter(p -> !p.isEmpty()).forEach(c -> focusType.subtype(c.toString())); - - getMidpointApplication().getPrismContext().adopt(focusType); - object = (PrismObject) focusType.asPrismObject(); - } else { - LOGGER.trace("Loading object: New object (supplied): {}", objectToEdit); - object = objectToEdit; - } - } else { - - String focusOid = getObjectOidParameter(); - object = WebModelServiceUtils.loadObject(getCompileTimeClass(), focusOid, buildGetOptions(), this, task, result); - LOGGER.trace("Loading object: Existing object (loadled): {} -> {}", focusOid, object); - } - - result.recordSuccess(); - } catch (Exception ex) { - result.recordFatalError(getString("PageAdminObjectDetails.message.loadObjectWrapper.fatalError"), ex); - LoggingUtils.logUnexpectedException(LOGGER, "Couldn't load object", ex); - } - - showResult(result, false); - - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Loaded object:\n{}", object.debugDump()); - } - - if (object == null) { - if (isOidParameterExists()) { - getSession().error(getString("pageAdminFocus.message.cantEditFocus")); - } else { - getSession().error(getString("pageAdminFocus.message.cantNewFocus")); - } - throw new RestartResponseException(getRestartResponsePage()); - } - - ItemStatus itemStatus = isOidParameterExists() || editingFocus ? ItemStatus.NOT_CHANGED : ItemStatus.ADDED; - PrismObjectWrapper wrapper; - - PrismObjectWrapperFactory factory = getRegistry().getObjectWrapperFactory(object.getDefinition()); - WrapperContext context = new WrapperContext(task, result); - context.setCreateIfEmpty(ItemStatus.ADDED == itemStatus); - //we don't want to set to false.. refactor this method to take either enum (READONLY, AUTO, ...) or - // Boolean instead of boolean isReadonly - if (isReadonly) { - context.setReadOnly(isReadonly); - } - - - try { - wrapper = factory.createObjectWrapper(object.clone(), itemStatus, context); - } catch (Exception ex) { - result.recordFatalError(getString("PageAdminObjectDetails.message.loadObjectWrapper.fatalError"), ex); - LoggingUtils.logUnexpectedException(LOGGER, "Couldn't load object", ex); - showResult(result, false); - throw new RestartResponseException(getRestartResponsePage()); - } - - showResult(result, false); - - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Loaded focus wrapper:\n{}", wrapper.debugDump()); - } - - return wrapper; - } - - protected Collection> buildGetOptions() { - return getOperationOptionsBuilder() - .item(UserType.F_JPEG_PHOTO).retrieve() - .build(); - } - -// private void loadParentOrgs(PrismObjectWrapper wrapper, Task task, OperationResult result) { -// OperationResult subResult = result.createMinorSubresult(OPERATION_LOAD_PARENT_ORGS); -// PrismObject focus = wrapper.getObject(); -// // Load parent organizations (full objects). There are used in the -// // summary panel and also in the main form. -// // Do it here explicitly instead of using resolve option to have ability -// // to better handle (ignore) errors. -// for (ObjectReferenceType parentOrgRef : focus.asObjectable().getParentOrgRef()) { -// -// PrismObject parentOrg = null; -// try { -// -// parentOrg = getModelService().getObject(OrgType.class, parentOrgRef.getOid(), null, task, -// subResult); -// LOGGER.trace("Loaded parent org with result {}", -// new Object[] { subResult.getLastSubresult() }); -// } catch (AuthorizationException e) { -// // This can happen if the user has permission to read parentOrgRef but it does not have -// // the permission to read target org -// // It is OK to just ignore it. -// subResult.muteLastSubresultError(); -// LOGGER.debug("User {} does not have permission to read parent org unit {} (ignoring error)", task.getOwner().getName(), parentOrgRef.getOid()); -// } catch (Exception ex) { -// subResult.recordWarning(createStringResource("PageAdminObjectDetails.message.loadParentOrgs.warning", parentOrgRef.getOid()).getString(), ex); -// LOGGER.warn("Cannot load parent org {}: {}", parentOrgRef.getOid(), ex.getMessage(), ex); -// } -// -// if (parentOrg != null) { -// wrapper.getParentOrgs().add(parentOrg); -// } -// } -// subResult.computeStatus(); -// } - - protected abstract Class getRestartResponsePage(); - - public Object findParam(String param, String oid, OperationResult result) { - - Object object = null; - - for (OperationResult subResult : result.getSubresults()) { - if (subResult != null && subResult.getParams() != null) { - if (subResult.getParams().get(param) != null - && subResult.getParams().get(OperationResult.PARAM_OID) != null - && subResult.getParams().get(OperationResult.PARAM_OID).equals(oid)) { - return subResult.getParams().get(param); - } - object = findParam(param, oid, subResult); - - } - } - return object; - } - - // TODO put this into correct place - protected boolean previewRequested; - - /** - * This will be called from the main form when save button is pressed. - */ - public void savePerformed(AjaxRequestTarget target) { - progressPanel.onBeforeSave(); - OperationResult result = new OperationResult(OPERATION_SAVE); - previewRequested = false; - saveOrPreviewPerformed(target, result, false); - } - - public void previewPerformed(AjaxRequestTarget target) { - progressPanel.onBeforeSave(); - OperationResult result = new OperationResult(OPERATION_PREVIEW_CHANGES); - previewRequested = true; - saveOrPreviewPerformed(target, result, true); - } - - public void saveOrPreviewPerformed(AjaxRequestTarget target, OperationResult result, boolean previewOnly) { - saveOrPreviewPerformed(target, result, previewOnly, null); - } - - public void saveOrPreviewPerformed(AjaxRequestTarget target, OperationResult result, boolean previewOnly, Task task) { - boolean delegationChangesExist = processDeputyAssignments(previewOnly); - - PrismObjectWrapper objectWrapper = getObjectWrapper(); - LOGGER.debug("Saving object {}", objectWrapper); - - // todo: improve, delta variable is quickfix for MID-1006 - // redirecting to user list page everytime user is created in repository - // during user add in gui, - // and we're not taking care about account/assignment create errors - // (error message is still displayed) - delta = null; - - if(task == null) { - task = createSimpleTask(OPERATION_SEND_TO_SUBMIT); - } - - ModelExecuteOptions options = getOptions(previewOnly); - - LOGGER.debug("Using execute options {}.", options); - - try { - reviveModels(); - - delta = objectWrapper.getObjectDelta(); - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("User delta computed from form:\n{}", new Object[] { delta.debugDump(3) }); - } - } catch (Exception ex) { - result.recordFatalError(getString("pageAdminObjectDetails.message.cantCreateObject"), ex); - LoggingUtils.logUnexpectedException(LOGGER, "Create Object failed", ex); - showResult(result); - target.add(getFeedbackPanel()); - return; - } - - switch (objectWrapper.getStatus()) { - case ADDED: - try { - PrismObject objectToAdd = delta.getObjectToAdd(); - WebComponentUtil.encryptCredentials(objectToAdd, true, getMidpointApplication()); - prepareObjectForAdd(objectToAdd); - getPrismContext().adopt(objectToAdd, getCompileTimeClass()); - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Delta before add user:\n{}", new Object[] { delta.debugDump(3) }); - } - - if (!delta.isEmpty()) { - delta.revive(getPrismContext()); - - final Collection> deltas = WebComponentUtil.createDeltaCollection(delta); - final Collection validationErrors = performCustomValidation(objectToAdd, deltas); - if (checkValidationErrors(target, validationErrors)) { - return; - } - if (isSaveInBackground()){ - progressPanel.executeChangesInBackground(deltas, previewOnly, options, task, result, target); - } else { - progressPanel.executeChanges(deltas, previewOnly, options, task, result, target); - } - } else { - result.recordSuccess(); - } - } catch (Exception ex) { - result.recordFatalError(getString("pageFocus.message.cantCreateFocus"), ex); - LoggingUtils.logUnexpectedException(LOGGER, "Create user failed", ex); - showResult(result); - } - break; - - case NOT_CHANGED: - try { - WebComponentUtil.encryptCredentials(delta, true, getMidpointApplication()); - prepareObjectDeltaForModify(delta); //preparing of deltas for projections (ADD, DELETE, UNLINK) - - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Delta before modify user:\n{}", new Object[] { delta.debugDump(3) }); - } - - Collection> deltas = new ArrayList<>(); - if (!delta.isEmpty()) { - delta.revive(getPrismContext()); - deltas.add(delta); - } - - List> additionalDeltas = getAdditionalModifyDeltas(result); - if (additionalDeltas != null) { - for (ObjectDelta additionalDelta : additionalDeltas) { - if (!additionalDelta.isEmpty()) { - additionalDelta.revive(getPrismContext()); - deltas.add(additionalDelta); - } - } - } - - if (delta.isEmpty() && ModelExecuteOptions.isReconcile(options)) { - ObjectDelta emptyDelta = getPrismContext().deltaFactory().object().createEmptyModifyDelta(getCompileTimeClass(), - objectWrapper.getObject().getOid()); - deltas.add(emptyDelta); - - Collection validationErrors = performCustomValidation(null, deltas); - if (checkValidationErrors(target, validationErrors)) { - return; - } - if (isSaveInBackground()){ - progressPanel.executeChangesInBackground(deltas, previewOnly, options, task, result, target); - } else { - progressPanel.executeChanges(deltas, previewOnly, options, task, result, target); - } - } else if (!deltas.isEmpty()) { - Collection validationErrors = performCustomValidation(null, deltas); - if (checkValidationErrors(target, validationErrors)) { - return; - } - if (isSaveInBackground()){ - progressPanel.executeChangesInBackground(deltas, previewOnly, options, task, result, target); - } else { - progressPanel.executeChanges(deltas, previewOnly, options, task, result, target); - } - } else if (previewOnly && delta.isEmpty() && delegationChangesExist){ - if (isSaveInBackground()){ - progressPanel.executeChangesInBackground(deltas, previewOnly, options, task, result, target); - } else { - progressPanel.executeChanges(deltas, previewOnly, options, task, result, target); - } - } else { - progressPanel.clearProgressPanel(); // from previous attempts (useful only if we would call finishProcessing at the end, but that's not the case now) - if (!previewOnly) { - if (!delegationChangesExist) { - result.recordWarning(getString("PageAdminObjectDetails.noChangesSave")); - showResult(result); - } - redirectBack(); - } else { - if (!delegationChangesExist) { - warn(getString("PageAdminObjectDetails.noChangesPreview")); - target.add(getFeedbackPanel()); - } - } - } - - } catch (Exception ex) { - if (!executeForceDelete(objectWrapper, task, options, result)) { - result.recordFatalError(getString("pageUser.message.cantUpdateUser"), ex); - LoggingUtils.logUnexpectedException(LOGGER, getString("pageUser.message.cantUpdateUser"), ex); - } else { - result.recomputeStatus(); - } - showResult(result); - } - break; - // support for add/delete containers (e.g. delete credentials) - default: - error(getString("pageAdminFocus.message.unsupportedState", objectWrapper.getStatus())); - } - -// result.recomputeStatus(); -// -// if (!result.isInProgress()) { -// LOGGER.trace("Result NOT in progress, calling finishProcessing"); -// finishProcessing(target, result, false); -// } - - LOGGER.trace("returning from saveOrPreviewPerformed"); - } - - protected boolean processDeputyAssignments(boolean previewOnly){ - return false; - } - - protected boolean checkValidationErrors(AjaxRequestTarget target, Collection validationErrors) { - if (validationErrors != null && !validationErrors.isEmpty()) { - for (SimpleValidationError error : validationErrors) { - LOGGER.error("Validation error, attribute: '" + error.printAttribute() - + "', message: '" + error.getMessage() + "'."); - error("Validation error, attribute: '" + error.printAttribute() - + "', message: '" + error.getMessage() + "'."); - } - - target.add(getFeedbackPanel()); - return true; - } - return false; - } - - @Override - public void startProcessing(AjaxRequestTarget target, OperationResult result) { - LOGGER.trace("startProcessing called, making main panel invisible"); - mainPanel.setVisible(false); - target.add(mainPanel); - } - - @NotNull - protected ModelExecuteOptions getOptions(boolean previewOnly) { - ModelExecuteOptions options = mainPanel.getExecuteChangeOptionsDto().createOptions(); - if (previewOnly) { - options.getOrCreatePartialProcessing().setApprovals(PartialProcessingTypeType.PROCESS); - } - return options; - } - - protected void prepareObjectForAdd(PrismObject object) throws SchemaException { - - } - - protected void prepareObjectDeltaForModify(ObjectDelta objectDelta) throws SchemaException { - - } - - protected List> getAdditionalModifyDeltas(OperationResult result) { - return null; - } - - protected boolean executeForceDelete(PrismObjectWrapper userWrapper, Task task, ModelExecuteOptions options, - OperationResult parentResult) { - return isForce(); - } - - protected boolean isForce() { - return getMainPanel().getExecuteChangeOptionsDto().isForce(); - } - - protected boolean isKeepDisplayingResults() { - return getMainPanel().getExecuteChangeOptionsDto().isKeepDisplayingResults(); - } - - protected boolean isSaveInBackground(){ - return getMainPanel().getExecuteChangeOptionsDto().isSaveInBackground(); - } - - protected Collection performCustomValidation(PrismObject object, - Collection> deltas) throws SchemaException { - Collection errors = null; - - if (object == null) { - if (getObjectWrapper() != null && getObjectWrapper().getObjectOld() != null) { - object = getObjectWrapper().getObjectOld().clone(); // otherwise original object could get corrupted e.g. by applying the delta below - - for (ObjectDelta delta : deltas) { - // because among deltas there can be also ShadowType deltas - if (UserType.class.isAssignableFrom(delta.getObjectTypeClass())) { - delta.applyTo(object); - } - } - } - } else { - object = object.clone(); - } - - performAdditionalValidation(object, deltas, errors); - - for (MidpointFormValidator validator : getFormValidatorRegistry().getValidators()) { - if (errors == null) { - errors = validator.validateObject(object, deltas); - } else { - errors.addAll(validator.validateObject(object, deltas)); - } - } - - return errors; - } - - protected void performAdditionalValidation(PrismObject object, - Collection> deltas, Collection errors) throws SchemaException { - - } - - public List getObjectFormTypes() { - Task task = createSimpleTask(OPERATION_LOAD_GUI_CONFIGURATION); - OperationResult result = task.getResult(); - CompiledGuiProfile adminGuiConfiguration; - try { - adminGuiConfiguration = getModelInteractionService().getCompiledGuiProfile(task, result); - } catch (ObjectNotFoundException | SchemaException | CommunicationException | ConfigurationException | SecurityViolationException | ExpressionEvaluationException e) { - throw new SystemException("Cannot load GUI configuration: "+e.getMessage(), e); - } - ObjectFormsType objectFormsType = adminGuiConfiguration.getObjectForms(); - if (objectFormsType == null) { - return null; - } - List objectForms = objectFormsType.getObjectForm(); - if (objectForms == null || objectForms.isEmpty()) { - return objectForms; - } - List validObjectForms = new ArrayList<>(); - for (ObjectFormType objectForm: objectForms) { - if (isSupportedObjectType(objectForm.getType())) { - validObjectForms.add(objectForm); - } - } - return validObjectForms; - } - - protected boolean isSupportedObjectType(QName type) { - ObjectTypes objectType = ObjectTypes.getObjectType(getCompileTimeClass()); - return QNameUtil.match(objectType.getTypeQName(),type); - } - - public void setSaveOnConfigure(boolean saveOnConfigure) { - this.saveOnConfigure = saveOnConfigure; - } - - public boolean isSaveOnConfigure() { - return saveOnConfigure; - } - - public boolean isForcedPreview() { - GuiObjectDetailsPageType objectDetails = getCompiledGuiProfile().findObjectDetailsConfiguration(getCompileTimeClass()); - return objectDetails != null && DetailsPageSaveMethodType.FORCED_PREVIEW.equals(objectDetails.getSaveMethod()); - } - -} +/* + * Copyright (c) 2010-2018 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.web.page.admin; + +import java.util.*; + +import javax.xml.namespace.QName; + +import com.evolveum.midpoint.gui.api.component.*; +import com.evolveum.midpoint.gui.api.component.tabs.PanelTab; +import com.evolveum.midpoint.gui.api.prism.PrismContainerWrapper; +import com.evolveum.midpoint.gui.api.util.WebPrismUtil; +import com.evolveum.midpoint.model.api.AssignmentCandidatesSpecification; +import com.evolveum.midpoint.model.api.context.ModelContext; +import com.evolveum.midpoint.prism.PrismContainerValue; +import com.evolveum.midpoint.prism.query.ObjectFilter; +import com.evolveum.midpoint.prism.query.ObjectQuery; +import com.evolveum.midpoint.schema.constants.SchemaConstants; +import com.evolveum.midpoint.util.exception.*; +import com.evolveum.midpoint.web.component.AjaxButton; +import com.evolveum.midpoint.web.component.prism.ValueStatus; +import com.evolveum.midpoint.web.component.prism.show.PagePreviewChanges; +import com.evolveum.midpoint.web.component.util.SelectableBean; +import com.evolveum.midpoint.web.component.util.VisibleBehaviour; +import com.evolveum.midpoint.web.page.admin.configuration.PageSystemConfiguration; +import com.evolveum.midpoint.web.page.admin.server.OperationalButtonsPanel; +import com.evolveum.midpoint.web.security.util.SecurityUtils; +import com.evolveum.midpoint.xml.ns._public.common.common_3.*; + +import org.apache.commons.lang.StringUtils; +import org.apache.wicket.Page; +import org.apache.wicket.RestartResponseException; +import org.apache.wicket.Session; +import org.apache.wicket.ajax.AbstractAjaxTimerBehavior; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.behavior.AttributeAppender; +import org.apache.wicket.behavior.Behavior; +import org.apache.wicket.extensions.markup.html.tabs.ITab; +import org.apache.wicket.markup.html.WebMarkupContainer; +import org.apache.wicket.markup.repeater.RepeatingView; +import org.apache.wicket.model.IModel; +import org.apache.wicket.model.Model; +import org.apache.wicket.model.StringResourceModel; +import org.apache.wicket.protocol.http.WebSession; +import org.apache.wicket.request.mapper.parameter.PageParameters; +import org.apache.wicket.util.string.StringValue; +import org.apache.wicket.util.time.Duration; +import org.jetbrains.annotations.NotNull; + +import com.evolveum.midpoint.gui.api.model.LoadableModel; +import com.evolveum.midpoint.gui.api.prism.ItemStatus; +import com.evolveum.midpoint.gui.api.prism.PrismObjectWrapper; +import com.evolveum.midpoint.gui.api.util.WebComponentUtil; +import com.evolveum.midpoint.gui.api.util.WebModelServiceUtils; +import com.evolveum.midpoint.gui.impl.factory.PrismObjectWrapperFactory; +import com.evolveum.midpoint.gui.impl.factory.WrapperContext; +import com.evolveum.midpoint.model.api.ModelExecuteOptions; +import com.evolveum.midpoint.model.api.authentication.CompiledGuiProfile; +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.delta.ObjectDelta; +import com.evolveum.midpoint.schema.GetOperationOptions; +import com.evolveum.midpoint.schema.SelectorOptions; +import com.evolveum.midpoint.schema.constants.ObjectTypes; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.util.QNameUtil; +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.web.component.ObjectSummaryPanel; +import com.evolveum.midpoint.web.component.objectdetails.AbstractObjectMainPanel; +import com.evolveum.midpoint.web.component.progress.ProgressPanel; +import com.evolveum.midpoint.web.component.progress.ProgressReportingAwarePage; +import com.evolveum.midpoint.web.component.util.VisibleEnableBehaviour; +import com.evolveum.midpoint.web.page.admin.users.dto.FocusSubwrapperDto; +import com.evolveum.midpoint.web.util.OnePageParameterEncoder; +import com.evolveum.midpoint.web.util.validation.MidpointFormValidator; +import com.evolveum.midpoint.web.util.validation.SimpleValidationError; + +/** + * @author semancik + */ +public abstract class PageAdminObjectDetails extends PageAdmin + implements ProgressReportingAwarePage { + private static final long serialVersionUID = 1L; + + private static final String DOT_CLASS = PageAdminObjectDetails.class.getName() + "."; + + public static final String PARAM_RETURN_PAGE = "returnPage"; + + private static final String OPERATION_LOAD_OBJECT = DOT_CLASS + "loadObject"; + private static final String OPERATION_LOAD_PARENT_ORGS = DOT_CLASS + "loadParentOrgs"; + private static final String OPERATION_LOAD_GUI_CONFIGURATION = DOT_CLASS + "loadGuiConfiguration"; + protected static final String OPERATION_SAVE = DOT_CLASS + "save"; + protected static final String OPERATION_PREVIEW_CHANGES = DOT_CLASS + "previewChanges"; + protected static final String OPERATION_SEND_TO_SUBMIT = DOT_CLASS + "sendToSubmit"; + protected static final String OPERATION_LOAD_ARCHETYPE_REF = DOT_CLASS + "loadArchetypeRef"; + protected static final String OPERATION_EXECUTE_CHANGES = DOT_CLASS + "executeChangesTask"; + protected static final String OPERATION_EXECUTE_ARCHETYPE_CHANGES = DOT_CLASS + "executeArchetypeChanges"; + protected static final String OPERATION_LOAD_FILTERED_ARCHETYPES = DOT_CLASS + "loadFilteredArchetypes"; + + protected static final String ID_SUMMARY_PANEL = "summaryPanel"; + protected static final String ID_MAIN_PANEL = "mainPanel"; + private static final String ID_PROGRESS_PANEL = "progressPanel"; + private static final String ID_BUTTONS = "buttons"; + + private static final Trace LOGGER = TraceManager.getTrace(PageAdminObjectDetails.class); + + private LoadableModel> objectModel; + private LoadableModel>> parentOrgModel; + + private ProgressPanel progressPanel; + + // used to determine whether to leave this page or stay on it (after + // operation finishing) + private ObjectDelta delta; + + private AbstractObjectMainPanel mainPanel; + private boolean saveOnConfigure; // ugly hack - whether to invoke 'Save' when returning to this page + + private boolean editingFocus = false; //before we got isOidParameterExists status depending only on oid parameter existence + //we should set editingFocus=true not only when oid parameter exists but also + //when object is given as a constructor parameter + + public boolean isEditingFocus() { + return editingFocus; + } + + @Override + protected void createBreadcrumb() { + createInstanceBreadcrumb(); + } + + @Override + protected void onConfigure() { + super.onConfigure(); + if (saveOnConfigure) { + saveOnConfigure = false; + add(new AbstractAjaxTimerBehavior(Duration.milliseconds(100)) { + @Override + protected void onTimer(AjaxRequestTarget target) { + stop(target); + savePerformed(target); + } + }); + } + } + + @Override + protected IModel createPageTitleModel() { + if (PageAdminObjectDetails.this instanceof PageSystemConfiguration){ + return super.createPageTitleModel(); + } + String simpleName = getObjectSimpleName(); + String lokalizedSimpleName = new StringResourceModel("ObjectType." + simpleName).setDefaultValue(simpleName).getString(); + if (isAdd()) { + return createStringResource("PageAdminObjectDetails.title.new", lokalizedSimpleName); + } + + String name = null; + if (getObjectWrapper() != null && getObjectWrapper().getObject() != null) { + name = WebComponentUtil.getName(getObjectWrapper().getObject()); + } + + return createStringResource("PageAdminObjectDetails.title.edit.readonly.${readOnly}", getObjectModel(), lokalizedSimpleName, name); + } + + private String getObjectSimpleName(){ + if (getObjectWrapper() != null && getObjectWrapper().getObject() != null + && getObjectWrapper().getObject().asObjectable() instanceof AssignmentHolderType){ + AssignmentHolderType assignmentHolderObj = (AssignmentHolderType) getObjectWrapper().getObject().asObjectable(); + DisplayType displayType = WebComponentUtil + .getArchetypePolicyDisplayType(assignmentHolderObj, PageAdminObjectDetails.this); + if (displayType == null){ + ObjectReferenceType archetypeReference = getObjectArchetypeRef(); + if (archetypeReference != null){ + OperationResult result = new OperationResult(OPERATION_LOAD_ARCHETYPE_REF); + Task task = createSimpleTask(OPERATION_LOAD_ARCHETYPE_REF); + PrismObject archetypeObj = WebModelServiceUtils.resolveReferenceNoFetch(archetypeReference, + this, task, result); + displayType = archetypeObj != null && archetypeObj.asObjectable().getArchetypePolicy() != null ? + archetypeObj.asObjectable().getArchetypePolicy().getDisplay() : null; + } + } + if (displayType != null && displayType.getLabel() != null) { + String archetypeLocalizedName = getLocalizationService() + .translate(displayType.getLabel().toPolyString(), WebComponentUtil.getCurrentLocale(), true); + if (StringUtils.isNotEmpty(archetypeLocalizedName)) { + return archetypeLocalizedName; + } + } + } + return getCompileTimeClass().getSimpleName(); + } + + public boolean isAdd() { + return !isOidParameterExists() && !editingFocus; + } + + public LoadableModel> getObjectModel() { + return objectModel; + } + + protected AbstractObjectMainPanel getMainPanel() { + return mainPanel; + } + + public PrismObjectWrapper getObjectWrapper() { + return objectModel.getObject(); + } + + public List> getParentOrgs() { + return parentOrgModel.getObject(); + } + + public ObjectDelta getDelta() { + return delta; + } + + public void setDelta(ObjectDelta delta) { + this.delta = delta; + } + + public ProgressPanel getProgressPanel() { + return progressPanel; + } + + protected void reviveModels() throws SchemaException { + WebComponentUtil.revive(objectModel, getPrismContext()); + WebComponentUtil.revive(parentOrgModel, getPrismContext()); + } + + public abstract Class getCompileTimeClass(); + + + public void initialize(final PrismObject objectToEdit) { + boolean isNewObject = objectToEdit == null && StringUtils.isEmpty(getObjectOidParameter()); + + initialize(objectToEdit, isNewObject, false); + } + + public void initialize(final PrismObject objectToEdit, boolean isNewObject) { + initialize(objectToEdit, isNewObject, false); + } + + public void initialize(final PrismObject objectToEdit, boolean isNewObject, boolean isReadonly) { + initializeModel(objectToEdit, isNewObject, isReadonly); +// initLayout(); + } + + protected void initializeModel(final PrismObject objectToEdit, boolean isNewObject, boolean isReadonly) { + editingFocus = !isNewObject; + + objectModel = new LoadableModel>(false) { + private static final long serialVersionUID = 1L; + + @Override + protected PrismObjectWrapper load() { + PrismObjectWrapper wrapper = loadObjectWrapper(objectToEdit, isReadonly); +// wrapper.sort(); + return wrapper; + } + }; + + parentOrgModel = new LoadableModel>>(false) { + private static final long serialVersionUID = 1L; + + @Override + protected List> load() { + return loadOrgWrappers(); + } + }; + } + + private ObjectReferenceType getObjectArchetypeRef() { + ObjectReferenceType archetypeReference = null; + if (getObjectWrapper() != null && getObjectWrapper().getObject() != null + && getObjectWrapper().getObject().asObjectable() instanceof AssignmentHolderType) { + AssignmentHolderType assignmentHolderObj = (AssignmentHolderType) getObjectWrapper().getObject().asObjectable(); + if (assignmentHolderObj.getAssignment() != null) { + for (AssignmentType assignment : assignmentHolderObj.getAssignment()) { + if (assignment.getTargetRef() != null && assignment.getTargetRef().getType() != null + && QNameUtil.match(assignment.getTargetRef().getType(), ArchetypeType.COMPLEX_TYPE)) { + archetypeReference = assignment.getTargetRef(); + break; + } + } + } + } + return archetypeReference; + } + + protected List> loadOrgWrappers() { + // WRONG!! TODO: fix + return null; + } + + protected abstract O createNewObject(); + + @Override + protected void onInitialize() { + super.onInitialize(); + initLayout(); + } + + protected void initLayout() { + initLayoutSummaryPanel(); + initOperationalButtonsPanel(); + + mainPanel = createMainPanel(ID_MAIN_PANEL); + mainPanel.setOutputMarkupId(true); + add(mainPanel); + + progressPanel = new ProgressPanel(ID_PROGRESS_PANEL); + add(progressPanel); + } + + protected abstract ObjectSummaryPanel createSummaryPanel(); + + protected void initLayoutSummaryPanel() { + + ObjectSummaryPanel summaryPanel = createSummaryPanel(); + summaryPanel.setOutputMarkupId(true); + + setSummaryPanelVisibility(summaryPanel); + add(summaryPanel); + } + + protected void setSummaryPanelVisibility(ObjectSummaryPanel summaryPanel){ + summaryPanel.add(new VisibleEnableBehaviour() { + private static final long serialVersionUID = 1L; + + @Override + public boolean isVisible() { + return isOidParameterExists() || editingFocus; + } + }); + } + + private void initOperationalButtonsPanel(){ + OperationalButtonsPanel opButtonPanel = new OperationalButtonsPanel(ID_BUTTONS) { + private static final long serialVersionUID = 1L; + + @Override + protected void addButtons(RepeatingView repeatingView) { + initOperationalButtons(repeatingView); + } + }; + if (getAdditionalOperationalButtonPanelBehaviors() != null && !getAdditionalOperationalButtonPanelBehaviors().isEmpty()){ + getAdditionalOperationalButtonPanelBehaviors().forEach(this::add); + } + opButtonPanel.setOutputMarkupId(true); + opButtonPanel.add(new VisibleBehaviour(() -> isEditingFocus() && opButtonPanel.buttonsExist())); + add(opButtonPanel); + } + + protected List getAdditionalOperationalButtonPanelBehaviors(){ + return new ArrayList<>(); + } + + protected void initOperationalButtons(RepeatingView repeatingView){ + if (getObjectArchetypeRef() != null) { + AjaxButton changeArchetype = new AjaxButton(repeatingView.newChildId(), createStringResource("PageAdminObjectDetails.button.changeArchetype")) { + @Override + public void onClick(AjaxRequestTarget target) { + changeArchetypeButtonClicked(target); + } + }; + changeArchetype.add(new VisibleBehaviour(() -> getObjectArchetypeRef() != null)); + changeArchetype.add(AttributeAppender.append("class", "btn-default")); + repeatingView.add(changeArchetype); + } + } + + protected OperationalButtonsPanel getOperationalButtonsPanel(){ + return (OperationalButtonsPanel) get(ID_BUTTONS); + } + + private void changeArchetypeButtonClicked(AjaxRequestTarget target){ + + AssignmentPopup changeArchetypePopup = new AssignmentPopup(getMainPopupBodyId()) { + + private static final long serialVersionUID = 1L; + + @Override + protected void addPerformed(AjaxRequestTarget target, List newAssignmentsList) { + super.addPerformed(target, newAssignmentsList); + try { + PrismContainerWrapper assignmentsWrapper = getObjectWrapper().findContainer(FocusType.F_ASSIGNMENT); + ((List) newAssignmentsList).forEach(assignment -> { + PrismContainerValue newAssignment = assignmentsWrapper.getItem().createNewValue(); + assignmentsWrapper.getValues().forEach(assignmentValue -> { + if (assignmentValue.getRealValue().getTargetRef() != null + && assignmentValue.getRealValue().getTargetRef().getType() != null + && QNameUtil.match(assignmentValue.getRealValue().getTargetRef().getType(), ArchetypeType.COMPLEX_TYPE)){ + assignmentValue.setStatus(ValueStatus.DELETED); + } + }); + AssignmentType assignmentType = newAssignment.asContainerable(); + assignmentType.setTargetRef(assignment.getTargetRef()); + WebPrismUtil.createNewValueWrapper(assignmentsWrapper, newAssignment, PageAdminObjectDetails.this, target); + OperationResult result = new OperationResult(OPERATION_EXECUTE_ARCHETYPE_CHANGES); + Task task = createSimpleTask(OPERATION_EXECUTE_ARCHETYPE_CHANGES); + try { + ObjectDelta archetypeDelta = getObjectWrapper().getObjectDelta(); + if (!archetypeDelta.isEmpty()) { + archetypeDelta.revive(getPrismContext()); + getModelService().executeChanges(WebComponentUtil.createDeltaCollection(archetypeDelta), null, task, result); + result.computeStatus(); + } + } catch (Exception e) { + LOGGER.error("Cannot save archetype assignment changes: {}", e.getMessage()); + } + showResult(result); + }); + } catch (SchemaException e) { + LOGGER.error("Cannot find assignment wrapper: {}", e.getMessage()); + } + target.add(PageAdminObjectDetails.this.getFeedbackPanel()); + } + + @Override + protected List createAssignmentTabs() { + List tabs = new ArrayList<>(); + + tabs.add(new PanelTab(getPageBase().createStringResource("ObjectTypes.ARCHETYPE"), + new VisibleBehaviour(() -> true)) { + + private static final long serialVersionUID = 1L; + + @Override + public WebMarkupContainer createPanel(String panelId) { + return new FocusTypeAssignmentPopupTabPanel(panelId, ObjectTypes.ARCHETYPE) { + private static final long serialVersionUID = 1L; + + @Override + protected PrismContainerWrapper getAssignmentWrapperModel() { + PrismContainerWrapper assignmentsWrapper = null; + try { + assignmentsWrapper = getObjectWrapper().findContainer(FocusType.F_ASSIGNMENT); + } catch (SchemaException e) { + LOGGER.error("Cannot find assignment wrapper: {}", e.getMessage()); + } + return assignmentsWrapper; + } + + @Override + protected List getSupportedRelations() { + return Collections.singletonList(SchemaConstants.ORG_DEFAULT); + } + + @Override + protected void onSelectionPerformed(AjaxRequestTarget target, IModel> rowModel) { + target.add(getObjectListPanel()); + tabLabelPanelUpdate(target); + } + + @Override + protected IModel getObjectSelectCheckBoxEnableModel(IModel> rowModel){ + if (rowModel == null){ + return Model.of(false); + } + List selectedObjects = getSelectedObjectsList(); + return Model.of(selectedObjects == null || selectedObjects.size() == 0 + || (rowModel.getObject() != null && rowModel.getObject().isSelected())); + } + + + @Override + protected ObjectTypes getObjectType() { + return ObjectTypes.ARCHETYPE; + } + + @Override + protected ObjectQuery addFilterToContentQuery(ObjectQuery query){ + super.addFilterToContentQuery(query); + if (query == null) { + query = getPrismContext().queryFactory().createQuery(); + } + List archetypeOidsList = getFilteredArchetypeOidsList(); + ObjectFilter filter = getPrismContext().queryFor(ArchetypeType.class) + .id(archetypeOidsList.toArray(new String[0])) + .buildFilter(); + query.addFilter(filter); + return query; + } + }; + } + }); + return tabs; + } + }; + + changeArchetypePopup.setOutputMarkupPlaceholderTag(true); + showMainPopup(changeArchetypePopup, target); + + } + + private List getFilteredArchetypeOidsList(){ + OperationResult result = new OperationResult(OPERATION_LOAD_FILTERED_ARCHETYPES); + PrismObject obj = getObjectWrapper().getObject(); + List oidsList = new ArrayList<>(); + try { + List filteredArchetypes = getModelInteractionService().getFilteredArchetypesByHolderType(obj, result); + if (filteredArchetypes != null){ + filteredArchetypes.forEach(archetype -> oidsList.add(archetype.getOid())); + } + } catch (SchemaException ex){ + result.recordPartialError(ex.getLocalizedMessage()); + LOGGER.error("Couldn't load assignment target specification for the object {} , {}", obj.getName(), ex.getLocalizedMessage()); + } + return oidsList; + } + + protected abstract AbstractObjectMainPanel createMainPanel(String id); + + protected String getObjectOidParameter() { + PageParameters parameters = getPageParameters(); + LOGGER.trace("Page parameters: {}", parameters); + StringValue oidValue = parameters.get(OnePageParameterEncoder.PARAMETER); + LOGGER.trace("OID parameter: {}", oidValue); + if (oidValue == null) { + return null; + } + String oid = oidValue.toString(); + if (StringUtils.isBlank(oid)) { + return null; + } + return oid; + } + + protected ObjectSummaryPanel getSummaryPanel() { + return (ObjectSummaryPanel) get(ID_SUMMARY_PANEL); + } + + public boolean isOidParameterExists() { + return getObjectOidParameter() != null; + } + + protected PrismObjectWrapper loadObjectWrapper(PrismObject objectToEdit, boolean isReadonly) { + Task task = createSimpleTask(OPERATION_LOAD_OBJECT); + OperationResult result = task.getResult(); + PrismObject object = null; + try { + if (!isOidParameterExists()) { + if (objectToEdit == null) { + LOGGER.trace("Loading object: New object (creating)"); + O focusType = createNewObject(); + + // Apply subtype using page parameters + List subtypes = getPageParameters().getValues(ObjectType.F_SUBTYPE.getLocalPart()); + subtypes.stream().filter(p -> !p.isEmpty()).forEach(c -> focusType.subtype(c.toString())); + + getMidpointApplication().getPrismContext().adopt(focusType); + object = (PrismObject) focusType.asPrismObject(); + } else { + LOGGER.trace("Loading object: New object (supplied): {}", objectToEdit); + object = objectToEdit; + } + } else { + + String focusOid = getObjectOidParameter(); + object = WebModelServiceUtils.loadObject(getCompileTimeClass(), focusOid, buildGetOptions(), this, task, result); + LOGGER.trace("Loading object: Existing object (loadled): {} -> {}", focusOid, object); + } + + result.recordSuccess(); + } catch (Exception ex) { + result.recordFatalError(getString("PageAdminObjectDetails.message.loadObjectWrapper.fatalError"), ex); + LoggingUtils.logUnexpectedException(LOGGER, "Couldn't load object", ex); + } + + showResult(result, false); + + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Loaded object:\n{}", object.debugDump()); + } + + if (object == null) { + if (isOidParameterExists()) { + getSession().error(getString("pageAdminFocus.message.cantEditFocus")); + } else { + getSession().error(getString("pageAdminFocus.message.cantNewFocus")); + } + throw new RestartResponseException(getRestartResponsePage()); + } + + ItemStatus itemStatus = isOidParameterExists() || editingFocus ? ItemStatus.NOT_CHANGED : ItemStatus.ADDED; + PrismObjectWrapper wrapper; + + PrismObjectWrapperFactory factory = getRegistry().getObjectWrapperFactory(object.getDefinition()); + WrapperContext context = new WrapperContext(task, result); + context.setCreateIfEmpty(ItemStatus.ADDED == itemStatus); + //we don't want to set to false.. refactor this method to take either enum (READONLY, AUTO, ...) or + // Boolean instead of boolean isReadonly + if (isReadonly) { + context.setReadOnly(isReadonly); + } + + + try { + wrapper = factory.createObjectWrapper(object.clone(), itemStatus, context); + } catch (Exception ex) { + result.recordFatalError(getString("PageAdminObjectDetails.message.loadObjectWrapper.fatalError"), ex); + LoggingUtils.logUnexpectedException(LOGGER, "Couldn't load object", ex); + showResult(result, false); + throw new RestartResponseException(getRestartResponsePage()); + } + + showResult(result, false); + + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Loaded focus wrapper:\n{}", wrapper.debugDump()); + } + + return wrapper; + } + + protected Collection> buildGetOptions() { + return getOperationOptionsBuilder() + .item(UserType.F_JPEG_PHOTO).retrieve() + .build(); + } + +// private void loadParentOrgs(PrismObjectWrapper wrapper, Task task, OperationResult result) { +// OperationResult subResult = result.createMinorSubresult(OPERATION_LOAD_PARENT_ORGS); +// PrismObject focus = wrapper.getObject(); +// // Load parent organizations (full objects). There are used in the +// // summary panel and also in the main form. +// // Do it here explicitly instead of using resolve option to have ability +// // to better handle (ignore) errors. +// for (ObjectReferenceType parentOrgRef : focus.asObjectable().getParentOrgRef()) { +// +// PrismObject parentOrg = null; +// try { +// +// parentOrg = getModelService().getObject(OrgType.class, parentOrgRef.getOid(), null, task, +// subResult); +// LOGGER.trace("Loaded parent org with result {}", +// new Object[] { subResult.getLastSubresult() }); +// } catch (AuthorizationException e) { +// // This can happen if the user has permission to read parentOrgRef but it does not have +// // the permission to read target org +// // It is OK to just ignore it. +// subResult.muteLastSubresultError(); +// LOGGER.debug("User {} does not have permission to read parent org unit {} (ignoring error)", task.getOwner().getName(), parentOrgRef.getOid()); +// } catch (Exception ex) { +// subResult.recordWarning(createStringResource("PageAdminObjectDetails.message.loadParentOrgs.warning", parentOrgRef.getOid()).getString(), ex); +// LOGGER.warn("Cannot load parent org {}: {}", parentOrgRef.getOid(), ex.getMessage(), ex); +// } +// +// if (parentOrg != null) { +// wrapper.getParentOrgs().add(parentOrg); +// } +// } +// subResult.computeStatus(); +// } + + protected abstract Class getRestartResponsePage(); + + public Object findParam(String param, String oid, OperationResult result) { + + Object object = null; + + for (OperationResult subResult : result.getSubresults()) { + if (subResult != null && subResult.getParams() != null) { + if (subResult.getParams().get(param) != null + && subResult.getParams().get(OperationResult.PARAM_OID) != null + && subResult.getParams().get(OperationResult.PARAM_OID).equals(oid)) { + return subResult.getParams().get(param); + } + object = findParam(param, oid, subResult); + + } + } + return object; + } + + // TODO put this into correct place + protected boolean previewRequested; + + /** + * This will be called from the main form when save button is pressed. + */ + public void savePerformed(AjaxRequestTarget target) { + progressPanel.onBeforeSave(); + OperationResult result = new OperationResult(OPERATION_SAVE); + previewRequested = false; + saveOrPreviewPerformed(target, result, false); + } + + public void previewPerformed(AjaxRequestTarget target) { + progressPanel.onBeforeSave(); + OperationResult result = new OperationResult(OPERATION_PREVIEW_CHANGES); + previewRequested = true; + saveOrPreviewPerformed(target, result, true); + } + + public void saveOrPreviewPerformed(AjaxRequestTarget target, OperationResult result, boolean previewOnly) { + saveOrPreviewPerformed(target, result, previewOnly, null); + } + + public void saveOrPreviewPerformed(AjaxRequestTarget target, OperationResult result, boolean previewOnly, Task task) { + boolean delegationChangesExist = processDeputyAssignments(previewOnly); + + PrismObjectWrapper objectWrapper = getObjectWrapper(); + LOGGER.debug("Saving object {}", objectWrapper); + + // todo: improve, delta variable is quickfix for MID-1006 + // redirecting to user list page everytime user is created in repository + // during user add in gui, + // and we're not taking care about account/assignment create errors + // (error message is still displayed) + delta = null; + + if(task == null) { + task = createSimpleTask(OPERATION_SEND_TO_SUBMIT); + } + + ModelExecuteOptions options = getOptions(previewOnly); + + LOGGER.debug("Using execute options {}.", options); + + try { + reviveModels(); + + delta = objectWrapper.getObjectDelta(); + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("User delta computed from form:\n{}", new Object[] { delta.debugDump(3) }); + } + } catch (Exception ex) { + result.recordFatalError(getString("pageAdminObjectDetails.message.cantCreateObject"), ex); + LoggingUtils.logUnexpectedException(LOGGER, "Create Object failed", ex); + showResult(result); + target.add(getFeedbackPanel()); + return; + } + + switch (objectWrapper.getStatus()) { + case ADDED: + try { + PrismObject objectToAdd = delta.getObjectToAdd(); + WebComponentUtil.encryptCredentials(objectToAdd, true, getMidpointApplication()); + prepareObjectForAdd(objectToAdd); + getPrismContext().adopt(objectToAdd, getCompileTimeClass()); + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Delta before add user:\n{}", new Object[] { delta.debugDump(3) }); + } + + if (!delta.isEmpty()) { + delta.revive(getPrismContext()); + + final Collection> deltas = WebComponentUtil.createDeltaCollection(delta); + final Collection validationErrors = performCustomValidation(objectToAdd, deltas); + if (checkValidationErrors(target, validationErrors)) { + return; + } + if (isSaveInBackground()){ + progressPanel.executeChangesInBackground(deltas, previewOnly, options, task, result, target); + } else { + progressPanel.executeChanges(deltas, previewOnly, options, task, result, target); + } + } else { + result.recordSuccess(); + } + } catch (Exception ex) { + result.recordFatalError(getString("pageFocus.message.cantCreateFocus"), ex); + LoggingUtils.logUnexpectedException(LOGGER, "Create user failed", ex); + showResult(result); + } + break; + + case NOT_CHANGED: + try { + WebComponentUtil.encryptCredentials(delta, true, getMidpointApplication()); + prepareObjectDeltaForModify(delta); //preparing of deltas for projections (ADD, DELETE, UNLINK) + + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Delta before modify user:\n{}", new Object[] { delta.debugDump(3) }); + } + + Collection> deltas = new ArrayList<>(); + if (!delta.isEmpty()) { + delta.revive(getPrismContext()); + deltas.add(delta); + } + + List> additionalDeltas = getAdditionalModifyDeltas(result); + if (additionalDeltas != null) { + for (ObjectDelta additionalDelta : additionalDeltas) { + if (!additionalDelta.isEmpty()) { + additionalDelta.revive(getPrismContext()); + deltas.add(additionalDelta); + } + } + } + + if (delta.isEmpty() && ModelExecuteOptions.isReconcile(options)) { + ObjectDelta emptyDelta = getPrismContext().deltaFactory().object().createEmptyModifyDelta(getCompileTimeClass(), + objectWrapper.getObject().getOid()); + deltas.add(emptyDelta); + + Collection validationErrors = performCustomValidation(null, deltas); + if (checkValidationErrors(target, validationErrors)) { + return; + } + if (isSaveInBackground()){ + progressPanel.executeChangesInBackground(deltas, previewOnly, options, task, result, target); + } else { + progressPanel.executeChanges(deltas, previewOnly, options, task, result, target); + } + } else if (!deltas.isEmpty()) { + Collection validationErrors = performCustomValidation(null, deltas); + if (checkValidationErrors(target, validationErrors)) { + return; + } + if (isSaveInBackground()){ + progressPanel.executeChangesInBackground(deltas, previewOnly, options, task, result, target); + } else { + progressPanel.executeChanges(deltas, previewOnly, options, task, result, target); + } + } else if (previewOnly && delta.isEmpty() && delegationChangesExist){ + if (isSaveInBackground()){ + progressPanel.executeChangesInBackground(deltas, previewOnly, options, task, result, target); + } else { + progressPanel.executeChanges(deltas, previewOnly, options, task, result, target); + } + } else { + progressPanel.clearProgressPanel(); // from previous attempts (useful only if we would call finishProcessing at the end, but that's not the case now) + if (!previewOnly) { + if (!delegationChangesExist) { + result.recordWarning(getString("PageAdminObjectDetails.noChangesSave")); + showResult(result); + } + redirectBack(); + } else { + if (!delegationChangesExist) { + warn(getString("PageAdminObjectDetails.noChangesPreview")); + target.add(getFeedbackPanel()); + } + } + } + + } catch (Exception ex) { + if (!executeForceDelete(objectWrapper, task, options, result)) { + result.recordFatalError(getString("pageUser.message.cantUpdateUser"), ex); + LoggingUtils.logUnexpectedException(LOGGER, getString("pageUser.message.cantUpdateUser"), ex); + } else { + result.recomputeStatus(); + } + showResult(result); + } + break; + // support for add/delete containers (e.g. delete credentials) + default: + error(getString("pageAdminFocus.message.unsupportedState", objectWrapper.getStatus())); + } + +// result.recomputeStatus(); +// +// if (!result.isInProgress()) { +// LOGGER.trace("Result NOT in progress, calling finishProcessing"); +// finishProcessing(target, result, false); +// } + + LOGGER.trace("returning from saveOrPreviewPerformed"); + } + + protected boolean processDeputyAssignments(boolean previewOnly){ + return false; + } + + protected boolean checkValidationErrors(AjaxRequestTarget target, Collection validationErrors) { + if (validationErrors != null && !validationErrors.isEmpty()) { + for (SimpleValidationError error : validationErrors) { + LOGGER.error("Validation error, attribute: '" + error.printAttribute() + + "', message: '" + error.getMessage() + "'."); + error("Validation error, attribute: '" + error.printAttribute() + + "', message: '" + error.getMessage() + "'."); + } + + target.add(getFeedbackPanel()); + return true; + } + return false; + } + + @Override + public void startProcessing(AjaxRequestTarget target, OperationResult result) { + LOGGER.trace("startProcessing called, making main panel invisible"); + mainPanel.setVisible(false); + target.add(mainPanel); + } + + @NotNull + protected ModelExecuteOptions getOptions(boolean previewOnly) { + ModelExecuteOptions options = mainPanel.getExecuteChangeOptionsDto().createOptions(); + if (previewOnly) { + options.getOrCreatePartialProcessing().setApprovals(PartialProcessingTypeType.PROCESS); + } + return options; + } + + protected void prepareObjectForAdd(PrismObject object) throws SchemaException { + + } + + protected void prepareObjectDeltaForModify(ObjectDelta objectDelta) throws SchemaException { + + } + + protected List> getAdditionalModifyDeltas(OperationResult result) { + return null; + } + + protected boolean executeForceDelete(PrismObjectWrapper userWrapper, Task task, ModelExecuteOptions options, + OperationResult parentResult) { + return isForce(); + } + + protected boolean isForce() { + return getMainPanel().getExecuteChangeOptionsDto().isForce(); + } + + protected boolean isKeepDisplayingResults() { + return getMainPanel().getExecuteChangeOptionsDto().isKeepDisplayingResults(); + } + + protected boolean isSaveInBackground(){ + return getMainPanel().getExecuteChangeOptionsDto().isSaveInBackground(); + } + + protected Collection performCustomValidation(PrismObject object, + Collection> deltas) throws SchemaException { + Collection errors = null; + + if (object == null) { + if (getObjectWrapper() != null && getObjectWrapper().getObjectOld() != null) { + object = getObjectWrapper().getObjectOld().clone(); // otherwise original object could get corrupted e.g. by applying the delta below + + for (ObjectDelta delta : deltas) { + // because among deltas there can be also ShadowType deltas + if (UserType.class.isAssignableFrom(delta.getObjectTypeClass())) { + delta.applyTo(object); + } + } + } + } else { + object = object.clone(); + } + + performAdditionalValidation(object, deltas, errors); + + for (MidpointFormValidator validator : getFormValidatorRegistry().getValidators()) { + if (errors == null) { + errors = validator.validateObject(object, deltas); + } else { + errors.addAll(validator.validateObject(object, deltas)); + } + } + + return errors; + } + + protected void performAdditionalValidation(PrismObject object, + Collection> deltas, Collection errors) throws SchemaException { + + } + + public List getObjectFormTypes() { + Task task = createSimpleTask(OPERATION_LOAD_GUI_CONFIGURATION); + OperationResult result = task.getResult(); + CompiledGuiProfile adminGuiConfiguration; + try { + adminGuiConfiguration = getModelInteractionService().getCompiledGuiProfile(task, result); + } catch (ObjectNotFoundException | SchemaException | CommunicationException | ConfigurationException | SecurityViolationException | ExpressionEvaluationException e) { + throw new SystemException("Cannot load GUI configuration: "+e.getMessage(), e); + } + ObjectFormsType objectFormsType = adminGuiConfiguration.getObjectForms(); + if (objectFormsType == null) { + return null; + } + List objectForms = objectFormsType.getObjectForm(); + if (objectForms == null || objectForms.isEmpty()) { + return objectForms; + } + List validObjectForms = new ArrayList<>(); + for (ObjectFormType objectForm: objectForms) { + if (isSupportedObjectType(objectForm.getType())) { + validObjectForms.add(objectForm); + } + } + return validObjectForms; + } + + protected boolean isSupportedObjectType(QName type) { + ObjectTypes objectType = ObjectTypes.getObjectType(getCompileTimeClass()); + return QNameUtil.match(objectType.getTypeQName(),type); + } + + public void setSaveOnConfigure(boolean saveOnConfigure) { + this.saveOnConfigure = saveOnConfigure; + } + + public boolean isSaveOnConfigure() { + return saveOnConfigure; + } + + public boolean isForcedPreview() { + GuiObjectDetailsPageType objectDetails = getCompiledGuiProfile().findObjectDetailsConfiguration(getCompileTimeClass()); + return objectDetails != null && DetailsPageSaveMethodType.FORCED_PREVIEW.equals(objectDetails.getSaveMethod()); + } + + //TODO moved from PageAdminFocus.. maybe we need PageAssignmentHolderDetails? + @Override + public void finishProcessing(AjaxRequestTarget target, OperationResult result, boolean returningFromAsync) { + + if (previewRequested) { + finishPreviewProcessing(target, result); + return; + } + if (result.isSuccess() && getDelta() != null && SecurityUtils.getPrincipalUser().getOid().equals(getDelta().getOid())) { + Session.get().setLocale(WebModelServiceUtils.getLocale()); + LOGGER.debug("Using {} as locale", getLocale()); + WebSession.get().getClientInfo().getProperties(). + setTimeZone(WebModelServiceUtils.getTimezone()); + LOGGER.debug("Using {} as time zone", WebSession.get().getClientInfo().getProperties().getTimeZone()); + } + boolean focusAddAttempted = getDelta() != null && getDelta().isAdd(); + boolean focusAddSucceeded = focusAddAttempted && StringUtils.isNotEmpty(getDelta().getOid()); + + // we don't want to allow resuming editing if a new focal object was created (on second 'save' there would be a conflict with itself) + // and also in case of partial errors, like those related to projections (many deltas would be already executed, and this could cause problems on second 'save'). + boolean canContinueEditing = !focusAddSucceeded && result.isFatalError(); + + boolean canExitPage; + if (returningFromAsync) { + canExitPage = getProgressPanel().isAllSuccess() || result.isInProgress() || result.isHandledError(); // if there's at least a warning in the progress table, we would like to keep the table open + } else { + canExitPage = !canContinueEditing; // no point in staying on page if we cannot continue editing (in synchronous case i.e. no progress table present) + } + + if (!isKeepDisplayingResults() && canExitPage) { + showResult(result); + redirectBack(); + } else { + if (returningFromAsync) { + getProgressPanel().showBackButton(target); + getProgressPanel().hideAbortButton(target); + } + showResult(result); + target.add(getFeedbackPanel()); + + if (canContinueEditing) { + getProgressPanel().hideBackButton(target); + getProgressPanel().showContinueEditingButton(target); + } + } + } + + private void finishPreviewProcessing(AjaxRequestTarget target, OperationResult result) { + getMainPanel().setVisible(true); + getProgressPanel().hide(); + getProgressPanel().hideAbortButton(target); + getProgressPanel().hideBackButton(target); + getProgressPanel().hideContinueEditingButton(target); + + showResult(result); + target.add(getFeedbackPanel()); + + Map, ModelContext> modelContextMap = new LinkedHashMap<>(); + modelContextMap.put(getObjectWrapper().getObject(), getProgressPanel().getPreviewResult()); + + processAdditionalFocalObjectsForPreview(modelContextMap); + + navigateToNext(new PagePreviewChanges(modelContextMap, getModelInteractionService())); + } + + protected void processAdditionalFocalObjectsForPreview(Map, ModelContext> modelContextMap){ + } +} diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/PageTask.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/PageTask.java index 3c4332850b8..67e6061a71b 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/PageTask.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/PageTask.java @@ -582,15 +582,7 @@ private TaskType getTask(){ protected Class getRestartResponsePage() { return PageTasks.class; } - - @Override - public void finishProcessing(AjaxRequestTarget target, OperationResult result, boolean returningFromAsync) { - if (!isKeepDisplayingResults()) { - showResult(result); - redirectBack(); - } - } - + @Override public void continueEditing(AjaxRequestTarget target) {