From 67e5586538ce9bceabf7570bfcf16e3c2dc596e5 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Mon, 30 Mar 2020 16:26:26 +0200 Subject: [PATCH 1/6] Fix unqualified 'skip' auto-completion result When auto-completion expression returned 'skip' (as unqualified string or QName), the stage was not properly recognized as empty, and the approval process was started. Now the comparison is properly done with QNameUtil.matchUri. This resolves MID-5895. --- .../primary/PrimaryChangeProcessor.java | 6 ++-- .../assignments/TestAssignmentsAdvanced.java | 32 +++++++++++++++++++ .../assignments-advanced/role-skipped.xml | 31 ++++++++++++++++++ 3 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 model/workflow-impl/src/test/resources/assignments-advanced/role-skipped.xml diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PrimaryChangeProcessor.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PrimaryChangeProcessor.java index 8336aebc3e8..f041c4f697e 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PrimaryChangeProcessor.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PrimaryChangeProcessor.java @@ -32,6 +32,7 @@ import com.evolveum.midpoint.task.api.TaskExecutionStatus; import com.evolveum.midpoint.task.api.TaskManager; import com.evolveum.midpoint.util.DebugUtil; +import com.evolveum.midpoint.util.QNameUtil; import com.evolveum.midpoint.util.exception.*; import com.evolveum.midpoint.util.logging.LoggingUtils; import com.evolveum.midpoint.util.logging.Trace; @@ -204,8 +205,9 @@ public boolean isEmpty(PcpStartInstruction instruction, } // second pass: check the conditions for (ApprovalStageDefinitionType stage : stages) { - if (!SchemaConstants.MODEL_APPROVAL_OUTCOME_SKIP.equals( - evaluateAutoCompleteExpression(instruction.getCase(), stage, instruction, stageComputeHelper, ctx, result))) { + String autoCompletionResult = evaluateAutoCompleteExpression(instruction.getCase(), stage, instruction, + stageComputeHelper, ctx, result); + if (!QNameUtil.matchUri(SchemaConstants.MODEL_APPROVAL_OUTCOME_SKIP, autoCompletionResult)) { return false; } } diff --git a/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/assignments/TestAssignmentsAdvanced.java b/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/assignments/TestAssignmentsAdvanced.java index 0d55bba59d4..8c10493ab98 100644 --- a/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/assignments/TestAssignmentsAdvanced.java +++ b/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/assignments/TestAssignmentsAdvanced.java @@ -73,6 +73,9 @@ public class TestAssignmentsAdvanced extends AbstractWfTestPolicy { private static final File ROLE_ROLE27_FILE = new File(TEST_RESOURCE_DIR, "role-role27-modifications-and.xml"); private static final File ROLE_ROLE28_FILE = new File(TEST_RESOURCE_DIR, "role-role28-modifications-or.xml"); private static final File ROLE_ROLE29_FILE = new File(TEST_RESOURCE_DIR, "role-role29-modifications-no-items.xml"); + + private static final TestResource ROLE_SKIPPED_FILE = new TestResource(TEST_RESOURCE_DIR, "role-skipped.xml", "66134203-f023-4986-bb5c-a350941909eb"); + private static final TestResource ROLE_IDEMPOTENT = new TestResource(TEST_RESOURCE_DIR, "role-idempotent.xml", "e2f2d977-887b-4ea1-99d8-a6a030a1a6c0"); private static final TestResource ROLE_WITH_IDEMPOTENT_METAROLE = new TestResource(TEST_RESOURCE_DIR, "role-with-idempotent-metarole.xml", "34855a80-3899-4ecf-bdb3-9fc008c4ff70"); @@ -127,6 +130,7 @@ public void initSystem(Task initTask, OperationResult initResult) throws Excepti roleRole29Oid = repoAddObjectFromFile(ROLE_ROLE29_FILE, initResult).getOid(); repoAdd(ROLE_IDEMPOTENT, initResult); repoAdd(ROLE_WITH_IDEMPOTENT_METAROLE, initResult); + repoAdd(ROLE_SKIPPED_FILE, initResult); orgLeads2122Oid = repoAddObjectFromFile(ORG_LEADS2122_FILE, initResult).getOid(); @@ -1071,6 +1075,34 @@ public void test910AssignRoleWithIdempotentMetarole() throws Exception { deleteCaseTree(rootCaseOid, result); } + /** + * MID-5895 + */ + @Test + public void test920AssignRoleWithComputedSkip() throws Exception { + given(); + login(userAdministrator); + Task task = getTestTask(); + OperationResult result = task.getResult(); + + when(); + unassignAllRoles(userJackOid); + + ObjectDelta delta = prismContext.deltaFor(UserType.class) + .item(UserType.F_ASSIGNMENT) + .add(new AssignmentType(prismContext).targetRef(ROLE_SKIPPED_FILE.oid, RoleType.COMPLEX_TYPE)) + .asObjectDeltaCast(userJackOid); + + executeChanges(delta, null, task, result); + + then(); + String ref = result.findAsynchronousOperationReference(); + assertNull("Present async operation reference", ref); + + assertUser(userJackOid, "after") + .assertAssignments(1); + } + private void executeAssignRoles123ToJack(boolean immediate, boolean approve1, boolean approve2, boolean approve3a, boolean approve3b, boolean securityDeputy) throws Exception { Task task = getTestTask(); diff --git a/model/workflow-impl/src/test/resources/assignments-advanced/role-skipped.xml b/model/workflow-impl/src/test/resources/assignments-advanced/role-skipped.xml new file mode 100644 index 00000000000..058d13d4b36 --- /dev/null +++ b/model/workflow-impl/src/test/resources/assignments-advanced/role-skipped.xml @@ -0,0 +1,31 @@ + + + + skipped + + + + + + + + + + + + + + + + + + + + From a0a34d3dee925fbd7bc1589cd4ef23d4fba76f62 Mon Sep 17 00:00:00 2001 From: lskublik Date: Mon, 30 Mar 2020 17:48:17 +0200 Subject: [PATCH 2/6] fix for schrodinger tests UsersTest --- .../com/evolveum/midpoint/testing/schrodinger/UsersTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testing/schrodingertest/src/test/java/com/evolveum/midpoint/testing/schrodinger/UsersTest.java b/testing/schrodingertest/src/test/java/com/evolveum/midpoint/testing/schrodinger/UsersTest.java index f164294eb5a..7a67c1e5ea8 100644 --- a/testing/schrodingertest/src/test/java/com/evolveum/midpoint/testing/schrodinger/UsersTest.java +++ b/testing/schrodingertest/src/test/java/com/evolveum/midpoint/testing/schrodinger/UsersTest.java @@ -48,7 +48,7 @@ public void beforeClass() throws IOException { } @Test - public void testUserTablePaging() { + public void test001UserTablePaging() { ListUsersPage users = basicPage.listUsers(); screenshot("listUsers"); @@ -78,7 +78,7 @@ public void testUserTablePaging() { } @Test - public void testSearchWithLookupTable() { + public void test002SearchWithLookupTable() { UserPage user = basicPage.newUser(); user.selectTabBasic() From 11625b9ed5b1f0cc28253305fbc691af65920b59 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Mon, 30 Mar 2020 18:23:53 +0200 Subject: [PATCH 3/6] Fix working with ScriptExpressionEvaluationContext The thread-local instance of this context was set up and teared down with no regards for re-entrance. This caused problems with scripts that called custom functions more than once: the context went away, falling back to initialization-time operation result, which is obviously wrong. So we removed the fallback (now will fail immediately if no context is present) and fixed the re-entrance treatment. This should resolve MID-6145. --- .../expression/functions/CustomFunctions.java | 33 +++++-------------- .../expression/script/ScriptExpression.java | 4 +-- .../ScriptExpressionEvaluationContext.java | 12 +++---- .../script/ScriptExpressionFactory.java | 6 ++-- ...resource-dummy-custom-function-crimson.xml | 1 + 5 files changed, 20 insertions(+), 36 deletions(-) diff --git a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/functions/CustomFunctions.java b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/functions/CustomFunctions.java index 0398200a0b5..37d81018189 100644 --- a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/functions/CustomFunctions.java +++ b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/functions/CustomFunctions.java @@ -56,25 +56,12 @@ public class CustomFunctions { private FunctionLibraryType library; private ExpressionProfile expressionProfile; private PrismContext prismContext; - /** - * Operation result existing at the initialization time. It is used only if we cannot obtain current operation - * result in any other way. - */ - private OperationResult initializationTimeResult; - /** - * Operation result existing at the initialization time. It is used only if we cannot obtain current operation - * result in any other way. - */ - private Task initializationTimeTask; - public CustomFunctions(FunctionLibraryType library, ExpressionFactory expressionFactory, ExpressionProfile expressionProfile, - OperationResult result, Task task) { + public CustomFunctions(FunctionLibraryType library, ExpressionFactory expressionFactory, ExpressionProfile expressionProfile) { this.library = library; this.expressionFactory = expressionFactory; this.expressionProfile = expressionProfile; this.prismContext = expressionFactory.getPrismContext(); - this.initializationTimeResult = result; - this.initializationTimeTask = task; } /** @@ -91,22 +78,20 @@ public Object execute(String fu if (ctx.getTask() != null) { task = ctx.getTask(); } else { - LOGGER.warn("No task in ScriptExpressionEvaluationContext for the current thread found. Using " - + "initialization-time task: {}", initializationTimeTask); - task = initializationTimeTask; + // We shouldn't use task of unknown provenience. + throw new IllegalStateException("No task in ScriptExpressionEvaluationContext for the current thread found"); } if (ctx.getResult() != null) { result = ctx.getResult(); } else { - LOGGER.warn("No operation result in ScriptExpressionEvaluationContext for the current thread found. Using " - + "initialization-time op. result"); - result = initializationTimeResult; + // Better throwing an exception than introducing memory leak if initialization-time result is used. + // This situation should never occur anyway. + throw new IllegalStateException("No operation result in ScriptExpressionEvaluationContext for the current thread found"); } } else { - LOGGER.warn("No ScriptExpressionEvaluationContext for current thread found. Using initialization-time task " - + "and operation result: {}", initializationTimeTask); - task = initializationTimeTask; - result = initializationTimeResult; + // Better throwing an exception than introducing memory leak if initialization-time result is used. + // This situation should never occur anyway. + throw new IllegalStateException("No ScriptExpressionEvaluationContext for current thread found"); } List functions = library.getFunction().stream().filter(expression -> functionName.equals(expression.getName())).collect(Collectors.toList()); diff --git a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/script/ScriptExpression.java b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/script/ScriptExpression.java index f4fca562274..b270e68f7e8 100644 --- a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/script/ScriptExpression.java +++ b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/script/ScriptExpression.java @@ -181,8 +181,8 @@ public List evaluate(ScriptExpressionEvaluationContext context.setTrace(null); } context.setResult(result); // a bit of hack: this is to provide some tracing of script evaluation + ScriptExpressionEvaluationContext oldContext = context.setupThreadLocal(); try { - context.setupThreadLocal(); List expressionResult = evaluator.evaluate(context); if (context.getTrace() != null) { @@ -197,7 +197,7 @@ public List evaluate(ScriptExpressionEvaluationContext result.recordFatalError(ex.getMessage(), ex); throw ex; } finally { - context.cleanupThreadLocal(); + context.cleanupThreadLocal(oldContext); result.computeStatusIfUnknown(); context.setResult(parentResult); // a bit of hack } diff --git a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/script/ScriptExpressionEvaluationContext.java b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/script/ScriptExpressionEvaluationContext.java index 2e5b73a9008..c7a28dd2424 100644 --- a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/script/ScriptExpressionEvaluationContext.java +++ b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/script/ScriptExpressionEvaluationContext.java @@ -160,16 +160,14 @@ public void setResult(OperationResult result) { this.result = result; } - public static ThreadLocal getThreadlocalcontext() { - return THREAD_LOCAL_CONTEXT; - } - - public void setupThreadLocal() { + ScriptExpressionEvaluationContext setupThreadLocal() { + ScriptExpressionEvaluationContext oldContext = THREAD_LOCAL_CONTEXT.get(); THREAD_LOCAL_CONTEXT.set(this); + return oldContext; } - public void cleanupThreadLocal() { - THREAD_LOCAL_CONTEXT.set(null); + void cleanupThreadLocal(ScriptExpressionEvaluationContext oldContext) { + THREAD_LOCAL_CONTEXT.set(oldContext); } public static ScriptExpressionEvaluationContext getThreadLocal() { diff --git a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/script/ScriptExpressionFactory.java b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/script/ScriptExpressionFactory.java index 27fb55044ed..286e43881bd 100644 --- a/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/script/ScriptExpressionFactory.java +++ b/model/model-common/src/main/java/com/evolveum/midpoint/model/common/expression/script/ScriptExpressionFactory.java @@ -119,7 +119,7 @@ public ScriptExpression createScriptExpression( String shortDesc, Task task, OperationResult result) throws ExpressionSyntaxException, SecurityViolationException { - initializeCustomFunctionsLibraryCache(expressionFactory, task, result); + initializeCustomFunctionsLibraryCache(expressionFactory, result); //cache cleanup method String language = getLanguage(expressionType); @@ -168,7 +168,7 @@ private ScriptExpressionProfile processScriptExpressionProfile(ExpressionProfile } // if performance becomes an issue, replace 'synchronized' with something more elaborate - private synchronized void initializeCustomFunctionsLibraryCache(ExpressionFactory expressionFactory, Task task, + private synchronized void initializeCustomFunctionsLibraryCache(ExpressionFactory expressionFactory, OperationResult result) throws ExpressionSyntaxException { if (customFunctionLibraryCache != null) { return; @@ -187,7 +187,7 @@ private synchronized void initializeCustomFunctionsLibraryCache(ExpressionFactor FunctionLibrary customLibrary = new FunctionLibrary(); customLibrary.setVariableName(object.getName().getOrig()); customLibrary.setGenericFunctions( - new CustomFunctions(object.asObjectable(), expressionFactory, expressionProfile, result, task)); + new CustomFunctions(object.asObjectable(), expressionFactory, expressionProfile)); customLibrary.setNamespace(MidPointConstants.NS_FUNC_CUSTOM); customFunctionLibraryCache.put(object.getName().getOrig(), customLibrary); return true; diff --git a/model/model-intest/src/test/resources/mapping/resource-dummy-custom-function-crimson.xml b/model/model-intest/src/test/resources/mapping/resource-dummy-custom-function-crimson.xml index d95005dd8a0..d9fc2446fd1 100644 --- a/model/model-intest/src/test/resources/mapping/resource-dummy-custom-function-crimson.xml +++ b/model/model-intest/src/test/resources/mapping/resource-dummy-custom-function-crimson.xml @@ -62,6 +62,7 @@ map = new HashMap(); map.put("username", name); + myLib.execute("getName", map) // dummy execution, to demonstrate MID-6145 name = myLib.execute("getName", map); log.info("custom library name: " + name) return name; From ac56df85d4a8411d26587f3e63a30fb9eaca6bf7 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Tue, 31 Mar 2020 15:14:14 +0200 Subject: [PATCH 4/6] Add XML-JSON-YAML switch to Query playground Experimental! --- .../configuration/PageRepositoryQuery.html | 4 +- .../configuration/PageRepositoryQuery.java | 51 +++++++++++++++++-- 2 files changed, 50 insertions(+), 5 deletions(-) diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/PageRepositoryQuery.html b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/PageRepositoryQuery.html index 391db944d77..699b0b3ac69 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/PageRepositoryQuery.html +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/PageRepositoryQuery.html @@ -20,7 +20,9 @@

