diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/data/column/InlineMenuButtonColumn.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/data/column/InlineMenuButtonColumn.java index 086bc0d1f4a..86158f88a14 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/data/column/InlineMenuButtonColumn.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/data/column/InlineMenuButtonColumn.java @@ -27,6 +27,8 @@ import com.evolveum.midpoint.web.component.util.EnableBehaviour; import com.evolveum.midpoint.web.component.util.VisibleBehaviour; import com.evolveum.midpoint.web.page.admin.configuration.component.HeaderMenuAction; + +import org.apache.commons.lang.BooleanUtils; import org.apache.wicket.Component; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator; @@ -46,6 +48,7 @@ * @author honchar * @author Viliam Repan (lazyman) *

+ * */ public class InlineMenuButtonColumn extends AbstractColumn { @@ -88,6 +91,11 @@ private Component getPanel(String componentId, IModel rowModel, if (rowModel != null && menuItem.getAction() != null && menuItem.getAction() instanceof ColumnMenuAction){ ((ColumnMenuAction) menuItem.getAction()).setRowModel(rowModel); } + + if (menuItem.isCheckVisibility() && !isInlineMenuVisible(rowModel, isHeaderPanel)) { + continue; + } + filteredMenuItems.add(menuItem); } if (rowModel != null && rowModel.getObject() instanceof InlineMenuable && @@ -127,6 +135,10 @@ protected AjaxIconButton createButton(int index, String componentId, IModel m } }; } + + protected boolean isInlineMenuVisible(IModel rowModel, boolean isHeader) { + return true; + } protected boolean isButtonMenuItemEnabled(IModel rowModel){ return true; @@ -233,6 +245,7 @@ private boolean isPanelVisible(boolean isHeaderPanel){ if (!isHeaderPanel && !(item.getAction() instanceof HeaderMenuAction)){ return true; } + } return false; } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/menu/cog/InlineMenuItem.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/menu/cog/InlineMenuItem.java index bfc2c8ac610..4e97cfda3a1 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/menu/cog/InlineMenuItem.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/menu/cog/InlineMenuItem.java @@ -20,6 +20,7 @@ import org.apache.wicket.model.Model; import java.io.Serializable; +import java.util.function.Supplier; /** * TODO: update to better use with DropdownButtonPanel. Move away from depreated com.evolveum.midpoint.web.component.menu.cog. @@ -35,6 +36,8 @@ public abstract class InlineMenuItem implements Serializable { private boolean submit = false; private InlineMenuItemAction action; private int id = -1; + + private boolean checkVisibility; public InlineMenuItem(IModel label) { this.label = label; @@ -115,4 +118,13 @@ public IModel getConfirmationMessageModel() { public boolean showConfirmationDialog() { return true; } + + public boolean isCheckVisibility() { + return checkVisibility; + } + + public void setCheckVisibility(boolean checkVisibility) { + this.checkVisibility = checkVisibility; + } + } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/PageTasks.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/PageTasks.java index 6f86b8f7a0d..0a79d9fa2c8 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/PageTasks.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/PageTasks.java @@ -679,7 +679,31 @@ protected DisplayType getIconDisplayType(final IModel rowModel) { }); IColumn menuColumn = new InlineMenuButtonColumn(createTasksInlineMenu(false, null), - PageTasks.this); + PageTasks.this) { + + @Override + protected boolean isInlineMenuVisible(IModel rowModel, boolean isHeader) { + if (rowModel == null) { + return isHeader; + } + TaskDto dto = rowModel.getObject(); + if (isHeader) { + return false; + } + + if (dto == null) { + return false; + } + + TaskWorkManagementType workManagement = dto.getTaskType().getWorkManagement(); + if (workManagement == null) { + return false; + } + + return TaskKindType.COORDINATOR == workManagement.getTaskKind(); + + } + }; columns.add(menuColumn); return columns; @@ -825,116 +849,123 @@ public IModel getConfirmationMessageModel() { } }); - if (!isHeader && dto != null) { - if (dto.getTaskType().getWorkManagement() != null - && dto.getTaskType().getWorkManagement().getTaskKind() == TaskKindType.COORDINATOR) { - items.add(new InlineMenuItem(createStringResource("pageTasks.button.reconcileWorkers")) { + InlineMenuItem reconcileWorkers = new InlineMenuItem(createStringResource("pageTasks.button.reconcileWorkers")) { + private static final long serialVersionUID = 1L; + + @Override + public InlineMenuItemAction initAction() { + return new ColumnMenuAction() { private static final long serialVersionUID = 1L; @Override - public InlineMenuItemAction initAction() { - return new ColumnMenuAction() { - private static final long serialVersionUID = 1L; - - @Override - public void onClick(AjaxRequestTarget target) { - if (getRowModel() == null) { - throw new UnsupportedOperationException(); - } else { - TaskDto rowDto = getRowModel().getObject(); - reconcileWorkersConfirmedPerformed(target, rowDto); - } - } - }; + public void onClick(AjaxRequestTarget target) { + if (getRowModel() == null) { + throw new UnsupportedOperationException(); + } else { + TaskDto rowDto = getRowModel().getObject(); + reconcileWorkersConfirmedPerformed(target, rowDto); + } } + }; + } - @Override - public IModel getConfirmationMessageModel() { - String actionName = createStringResource("pageTasks.message.reconcileWorkersAction").getString(); - return PageTasks.this.getTaskConfirmationMessageModel((ColumnMenuAction) getAction(), actionName); - } - }); + @Override + public IModel getConfirmationMessageModel() { + String actionName = createStringResource("pageTasks.message.reconcileWorkersAction").getString(); + return PageTasks.this.getTaskConfirmationMessageModel((ColumnMenuAction) getAction(), actionName); + } + }; + reconcileWorkers.setCheckVisibility(true); + + items.add(reconcileWorkers); + + InlineMenuItem suspendCoordinatorOnly = new InlineMenuItem(createStringResource("pageTasks.button.suspendCoordinatorOnly")) { + private static final long serialVersionUID = 1L; - items.add(new InlineMenuItem(createStringResource("pageTasks.button.suspendCoordinatorOnly")) { + @Override + public InlineMenuItemAction initAction() { + return new ColumnMenuAction() { private static final long serialVersionUID = 1L; @Override - public InlineMenuItemAction initAction() { - return new ColumnMenuAction() { - private static final long serialVersionUID = 1L; - - @Override - public void onClick(AjaxRequestTarget target) { - if (getRowModel() == null) { - throw new UnsupportedOperationException(); - } else { - TaskDto rowDto = getRowModel().getObject(); - suspendCoordinatorOnly(target, rowDto); - } - } - }; + public void onClick(AjaxRequestTarget target) { + if (getRowModel() == null) { + throw new UnsupportedOperationException(); + } else { + TaskDto rowDto = getRowModel().getObject(); + suspendCoordinatorOnly(target, rowDto); + } } + }; + } - @Override - public IModel getConfirmationMessageModel() { - String actionName = createStringResource("pageTasks.message.suspendAction").getString(); - return PageTasks.this.getTaskConfirmationMessageModel((ColumnMenuAction) getAction(), actionName); - } - }); - items.add(new InlineMenuItem(createStringResource("pageTasks.button.resumeCoordinatorOnly")) { + @Override + public IModel getConfirmationMessageModel() { + String actionName = createStringResource("pageTasks.message.suspendAction").getString(); + return PageTasks.this.getTaskConfirmationMessageModel((ColumnMenuAction) getAction(), actionName); + } + }; + suspendCoordinatorOnly.setCheckVisibility(true); + items.add(suspendCoordinatorOnly); + + InlineMenuItem resumeCoordinatorOnly = new InlineMenuItem(createStringResource("pageTasks.button.resumeCoordinatorOnly")) { + private static final long serialVersionUID = 1L; + + @Override + public InlineMenuItemAction initAction() { + return new ColumnMenuAction() { private static final long serialVersionUID = 1L; @Override - public InlineMenuItemAction initAction() { - return new ColumnMenuAction() { - private static final long serialVersionUID = 1L; - - @Override - public void onClick(AjaxRequestTarget target) { - if (getRowModel() == null) { - throw new UnsupportedOperationException(); - } else { - TaskDto rowDto = getRowModel().getObject(); - resumeCoordinatorOnly(target, rowDto); - } - } - }; + public void onClick(AjaxRequestTarget target) { + if (getRowModel() == null) { + throw new UnsupportedOperationException(); + } else { + TaskDto rowDto = getRowModel().getObject(); + resumeCoordinatorOnly(target, rowDto); + } } + }; + } - @Override - public IModel getConfirmationMessageModel() { - String actionName = createStringResource("pageTasks.message.resumeAction").getString(); - return PageTasks.this.getTaskConfirmationMessageModel((ColumnMenuAction) getAction(), actionName); - } - }); - items.add(new InlineMenuItem(createStringResource("pageTasks.button.deleteWorkersAndWorkState")) { + @Override + public IModel getConfirmationMessageModel() { + String actionName = createStringResource("pageTasks.message.resumeAction").getString(); + return PageTasks.this.getTaskConfirmationMessageModel((ColumnMenuAction) getAction(), actionName); + } + }; + resumeCoordinatorOnly.setCheckVisibility(true); + items.add(resumeCoordinatorOnly); + + InlineMenuItem deleteWorkStateAndWorkers = new InlineMenuItem(createStringResource("pageTasks.button.deleteWorkersAndWorkState")) { + private static final long serialVersionUID = 1L; + + @Override + public InlineMenuItemAction initAction() { + return new ColumnMenuAction() { private static final long serialVersionUID = 1L; @Override - public InlineMenuItemAction initAction() { - return new ColumnMenuAction() { - private static final long serialVersionUID = 1L; - - @Override - public void onClick(AjaxRequestTarget target) { - if (getRowModel() == null) { - throw new UnsupportedOperationException(); - } else { - TaskDto rowDto = getRowModel().getObject(); - deleteWorkersAndWorkState(target, rowDto); - } - } - }; + public void onClick(AjaxRequestTarget target) { + if (getRowModel() == null) { + throw new UnsupportedOperationException(); + } else { + TaskDto rowDto = getRowModel().getObject(); + deleteWorkersAndWorkState(target, rowDto); + } } + }; + } - @Override - public IModel getConfirmationMessageModel() { - String actionName = createStringResource("pageTasks.message.deleteWorkersAndWorkState").getString(); - return PageTasks.this.getTaskConfirmationMessageModel((ColumnMenuAction) getAction(), actionName); - } - }); + @Override + public IModel getConfirmationMessageModel() { + String actionName = createStringResource("pageTasks.message.deleteWorkersAndWorkState").getString(); + return PageTasks.this.getTaskConfirmationMessageModel((ColumnMenuAction) getAction(), actionName); } - } + }; + deleteWorkStateAndWorkers.setCheckVisibility(true); + items.add(deleteWorkStateAndWorkers); + if (isHeader) { items.add(new InlineMenuItem(createStringResource("pageTasks.button.deleteAllClosedTasks")) { private static final long serialVersionUID = 1L; @@ -1330,644 +1361,671 @@ private void scheduleTasksPerformed(AjaxRequestTarget target, List oids) private void scheduleTaskPerformed(AjaxRequestTarget target, TaskDto dto) { scheduleTasksPerformed(target, Arrays.asList(dto.getOid())); - } + } - private void scheduleTasksPerformed(AjaxRequestTarget target) { - List taskDtoList = WebComponentUtil.getSelectedData(getTaskTable()); - if (!isSomeTaskSelected(taskDtoList, target)) { - return; - } + private void scheduleTasksPerformed(AjaxRequestTarget target) { + List taskDtoList = WebComponentUtil.getSelectedData(getTaskTable()); + if (!isSomeTaskSelected(taskDtoList, target)) { + return; + } - scheduleTasksPerformed(target, TaskDto.getOids(taskDtoList)); - } - //endregion + scheduleTasksPerformed(target, TaskDto.getOids(taskDtoList)); + } + // endregion - //region Node-level actions - private void nodeDetailsPerformed(AjaxRequestTarget target, String oid) { + // region Node-level actions + private void nodeDetailsPerformed(AjaxRequestTarget target, String oid) { - } + } - private void stopSchedulersAndTasksPerformed(AjaxRequestTarget target, List identifiers) { - Task opTask = createSimpleTask(OPERATION_STOP_SCHEDULERS_AND_TASKS); - OperationResult result = opTask.getResult(); - try { - boolean suspended = getTaskService().stopSchedulersAndTasks(identifiers, WAIT_FOR_TASK_STOP, opTask, result); - result.computeStatus(); - if (result.isSuccess()) { - if (suspended) { - result.recordStatus(OperationResultStatus.SUCCESS, createStringResource("pageTasks.message.stopSchedulersAndTasksPerformed.success").getString()); - } else { - result.recordWarning(createStringResource("pageTasks.message.stopSchedulersAndTasksPerformed.warning").getString()); - } - } - } catch (SecurityViolationException | ObjectNotFoundException | SchemaException | ExpressionEvaluationException | RuntimeException | CommunicationException | ConfigurationException e) { - result.recordFatalError(createStringResource("pageTasks.message.stopSchedulersAndTasksPerformed.fatalError").getString(), e); - } - showResult(result); + private void stopSchedulersAndTasksPerformed(AjaxRequestTarget target, List identifiers) { + Task opTask = createSimpleTask(OPERATION_STOP_SCHEDULERS_AND_TASKS); + OperationResult result = opTask.getResult(); + try { + boolean suspended = getTaskService().stopSchedulersAndTasks(identifiers, WAIT_FOR_TASK_STOP, opTask, result); + result.computeStatus(); + if (result.isSuccess()) { + if (suspended) { + result.recordStatus(OperationResultStatus.SUCCESS, + createStringResource("pageTasks.message.stopSchedulersAndTasksPerformed.success").getString()); + } else { + result.recordWarning( + createStringResource("pageTasks.message.stopSchedulersAndTasksPerformed.warning").getString()); + } + } + } catch (SecurityViolationException | ObjectNotFoundException | SchemaException | ExpressionEvaluationException + | RuntimeException | CommunicationException | ConfigurationException e) { + result.recordFatalError( + createStringResource("pageTasks.message.stopSchedulersAndTasksPerformed.fatalError").getString(), e); + } + showResult(result); - //refresh feedback and table - refreshTables(target); - } + // refresh feedback and table + refreshTables(target); + } - private void stopSchedulersAndTasksPerformed(AjaxRequestTarget target, NodeDto dto) { - List nodeDtoList = new ArrayList<>(); - if (dto != null){ - nodeDtoList.add(dto); - } else { - nodeDtoList.addAll(WebComponentUtil.getSelectedData(getNodeTable())); - } - if (!isSomeNodeSelected(nodeDtoList, target)) { - return; - } + private void stopSchedulersAndTasksPerformed(AjaxRequestTarget target, NodeDto dto) { + List nodeDtoList = new ArrayList<>(); + if (dto != null) { + nodeDtoList.add(dto); + } else { + nodeDtoList.addAll(WebComponentUtil.getSelectedData(getNodeTable())); + } + if (!isSomeNodeSelected(nodeDtoList, target)) { + return; + } - stopSchedulersAndTasksPerformed(target, NodeDto.getNodeIdentifiers(nodeDtoList)); - } + stopSchedulersAndTasksPerformed(target, NodeDto.getNodeIdentifiers(nodeDtoList)); + } - private void startSchedulersPerformed(AjaxRequestTarget target, List identifiers) { - Task opTask = createSimpleTask(OPERATION_START_SCHEDULERS); - OperationResult result = opTask.getResult(); - try { - getTaskService().startSchedulers(identifiers, opTask, result); - result.computeStatus(); - if (result.isSuccess()) { - result.recordStatus(OperationResultStatus.SUCCESS, createStringResource("pageTasks.message.startSchedulersPerformed.success").getString()); - } - } catch (SecurityViolationException | ObjectNotFoundException | SchemaException | ExpressionEvaluationException | RuntimeException | CommunicationException | ConfigurationException e) { - result.recordFatalError(createStringResource("pageTasks.message.startSchedulersPerformed.fatalError").getString(), e); - } + private void startSchedulersPerformed(AjaxRequestTarget target, List identifiers) { + Task opTask = createSimpleTask(OPERATION_START_SCHEDULERS); + OperationResult result = opTask.getResult(); + try { + getTaskService().startSchedulers(identifiers, opTask, result); + result.computeStatus(); + if (result.isSuccess()) { + result.recordStatus(OperationResultStatus.SUCCESS, + createStringResource("pageTasks.message.startSchedulersPerformed.success").getString()); + } + } catch (SecurityViolationException | ObjectNotFoundException | SchemaException | ExpressionEvaluationException + | RuntimeException | CommunicationException | ConfigurationException e) { + result.recordFatalError(createStringResource("pageTasks.message.startSchedulersPerformed.fatalError").getString(), e); + } - showResult(result); + showResult(result); - //refresh feedback and table - refreshTables(target); - } + // refresh feedback and table + refreshTables(target); + } - private void startSchedulersPerformed(AjaxRequestTarget target, NodeDto dto) { - startSchedulersPerformed(target, Collections.singletonList(dto.getNodeIdentifier())); - } + private void startSchedulersPerformed(AjaxRequestTarget target, NodeDto dto) { + startSchedulersPerformed(target, Collections.singletonList(dto.getNodeIdentifier())); + } - private void startSchedulersPerformed(AjaxRequestTarget target) { - List nodeDtoList = WebComponentUtil.getSelectedData(getNodeTable()); - if (!isSomeNodeSelected(nodeDtoList, target)) { - return; - } + private void startSchedulersPerformed(AjaxRequestTarget target) { + List nodeDtoList = WebComponentUtil.getSelectedData(getNodeTable()); + if (!isSomeNodeSelected(nodeDtoList, target)) { + return; + } - startSchedulersPerformed(target, NodeDto.getNodeIdentifiers(nodeDtoList)); - } + startSchedulersPerformed(target, NodeDto.getNodeIdentifiers(nodeDtoList)); + } - private void stopSchedulersPerformed(AjaxRequestTarget target, List identifiers) { - Task opTask = createSimpleTask(OPERATION_STOP_SCHEDULERS); - OperationResult result = opTask.getResult(); - try { - getTaskService().stopSchedulers(identifiers, opTask, result); - result.computeStatus(); - if (result.isSuccess()) { - result.recordStatus(OperationResultStatus.SUCCESS, createStringResource("pageTasks.message.stopSchedulersPerformed.success").getString()); - } - } catch (SecurityViolationException | ObjectNotFoundException | SchemaException | ExpressionEvaluationException | RuntimeException | CommunicationException | ConfigurationException e) { - result.recordFatalError(createStringResource("pageTasks.message.stopSchedulersPerformed.fatalError").getString(), e); - } - showResult(result); + private void stopSchedulersPerformed(AjaxRequestTarget target, List identifiers) { + Task opTask = createSimpleTask(OPERATION_STOP_SCHEDULERS); + OperationResult result = opTask.getResult(); + try { + getTaskService().stopSchedulers(identifiers, opTask, result); + result.computeStatus(); + if (result.isSuccess()) { + result.recordStatus(OperationResultStatus.SUCCESS, + createStringResource("pageTasks.message.stopSchedulersPerformed.success").getString()); + } + } catch (SecurityViolationException | ObjectNotFoundException | SchemaException | ExpressionEvaluationException + | RuntimeException | CommunicationException | ConfigurationException e) { + result.recordFatalError(createStringResource("pageTasks.message.stopSchedulersPerformed.fatalError").getString(), e); + } + showResult(result); - //refresh feedback and table - refreshTables(target); - } + // refresh feedback and table + refreshTables(target); + } - private void stopSchedulersPerformed(AjaxRequestTarget target, NodeDto dto) { - stopSchedulersPerformed(target, Collections.singletonList(dto.getNodeIdentifier())); - } + private void stopSchedulersPerformed(AjaxRequestTarget target, NodeDto dto) { + stopSchedulersPerformed(target, Collections.singletonList(dto.getNodeIdentifier())); + } - private void stopSchedulersPerformed(AjaxRequestTarget target) { - List nodeDtoList = WebComponentUtil.getSelectedData(getNodeTable()); - if (!isSomeNodeSelected(nodeDtoList, target)) { - return; - } + private void stopSchedulersPerformed(AjaxRequestTarget target) { + List nodeDtoList = WebComponentUtil.getSelectedData(getNodeTable()); + if (!isSomeNodeSelected(nodeDtoList, target)) { + return; + } - stopSchedulersPerformed(target, NodeDto.getNodeIdentifiers(nodeDtoList)); - } + stopSchedulersPerformed(target, NodeDto.getNodeIdentifiers(nodeDtoList)); + } - private void deleteNodesPerformed(AjaxRequestTarget target, List nodes) { - OperationResult result = new OperationResult(OPERATION_DELETE_NODES); + private void deleteNodesPerformed(AjaxRequestTarget target, List nodes) { + OperationResult result = new OperationResult(OPERATION_DELETE_NODES); - Task task = createSimpleTask(OPERATION_DELETE_NODES); + Task task = createSimpleTask(OPERATION_DELETE_NODES); - for (NodeDto nodeDto : nodes) { - Collection> deltas = new ArrayList<>(); - deltas.add(getPrismContext().deltaFactory().object().createDeleteDelta(NodeType.class, nodeDto.getOid() - )); - try { - getModelService().executeChanges(deltas, null, task, result); - } catch (Exception e) { // until java 7 we do it in this way - result.recordFatalError(createStringResource("pageTasks.message.deleteNodesPerformed.fatalError").getString() + nodeDto.getNodeIdentifier(), e); - } - } + for (NodeDto nodeDto : nodes) { + Collection> deltas = new ArrayList<>(); + deltas.add(getPrismContext().deltaFactory().object().createDeleteDelta(NodeType.class, nodeDto.getOid())); + try { + getModelService().executeChanges(deltas, null, task, result); + } catch (Exception e) { // until java 7 we do it in this way + result.recordFatalError(createStringResource("pageTasks.message.deleteNodesPerformed.fatalError").getString() + + nodeDto.getNodeIdentifier(), e); + } + } - result.computeStatus(); - if (result.isSuccess()) { - result.recordStatus(OperationResultStatus.SUCCESS, createStringResource("pageTasks.message.deleteNodesPerformed.success").getString()); - } - showResult(result); + result.computeStatus(); + if (result.isSuccess()) { + result.recordStatus(OperationResultStatus.SUCCESS, + createStringResource("pageTasks.message.deleteNodesPerformed.success").getString()); + } + showResult(result); - NodeDtoProvider provider = (NodeDtoProvider) getNodeTable().getDataTable().getDataProvider(); - provider.clearCache(); + NodeDtoProvider provider = (NodeDtoProvider) getNodeTable().getDataTable().getDataProvider(); + provider.clearCache(); - //refresh feedback and table - refreshTables(target); - } + // refresh feedback and table + refreshTables(target); + } - private void deleteNodesPerformed(AjaxRequestTarget target, NodeDto dto) { - deleteNodesPerformed(target, Collections.singletonList(dto)); - } + private void deleteNodesPerformed(AjaxRequestTarget target, NodeDto dto) { + deleteNodesPerformed(target, Collections.singletonList(dto)); + } - private void deleteNodesPerformed(AjaxRequestTarget target) { - List nodeDtoList = WebComponentUtil.getSelectedData(getNodeTable()); - if (!isSomeNodeSelected(nodeDtoList, target)) { - return; - } + private void deleteNodesPerformed(AjaxRequestTarget target) { + List nodeDtoList = WebComponentUtil.getSelectedData(getNodeTable()); + if (!isSomeNodeSelected(nodeDtoList, target)) { + return; + } - deleteNodesPerformed(target, nodeDtoList); - } - //endregion + deleteNodesPerformed(target, nodeDtoList); + } + // endregion - //region Diagnostics actions - private void deactivateServiceThreadsPerformed(AjaxRequestTarget target) { - Task opTask = createSimpleTask(OPERATION_DEACTIVATE_SERVICE_THREADS); - OperationResult result = opTask.getResult(); + // region Diagnostics actions + private void deactivateServiceThreadsPerformed(AjaxRequestTarget target) { + Task opTask = createSimpleTask(OPERATION_DEACTIVATE_SERVICE_THREADS); + OperationResult result = opTask.getResult(); - try { - boolean stopped = getTaskService().deactivateServiceThreads(WAIT_FOR_TASK_STOP, opTask, result); - result.computeStatus(); - if (result.isSuccess()) { - if (stopped) { - result.recordStatus(OperationResultStatus.SUCCESS, createStringResource("pageTasks.message.deactivateServiceThreadsPerformed.success").getString()); - } else { - result.recordWarning(createStringResource("pageTasks.message.deactivateServiceThreadsPerformed.warning").getString()); - } - } - } catch (RuntimeException | SchemaException | SecurityViolationException | ExpressionEvaluationException | ObjectNotFoundException | CommunicationException | ConfigurationException e) { - result.recordFatalError(createStringResource("pageTasks.message.deactivateServiceThreadsPerformed.fatalError").getString(), e); - } - showResult(result); + try { + boolean stopped = getTaskService().deactivateServiceThreads(WAIT_FOR_TASK_STOP, opTask, result); + result.computeStatus(); + if (result.isSuccess()) { + if (stopped) { + result.recordStatus(OperationResultStatus.SUCCESS, + createStringResource("pageTasks.message.deactivateServiceThreadsPerformed.success").getString()); + } else { + result.recordWarning( + createStringResource("pageTasks.message.deactivateServiceThreadsPerformed.warning").getString()); + } + } + } catch (RuntimeException | SchemaException | SecurityViolationException | ExpressionEvaluationException + | ObjectNotFoundException | CommunicationException | ConfigurationException e) { + result.recordFatalError( + createStringResource("pageTasks.message.deactivateServiceThreadsPerformed.fatalError").getString(), e); + } + showResult(result); - //refresh feedback and table - refreshTables(target); - } + // refresh feedback and table + refreshTables(target); + } - private void reactivateServiceThreadsPerformed(AjaxRequestTarget target) { - Task opTask = createSimpleTask(OPERATION_REACTIVATE_SERVICE_THREADS); - OperationResult result = opTask.getResult(); + private void reactivateServiceThreadsPerformed(AjaxRequestTarget target) { + Task opTask = createSimpleTask(OPERATION_REACTIVATE_SERVICE_THREADS); + OperationResult result = opTask.getResult(); - try { - getTaskService().reactivateServiceThreads(opTask, result); - result.computeStatus(); - if (result.isSuccess()) { - result.recordStatus(OperationResultStatus.SUCCESS, createStringResource("pageTasks.message.reactivateServiceThreadsPerformed.success").getString()); - } - } catch (RuntimeException | SchemaException | SecurityViolationException | ExpressionEvaluationException | ObjectNotFoundException | CommunicationException | ConfigurationException e) { - result.recordFatalError(createStringResource("pageTasks.message.reactivateServiceThreadsPerformed.fatalError").getString(), e); - } - showResult(result); + try { + getTaskService().reactivateServiceThreads(opTask, result); + result.computeStatus(); + if (result.isSuccess()) { + result.recordStatus(OperationResultStatus.SUCCESS, + createStringResource("pageTasks.message.reactivateServiceThreadsPerformed.success").getString()); + } + } catch (RuntimeException | SchemaException | SecurityViolationException | ExpressionEvaluationException + | ObjectNotFoundException | CommunicationException | ConfigurationException e) { + result.recordFatalError( + createStringResource("pageTasks.message.reactivateServiceThreadsPerformed.fatalError").getString(), e); + } + showResult(result); - //refresh feedback and table - refreshTables(target); - } + // refresh feedback and table + refreshTables(target); + } - private void refreshTables(AjaxRequestTarget target) { - clearTablesCache(); - target.add(getFeedbackPanel()); - target.add((Component) getTaskTable()); - target.add((Component) getNodeTable()); - } + private void refreshTables(AjaxRequestTarget target) { + clearTablesCache(); + target.add(getFeedbackPanel()); + target.add((Component) getTaskTable()); + target.add((Component) getNodeTable()); + } - private void clearTablesCache(){ - if (getTaskTable() != null && getTaskTable().getDataTable() != null){ - WebComponentUtil.clearProviderCache(getTaskTable().getDataTable().getDataProvider()); - } - if (getNodeTable() != null && getNodeTable().getDataTable() != null){ - WebComponentUtil.clearProviderCache(getNodeTable().getDataTable().getDataProvider()); - } - } + private void clearTablesCache() { + if (getTaskTable() != null && getTaskTable().getDataTable() != null) { + WebComponentUtil.clearProviderCache(getTaskTable().getDataTable().getDataProvider()); + } + if (getNodeTable() != null && getNodeTable().getDataTable() != null) { + WebComponentUtil.clearProviderCache(getNodeTable().getDataTable().getDataProvider()); + } + } - private void synchronizeTasksPerformed(AjaxRequestTarget target) { - Task opTask = createSimpleTask(OPERATION_SYNCHRONIZE_TASKS); - OperationResult result = opTask.getResult(); + private void synchronizeTasksPerformed(AjaxRequestTarget target) { + Task opTask = createSimpleTask(OPERATION_SYNCHRONIZE_TASKS); + OperationResult result = opTask.getResult(); - try { - getTaskService().synchronizeTasks(opTask, result); - result.computeStatus(); - if (result.isSuccess()) { // brutal hack - the subresult's message contains statistics - result.recordStatus(OperationResultStatus.SUCCESS, result.getLastSubresult().getMessage()); - } - } catch (RuntimeException | SchemaException | SecurityViolationException | ExpressionEvaluationException | ObjectNotFoundException | CommunicationException | ConfigurationException e) { - result.recordFatalError(createStringResource("pageTasks.message.synchronizeTasksPerformed.fatalError").getString(), e); - } - showResult(result); + try { + getTaskService().synchronizeTasks(opTask, result); + result.computeStatus(); + if (result.isSuccess()) { // brutal hack - the subresult's message + // contains statistics + result.recordStatus(OperationResultStatus.SUCCESS, result.getLastSubresult().getMessage()); + } + } catch (RuntimeException | SchemaException | SecurityViolationException | ExpressionEvaluationException + | ObjectNotFoundException | CommunicationException | ConfigurationException e) { + result.recordFatalError(createStringResource("pageTasks.message.synchronizeTasksPerformed.fatalError").getString(), + e); + } + showResult(result); - //refresh feedback and table - refreshTables(target); - } + // refresh feedback and table + refreshTables(target); + } private void synchronizeWorkflowRequestsPerformed(AjaxRequestTarget target) { Task opTask = createSimpleTask(OPERATION_SYNCHRONIZE_WORKFLOW_REQUESTS); - OperationResult result = opTask.getResult(); + OperationResult result = opTask.getResult(); try { getTaskService().synchronizeWorkflowRequests(opTask, result); result.computeStatusIfUnknown(); - if (result.isSuccess()) { // brutal hack - the subresult's message contains statistics + if (result.isSuccess()) { // brutal hack - the subresult's message + // contains statistics result.recordStatus(OperationResultStatus.SUCCESS, result.getLastSubresult().getMessage()); } - } catch (RuntimeException | SchemaException | SecurityViolationException | ExpressionEvaluationException | ObjectNotFoundException | CommunicationException | ConfigurationException e) { - result.recordFatalError(createStringResource("pageTasks.message.synchronizeTasksPerformed.fatalError").getString(), e); + } catch (RuntimeException | SchemaException | SecurityViolationException | ExpressionEvaluationException + | ObjectNotFoundException | CommunicationException | ConfigurationException e) { + result.recordFatalError(createStringResource("pageTasks.message.synchronizeTasksPerformed.fatalError").getString(), + e); } showResult(result); - //refresh feedback and table + // refresh feedback and table refreshTables(target); } - //endregion + // endregion - private void refreshTasks(AjaxRequestTarget target) { -// searchModel = new LoadableModel(false) { -// -// @Override -// protected TasksSearchDto load() { -// return loadTasksSearchDto(); -// } -// }; + private void refreshTasks(AjaxRequestTarget target) { + // searchModel = new LoadableModel(false) { + // + // @Override + // protected TasksSearchDto load() { + // return loadTasksSearchDto(); + // } + // }; target.add(refreshPanel); - //refresh feedback and table - refreshTables(target); + // refresh feedback and table + refreshTables(target); if (refreshModel.getObject().isEnabled()) { refreshPanel.startRefreshing(this, target); } - } + } - private void searchFilterPerformed(AjaxRequestTarget target) { - TasksSearchDto dto = searchModel.getObject(); + private void searchFilterPerformed(AjaxRequestTarget target) { + TasksSearchDto dto = searchModel.getObject(); -// ObjectQuery query = createTaskQuery(dto.getStatus(), dto.getCategory(), dto.isShowSubtasks()); - ObjectQuery query = createTaskQuery(); + // ObjectQuery query = createTaskQuery(dto.getStatus(), + // dto.getCategory(), dto.isShowSubtasks()); + ObjectQuery query = createTaskQuery(); - Table panel = getTaskTable(); - DataTable table = panel.getDataTable(); - TaskDtoProvider provider = (TaskDtoProvider) table.getDataProvider(); - provider.setQuery(query); - table.setCurrentPage(0); + Table panel = getTaskTable(); + DataTable table = panel.getDataTable(); + TaskDtoProvider provider = (TaskDtoProvider) table.getDataProvider(); + provider.setQuery(query); + table.setCurrentPage(0); - TasksStorage storage = getSessionStorage().getTasks(); - storage.setTasksSearch(dto); + TasksStorage storage = getSessionStorage().getTasks(); + storage.setTasksSearch(dto); - target.add(getFeedbackPanel()); - target.add((Component) getTaskTable()); - } + target.add(getFeedbackPanel()); + target.add((Component) getTaskTable()); + } - private ObjectQuery createTaskQuery() { - TasksSearchDto dto = searchModel.getObject(); - TaskDtoExecutionStatusFilter status = dto.getStatus(); - String category = dto.getCategory(); - boolean showSubtasks = dto.isShowSubtasks(); + private ObjectQuery createTaskQuery() { + TasksSearchDto dto = searchModel.getObject(); + TaskDtoExecutionStatusFilter status = dto.getStatus(); + String category = dto.getCategory(); + boolean showSubtasks = dto.isShowSubtasks(); - S_AtomicFilterEntry q = getPrismContext().queryFor(TaskType.class); - if (status != null) { - q = status.appendFilter(q); - } - if (category != null && !ALL_CATEGORIES.equals(category)) { - q = q.item(TaskType.F_CATEGORY).eq(category).and(); - } - if (StringUtils.isNotBlank(searchText)) { - PolyStringNormalizer normalizer = getPrismContext().getDefaultPolyStringNormalizer(); - String normalizedString = normalizer.normalize(searchText); - q = q.item(TaskType.F_NAME).containsPoly(normalizedString, normalizedString).matchingNorm().and(); - searchText = ""; // ??? - } - if (!Boolean.TRUE.equals(showSubtasks)) { - q = q.item(TaskType.F_PARENT).isNull().and(); - } - return q.all().build(); - } + S_AtomicFilterEntry q = getPrismContext().queryFor(TaskType.class); + if (status != null) { + q = status.appendFilter(q); + } + if (category != null && !ALL_CATEGORIES.equals(category)) { + q = q.item(TaskType.F_CATEGORY).eq(category).and(); + } + if (StringUtils.isNotBlank(searchText)) { + PolyStringNormalizer normalizer = getPrismContext().getDefaultPolyStringNormalizer(); + String normalizedString = normalizer.normalize(searchText); + q = q.item(TaskType.F_NAME).containsPoly(normalizedString, normalizedString).matchingNorm().and(); + searchText = ""; // ??? + } + if (!Boolean.TRUE.equals(showSubtasks)) { + q = q.item(TaskType.F_PARENT).isNull().and(); + } + return q.all().build(); + } - private void clearSearchPerformed(AjaxRequestTarget target) { - TasksSearchDto tasksSearchDto = new TasksSearchDto(); - tasksSearchDto.setCategory(ALL_CATEGORIES); - tasksSearchDto.setStatus(TaskDtoExecutionStatusFilter.ALL); - searchModel.setObject(tasksSearchDto); + private void clearSearchPerformed(AjaxRequestTarget target) { + TasksSearchDto tasksSearchDto = new TasksSearchDto(); + tasksSearchDto.setCategory(ALL_CATEGORIES); + tasksSearchDto.setStatus(TaskDtoExecutionStatusFilter.ALL); + searchModel.setObject(tasksSearchDto); - Table panel = getTaskTable(); - DataTable table = panel.getDataTable(); - TaskDtoProvider provider = (TaskDtoProvider) table.getDataProvider(); - provider.setQuery(null); + Table panel = getTaskTable(); + DataTable table = panel.getDataTable(); + TaskDtoProvider provider = (TaskDtoProvider) table.getDataProvider(); + provider.setQuery(null); - TasksStorage storage = getSessionStorage().getTasks(); - storage.setTasksSearch(searchModel.getObject()); - panel.setCurrentPage(storage.getPaging()); + TasksStorage storage = getSessionStorage().getTasks(); + storage.setTasksSearch(searchModel.getObject()); + panel.setCurrentPage(storage.getPaging()); - target.add((Component) panel); - } + target.add((Component) panel); + } - private void deleteTaskConfirmedPerformed(AjaxRequestTarget target, TaskDto task) { - List taskDtoList = new ArrayList<>(); - if (task != null){ - taskDtoList.add(task); - } else { - taskDtoList.addAll(WebComponentUtil.getSelectedData(getTaskTable())); - } - if (!isSomeTaskSelected(taskDtoList, target)) { - return; - } + private void deleteTaskConfirmedPerformed(AjaxRequestTarget target, TaskDto task) { + List taskDtoList = new ArrayList<>(); + if (task != null) { + taskDtoList.add(task); + } else { + taskDtoList.addAll(WebComponentUtil.getSelectedData(getTaskTable())); + } + if (!isSomeTaskSelected(taskDtoList, target)) { + return; + } - Task opTask = createSimpleTask(OPERATION_DELETE_TASKS); - OperationResult result = opTask.getResult(); - try { - getTaskService().suspendAndDeleteTasks(TaskDto.getOids(taskDtoList), WAIT_FOR_TASK_STOP, true, opTask, result); - result.computeStatus(); - if (result.isSuccess()) { - result.recordStatus(OperationResultStatus.SUCCESS, createStringResource("pageTasks.message.deleteTaskConfirmedPerformed.success").getString()); - } - } catch (ObjectNotFoundException | SchemaException | SecurityViolationException | ExpressionEvaluationException | RuntimeException | CommunicationException | ConfigurationException e) { - result.recordFatalError(createStringResource("pageTasks.message.deleteTaskConfirmedPerformed.fatalError").getString(), e); - } - showResult(result); + Task opTask = createSimpleTask(OPERATION_DELETE_TASKS); + OperationResult result = opTask.getResult(); + try { + getTaskService().suspendAndDeleteTasks(TaskDto.getOids(taskDtoList), WAIT_FOR_TASK_STOP, true, opTask, result); + result.computeStatus(); + if (result.isSuccess()) { + result.recordStatus(OperationResultStatus.SUCCESS, + createStringResource("pageTasks.message.deleteTaskConfirmedPerformed.success").getString()); + } + } catch (ObjectNotFoundException | SchemaException | SecurityViolationException | ExpressionEvaluationException + | RuntimeException | CommunicationException | ConfigurationException e) { + result.recordFatalError(createStringResource("pageTasks.message.deleteTaskConfirmedPerformed.fatalError").getString(), + e); + } + showResult(result); - TaskDtoProvider provider = (TaskDtoProvider) getTaskTable().getDataTable().getDataProvider(); - provider.clearCache(); + TaskDtoProvider provider = (TaskDtoProvider) getTaskTable().getDataTable().getDataProvider(); + provider.clearCache(); - //refresh feedback and table - refreshTables(target); - } + // refresh feedback and table + refreshTables(target); + } - private void reconcileWorkersConfirmedPerformed(AjaxRequestTarget target, @NotNull TaskDto task) { - Task opTask = createSimpleTask(OPERATION_RECONCILE_WORKERS); - OperationResult result = opTask.getResult(); - try { - getTaskService().reconcileWorkers(task.getOid(), opTask, result); - result.computeStatus(); - if (result.isSuccess() && result.getSubresults().size() == 1) { // brutal hack: to show statistics - result.setMessage(result.getSubresults().get(0).getMessage()); - } - } catch (ObjectAlreadyExistsException | ObjectNotFoundException | SchemaException | SecurityViolationException | ExpressionEvaluationException | RuntimeException | CommunicationException | ConfigurationException e) { - result.recordFatalError(createStringResource("pageTasks.message.reconcileWorkersConfirmedPerformed.fatalError").getString(), e); - } - showResult(result); + private void reconcileWorkersConfirmedPerformed(AjaxRequestTarget target, @NotNull TaskDto task) { + Task opTask = createSimpleTask(OPERATION_RECONCILE_WORKERS); + OperationResult result = opTask.getResult(); + try { + getTaskService().reconcileWorkers(task.getOid(), opTask, result); + result.computeStatus(); + if (result.isSuccess() && result.getSubresults().size() == 1) { // brutal + // hack: + // to + // show + // statistics + result.setMessage(result.getSubresults().get(0).getMessage()); + } + } catch (ObjectAlreadyExistsException | ObjectNotFoundException | SchemaException | SecurityViolationException + | ExpressionEvaluationException | RuntimeException | CommunicationException | ConfigurationException e) { + result.recordFatalError( + createStringResource("pageTasks.message.reconcileWorkersConfirmedPerformed.fatalError").getString(), e); + } + showResult(result); - TaskDtoProvider provider = (TaskDtoProvider) getTaskTable().getDataTable().getDataProvider(); - provider.clearCache(); + TaskDtoProvider provider = (TaskDtoProvider) getTaskTable().getDataTable().getDataProvider(); + provider.clearCache(); - //refresh feedback and table - refreshTables(target); - } + // refresh feedback and table + refreshTables(target); + } - private void suspendCoordinatorOnly(AjaxRequestTarget target, @NotNull TaskDto task) { - Task opTask = createSimpleTask(OPERATION_SUSPEND_TASK); - OperationResult result = opTask.getResult(); - try { - getTaskService().suspendTasks(Collections.singleton(task.getOid()), WAIT_FOR_TASK_STOP, opTask, result); - // TODO check whether the suspension was complete - result.computeStatus(); - } catch (ObjectNotFoundException | SchemaException | SecurityViolationException | ExpressionEvaluationException | RuntimeException | CommunicationException | ConfigurationException e) { - result.recordFatalError(createStringResource("pageTasks.message.suspendCoordinatorOnly.fatalError").getString(), e); - } - showResult(result); + private void suspendCoordinatorOnly(AjaxRequestTarget target, @NotNull TaskDto task) { + Task opTask = createSimpleTask(OPERATION_SUSPEND_TASK); + OperationResult result = opTask.getResult(); + try { + getTaskService().suspendTasks(Collections.singleton(task.getOid()), WAIT_FOR_TASK_STOP, opTask, result); + // TODO check whether the suspension was complete + result.computeStatus(); + } catch (ObjectNotFoundException | SchemaException | SecurityViolationException | ExpressionEvaluationException + | RuntimeException | CommunicationException | ConfigurationException e) { + result.recordFatalError(createStringResource("pageTasks.message.suspendCoordinatorOnly.fatalError").getString(), e); + } + showResult(result); - TaskDtoProvider provider = (TaskDtoProvider) getTaskTable().getDataTable().getDataProvider(); - provider.clearCache(); - refreshTables(target); - } + TaskDtoProvider provider = (TaskDtoProvider) getTaskTable().getDataTable().getDataProvider(); + provider.clearCache(); + refreshTables(target); + } - private void resumeCoordinatorOnly(AjaxRequestTarget target, @NotNull TaskDto task) { - Task opTask = createSimpleTask(OPERATION_RESUME_TASK); - OperationResult result = opTask.getResult(); - try { - getTaskService().resumeTasks(Collections.singleton(task.getOid()), opTask, result); - result.computeStatus(); - } catch (ObjectNotFoundException | SchemaException | SecurityViolationException | ExpressionEvaluationException | RuntimeException | CommunicationException | ConfigurationException e) { - result.recordFatalError(createStringResource("pageTasks.message.resumeCoordinatorOnly.fatalError").getString(), e); - } - showResult(result); + private void resumeCoordinatorOnly(AjaxRequestTarget target, @NotNull TaskDto task) { + Task opTask = createSimpleTask(OPERATION_RESUME_TASK); + OperationResult result = opTask.getResult(); + try { + getTaskService().resumeTasks(Collections.singleton(task.getOid()), opTask, result); + result.computeStatus(); + } catch (ObjectNotFoundException | SchemaException | SecurityViolationException | ExpressionEvaluationException + | RuntimeException | CommunicationException | ConfigurationException e) { + result.recordFatalError(createStringResource("pageTasks.message.resumeCoordinatorOnly.fatalError").getString(), e); + } + showResult(result); - TaskDtoProvider provider = (TaskDtoProvider) getTaskTable().getDataTable().getDataProvider(); - provider.clearCache(); - refreshTables(target); - } + TaskDtoProvider provider = (TaskDtoProvider) getTaskTable().getDataTable().getDataProvider(); + provider.clearCache(); + refreshTables(target); + } - private void deleteWorkersAndWorkState(AjaxRequestTarget target, @NotNull TaskDto task) { - Task opTask = createSimpleTask(OPERATION_DELETE_WORKERS_AND_WORK_STATE); - OperationResult result = opTask.getResult(); - try { - getTaskService().deleteWorkersAndWorkState(task.getOid(), WAIT_FOR_TASK_STOP, opTask, result); - result.computeStatus(); - } catch (ObjectNotFoundException | SchemaException | SecurityViolationException | ExpressionEvaluationException | RuntimeException | CommunicationException | ConfigurationException e) { - result.recordFatalError(createStringResource("pageTasks.message.deleteWorkersAndWorkState.fatalError").getString(), e); - } - showResult(result); + private void deleteWorkersAndWorkState(AjaxRequestTarget target, @NotNull TaskDto task) { + Task opTask = createSimpleTask(OPERATION_DELETE_WORKERS_AND_WORK_STATE); + OperationResult result = opTask.getResult(); + try { + getTaskService().deleteWorkersAndWorkState(task.getOid(), WAIT_FOR_TASK_STOP, opTask, result); + result.computeStatus(); + } catch (ObjectNotFoundException | SchemaException | SecurityViolationException | ExpressionEvaluationException + | RuntimeException | CommunicationException | ConfigurationException e) { + result.recordFatalError(createStringResource("pageTasks.message.deleteWorkersAndWorkState.fatalError").getString(), + e); + } + showResult(result); - TaskDtoProvider provider = (TaskDtoProvider) getTaskTable().getDataTable().getDataProvider(); - provider.clearCache(); - refreshTables(target); - } + TaskDtoProvider provider = (TaskDtoProvider) getTaskTable().getDataTable().getDataProvider(); + provider.clearCache(); + refreshTables(target); + } - private static class SearchFragment extends Fragment { + private static class SearchFragment extends Fragment { - public SearchFragment(String id, String markupId, MarkupContainer markupProvider, - IModel model) { - super(id, markupId, markupProvider, model); + public SearchFragment(String id, String markupId, MarkupContainer markupProvider, IModel model) { + super(id, markupId, markupProvider, model); - initLayout(); - } + initLayout(); + } - private void initLayout() { - final Form searchForm = new com.evolveum.midpoint.web.component.form.Form(ID_SEARCH_FORM); - add(searchForm); - searchForm.setOutputMarkupId(true); - - final IModel searchModel = (IModel) getDefaultModel(); - - DropDownChoice listSelect = new DropDownChoice<>(ID_STATE, - new PropertyModel<>(searchModel, TasksSearchDto.F_STATUS), - new ReadOnlyEnumValuesModel<>(TaskDtoExecutionStatusFilter.class), - new EnumChoiceRenderer<>(this)); - listSelect.add(createFilterAjaxBehaviour()); - listSelect.setOutputMarkupId(true); - listSelect.setNullValid(false); - if (listSelect.getModel().getObject() == null) { - listSelect.getModel().setObject(TaskDtoExecutionStatusFilter.ALL); - } - searchForm.add(listSelect); - - DropDownChoice categorySelect = new DropDownChoice(ID_CATEGORY, - new PropertyModel(searchModel, TasksSearchDto.F_CATEGORY), - new IModel>() { - - @Override - public List getObject() { - return createCategoryList(); - } - }, - new StringChoiceRenderer.Prefixed("pageTasks.category.") { - - @Override - public String getDisplayValue(String object) { - if (ALL_CATEGORIES.equals(object)) { - object = "AllCategories"; - } - return getPage().getString("pageTasks.category." + object); - } - - } - ); - categorySelect.setOutputMarkupId(true); - categorySelect.setNullValid(false); - categorySelect.add(createFilterAjaxBehaviour()); - if (categorySelect.getModel().getObject() == null) { - categorySelect.getModel().setObject(ALL_CATEGORIES); - } - searchForm.add(categorySelect); - - CheckBox showSubtasks = new CheckBox(ID_SHOW_SUBTASKS, - new PropertyModel(searchModel, TasksSearchDto.F_SHOW_SUBTASKS)); - showSubtasks.add(createFilterAjaxBehaviour()); - searchForm.add(showSubtasks); - - AjaxSubmitButton clearButton = new AjaxSubmitButton(ID_SEARCH_CLEAR) { - - @Override - protected void onSubmit(AjaxRequestTarget target) { - PageTasks page = (PageTasks) getPage(); - page.clearSearchPerformed(target); - } - - @Override - protected void onError(AjaxRequestTarget target) { - PageTasks page = (PageTasks) getPage(); - target.add(page.getFeedbackPanel()); - } - }; - searchForm.add(clearButton); - } + private void initLayout() { + final Form searchForm = new com.evolveum.midpoint.web.component.form.Form(ID_SEARCH_FORM); + add(searchForm); + searchForm.setOutputMarkupId(true); - private AjaxFormComponentUpdatingBehavior createFilterAjaxBehaviour() { - return new AjaxFormComponentUpdatingBehavior("change") { + final IModel searchModel = (IModel) getDefaultModel(); - @Override - protected void onUpdate(AjaxRequestTarget target) { - PageTasks page = (PageTasks) getPage(); - page.searchFilterPerformed(target); - } - }; - } + DropDownChoice listSelect = new DropDownChoice<>(ID_STATE, new PropertyModel<>(searchModel, TasksSearchDto.F_STATUS), + new ReadOnlyEnumValuesModel<>(TaskDtoExecutionStatusFilter.class), new EnumChoiceRenderer<>(this)); + listSelect.add(createFilterAjaxBehaviour()); + listSelect.setOutputMarkupId(true); + listSelect.setNullValid(false); + if (listSelect.getModel().getObject() == null) { + listSelect.getModel().setObject(TaskDtoExecutionStatusFilter.ALL); + } + searchForm.add(listSelect); - private List createCategoryList() { - List categories = new ArrayList<>(); - categories.add(ALL_CATEGORIES); + DropDownChoice categorySelect = new DropDownChoice(ID_CATEGORY, + new PropertyModel(searchModel, TasksSearchDto.F_CATEGORY), new IModel>() { - PageTasks page = (PageTasks) getPage(); - List list = page.getTaskService().getAllTaskCategories(); - if (list != null) { - categories.addAll(list); - Collections.sort(categories); - } + @Override + public List getObject() { + return createCategoryList(); + } + }, new StringChoiceRenderer.Prefixed("pageTasks.category.") { - return categories; - } - } + @Override + public String getDisplayValue(String object) { + if (ALL_CATEGORIES.equals(object)) { + object = "AllCategories"; + } + return getPage().getString("pageTasks.category." + object); + } - private void deleteAllClosedTasksConfirmedPerformed(AjaxRequestTarget target) { - OperationResult launchResult = new OperationResult(OPERATION_DELETE_ALL_CLOSED_TASKS); - Task task = createSimpleTask(OPERATION_DELETE_ALL_CLOSED_TASKS); + }); + categorySelect.setOutputMarkupId(true); + categorySelect.setNullValid(false); + categorySelect.add(createFilterAjaxBehaviour()); + if (categorySelect.getModel().getObject() == null) { + categorySelect.getModel().setObject(ALL_CATEGORIES); + } + searchForm.add(categorySelect); - task.setHandlerUri(ModelPublicConstants.CLEANUP_TASK_HANDLER_URI); - task.setName("Closed tasks cleanup"); + CheckBox showSubtasks = new CheckBox(ID_SHOW_SUBTASKS, + new PropertyModel(searchModel, TasksSearchDto.F_SHOW_SUBTASKS)); + showSubtasks.add(createFilterAjaxBehaviour()); + searchForm.add(showSubtasks); - try { - CleanupPolicyType policy = new CleanupPolicyType(); - policy.setMaxAge(XmlTypeConverter.createDuration(0)); - - CleanupPoliciesType policies = new CleanupPoliciesType(getPrismContext()); - policies.setClosedTasks(policy); - task.setExtensionContainerValue(SchemaConstants.MODEL_EXTENSION_CLEANUP_POLICIES, policies); - } catch (SchemaException e) { - LOGGER.error("Error dealing with schema (task {})", task, e); - launchResult.recordFatalError(createStringResource("pageTasks.message.deleteAllClosedTasksConfirmedPerformed.fatalError").getString(), e); - throw new IllegalStateException("Error dealing with schema", e); - } + AjaxSubmitButton clearButton = new AjaxSubmitButton(ID_SEARCH_CLEAR) { + + @Override + protected void onSubmit(AjaxRequestTarget target) { + PageTasks page = (PageTasks) getPage(); + page.clearSearchPerformed(target); + } + + @Override + protected void onError(AjaxRequestTarget target) { + PageTasks page = (PageTasks) getPage(); + target.add(page.getFeedbackPanel()); + } + }; + searchForm.add(clearButton); + } - getTaskManager().switchToBackground(task, launchResult); + private AjaxFormComponentUpdatingBehavior createFilterAjaxBehaviour() { + return new AjaxFormComponentUpdatingBehavior("change") { + + @Override + protected void onUpdate(AjaxRequestTarget target) { + PageTasks page = (PageTasks) getPage(); + page.searchFilterPerformed(target); + } + }; + } + + private List createCategoryList() { + List categories = new ArrayList<>(); + categories.add(ALL_CATEGORIES); + + PageTasks page = (PageTasks) getPage(); + List list = page.getTaskService().getAllTaskCategories(); + if (list != null) { + categories.addAll(list); + Collections.sort(categories); + } + + return categories; + } + } + + private void deleteAllClosedTasksConfirmedPerformed(AjaxRequestTarget target) { + OperationResult launchResult = new OperationResult(OPERATION_DELETE_ALL_CLOSED_TASKS); + Task task = createSimpleTask(OPERATION_DELETE_ALL_CLOSED_TASKS); + + task.setHandlerUri(ModelPublicConstants.CLEANUP_TASK_HANDLER_URI); + task.setName("Closed tasks cleanup"); + + try { + CleanupPolicyType policy = new CleanupPolicyType(); + policy.setMaxAge(XmlTypeConverter.createDuration(0)); + + CleanupPoliciesType policies = new CleanupPoliciesType(getPrismContext()); + policies.setClosedTasks(policy); + task.setExtensionContainerValue(SchemaConstants.MODEL_EXTENSION_CLEANUP_POLICIES, policies); + } catch (SchemaException e) { + LOGGER.error("Error dealing with schema (task {})", task, e); + launchResult.recordFatalError( + createStringResource("pageTasks.message.deleteAllClosedTasksConfirmedPerformed.fatalError").getString(), e); + throw new IllegalStateException("Error dealing with schema", e); + } + + getTaskManager().switchToBackground(task, launchResult); launchResult.setBackgroundTaskOid(task.getOid()); - showResult(launchResult); - target.add(getFeedbackPanel()); - } + showResult(launchResult); + target.add(getFeedbackPanel()); + } - private void addInlineMenuToTaskRow(TaskDto dto) { - addInlineMenuToTaskDto(dto); + private void addInlineMenuToTaskRow(TaskDto dto) { + addInlineMenuToTaskDto(dto); - List list = new ArrayList<>(); - if (dto.getSubtasks() != null) { - list.addAll(dto.getTransientSubtasks()); - } - if (dto.getTransientSubtasks() != null) { - list.addAll(dto.getSubtasks()); - } + List list = new ArrayList<>(); + if (dto.getSubtasks() != null) { + list.addAll(dto.getTransientSubtasks()); + } + if (dto.getTransientSubtasks() != null) { + list.addAll(dto.getSubtasks()); + } - for (TaskDto task : list) { - addInlineMenuToTaskDto(task); - } - } + for (TaskDto task : list) { + addInlineMenuToTaskDto(task); + } + } - private void addInlineMenuToTaskDto(final TaskDto dto) { - List items = dto.getMenuItems(); - if (!items.isEmpty()) { - //menu was already added - return; - } + private void addInlineMenuToTaskDto(final TaskDto dto) { + List items = dto.getMenuItems(); + if (!items.isEmpty()) { + // menu was already added + return; + } - items.addAll(createTasksInlineMenu(false, dto)); - } + items.addAll(createTasksInlineMenu(false, dto)); + } - private void addInlineMenuToNodeRow(final NodeDto dto) { - List items = dto.getMenuItems(); - if (!items.isEmpty()) { - //menu already added - return; - } + private void addInlineMenuToNodeRow(final NodeDto dto) { + List items = dto.getMenuItems(); + if (!items.isEmpty()) { + // menu already added + return; + } - items.addAll(createNodesInlineMenu()); - } + items.addAll(createNodesInlineMenu()); + } - private IModel getTaskConfirmationMessageModel(ColumnMenuAction action, String actionName){ - if (action.getRowModel() == null) { - return createStringResource("pageTasks.message.confirmationMessageForMultipleTaskObject", - actionName, WebComponentUtil.getSelectedData(getTaskTable()).size()); - } else { - String objectName = ((TaskDto)(action.getRowModel().getObject())).getName(); - return createStringResource("pageTasks.message.confirmationMessageForSingleTaskObject", - actionName, objectName); - } + private IModel getTaskConfirmationMessageModel(ColumnMenuAction action, String actionName) { + if (action.getRowModel() == null) { + return createStringResource("pageTasks.message.confirmationMessageForMultipleTaskObject", actionName, + WebComponentUtil.getSelectedData(getTaskTable()).size()); + } else { + String objectName = ((TaskDto) (action.getRowModel().getObject())).getName(); + return createStringResource("pageTasks.message.confirmationMessageForSingleTaskObject", actionName, objectName); + } - } + } - private boolean isTaskShowConfirmationDialog(ColumnMenuAction action){ - return action.getRowModel() != null || - WebComponentUtil.getSelectedData(getTaskTable()).size() > 0; - } + private boolean isTaskShowConfirmationDialog(ColumnMenuAction action) { + return action.getRowModel() != null || WebComponentUtil.getSelectedData(getTaskTable()).size() > 0; + } - private IModel getNodeConfirmationMessageModel(ColumnMenuAction action, String actionName){ - if (action.getRowModel() == null) { - return createStringResource("pageTasks.message.confirmationMessageForMultipleNodeObject", - actionName, WebComponentUtil.getSelectedData(getNodeTable()).size()); - } else { - String objectName = ((NodeDto)(action.getRowModel().getObject())).getName(); - return createStringResource("pageTasks.message.confirmationMessageForSingleNodeObject", - actionName, objectName); - } + private IModel getNodeConfirmationMessageModel(ColumnMenuAction action, String actionName) { + if (action.getRowModel() == null) { + return createStringResource("pageTasks.message.confirmationMessageForMultipleNodeObject", actionName, + WebComponentUtil.getSelectedData(getNodeTable()).size()); + } else { + String objectName = ((NodeDto) (action.getRowModel().getObject())).getName(); + return createStringResource("pageTasks.message.confirmationMessageForSingleNodeObject", actionName, objectName); + } - } + } - private boolean isNodeShowConfirmationDialog(ColumnMenuAction action){ - return action.getRowModel() != null || - WebComponentUtil.getSelectedData(getNodeTable()).size() > 0; - } + private boolean isNodeShowConfirmationDialog(ColumnMenuAction action) { + return action.getRowModel() != null || WebComponentUtil.getSelectedData(getNodeTable()).size() > 0; + } } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskSubtasksAndThreadsTabPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskSubtasksAndThreadsTabPanel.java index 1c5ab78cfc1..8db36b9b3a3 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskSubtasksAndThreadsTabPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskSubtasksAndThreadsTabPanel.java @@ -107,7 +107,7 @@ public boolean isVisible() { Label subtasksLabel = new Label(ID_SUBTASKS_LABEL, new ResourceModel("pageTaskEdit.subtasksLabel")); subtasksLabel.add(hiddenWhenEditingOrNoSubtasks); add(subtasksLabel); - SubtasksPanel subtasksPanel = new SubtasksPanel(ID_SUBTASKS_PANEL, new PropertyModel<>(taskDtoModel, TaskDto.F_SUBTASKS), parentPage.getWorkflowManager().isEnabled(), parentPage); + SubtasksPanel subtasksPanel = new SubtasksPanel(ID_SUBTASKS_PANEL, new PropertyModel<>(taskDtoModel, TaskDto.F_SUBTASKS), parentPage.getWorkflowManager().isEnabled()); subtasksPanel.add(hiddenWhenEditingOrNoSubtasks); add(subtasksPanel); diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/dto/TaskDto.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/dto/TaskDto.java index 105d0e8e559..b3b9bcaf62c 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/dto/TaskDto.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/dto/TaskDto.java @@ -94,6 +94,7 @@ public class TaskDto extends Selectable implements InlineMenuable { public static final String F_MODEL_OPERATION_STATUS = "modelOperationStatus"; public static final String F_SUBTASKS = "subtasks"; public static final String F_NAME = "name"; + public static final String F_TASK_KIND = "taskKind"; public static final String F_OID = "oid"; public static final String F_DESCRIPTION = "description"; public static final String F_CATEGORY = "category"; @@ -169,7 +170,7 @@ public class TaskDto extends Selectable implements InlineMenuable { private List triggers; // initialized on demand private PageBase pageBase; - //region Construction + //region Construction // parentTaskBean can be filled-in for optimization purposes (MID-4238); but take care to provide it in a suitable form // (e.g. with subtasks, if they are needed) - a conservative approach to this is implemented in fillInChildren @@ -639,6 +640,14 @@ public void setWorkerThreads(Integer workerThreads) { //endregion //region Getters for read-only properties + public TaskKindType getTaskKind() { + if (taskType.getWorkManagement() == null) { + return null; + } + + return taskType.getWorkManagement().getTaskKind(); + } + public String getCategory() { return taskType.getCategory(); } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/subtasks/SubtasksPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/subtasks/SubtasksPanel.java index 12c00414a08..423667f003f 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/subtasks/SubtasksPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/subtasks/SubtasksPanel.java @@ -20,15 +20,23 @@ import java.util.List; import com.evolveum.midpoint.gui.api.page.PageBase; + +import org.apache.wicket.Component; +import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn; import org.apache.wicket.extensions.markup.html.repeater.data.table.ISortableDataProvider; import org.apache.wicket.model.IModel; +import org.apache.wicket.request.mapper.parameter.PageParameters; import com.evolveum.midpoint.gui.api.component.BasePanel; import com.evolveum.midpoint.web.component.data.TablePanel; +import com.evolveum.midpoint.web.component.data.column.EnumPropertyColumn; +import com.evolveum.midpoint.web.component.data.column.LinkColumn; import com.evolveum.midpoint.web.component.util.ListDataProvider; +import com.evolveum.midpoint.web.page.admin.server.PageTaskEdit; import com.evolveum.midpoint.web.page.admin.server.PageTasks; import com.evolveum.midpoint.web.page.admin.server.dto.TaskDto; +import com.evolveum.midpoint.web.util.OnePageParameterEncoder; /** * @author mederly @@ -36,18 +44,28 @@ public class SubtasksPanel extends BasePanel> { private static final String ID_SUBTASKS_TABLE = "subtasksTable"; + + private boolean workflowsEnabled; - public SubtasksPanel(String id, IModel> model, boolean workflowsEnabled, PageBase pageBase) { + public SubtasksPanel(String id, IModel> model, boolean workflowsEnabled) { super(id, model); - initLayout(workflowsEnabled, pageBase); + this.workflowsEnabled = workflowsEnabled; + + } + + @Override + protected void onInitialize() { + super.onInitialize(); + initLayout(); } - private void initLayout(boolean workflowsEnabled, PageBase pageBase) { + private void initLayout() { List> columns = new ArrayList<>(); columns.add(PageTasks.createTaskNameColumn(this, "SubtasksPanel.label.name")); + columns.add(createTaskKindColumn()); columns.add(PageTasks.createTaskCategoryColumn(this, "SubtasksPanel.label.category")); columns.add(PageTasks.createTaskExecutionStatusColumn(this, "SubtasksPanel.label.executionState")); - columns.add(PageTasks.createProgressColumn(pageBase, "SubtasksPanel.label.progress")); + columns.add(PageTasks.createProgressColumn(getPageBase(), "SubtasksPanel.label.progress")); columns.add(PageTasks.createTaskResultStatusColumn(this, "SubtasksPanel.label.result")); //columns.add(PageTasks.createTaskDetailColumn(this, "SubtasksPanel.label.detail", workflowsEnabled)); @@ -55,4 +73,15 @@ private void initLayout(boolean workflowsEnabled, PageBase pageBase) { add(new TablePanel<>(ID_SUBTASKS_TABLE, provider, columns)); } + + public EnumPropertyColumn createTaskKindColumn() { + return new EnumPropertyColumn(createStringResource("SubtasksPanel.label.kind"), TaskDto.F_TASK_KIND) { + + @Override + protected String translate(Enum en) { + return createStringResource(en).getString(); + } + }; + } + } diff --git a/gui/admin-gui/src/main/resources/localization/Midpoint.properties b/gui/admin-gui/src/main/resources/localization/Midpoint.properties index cfef5865efe..939317baee5 100755 --- a/gui/admin-gui/src/main/resources/localization/Midpoint.properties +++ b/gui/admin-gui/src/main/resources/localization/Midpoint.properties @@ -4389,4 +4389,9 @@ PolyStringEditorPanel.keyLabel=key PolyStringEditorPanel.showLanguages=Show languages PolyStringEditorPanel.hideLanguages=Hide languages PolyStringEditorPanel.addLanguage=Add language -ValueChoosePanel.undefined=Undefined \ No newline at end of file +ValueChoosePanel.undefined=Undefined +TaskKindType.STANDALONE=Standalone +TaskKindType.COORDINATOR=Coordinator +TaskKindType.WORKER=Worker +TaskKindType.PARTITIONED_MASTER=Partitioned master +SubtasksPanel.label.kind=Task kind \ No newline at end of file diff --git a/icf-connectors/dummy-connector/src/main/java/com/evolveum/icf/dummy/connector/AbstractDummyConnector.java b/icf-connectors/dummy-connector/src/main/java/com/evolveum/icf/dummy/connector/AbstractDummyConnector.java index b056b70508a..697c504b665 100644 --- a/icf-connectors/dummy-connector/src/main/java/com/evolveum/icf/dummy/connector/AbstractDummyConnector.java +++ b/icf-connectors/dummy-connector/src/main/java/com/evolveum/icf/dummy/connector/AbstractDummyConnector.java @@ -41,6 +41,7 @@ import java.util.Map; import java.util.Set; import java.util.function.Consumer; +import java.util.stream.Collectors; import javax.security.sasl.AuthenticationException; @@ -558,7 +559,11 @@ private List createAuxiliaryObjectClasses() { private void buildAttributes(ObjectClassInfoBuilder icfObjClassBuilder, DummyObjectClass dummyObjectClass) { for (DummyAttributeDefinition dummyAttrDef : dummyObjectClass.getAttributeDefinitions()) { - AttributeInfoBuilder attrBuilder = new AttributeInfoBuilder(dummyAttrDef.getAttributeName(), dummyAttrDef.getAttributeType()); + Class attributeClass = dummyAttrDef.getAttributeType(); + if (dummyAttrDef.isSensitive()) { + attributeClass = GuardedString.class; + } + AttributeInfoBuilder attrBuilder = new AttributeInfoBuilder(dummyAttrDef.getAttributeName(), attributeClass); attrBuilder.setMultiValued(dummyAttrDef.isMulti()); attrBuilder.setRequired(dummyAttrDef.isRequired()); attrBuilder.setReturnedByDefault(dummyAttrDef.isReturnedByDefault()); @@ -1209,7 +1214,7 @@ private ConnectorObjectBuilder createConnectorObjectBuilderCommon(DummyObject du } } // Return all attributes that are returned by default. We will filter them out later. - Set values = dummyObject.getAttributeValues(name, Object.class); + Set values = toConnIdAttributeValues(name, attrDef, dummyObject.getAttributeValues(name, Object.class)); if (configuration.isVaryLetterCase()) { name = varyLetterCase(name); } @@ -1259,6 +1264,17 @@ private ConnectorObjectBuilder createConnectorObjectBuilderCommon(DummyObject du return builder; } + private Set toConnIdAttributeValues(String name, DummyAttributeDefinition attrDef, Set dummyAttributeValues) { + if (dummyAttributeValues == null || dummyAttributeValues.isEmpty()) { + return dummyAttributeValues; + } + if (attrDef.isSensitive()) { + return dummyAttributeValues.stream().map(val -> new GuardedString(((String)val).toCharArray())).collect(Collectors.toSet()); + } else { + return dummyAttributeValues; + } + } + protected void addAdditionalCommonAttributes(ConnectorObjectBuilder builder, DummyObject dummyObject) { String connectorInstanceNumberAttribute = getConfiguration().getConnectorInstanceNumberAttribute(); if (connectorInstanceNumberAttribute != null) { diff --git a/icf-connectors/dummy-resource/src/main/java/com/evolveum/icf/dummy/resource/DummyAttributeDefinition.java b/icf-connectors/dummy-resource/src/main/java/com/evolveum/icf/dummy/resource/DummyAttributeDefinition.java index 227be2c72d3..0f795351800 100644 --- a/icf-connectors/dummy-resource/src/main/java/com/evolveum/icf/dummy/resource/DummyAttributeDefinition.java +++ b/icf-connectors/dummy-resource/src/main/java/com/evolveum/icf/dummy/resource/DummyAttributeDefinition.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2013 Evolveum + * Copyright (c) 2010-2019 Evolveum * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,6 +27,8 @@ public class DummyAttributeDefinition { private boolean isMulti; private boolean isReturnedByDefault = true; private boolean isReturnedAsIncomplete; + // setting to sensitive will cause this attr to be presented as GuardedString + private boolean sensitive; public DummyAttributeDefinition(String attributeName, Class attributeType) { super(); @@ -92,4 +94,12 @@ public boolean isReturnedAsIncomplete() { public void setReturnedAsIncomplete(boolean returnedAsIncomplete) { isReturnedAsIncomplete = returnedAsIncomplete; } + + public boolean isSensitive() { + return sensitive; + } + + public void setSensitive(boolean sensitive) { + this.sensitive = sensitive; + } } diff --git a/infra/prism-api/src/main/java/com/evolveum/midpoint/prism/crypto/Protector.java b/infra/prism-api/src/main/java/com/evolveum/midpoint/prism/crypto/Protector.java index db1736af5a3..ea2bf3a180b 100644 --- a/infra/prism-api/src/main/java/com/evolveum/midpoint/prism/crypto/Protector.java +++ b/infra/prism-api/src/main/java/com/evolveum/midpoint/prism/crypto/Protector.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2017 Evolveum + * Copyright (c) 2010-2019 Evolveum * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,6 +22,7 @@ import javax.net.ssl.TrustManager; import com.evolveum.prism.xml.ns._public.types_3.EncryptedDataType; +import com.evolveum.prism.xml.ns._public.types_3.ProtectedDataType; import com.evolveum.prism.xml.ns._public.types_3.ProtectedStringType; import com.evolveum.midpoint.util.exception.SchemaException; @@ -74,7 +75,68 @@ public interface Protector { void hash(ProtectedData protectedData) throws EncryptionException, SchemaException; - boolean compare(ProtectedStringType a, ProtectedStringType b) throws EncryptionException, SchemaException; + /** + * Compare cleartext values protected inside the protected strings. + * + * This method only deals with the equality of the original values (cleartext). + * If the two protected strings are representation of the same value then true value + * is returned. In all other cases false value is returned. + * + * Please note that some cases are not decidable. For example it may not be possible + * to compare two hashed values, e.g. in case that they are using different salt values. + * SchemaException is thrown in that case. + * + * This method does not deal with any details about the protection. It just deals + * with equality of the values. E.g. if encrypted and hashed version of the same value + * is compared, this method returns true. This is ideal for use cases such as checking + * equality of a password during authentication. But it is not the right algorithm for + * data management purposes. E.g. it will provide bad results if it is used to decide + * whether a particular value should be replaced with a new value in a data store. + * Please see areEquivalent() method. + * + * @see #areEquivalent(ProtectedStringType, ProtectedStringType) + */ + boolean compareCleartext(ProtectedStringType a, ProtectedStringType b) throws EncryptionException, SchemaException; + + /** + * Decides equivalence of two protected data objects (for data management purposes). + * + * The concept of equivalence is a very tricky one when it comes + * to protected (encrypted and hashed) data. We want to compare + * the original values (cleartext) and not the bytes that are + * a product of encryption (ciphertext). As many ciphers have + * randomized initialization vectors, encrypting the same cleartext + * will produce different ciphertext. Therefore we cannot rely on + * equality of ciphertexts. On the other hand, we want to allow + * re-keying. Therefore protected data types that are produced + * from the same cleartext may still be non-equivalent if a + * different key was used to create them. Otherwise we want + * be able to change the key, as the value with old key will be + * considered equivalent and it may never get replaced. + * + * And all of that is further complicated with hashing. + * Hash algorithms are often salted, therefore we cannot rely on + * comparing just the hashes. The situation is a bit easier here + * as we do not need to deal with the key, but on the other hand + * we do not have access to a cleartext at all. Therefore all we can + * do is to look at hashed values and suffer re-salting all the time. + * But it is better than the alternative, which means never be able to + * change hashed value. If any more intelligent behavior is expected, it + * has to be implemented in higher layers of the system where we still + * have at least one unhashed clear value available. + * + * This method is designed for data management purposes. E.g. it can be used + * to decide whether to replace certain value in a data store. This method + * is not suitable for all purposes. E.g. it should NOT be used for password + * management. This method may return false even if the cleartext in two + * protected strings is the same, e.g. in case that one is encrypted and + * the other is hashed. For that purpose see the compareCleartext method. + * + * @see #compareCleartext(ProtectedStringType, ProtectedStringType) + */ + boolean areEquivalent(ProtectedStringType a, ProtectedStringType b) throws EncryptionException, SchemaException; + + boolean isEncryptedByCurrentKey(@NotNull EncryptedDataType data) throws EncryptionException; } diff --git a/infra/prism-api/src/main/java/com/evolveum/prism/xml/ns/_public/types_3/ProtectedDataType.java b/infra/prism-api/src/main/java/com/evolveum/prism/xml/ns/_public/types_3/ProtectedDataType.java index 90b787076bc..7e5e759fc59 100644 --- a/infra/prism-api/src/main/java/com/evolveum/prism/xml/ns/_public/types_3/ProtectedDataType.java +++ b/infra/prism-api/src/main/java/com/evolveum/prism/xml/ns/_public/types_3/ProtectedDataType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2018 Evolveum + * Copyright (c) 2010-2019 Evolveum * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -56,7 +56,8 @@ ProtectedStringType.class }) public abstract class ProtectedDataType implements ProtectedData, Serializable { - + private static final long serialVersionUID = 1L; + public static final QName COMPLEX_TYPE = new QName("http://prism.evolveum.com/xml/ns/public/types-3", "ProtectedDataType"); public final static QName F_ENCRYPTED_DATA = new QName("http://prism.evolveum.com/xml/ns/public/types-3", "encryptedData"); public final static QName F_HASHED_DATA = new QName("http://prism.evolveum.com/xml/ns/public/types-3", "hashedData"); @@ -278,7 +279,24 @@ public int hashCode() { result = prime * result + ((hashedDataType == null) ? 0 : hashedDataType.hashCode()); return result; } - + + /** + * Indicates whether some other object is "equal to" this one. + * This is standard Java equality comparison. I.e. it will return true if + * the Java objects contain the same data. This means that both object must + * use the same protection mechanism (enctyption,hash), same keys must be used, + * ciphertext or hashes must be the same and so on. If this method returns true + * then obviously also the cleartext data are the same. However, if this method + * returns false then no information about the cleartext data can be inferred. + * Cleartext data may still be the same in both objects. Therefore this method + * is not suitable for almost any practical purpose. It is here mostly just to keep + * the Java interface contract. + * + * See the methods of Protector for a more practical comparison algorithms. + * + * @see Protector#compareCleartext(ProtectedStringType, ProtectedStringType) + * @see Protector#areEquivalent(ProtectedStringType, ProtectedStringType) + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -314,7 +332,7 @@ public boolean equals(Object obj) { } return true; } - + @Override public String toString() { StringBuilder sb = new StringBuilder(getClass().getSimpleName()); diff --git a/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/PrismPropertyValueImpl.java b/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/PrismPropertyValueImpl.java index 960a1b95fc9..e4a9817f224 100644 --- a/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/PrismPropertyValueImpl.java +++ b/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/PrismPropertyValueImpl.java @@ -17,6 +17,7 @@ package com.evolveum.midpoint.prism.impl; import com.evolveum.midpoint.prism.*; +import com.evolveum.midpoint.prism.crypto.EncryptionException; import com.evolveum.midpoint.prism.equivalence.ParameterizedEquivalenceStrategy; import com.evolveum.midpoint.prism.impl.marshaller.BeanMarshaller; import com.evolveum.midpoint.prism.match.MatchingRule; @@ -34,6 +35,7 @@ import com.evolveum.midpoint.util.DebugUtil; import com.evolveum.midpoint.util.PrettyPrinter; import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.util.exception.SystemException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; @@ -434,16 +436,30 @@ public boolean equals(PrismPropertyValue other, ParameterizedEquivalenceStrat } } else { - if (thisRealValue instanceof Element && - otherRealValue instanceof Element) { + if (thisRealValue instanceof Element && otherRealValue instanceof Element) { return DOMUtil.compareElement((Element)thisRealValue, (Element)otherRealValue, strategy.isLiteralDomComparison()); } - if (thisRealValue instanceof SchemaDefinitionType && - otherRealValue instanceof SchemaDefinitionType) { + if (thisRealValue instanceof SchemaDefinitionType && otherRealValue instanceof SchemaDefinitionType) { SchemaDefinitionType thisSchema = (SchemaDefinitionType) thisRealValue; return thisSchema.equals(otherRealValue, strategy.isLiteralDomComparison()); } + + if (thisRealValue instanceof ProtectedStringType && otherRealValue instanceof ProtectedStringType) { + PrismContext prismContext = getPrismContext(); + if (prismContext == null || prismContext.getDefaultProtector() == null) { + // Slightly dangerous, may get wrong results. See javadoc of ProtectedDataType.equals() + // But what else can we do? + return thisRealValue.equals(otherRealValue); + } else { + try { + return prismContext.getDefaultProtector().areEquivalent((ProtectedStringType)thisRealValue, (ProtectedStringType)otherRealValue); + } catch (SchemaException | EncryptionException e) { + // Not absolutely correct. But adding those throws clauses to all equals(...) signature will wreak havoc. + throw new SystemException("Error comparing protected string values: "+e.getMessage(), e); + } + } + } if (thisRealValue instanceof byte[] && otherRealValue instanceof byte[]) { return Arrays.equals((byte[]) thisRealValue, (byte[]) otherRealValue); diff --git a/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/crypto/KeyStoreBasedProtectorImpl.java b/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/crypto/KeyStoreBasedProtectorImpl.java index cdb84c8c433..9150da465e6 100644 --- a/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/crypto/KeyStoreBasedProtectorImpl.java +++ b/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/crypto/KeyStoreBasedProtectorImpl.java @@ -66,6 +66,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Random; import java.util.Set; @@ -573,7 +574,7 @@ private byte[] generatePbkdSalt() { } @Override - public boolean compare(ProtectedStringType a, ProtectedStringType b) throws EncryptionException, SchemaException { + public boolean compareCleartext(ProtectedStringType a, ProtectedStringType b) throws EncryptionException, SchemaException { if (a == b) { return true; } @@ -600,16 +601,20 @@ public boolean compare(ProtectedStringType a, ProtectedStringType b) throws Encr return compareHashed(hashedPs, clear.toCharArray()); } else { - String aClear = decryptString(a); - String bClear = decryptString(b); - if (aClear == null && bClear == null) { - return true; - } - if (aClear == null || bClear == null) { - return false; - } - return aClear.equals(bClear); + return compareEncryptedCleartext(a, b); + } + } + + private boolean compareEncryptedCleartext(ProtectedStringType a, ProtectedStringType b) throws EncryptionException { + String aClear = decryptString(a); + String bClear = decryptString(b); + if (aClear == null && bClear == null) { + return true; + } + if (aClear == null || bClear == null) { + return false; } + return aClear.equals(bClear); } private boolean compareHashed(ProtectedStringType hashedPs, char[] clearChars) throws SchemaException, EncryptionException { @@ -657,8 +662,51 @@ private boolean compareHashedPbkd(HashedDataType hashedDataType, String algorith return Arrays.equals(digestValue, hashBytes); } - + @Override + public boolean areEquivalent(ProtectedStringType a, ProtectedStringType b) throws EncryptionException, SchemaException { + if (a == b) { + return true; + } + if (a == null || b == null) { + return false; + } + if (a.isHashed()) { + if (b.isHashed()) { + return areEquivalentHashed(a, b); + } else { + return false; + } + } + if (a.isEncrypted()) { + if (b.isEncrypted()) { + return areEquivalentEncrypted(a, b); + } else { + return false; + } + } + return Objects.equals(a.getClearValue(), a.getClearValue()); + } + + private boolean areEquivalentHashed(ProtectedStringType a, ProtectedStringType b) { + // We cannot compare two hashes in any other way. + return Objects.equals(a.getHashedDataType(), a.getHashedDataType()); + } + + private boolean areEquivalentEncrypted(ProtectedStringType a, ProtectedStringType b) throws EncryptionException { + EncryptedDataType ae = a.getEncryptedDataType(); + EncryptedDataType be = b.getEncryptedDataType(); + if (!Objects.equals(ae.getEncryptionMethod(), be.getEncryptionMethod())) { + return false; + } + if (!Objects.equals(ae.getKeyInfo(), be.getKeyInfo())) { + return false; + } + return compareEncryptedCleartext(a, b); + } + + + @Override public boolean isEncryptedByCurrentKey(@NotNull EncryptedDataType data) throws EncryptionException { String encryptedUsingKeyName = data.getKeyInfo().getKeyName(); if (encryptedUsingKeyName == null) { diff --git a/infra/prism-impl/src/test/java/com/evolveum/midpoint/prism/crypto/TestProtector.java b/infra/prism-impl/src/test/java/com/evolveum/midpoint/prism/crypto/TestProtector.java index 336d8989c3b..5b4accfe2e8 100644 --- a/infra/prism-impl/src/test/java/com/evolveum/midpoint/prism/crypto/TestProtector.java +++ b/infra/prism-impl/src/test/java/com/evolveum/midpoint/prism/crypto/TestProtector.java @@ -79,13 +79,13 @@ public void testProtectorEncryptionRoundTrip() throws Exception { AssertJUnit.assertEquals(value, clear); // WHEN - boolean compare1 = protector256.compare(pdt, pstEnc); + boolean compare1 = protector256.compareCleartext(pdt, pstEnc); // THEN assertTrue("compare1 failed", compare1); // WHEN - boolean compare2 = protector256.compare(pstEnc, pdt); + boolean compare2 = protector256.compareCleartext(pstEnc, pdt); // THEN assertTrue("compare2 failed", compare2); @@ -94,13 +94,13 @@ public void testProtectorEncryptionRoundTrip() throws Exception { wrongPst.setClearValue("nonono This is not it"); // WHEN - boolean compare5 = protector256.compare(pdt, wrongPst); + boolean compare5 = protector256.compareCleartext(pdt, wrongPst); // THEN assertFalse("compare5 unexpected success", compare5); // WHEN - boolean compare6 = protector256.compare(wrongPst, pdt); + boolean compare6 = protector256.compareCleartext(wrongPst, pdt); // THEN assertFalse("compare6 unexpected success", compare6); @@ -128,13 +128,13 @@ public void testProtectorHashRoundTrip() throws Exception { checkPstClear.setClearValue(value); // WHEN - boolean compare1 = protector256.compare(pst, checkPstClear); + boolean compare1 = protector256.compareCleartext(pst, checkPstClear); // THEN assertTrue("compare1 failed", compare1); // WHEN - boolean compare2 = protector256.compare(checkPstClear, pst); + boolean compare2 = protector256.compareCleartext(checkPstClear, pst); // THEN assertTrue("compare2 failed", compare2); @@ -144,13 +144,13 @@ public void testProtectorHashRoundTrip() throws Exception { protector256.encrypt(checkPstEnc); // WHEN - boolean compare3 = protector256.compare(pst, checkPstEnc); + boolean compare3 = protector256.compareCleartext(pst, checkPstEnc); // THEN assertTrue("compare3 failed", compare3); // WHEN - boolean compare4 = protector256.compare(checkPstEnc, pst); + boolean compare4 = protector256.compareCleartext(checkPstEnc, pst); // THEN assertTrue("compare4 failed", compare4); @@ -159,13 +159,13 @@ public void testProtectorHashRoundTrip() throws Exception { wrongPst.setClearValue("nonono This is not it"); // WHEN - boolean compare5 = protector256.compare(pst, wrongPst); + boolean compare5 = protector256.compareCleartext(pst, wrongPst); // THEN assertFalse("compare5 unexpected success", compare5); // WHEN - boolean compare6 = protector256.compare(wrongPst, pst); + boolean compare6 = protector256.compareCleartext(wrongPst, pst); // THEN assertFalse("compare6 unexpected success", compare6); @@ -175,13 +175,13 @@ public void testProtectorHashRoundTrip() throws Exception { protector256.encrypt(wrongPstEnc); // WHEN - boolean compare7 = protector256.compare(pst, wrongPstEnc); + boolean compare7 = protector256.compareCleartext(pst, wrongPstEnc); // THEN assertFalse("compare7 unexpected success", compare7); // WHEN - boolean compare8 = protector256.compare(wrongPstEnc, pst); + boolean compare8 = protector256.compareCleartext(wrongPstEnc, pst); // THEN assertFalse("compare8 unexpected success", compare8); @@ -190,13 +190,13 @@ public void testProtectorHashRoundTrip() throws Exception { pst.getHashedDataType().getDigestValue()[1] = 0x12; // WHEN - boolean compare9 = protector256.compare(pst, checkPstClear); + boolean compare9 = protector256.compareCleartext(pst, checkPstClear); // THEN assertFalse("compare9 unexpected success", compare9); // WHEN - boolean compare10 = protector256.compare(checkPstClear, pst); + boolean compare10 = protector256.compareCleartext(checkPstClear, pst); // THEN assertFalse("compare10 unexpected success", compare10); @@ -216,25 +216,25 @@ public void testProtectorHashRoundTrip() throws Exception { assertNull(pstEncHash.getClearValue()); // WHEN - boolean compare1e = protector256.compare(checkPstClear, pstEncHash); + boolean compare1e = protector256.compareCleartext(checkPstClear, pstEncHash); // THEN assertTrue("compare1e failed", compare1e); // WHEN - boolean compare2e = protector256.compare(pstEncHash, checkPstClear); + boolean compare2e = protector256.compareCleartext(pstEncHash, checkPstClear); // THEN assertTrue("compare2e failed", compare2e); // WHEN - boolean compare3e = protector256.compare(pstEncHash, checkPstEnc); + boolean compare3e = protector256.compareCleartext(pstEncHash, checkPstEnc); // THEN assertTrue("compare3e failed", compare3e); // WHEN - boolean compare4e = protector256.compare(checkPstEnc, pstEncHash); + boolean compare4e = protector256.compareCleartext(checkPstEnc, pstEncHash); // THEN assertTrue("compare4e failed", compare4e); diff --git a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/stringpolicy/ObjectValuePolicyEvaluator.java b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/stringpolicy/ObjectValuePolicyEvaluator.java index 40ffc5be566..5801b430497 100644 --- a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/stringpolicy/ObjectValuePolicyEvaluator.java +++ b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/stringpolicy/ObjectValuePolicyEvaluator.java @@ -474,7 +474,7 @@ private boolean passwordEquals(ProtectedStringType newPasswordPs, ProtectedStrin return newPasswordPs == null; } try { - return protector.compare(newPasswordPs, currentPassword); + return protector.compareCleartext(newPasswordPs, currentPassword); } catch (EncryptionException e) { throw new SystemException("Failed to compare " + shortDesc + ": " + e.getMessage(), e); } diff --git a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/stringpolicy/ValuePolicyProcessor.java b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/stringpolicy/ValuePolicyProcessor.java index 81c7b88c52c..db8f6dece8f 100644 --- a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/stringpolicy/ValuePolicyProcessor.java +++ b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/stringpolicy/ValuePolicyProcessor.java @@ -496,7 +496,7 @@ private boolean isMatching(String newPassword, PrismProperty objectPrope ProtectedStringType newPasswordPs = new ProtectedStringType(); newPasswordPs.setClearValue(newPassword); try { - if (protector.compare(newPasswordPs, (ProtectedStringType)objectRealValue)) { + if (protector.compareCleartext(newPasswordPs, (ProtectedStringType)objectRealValue)) { return true; } } catch (SchemaException | EncryptionException e) { diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/controller/ModelInteractionServiceImpl.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/controller/ModelInteractionServiceImpl.java index 767e5fa3573..16bfae3c594 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/controller/ModelInteractionServiceImpl.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/controller/ModelInteractionServiceImpl.java @@ -906,7 +906,7 @@ public boolean checkPassword(String userOid, ProtectedStringType password, Task ProtectedStringType currentPassword = userType.getCredentials().getPassword().getValue(); boolean cmp; try { - cmp = protector.compare(password, currentPassword); + cmp = protector.compareCleartext(password, currentPassword); } catch (EncryptionException e) { result.recordFatalError(e); throw new SystemException(e.getMessage(),e); diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/credentials/ProjectionCredentialsProcessor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/credentials/ProjectionCredentialsProcessor.java index 4dfb973d07c..cd313a3b08d 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/credentials/ProjectionCredentialsProcessor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/credentials/ProjectionCredentialsProcessor.java @@ -249,7 +249,7 @@ public ValuePolicyType resolve() { if (userPasswordDeltaOldValues != null && !userPasswordDeltaOldValues.isEmpty()) { ProtectedStringType oldUserPassword = userPasswordDeltaOldValues.iterator().next().getRealValue(); try { - if (oldUserPassword.canGetCleartext() && protector.compare(oldUserPassword, oldProjectionPassword)) { + if (oldUserPassword.canGetCleartext() && protector.compareCleartext(oldUserPassword, oldProjectionPassword)) { outputTriple.clearMinusSet(); outputTriple.addToMinusSet(prismContext.itemFactory().createPropertyValue(oldUserPassword)); } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/focus/InboundProcessor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/focus/InboundProcessor.java index 0c44182d43b..16a771d3e71 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/focus/InboundProcessor.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/focus/InboundProcessor.java @@ -1011,7 +1011,7 @@ private DeltaSetTriple ItemDelta collectOutputDelta( - ItemDefinition outputDefinition, ItemPath outputPath, PrismObject focusNew, + D outputDefinition, ItemPath outputPath, PrismObject focusNew, DeltaSetTriple> consolidatedTriples, boolean tolerant, boolean hasRange, boolean isDelete) throws SchemaException { @@ -1023,14 +1023,15 @@ private It boolean isAssignment = FocusType.F_ASSIGNMENT.equivalent(outputPath); - Item shouldBeItem = outputDefinition.instantiate(); + Item shouldBeItem = outputDefinition.instantiate(); if (consolidatedTriples != null) { Collection> shouldBeItemValues = consolidatedTriples.getNonNegativeValues(); for (ItemValueWithOrigin itemWithOrigin : shouldBeItemValues) { - shouldBeItem.add(LensUtil.cloneAndApplyMetadata(itemWithOrigin.getItemValue(), + V clonedValue = LensUtil.cloneAndApplyMetadata(itemWithOrigin.getItemValue(), isAssignment, - shouldBeItemValues)); + shouldBeItemValues); + shouldBeItem.add(clonedValue, EquivalenceStrategy.REAL_VALUE); } if (consolidatedTriples.hasPlusSet()) { @@ -1404,7 +1405,7 @@ private void processSpecialPropertyInbound(Collection resourceDummyTeaGreen; - protected DummyResourceContoller dummyResourceCtlTeaGreen; - protected DummyResource dummyResourceTeaGreen; + + private static final String LOCKER_BIG_SECRET = "BIG secret"; + + private ProtectedStringType mancombLocker; @Override public void initSystem(Task initTask, OperationResult initResult) throws Exception { super.initSystem(initTask, initResult); assumeAssignmentPolicy(AssignmentPolicyEnforcementType.FULL); - dummyResourceCtlTeaGreen = DummyResourceContoller.create(RESOURCE_DUMMY_TEA_GREEN_NAME, null); - dummyResourceCtlTeaGreen.extendSchemaPirate(); - dummyResourceTeaGreen = dummyResourceCtlTeaGreen.getDummyResource(); - dummyResourceTeaGreen.setSyncStyle(DummySyncStyle.SMART); - resourceDummyTeaGreen = importAndGetObjectFromFile(ResourceType.class, RESOURCE_DUMMY_TEA_GREEN_FILE, RESOURCE_DUMMY_TEA_GREEN_OID, initTask, initResult); - dummyResourceCtlTeaGreen.setResource(resourceDummyTeaGreen); + initDummyResource(RESOURCE_DUMMY_TEA_GREEN_NAME, RESOURCE_DUMMY_TEA_GREEN_FILE, RESOURCE_DUMMY_TEA_GREEN_OID, + controller -> { + controller.extendSchemaPirate(); + controller.addAttrDef(controller.getDummyResource().getAccountObjectClass(), + DUMMY_ACCOUNT_ATTRIBUTE_LOCKER_NAME, String.class, false, false) + .setSensitive(true); + controller.setSyncStyle(DummySyncStyle.SMART); + }, + initTask, initResult); } + @Test + public void test010SanitySchema() throws Exception { + final String TEST_NAME = "test010SanitySchema"; + displayTestTitle(TEST_NAME); + + // GIVEN + Task task = createTask(TEST_NAME); + + /// WHEN + displayWhen(TEST_NAME); + OperationResult testResult = modelService.testResource(RESOURCE_DUMMY_TEA_GREEN_OID, task); + + // THEN + displayThen(TEST_NAME); + TestUtil.assertSuccess(testResult); + + ResourceType resourceType = getDummyResourceType(RESOURCE_DUMMY_TEA_GREEN_NAME); + ResourceSchema returnedSchema = RefinedResourceSchemaImpl.getResourceSchema(resourceType, prismContext); + display("Parsed resource schema (tea-green)", returnedSchema); + ObjectClassComplexTypeDefinition accountDef = getDummyResourceController(RESOURCE_DUMMY_TEA_GREEN_NAME) + .assertDummyResourceSchemaSanityExtended(returnedSchema, resourceType, false, + DummyResourceContoller.PIRATE_SCHEMA_NUMBER_OF_DEFINITIONS + 1); // MID-5197 + + ResourceAttributeDefinition lockerDef = accountDef.findAttributeDefinition(DUMMY_ACCOUNT_ATTRIBUTE_LOCKER_NAME); + assertNotNull("No locker attribute definition", lockerDef); + assertEquals("Wrong locker attribute definition type", ProtectedStringType.COMPLEX_TYPE, lockerDef.getTypeName()); + } + @Test public void test100ImportLiveSyncTaskDummyTeaGreen() throws Exception { final String TEST_NAME = "test100ImportLiveSyncTaskDummyTeaGreen"; displayTestTitle(TEST_NAME); // GIVEN - Task task = createTask(TestMappingInbound.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); /// WHEN @@ -101,7 +140,7 @@ public void test110AddDummyTeaGreenAccountMancomb() throws Exception { displayTestTitle(TEST_NAME); // GIVEN - Task task = createTask(TestMappingInbound.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); // Preconditions @@ -111,31 +150,39 @@ public void test110AddDummyTeaGreenAccountMancomb() throws Exception { account.setEnabled(true); account.addAttributeValues(DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_FULLNAME_NAME, "Mancomb Seepgood"); account.addAttributeValues(DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_LOCATION_NAME, "Melee Island"); + account.addAttributeValues(DUMMY_ACCOUNT_ATTRIBUTE_LOCKER_NAME, LOCKER_BIG_SECRET); // MID-5197 /// WHEN displayWhen(TEST_NAME); - dummyResourceTeaGreen.addAccount(account); + getDummyResource(RESOURCE_DUMMY_TEA_GREEN_NAME).addAccount(account); waitForSyncTaskNextRun(); // THEN displayThen(TEST_NAME); - PrismObject accountMancomb = findAccountByUsername(ACCOUNT_MANCOMB_DUMMY_USERNAME, resourceDummyTeaGreen); + PrismObject accountMancomb = findAccountByUsername(ACCOUNT_MANCOMB_DUMMY_USERNAME, getDummyResourceObject(RESOURCE_DUMMY_TEA_GREEN_NAME)); display("Account mancomb", accountMancomb); assertNotNull("No mancomb account shadow", accountMancomb); assertEquals("Wrong resourceRef in mancomb account", RESOURCE_DUMMY_TEA_GREEN_OID, accountMancomb.asObjectable().getResourceRef().getOid()); assertShadowOperationalData(accountMancomb, SynchronizationSituationType.LINKED, null); - PrismObject userMancomb = findUserByUsername(ACCOUNT_MANCOMB_DUMMY_USERNAME); - display("User mancomb", userMancomb); - assertNotNull("User mancomb was not created", userMancomb); - assertLinks(userMancomb, 1); - assertAdministrativeStatusEnabled(userMancomb); - - assertLinked(userMancomb, accountMancomb); + mancombLocker = assertUserAfterByUsername(ACCOUNT_MANCOMB_DUMMY_USERNAME) + .links() + .single() + .assertOid(accountMancomb.getOid()) + .end() + .end() + .assertAdministrativeStatus(ActivationStatusType.ENABLED) + .extension() + .property(PIRACY_LOCKER) + .singleValue() + .protectedString() + .assertIsEncrypted() + .assertCompareCleartext(LOCKER_BIG_SECRET) + .getProtectedString(); // assertUsers(6); @@ -143,13 +190,16 @@ public void test110AddDummyTeaGreenAccountMancomb() throws Exception { notificationManager.setDisabled(true); } + /** + * MID-5197 + */ @Test public void test150UserReconcile() throws Exception { final String TEST_NAME = "test150UserReconcile"; displayTestTitle(TEST_NAME); // GIVEN - Task task = createTask(TestMappingInbound.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); dummyAuditService.clear(); @@ -167,20 +217,31 @@ public void test150UserReconcile() throws Exception { // THEN displayThen(TEST_NAME); - PrismObject accountMancomb = findAccountByUsername(ACCOUNT_MANCOMB_DUMMY_USERNAME, resourceDummyTeaGreen); + PrismObject accountMancomb = findAccountByUsername(ACCOUNT_MANCOMB_DUMMY_USERNAME, getDummyResourceObject(RESOURCE_DUMMY_TEA_GREEN_NAME)); display("Account mancomb", accountMancomb); assertNotNull("No mancomb account shadow", accountMancomb); assertEquals("Wrong resourceRef in mancomb account", RESOURCE_DUMMY_TEA_GREEN_OID, accountMancomb.asObjectable().getResourceRef().getOid()); assertShadowOperationalData(accountMancomb, SynchronizationSituationType.LINKED, null); - userMancomb = findUserByUsername(ACCOUNT_MANCOMB_DUMMY_USERNAME); - display("User mancomb", userMancomb); - - assertLinks(userMancomb, 1); - assertAdministrativeStatusEnabled(userMancomb); - - assertLinked(userMancomb, accountMancomb); + assertUserAfterByUsername(ACCOUNT_MANCOMB_DUMMY_USERNAME) + .links() + .single() + .assertOid(accountMancomb.getOid()) + .end() + .end() + .assertAdministrativeStatus(ActivationStatusType.ENABLED) + .extension() + .property(PIRACY_LOCKER) + .singleValue() + .protectedString() + .assertIsEncrypted() + .assertCompareCleartext(LOCKER_BIG_SECRET) + // Make sure that this is exactly the same content of protected string + // including all the randomized things (IV). If it is the same, + // there is a good chance we haven't had any phantom changes + // MID-5197 + .assertEquals(mancombLocker); // assertUsers(6); @@ -197,14 +258,14 @@ public void test300DeleteDummyTeaGreenAccountMancomb() throws Exception { displayTestTitle(TEST_NAME); // GIVEN - Task task = createTask(TestMappingInbound.class.getName() + "." + TEST_NAME); + Task task = createTask(TEST_NAME); OperationResult result = task.getResult(); /// WHEN displayWhen(TEST_NAME); - dummyResourceTeaGreen.deleteAccountByName(ACCOUNT_MANCOMB_DUMMY_USERNAME); + getDummyResource(RESOURCE_DUMMY_TEA_GREEN_NAME).deleteAccountByName(ACCOUNT_MANCOMB_DUMMY_USERNAME); - display("Dummy (tea green) resource", dummyResourceTeaGreen.debugDump()); + display("Dummy (tea green) resource", getDummyResource(RESOURCE_DUMMY_TEA_GREEN_NAME).debugDump()); // Make sure we have steady state waitForSyncTaskNextRun(); @@ -230,7 +291,7 @@ public void test300DeleteDummyTeaGreenAccountMancomb() throws Exception { protected void importSyncTask() throws FileNotFoundException { - importObjectFromFile(TASK_LIVE_SYNC_DUMMY_TEA_GREEN_FILENAME); + importObjectFromFile(TASK_LIVE_SYNC_DUMMY_TEA_GREEN_FILE); } protected void waitForSyncTaskStart() throws Exception { diff --git a/model/model-intest/src/test/resources/mapping/resource-dummy-tea-green.xml b/model/model-intest/src/test/resources/mapping/resource-dummy-tea-green.xml index 9c885e7ae31..efef47deecb 100644 --- a/model/model-intest/src/test/resources/mapping/resource-dummy-tea-green.xml +++ b/model/model-intest/src/test/resources/mapping/resource-dummy-tea-green.xml @@ -1,6 +1,6 @@ ri:weapon Weapon - ri:drink Drink false - ri:quote Quote true - + + extension/locker + + @@ -239,50 +157,18 @@ An authoritative resource, used to test for MID-2100 (inbound mappings acting bo - - - - weak diff --git a/model/model-intest/src/test/resources/schema/piracy.xsd b/model/model-intest/src/test/resources/schema/piracy.xsd index c2d7dad61bb..aa34b2675e5 100644 --- a/model/model-intest/src/test/resources/schema/piracy.xsd +++ b/model/model-intest/src/test/resources/schema/piracy.xsd @@ -20,7 +20,10 @@ xmlns:tns="http://midpoint.evolveum.com/xml/ns/samples/piracy" xmlns:c="http://midpoint.evolveum.com/xml/ns/public/common/common-3" xmlns:a="http://prism.evolveum.com/xml/ns/public/annotation-3" + xmlns:t="http://prism.evolveum.com/xml/ns/public/types-3" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> + + @@ -99,6 +102,15 @@ + + + MID-5197 + + Locker + 900 + + + diff --git a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ShadowCache.java b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ShadowCache.java index 4f130c45b10..0eeea8f72ce 100644 --- a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ShadowCache.java +++ b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ShadowCache.java @@ -3268,7 +3268,7 @@ public ItemComparisonResult compare(PrismObject repositoryShadow expectedProtectedString = new ProtectedStringType(); expectedProtectedString.setClearValue((String) expectedValue); } - if (protector.compare(repoProtectedString, expectedProtectedString)) { + if (protector.compareCleartext(repoProtectedString, expectedProtectedString)) { return ItemComparisonResult.MATCH; } else { return ItemComparisonResult.MISMATCH; diff --git a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/AbstractIntegrationTest.java b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/AbstractIntegrationTest.java index 918cf01df82..43fd89b1994 100644 --- a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/AbstractIntegrationTest.java +++ b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/AbstractIntegrationTest.java @@ -1447,7 +1447,7 @@ protected boolean compareProtectedString(String expectedClearValue, ProtectedStr } ProtectedStringType expectedPs = new ProtectedStringType(); expectedPs.setClearValue(expectedClearValue); - return protector.compare(actualValue, expectedPs); + return protector.compareCleartext(actualValue, expectedPs); default: throw new IllegalArgumentException("Unknown storage "+storageType); diff --git a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/DummyResourceContoller.java b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/DummyResourceContoller.java index 53eb0078c09..ec741cce695 100644 --- a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/DummyResourceContoller.java +++ b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/DummyResourceContoller.java @@ -43,6 +43,7 @@ import com.evolveum.icf.dummy.resource.DummyObjectClass; import com.evolveum.icf.dummy.resource.DummyOrg; import com.evolveum.icf.dummy.resource.DummyResource; +import com.evolveum.icf.dummy.resource.DummySyncStyle; import com.evolveum.icf.dummy.resource.ObjectAlreadyExistsException; import com.evolveum.icf.dummy.resource.ObjectDoesNotExistException; import com.evolveum.icf.dummy.resource.SchemaViolationException; @@ -125,6 +126,8 @@ public class DummyResourceContoller extends AbstractResourceController { public static final String OBJECTCLASS_ORG_LOCAL_PART = "CustomorgObjectClass"; public static final String DUMMY_POSIX_ACCOUNT_OBJECT_CLASS_NAME = "posixAccount"; + + public static final int PIRATE_SCHEMA_NUMBER_OF_DEFINITIONS = 19; private DummyResource dummyResource; private boolean isExtendedSchema = false; @@ -321,15 +324,24 @@ public void assertDummyResourceSchemaSanity(ResourceSchema resourceSchema, Resou } } - public void assertDummyResourceSchemaSanityExtended(ResourceSchema resourceSchema) { - assertDummyResourceSchemaSanityExtended(resourceSchema, resource.asObjectable(), true); + /** + * @return default account definition + */ + public ObjectClassComplexTypeDefinition assertDummyResourceSchemaSanityExtended(ResourceSchema resourceSchema) { + return assertDummyResourceSchemaSanityExtended(resourceSchema, resource.asObjectable(), true); } - public void assertDummyResourceSchemaSanityExtended(ResourceSchema resourceSchema, ResourceType resourceType, boolean checkDisplayOrder) { - assertDummyResourceSchemaSanityExtended(resourceSchema, resourceType, checkDisplayOrder, 19); + /** + * @return default account definition + */ + public ObjectClassComplexTypeDefinition assertDummyResourceSchemaSanityExtended(ResourceSchema resourceSchema, ResourceType resourceType, boolean checkDisplayOrder) { + return assertDummyResourceSchemaSanityExtended(resourceSchema, resourceType, checkDisplayOrder, PIRATE_SCHEMA_NUMBER_OF_DEFINITIONS); } - public void assertDummyResourceSchemaSanityExtended(ResourceSchema resourceSchema, ResourceType resourceType, boolean checkDisplayOrder, int numberOfAccountDefinitions) { + /** + * @return default account definition + */ + public ObjectClassComplexTypeDefinition assertDummyResourceSchemaSanityExtended(ResourceSchema resourceSchema, ResourceType resourceType, boolean checkDisplayOrder, int numberOfAccountDefinitions) { assertDummyResourceSchemaSanity(resourceSchema, resourceType, checkDisplayOrder); ObjectClassComplexTypeDefinition accountDef = resourceSchema.findDefaultObjectClassDefinition(ShadowKindType.ACCOUNT); @@ -353,6 +365,8 @@ public void assertDummyResourceSchemaSanityExtended(ResourceSchema resourceSchem assertNull("Non-null intent in account definition", accountDef.getIntent()); assertFalse("Account definition is deprecated", accountDef.isDeprecated()); assertFalse("Account definition is auxiliary", accountDef.isAuxiliary()); + + return accountDef; } public void assertRefinedSchemaSanity(RefinedResourceSchema refinedSchema) { @@ -492,4 +506,8 @@ public DummyGroupAsserter assertGroupByName(String name) throws ConnectExc private DummyGroupAsserter assertGroup(DummyGroup group) { return new DummyGroupAsserter<>(group, getName()); } + + public void setSyncStyle(DummySyncStyle syncStyle) { + dummyResource.setSyncStyle(syncStyle); + } } diff --git a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/IntegrationTestTools.java b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/IntegrationTestTools.java index 3c990a664a0..2b0d5380ab4 100644 --- a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/IntegrationTestTools.java +++ b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/IntegrationTestTools.java @@ -1087,7 +1087,7 @@ public static void assertProtectedString(String message, String expectedClearVal ProtectedStringType expectedPs = new ProtectedStringType(); expectedPs.setClearValue(expectedClearValue); assertTrue(message+": hash does not match, expected "+expectedClearValue+", but was "+actualValue, - protector.compare(actualValue, expectedPs)); + protector.compareCleartext(actualValue, expectedPs)); assertFalse(message+": unexpected encrypted value: "+actualValue, actualValue.isEncrypted()); assertNull(message+": unexpected clear value: "+actualValue, actualValue.getClearValue()); break; diff --git a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/prism/PrismContainerValueAsserter.java b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/prism/PrismContainerValueAsserter.java index 83fbfc02c4a..12663895de9 100644 --- a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/prism/PrismContainerValueAsserter.java +++ b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/prism/PrismContainerValueAsserter.java @@ -198,6 +198,14 @@ public PrismContainerAsserter PrismPropertyAsserter> property(QName propertyName) { + PrismProperty property = findProperty(propertyName); + assertNotNull("No property "+propertyName+" in "+desc(), property); + PrismPropertyAsserter> asserter = new PrismPropertyAsserter<>(property, this, propertyName.getLocalPart() + " in " + desc()); + copySetupTo(asserter); + return asserter; + } + // TODO protected String desc() { diff --git a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/prism/PrismPropertyAsserter.java b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/prism/PrismPropertyAsserter.java new file mode 100644 index 00000000000..1cd6149aa56 --- /dev/null +++ b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/prism/PrismPropertyAsserter.java @@ -0,0 +1,86 @@ +/** + * Copyright (c) 2019 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.evolveum.midpoint.test.asserter.prism; + +import static org.testng.AssertJUnit.assertEquals; +import static org.testng.AssertJUnit.assertFalse; +import static org.testng.AssertJUnit.assertNotNull; +import static org.testng.AssertJUnit.assertNull; +import static org.testng.AssertJUnit.assertTrue; + +import java.util.Iterator; +import java.util.List; + +import javax.xml.datatype.XMLGregorianCalendar; +import javax.xml.namespace.QName; + +import com.evolveum.midpoint.prism.Containerable; +import com.evolveum.midpoint.prism.Item; +import com.evolveum.midpoint.prism.ItemDefinition; +import com.evolveum.midpoint.prism.PrismContainer; +import com.evolveum.midpoint.prism.PrismContainerValue; +import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.prism.PrismProperty; +import com.evolveum.midpoint.prism.PrismPropertyValue; +import com.evolveum.midpoint.prism.PrismReference; +import com.evolveum.midpoint.prism.PrismReferenceValue; +import com.evolveum.midpoint.prism.PrismValue; +import com.evolveum.midpoint.prism.path.ItemName; +import com.evolveum.midpoint.prism.util.PrismAsserts; +import com.evolveum.midpoint.test.util.TestUtil; +import com.evolveum.midpoint.util.PrettyPrinter; +import com.evolveum.midpoint.util.QNameUtil; +import com.evolveum.prism.xml.ns._public.types_3.RawType; + +/** + * @author semancik + * + */ +public class PrismPropertyAsserter extends PrismItemAsserter, RA> { + + public PrismPropertyAsserter(PrismProperty property) { + super(property); + } + + public PrismPropertyAsserter(PrismProperty property, String detail) { + super(property, detail); + } + + public PrismPropertyAsserter(PrismProperty property, RA returnAsserter, String detail) { + super(property, returnAsserter, detail); + } + + @Override + public PrismPropertyAsserter assertSize(int expected) { + super.assertSize(expected); + return this; + } + + public PrismPropertyValueAsserter> singleValue() { + assertSize(1); + PrismPropertyValue pval = getItem().getValue(); + PrismPropertyValueAsserter> asserter = new PrismPropertyValueAsserter<>(pval, this, "single value in "+desc()); + copySetupTo(asserter); + return asserter; + } + + // TODO + + protected String desc() { + return getDetails(); + } + +} diff --git a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/prism/PrismPropertyValueAsserter.java b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/prism/PrismPropertyValueAsserter.java index c6e6bcac883..09fec9b548d 100644 --- a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/prism/PrismPropertyValueAsserter.java +++ b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/prism/PrismPropertyValueAsserter.java @@ -43,6 +43,7 @@ import com.evolveum.midpoint.test.util.TestUtil; import com.evolveum.midpoint.util.PrettyPrinter; import com.evolveum.midpoint.util.QNameUtil; +import com.evolveum.prism.xml.ns._public.types_3.ProtectedStringType; import com.evolveum.prism.xml.ns._public.types_3.RawType; /** @@ -67,6 +68,12 @@ public PrismPropertyValueAsserter assertValue(T expectedValue) { assertEquals("Wrong property value in "+desc(), expectedValue, getPrismValue().getValue()); return this; } + + public ProtectedStringAsserter> protectedString() { + ProtectedStringAsserter> asserter = new ProtectedStringAsserter>((ProtectedStringType)getPrismValue().getValue(), this, desc()); + copySetupTo(asserter); + return asserter; + } // TODO diff --git a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/prism/ProtectedStringAsserter.java b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/prism/ProtectedStringAsserter.java new file mode 100644 index 00000000000..7fd391e06d6 --- /dev/null +++ b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/prism/ProtectedStringAsserter.java @@ -0,0 +1,132 @@ +/** + * Copyright (c) 2019 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.evolveum.midpoint.test.asserter.prism; + +import static org.testng.AssertJUnit.assertEquals; +import static org.testng.AssertJUnit.assertFalse; +import static org.testng.AssertJUnit.assertNotNull; +import static org.testng.AssertJUnit.assertNull; +import static org.testng.AssertJUnit.assertTrue; + +import java.util.Map; +import java.util.Map.Entry; + +import javax.xml.namespace.QName; + +import org.testng.AssertJUnit; + +import com.evolveum.midpoint.prism.Containerable; +import com.evolveum.midpoint.prism.crypto.EncryptionException; +import com.evolveum.midpoint.prism.delta.ChangeType; +import com.evolveum.midpoint.prism.delta.ContainerDelta; +import com.evolveum.midpoint.prism.delta.ObjectDelta; +import com.evolveum.midpoint.prism.path.ItemName; +import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.prism.polystring.PolyString; +import com.evolveum.midpoint.prism.schema.PrismSchema; +import com.evolveum.midpoint.test.IntegrationTestTools; +import com.evolveum.midpoint.test.asserter.AbstractAsserter; +import com.evolveum.midpoint.util.MiscUtil; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; +import com.evolveum.prism.xml.ns._public.types_3.ProtectedStringType; + +/** + * @author semancik + * + */ +public class ProtectedStringAsserter extends AbstractAsserter { + + private ProtectedStringType protectedString; + + public ProtectedStringAsserter(ProtectedStringType protectedString) { + super(); + this.protectedString = protectedString; + } + + public ProtectedStringAsserter(ProtectedStringType protectedString, String detail) { + super(detail); + this.protectedString = protectedString; + } + + public ProtectedStringAsserter(ProtectedStringType protectedString, RA returnAsserter, String detail) { + super(returnAsserter, detail); + this.protectedString = protectedString; + } + + public ProtectedStringType getProtectedString() { + return protectedString; + } + + public ProtectedStringAsserter assertIsEncrypted() { + assertTrue("Non-encrypted procted string in "+desc(), protectedString.isEncrypted()); + return this; + } + + public ProtectedStringAsserter assertIsHashed() { + assertTrue("Non-encrypted procted string in "+desc(), protectedString.isHashed()); + return this; + } + + public ProtectedStringAsserter assertHasClearValue() { + assertNotNull("No clear value procted string in "+desc(), protectedString.getClearValue()); + return this; + } + + public ProtectedStringAsserter assertNoClearValue() { + assertNull("Unexpected clear value procted string in "+desc(), protectedString.getClearValue()); + return this; + } + + public ProtectedStringAsserter assertClearValue(String expected) { + AssertJUnit.assertEquals("Wrong clear value in "+desc(), expected, protectedString.getClearValue()); + return this; + } + + /** + * Asserts that protected string is completely equal, including all the randomized things (salt, IV). + */ + public ProtectedStringAsserter assertEquals(ProtectedStringType expected) { + AssertJUnit.assertEquals("Non-equal protected string in "+desc(), expected, protectedString); + return this; + } + + /** + * Checks whether the value inside protected string matches with specified value. + * Works for all types: encrypted, hashed, clear. + */ + public ProtectedStringAsserter assertCompareCleartext(String expected) throws SchemaException, EncryptionException { + ProtectedStringType expectedPs = new ProtectedStringType(); + expectedPs.setClearValue(expected); + assertTrue("Wrong value, cannot match in "+desc(), getProtector().compareCleartext(expectedPs, protectedString)); + return this; + } + + protected String desc() { + return descWithDetails(protectedString); + } + + public ProtectedStringAsserter display() { + display(desc()); + return this; + } + + public ProtectedStringAsserter display(String message) { + IntegrationTestTools.display(message, protectedString); + return this; + } +}