-
+
+
+
diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/PageRepositoryQuery.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/PageRepositoryQuery.java index 399ae4d8f60..a889a69b27a 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/PageRepositoryQuery.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/PageRepositoryQuery.java @@ -37,6 +37,7 @@ import com.evolveum.midpoint.web.component.AceEditor; import com.evolveum.midpoint.web.component.AjaxSubmitButton; import com.evolveum.midpoint.web.component.form.CheckFormGroup; +import com.evolveum.midpoint.web.component.input.DataLanguagePanel; import com.evolveum.midpoint.web.component.input.DropDownChoicePanel; import com.evolveum.midpoint.web.component.input.QNameChoiceRenderer; import com.evolveum.midpoint.web.component.search.Search; @@ -109,6 +110,7 @@ public class PageRepositoryQuery extends PageAdminConfiguration { private static final String ID_DISTINCT = "distinct"; private static final String ID_HIBERNATE_PARAMETERS_NOTE = "hibernateParametersNote"; private static final String ID_INCOMPLETE_RESULTS_NOTE = "incompleteResultsNote"; + private static final String ID_VIEW_BUTTON_PANEL = "viewButtonPanel"; private static final String SAMPLES_DIR = "query-samples"; private static final List SAMPLES = Arrays.asList( @@ -138,8 +140,19 @@ public class PageRepositoryQuery extends PageAdminConfiguration { private final NonEmptyModel model = new NonEmptyWrapperModel<>(new Model<>(new RepoQueryDto())); private final boolean isAdmin; + private String dataLanguage; + enum Action {TRANSLATE_ONLY, EXECUTE_MIDPOINT, EXECUTE_HIBERNATE } + @Override + protected void onInitialize() { + super.onInitialize(); + if (dataLanguage == null) { + dataLanguage = determineDataLanguage(); + } + initLayout(); + } + public PageRepositoryQuery() { this(null, null); } @@ -156,8 +169,6 @@ public PageRepositoryQuery(QName objectType, String queryText) { admin = false; } isAdmin = admin; - - initLayout(); } private void initLayout() { @@ -219,6 +230,25 @@ protected void onUpdate(AjaxRequestTarget target) { midPointQueryButtonBar.setOutputMarkupId(true); mainForm.add(midPointQueryButtonBar); + DataLanguagePanel dataLanguagePanel = + new DataLanguagePanel(ID_VIEW_BUTTON_PANEL, dataLanguage, QueryType.class, PageRepositoryQuery.this) { + private static final long serialVersionUID = 1L; + + @Override + protected void onLanguageSwitched(AjaxRequestTarget target, int updatedIndex, String updatedLanguage, + String objectString) { + model.getObject().setMidPointQuery(objectString); + dataLanguage = updatedLanguage; + target.add(mainForm); + } + @Override + protected String getObjectStringRepresentation() { + return model.getObject().getMidPointQuery(); + } + }; + dataLanguagePanel.setOutputMarkupId(true); + mainForm.add(dataLanguagePanel); + AjaxSubmitButton executeMidPoint = new AjaxSubmitButton(ID_EXECUTE_MIDPOINT, createStringResource("PageRepositoryQuery.button.translateAndExecute")) { @Override protected void onError(AjaxRequestTarget target) { @@ -280,7 +310,20 @@ protected void onUpdate(AjaxRequestTarget target) { try { String localTypeName = StringUtils.substringBefore(sampleName, "_"); model.getObject().setObjectType(new QName(SchemaConstants.NS_C, localTypeName)); - model.getObject().setMidPointQuery(IOUtils.toString(is, StandardCharsets.UTF_8)); + String xml = IOUtils.toString(is, StandardCharsets.UTF_8); + String serialization; + if (PrismContext.LANG_XML.equals(dataLanguage)) { + serialization = xml; + } else { + PrismContext prismContext = getPrismContext(); + try { + QueryType parsed = prismContext.parserFor(xml).xml().parseRealValue(QueryType.class); + serialization = prismContext.serializerFor(dataLanguage).serializeRealValue(parsed); + } catch (Throwable t) { + serialization = "Couldn't serialize sample: " + t.getMessage(); + } + } + model.getObject().setMidPointQuery(serialization); model.getObject().setHibernateQuery(""); model.getObject().setHibernateParameters(""); model.getObject().setQueryResultObject(null); @@ -506,7 +549,7 @@ private void updateRequestWithMidpointQuery(RepositoryQueryDiagRequest request, if (clazz == null) { throw new SchemaException("Couldn't find compile-time class for object type of " + objectType); } - QueryType queryType = prismContext.parserFor(queryText).xml().parseRealValue(QueryType.class); + QueryType queryType = prismContext.parserFor(queryText).language(dataLanguage).parseRealValue(QueryType.class); request.setType(clazz); ObjectQuery objectQuery = prismContext.getQueryConverter().createObjectQuery(clazz, queryType); ObjectQuery queryWithExprEvaluated = ExpressionUtil.evaluateQueryExpressions(objectQuery, new ExpressionVariables(), From e0a8a9042d0b64d24e995371a05f0f7d844fb0c3 Mon Sep 17 00:00:00 2001 From: lskublik Date: Tue, 31 Mar 2020 17:19:46 +0200 Subject: [PATCH 5/6] fix for saving of new task with set handlerUri (MID-6146) --- .../page/admin/server/TaskBasicTabPanel.java | 9 --- .../server/TaskHandlerSelectorPanel.html | 4 +- .../schrodinger/page/TaskPageTest.java | 62 +++++++++++++++++++ .../schrodingertest/testng-integration.xml | 5 ++ 4 files changed, 69 insertions(+), 11 deletions(-) create mode 100644 testing/schrodingertest/src/test/java/com/evolveum/midpoint/testing/schrodinger/page/TaskPageTest.java diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskBasicTabPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskBasicTabPanel.java index 43ecee1e169..2e0f2ea7272 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskBasicTabPanel.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskBasicTabPanel.java @@ -92,15 +92,6 @@ protected void onUpdatePerformed(AjaxRequestTarget target) { } } - PrismObjectWrapperFactory wrapperFactory = TaskBasicTabPanel.this.getPageBase().findObjectWrapperFactory(getTask().asPrismObject().getDefinition()); - Task task = getPageBase().createSimpleTask(OPERATION_UPDATE_WRAPPER); - OperationResult result = task.getResult(); - WrapperContext ctx = new WrapperContext(task, result); - try { - wrapperFactory.updateWrapper(TaskBasicTabPanel.this.getModelObject(), ctx); - } catch (SchemaException e) { - LOGGER.error("Unexpected problem occurs during updating wrapper. Reason: {}", e.getMessage(), e); - } updateHandlerPerformed(target); } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskHandlerSelectorPanel.html b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskHandlerSelectorPanel.html index 7b2235cfb97..f32bc4d9712 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskHandlerSelectorPanel.html +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskHandlerSelectorPanel.html @@ -22,10 +22,10 @@
-
+
-
+
diff --git a/testing/schrodingertest/src/test/java/com/evolveum/midpoint/testing/schrodinger/page/TaskPageTest.java b/testing/schrodingertest/src/test/java/com/evolveum/midpoint/testing/schrodinger/page/TaskPageTest.java new file mode 100644 index 00000000000..dceba596a0a --- /dev/null +++ b/testing/schrodingertest/src/test/java/com/evolveum/midpoint/testing/schrodinger/page/TaskPageTest.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2010-2019 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.testing.schrodinger.page; + +import com.codeborne.selenide.Selenide; + +import com.evolveum.midpoint.schrodinger.component.AssignmentHolderBasicTab; +import com.evolveum.midpoint.schrodinger.component.common.PrismForm; +import com.evolveum.midpoint.schrodinger.page.AssignmentHolderDetailsPage; +import com.evolveum.midpoint.schrodinger.page.task.ListTasksPage; +import com.evolveum.midpoint.schrodinger.page.task.TaskPage; +import com.evolveum.midpoint.schrodinger.page.user.ListUsersPage; +import com.evolveum.midpoint.schrodinger.page.user.UserPage; +import com.evolveum.midpoint.testing.schrodinger.AbstractSchrodingerTest; +import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; + +import org.testng.Assert; +import org.testng.annotations.Test; + +/** + * @author skublik + */ + +public class TaskPageTest extends AbstractSchrodingerTest { + + @Test + public void test001createNewTask() { + + String name = "NewTest"; + String handler = "http://midpoint.evolveum.com/xml/ns/public/model/synchronization/task/recompute/handler-3"; + TaskPage task = basicPage.newTask(); + task.selectTabBasic().form().addAttributeValue("handlerUri", handler); + Selenide.sleep(2000); + task.selectTabBasic() + .form() + .addAttributeValue("name", name) + .selectOption("recurrence","Single") + .selectOption("objectType","User") + .and() + .and() + .clickSave(); + + ListTasksPage tasksPage = basicPage.listTasks(); + PrismForm> taskForm = tasksPage + .table() + .search() + .byName() + .inputValue(name) + .updateSearch() + .and() + .clickByName(name) + .selectTabBasic() + .form(); + + Assert.assertTrue(taskForm.compareInputAttributeValue("name", name)); + Assert.assertTrue(taskForm.compareInputAttributeValue("handlerUri", handler)); + } +} diff --git a/testing/schrodingertest/testng-integration.xml b/testing/schrodingertest/testng-integration.xml index 528cb4721ec..b1793f0ef4d 100644 --- a/testing/schrodingertest/testng-integration.xml +++ b/testing/schrodingertest/testng-integration.xml @@ -103,4 +103,9 @@ + + + + + \ No newline at end of file From 0f44c9119f8e9c385cb6bd598fa06b748bb28c51 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Wed, 1 Apr 2020 00:26:55 +0200 Subject: [PATCH 6/6] Add a couple of tests for MID-5846 (Fortunately, all of them pass. So this issue seems to be already fixed.) --- .../mapping/TestMappingAutoInbound.java | 32 +++++--- .../intest/mapping/TestMappingInbound.java | 50 +++++++++--- .../model/intest/rbac/TestAutoassign.java | 6 +- .../resources/mapping/archetype-pirate.xml | 11 +++ .../mapping/resource-dummy-autogreen.xml | 4 +- .../mapping/resource-dummy-tea-green.xml | 78 ++++++++++++++++++- .../test/resources/mapping/role-simple.xml | 11 +++ .../rbac/autoassign/role-unit-sleeper.xml | 2 +- .../rbac/autoassign/role-unit-walker.xml | 2 +- .../test/asserter/AssignmentAsserter.java | 9 +++ .../test/asserter/AssignmentsAsserter.java | 7 ++ 11 files changed, 185 insertions(+), 27 deletions(-) create mode 100644 model/model-intest/src/test/resources/mapping/archetype-pirate.xml create mode 100644 model/model-intest/src/test/resources/mapping/role-simple.xml diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/mapping/TestMappingAutoInbound.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/mapping/TestMappingAutoInbound.java index 1aa62c982cf..28cce8fc5c4 100644 --- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/mapping/TestMappingAutoInbound.java +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/mapping/TestMappingAutoInbound.java @@ -15,6 +15,7 @@ import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.test.DummyResourceContoller; +import com.evolveum.midpoint.test.asserter.UserAsserter; import com.evolveum.midpoint.test.util.TestUtil; import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentPolicyEnforcementType; import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; @@ -25,6 +26,7 @@ import java.io.File; import java.util.Arrays; +import java.util.Collections; import javax.xml.namespace.QName; @@ -196,15 +198,25 @@ public void test200ImportFromResourceAssociations() throws Exception { SearchResultList> users = modelService.searchObjects(UserType.class, null, null, task, result); display("Users after import", users); - PrismObject userHermanAfter = findUserByUsername(USER_HERMAN_USERNAME); - display("User after", userHermanAfter); - userHermanOid = userHermanAfter.getOid(); - assertUser(userHermanAfter, userHermanAfter.getOid(), USER_HERMAN_USERNAME, USER_HERMAN_FULL_NAME, null, null); - assertAssignedRole(userHermanAfter, ROLE_AUTODIDACTIC_OID); - assertAssignedRole(userHermanAfter, ROLE_AUTOGRAPHIC_OID); - assertAssignedRole(userHermanAfter, ROLE_AUTOTESTERS_OID); - assertAssignedRole(userHermanAfter, ROLE_AUTOCRATIC_OID); - assertAssignments(userHermanAfter, 4); + UserAsserter userAsserter = assertUserAfterByUsername(USER_HERMAN_USERNAME); + userHermanOid = userAsserter.getOid(); + PrismObject userAfter = userAsserter.getObject(); + assertUser(userAfter, userHermanOid, USER_HERMAN_USERNAME, USER_HERMAN_FULL_NAME, null, null); + userAsserter + .assignments() + .forRole(ROLE_AUTODIDACTIC_OID) + .assertOriginMappingName("Assignment from title") // MID-5846 + .end() + .forRole(ROLE_AUTOGRAPHIC_OID) + .assertOriginMappingName("Assignment from title") // MID-5846 + .end() + .forRole(ROLE_AUTOTESTERS_OID) + .assertOriginMappingName("Assignment from group") // MID-5846 + .end() + .forRole(ROLE_AUTOCRATIC_OID) + .assertOriginMappingName("Assignment from group") // MID-5846 + .end() + .assertAssignments(4); assertEquals("Unexpected number of users", getNumberOfUsers() + 1, users.size()); } @@ -246,7 +258,7 @@ public void test301removeUserFromAutoGroup() throws Exception { craticGroup.removeMember(USER_HERMAN_USERNAME); DummyAccount hermanAccount = getDummyAccount(RESOURCE_DUMMY_AUTOGREEN_NAME, USER_HERMAN_USERNAME); - hermanAccount.removeAttributeValues(DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_TITLE_NAME, Arrays.asList("didactic")); + hermanAccount.removeAttributeValues(DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_TITLE_NAME, Collections.singletonList("didactic")); assertNoDummyGroupMember(RESOURCE_DUMMY_AUTOGREEN_NAME, GROUP_DUMMY_CRATIC_NAME, USER_HERMAN_USERNAME); diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/mapping/TestMappingInbound.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/mapping/TestMappingInbound.java index d6d45a36aef..9fe69742816 100644 --- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/mapping/TestMappingInbound.java +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/mapping/TestMappingInbound.java @@ -20,6 +20,8 @@ import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.test.TestResource; + import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.annotation.DirtiesContext.ClassMode; import org.springframework.test.context.ContextConfiguration; @@ -78,6 +80,11 @@ public class TestMappingInbound extends AbstractMappingTest { private static final ItemName VALUE = new ItemName(NS_PIRACY, "value"); private static final String DUMMY_ACCOUNT_ATTRIBUTE_CONTROLLER_NAME = "controllerName"; + private static final String DUMMY_ACCOUNT_ATTRIBUTE_ROLE_NAME = "roleName"; + private static final String DUMMY_ACCOUNT_ATTRIBUTE_ARCHETYPE_NAME = "archetypeName"; + + private static final TestResource ROLE_SIMPLE = new TestResource(TEST_DIR, "role-simple.xml", "dc2b28f4-3aab-4212-8ab7-c4f5fc0c511a"); + private static final TestResource ARCHETYPE_PIRATE = new TestResource(TEST_DIR, "archetype-pirate.xml", "0bb1d8df-501d-4648-9d36-c8395df95183"); private ProtectedStringType mancombLocker; private String userLeelooOid; @@ -87,6 +94,9 @@ public void initSystem(Task initTask, OperationResult initResult) throws Excepti super.initSystem(initTask, initResult); assumeAssignmentPolicy(AssignmentPolicyEnforcementType.FULL); + repoAdd(ROLE_SIMPLE, initResult); + repoAdd(ARCHETYPE_PIRATE, initResult); + initDummyResource(RESOURCE_DUMMY_TEA_GREEN_NAME, RESOURCE_DUMMY_TEA_GREEN_FILE, RESOURCE_DUMMY_TEA_GREEN_OID, controller -> { controller.extendSchemaPirate(); @@ -99,6 +109,10 @@ public void initSystem(Task initTask, OperationResult initResult) throws Excepti DUMMY_ACCOUNT_ATTRIBUTE_TREASON_RISK_NAME, Integer.class, false, false); controller.addAttrDef(controller.getDummyResource().getAccountObjectClass(), DUMMY_ACCOUNT_ATTRIBUTE_CONTROLLER_NAME, String.class, false, false); + controller.addAttrDef(controller.getDummyResource().getAccountObjectClass(), + DUMMY_ACCOUNT_ATTRIBUTE_ROLE_NAME, String.class, false, true); + controller.addAttrDef(controller.getDummyResource().getAccountObjectClass(), + DUMMY_ACCOUNT_ATTRIBUTE_ARCHETYPE_NAME, String.class, false, false); controller.setSyncStyle(DummySyncStyle.SMART); }, initTask, initResult); @@ -122,7 +136,7 @@ public void test010SanitySchema() throws Exception { displayDumpable("Parsed resource schema (tea-green)", returnedSchema); ObjectClassComplexTypeDefinition accountDef = getDummyResourceController(RESOURCE_DUMMY_TEA_GREEN_NAME) .assertDummyResourceSchemaSanityExtended(returnedSchema, resourceType, false, - DummyResourceContoller.PIRATE_SCHEMA_NUMBER_OF_DEFINITIONS + 4); // MID-5197 + DummyResourceContoller.PIRATE_SCHEMA_NUMBER_OF_DEFINITIONS + 6); // MID-5197 ResourceAttributeDefinition lockerDef = accountDef.findAttributeDefinition(DUMMY_ACCOUNT_ATTRIBUTE_LOCKER_NAME); assertNotNull("No locker attribute definition", lockerDef); @@ -153,6 +167,8 @@ public void test110AddDummyTeaGreenAccountMancomb() throws Exception { account.addAttributeValues(DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_LOCATION_NAME, "Melee Island"); account.addAttributeValues(DUMMY_ACCOUNT_ATTRIBUTE_LOCKER_NAME, LOCKER_BIG_SECRET); // MID-5197 account.addAttributeValues(DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_DRINK_NAME, "water"); + account.addAttributeValues(DUMMY_ACCOUNT_ATTRIBUTE_ROLE_NAME, "simple"); + account.addAttributeValues(DUMMY_ACCOUNT_ATTRIBUTE_ARCHETYPE_NAME, "pirate"); /// WHEN when(); @@ -172,20 +188,32 @@ public void test110AddDummyTeaGreenAccountMancomb() throws Exception { assertShadowOperationalData(accountMancomb, SynchronizationSituationType.LINKED, null); UserAsserter mancombUserAsserter = assertUserAfterByUsername(ACCOUNT_MANCOMB_DUMMY_USERNAME); + // @formatter:off mancombLocker = mancombUserAsserter .links() - .single() - .assertOid(accountMancomb.getOid()) - .end() - .end() + .single() + .assertOid(accountMancomb.getOid()) + .end() + .end() .assertAdministrativeStatus(ActivationStatusType.ENABLED) + .assignments() + .forRole(ROLE_SIMPLE.oid) + .assertSubtype("auto-role") + .assertOriginMappingName("Role by name") // MID-5846 + .end() + .forArchetype(ARCHETYPE_PIRATE.oid) + .assertSubtype("auto-archetype") + .assertOriginMappingName("Archetype by name") // MID-5846 + .end() + .end() .extension() - .property(PIRACY_LOCKER) - .singleValue() - .protectedString() - .assertIsEncrypted() - .assertCompareCleartext(LOCKER_BIG_SECRET) - .getProtectedString(); + .property(PIRACY_LOCKER) + .singleValue() + .protectedString() + .assertIsEncrypted() + .assertCompareCleartext(LOCKER_BIG_SECRET) + .getProtectedString(); + // @formatter:on assertJpegPhoto(UserType.class, mancombUserAsserter.getOid(), "water".getBytes(StandardCharsets.UTF_8), result); // assertUsers(6); diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/rbac/TestAutoassign.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/rbac/TestAutoassign.java index 5076a4b7bcd..08232a4986f 100644 --- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/rbac/TestAutoassign.java +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/rbac/TestAutoassign.java @@ -96,6 +96,7 @@ public void test100ModifyUnitWorker() throws Exception { .single() .assertTargetOid(ROLE_UNIT_WORKER_OID) .assertTargetType(RoleType.COMPLEX_TYPE) + .assertOriginMappingName("autoassign-worker") // MID-5846 .end() .end() .links() @@ -155,11 +156,14 @@ public void test110ModifyUnitSleepwalker() throws Exception { .targetOid(ROLE_UNIT_SLEEPER_OID) .find() .assertTargetType(RoleType.COMPLEX_TYPE) + .assertOriginMappingName("autoassign-sleeper") // MID-5846 .activation() .assertValidTo(ROLE_SLEEPER_AUTOASSIGN_VALID_TO) .end() .end() - .assertRole(ROLE_UNIT_WALKER_OID) + .forRole(ROLE_UNIT_WALKER_OID) + .assertOriginMappingName("autoassign-walker") // MID-5846 + .end() .end() .links() .single(); diff --git a/model/model-intest/src/test/resources/mapping/archetype-pirate.xml b/model/model-intest/src/test/resources/mapping/archetype-pirate.xml new file mode 100644 index 00000000000..f500b1229e0 --- /dev/null +++ b/model/model-intest/src/test/resources/mapping/archetype-pirate.xml @@ -0,0 +1,11 @@ + + + + pirate + diff --git a/model/model-intest/src/test/resources/mapping/resource-dummy-autogreen.xml b/model/model-intest/src/test/resources/mapping/resource-dummy-autogreen.xml index c663df47c7d..b8e1a26e88a 100644 --- a/model/model-intest/src/test/resources/mapping/resource-dummy-autogreen.xml +++ b/model/model-intest/src/test/resources/mapping/resource-dummy-autogreen.xml @@ -80,6 +80,7 @@ ri:title + Assignment from title strong @@ -137,6 +138,7 @@ ri:group + Assignment from group true strong @@ -208,7 +210,6 @@ icfs:name - @@ -257,7 +258,6 @@ ri:CustomprivilegeObjectClass - 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 abfe77f59f1..519a1afc6c7 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 @@ -208,7 +208,83 @@ An authoritative resource, used to test for MID-2100 (inbound mappings acting bo - + + + ri:roleName + + Role by name + strong + + + RoleType + + + name + + + + + + + auto-role + + + + + assignment + + + + + + + + + + + ri:archetypeName + + Archetype by name + strong + + + ArchetypeType + + + name + + + + + + + auto-archetype + + + + + assignment + + + + + + + + + + + 5 diff --git a/model/model-intest/src/test/resources/mapping/role-simple.xml b/model/model-intest/src/test/resources/mapping/role-simple.xml new file mode 100644 index 00000000000..085accebdad --- /dev/null +++ b/model/model-intest/src/test/resources/mapping/role-simple.xml @@ -0,0 +1,11 @@ + + + + simple + diff --git a/model/model-intest/src/test/resources/rbac/autoassign/role-unit-sleeper.xml b/model/model-intest/src/test/resources/rbac/autoassign/role-unit-sleeper.xml index f60237b1230..bb2f8d1b9f5 100644 --- a/model/model-intest/src/test/resources/rbac/autoassign/role-unit-sleeper.xml +++ b/model/model-intest/src/test/resources/rbac/autoassign/role-unit-sleeper.xml @@ -28,7 +28,7 @@ true - autoassign-worker + autoassign-sleeper true organizationalUnit diff --git a/model/model-intest/src/test/resources/rbac/autoassign/role-unit-walker.xml b/model/model-intest/src/test/resources/rbac/autoassign/role-unit-walker.xml index 610f97c7e71..fac2063254c 100644 --- a/model/model-intest/src/test/resources/rbac/autoassign/role-unit-walker.xml +++ b/model/model-intest/src/test/resources/rbac/autoassign/role-unit-walker.xml @@ -28,7 +28,7 @@ true - autoassign-worker + autoassign-walker true organizationalUnit diff --git a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/AssignmentAsserter.java b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/AssignmentAsserter.java index 24d2757bbd0..787c9efed7d 100644 --- a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/AssignmentAsserter.java +++ b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/AssignmentAsserter.java @@ -84,6 +84,15 @@ public AssignmentAsserter assertSubtype(String expected) { return this; } + public AssignmentAsserter assertOriginMappingName(String expected) { + assertEquals("Wrong origin mapping name", expected, getOriginMappingName()); + return this; + } + + private String getOriginMappingName() { + return assignment.getMetadata() != null ? assignment.getMetadata().getOriginMappingName() : null; + } + public ActivationAsserter> activation() { ActivationAsserter> asserter = new ActivationAsserter<>(assignment.getActivation(), this, getDetails()); copySetupTo(asserter); diff --git a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/AssignmentsAsserter.java b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/AssignmentsAsserter.java index 88e643f4c6c..22043a1bea5 100644 --- a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/AssignmentsAsserter.java +++ b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/asserter/AssignmentsAsserter.java @@ -97,6 +97,13 @@ public AssignmentAsserter> forRole(String roleOid) .find(); } + public AssignmentAsserter> forArchetype(String archetypeOid) throws ObjectNotFoundException, SchemaException { + return by() + .targetOid(archetypeOid) + .targetType(ArchetypeType.COMPLEX_TYPE) + .find(); + } + public AssignmentsAsserter assertRole(String roleOid) throws ObjectNotFoundException, SchemaException { by() .targetOid(roleOid)