diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/ReconciliationTaskHandler.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/ReconciliationTaskHandler.java index 8e2b71499a1..e4f9fde9d4c 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/ReconciliationTaskHandler.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/ReconciliationTaskHandler.java @@ -21,12 +21,6 @@ import javax.annotation.PostConstruct; import javax.xml.namespace.QName; -import com.evolveum.midpoint.prism.delta.ChangeType; -import com.evolveum.midpoint.repo.cache.RepositoryCache; -import com.evolveum.midpoint.schema.ResultHandler; -import com.evolveum.midpoint.util.logging.LoggingUtils; - -import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; @@ -42,15 +36,19 @@ import com.evolveum.midpoint.model.impl.util.Utils; import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.PrismObjectDefinition; +import com.evolveum.midpoint.prism.delta.ChangeType; import com.evolveum.midpoint.prism.delta.ItemDelta; import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.prism.delta.PropertyDelta; +import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.query.AndFilter; import com.evolveum.midpoint.prism.query.EqualFilter; import com.evolveum.midpoint.prism.query.LessFilter; import com.evolveum.midpoint.prism.query.NotFilter; import com.evolveum.midpoint.prism.query.ObjectFilter; import com.evolveum.midpoint.prism.query.ObjectQuery; +import com.evolveum.midpoint.prism.query.OrFilter; import com.evolveum.midpoint.prism.query.RefFilter; import com.evolveum.midpoint.prism.xml.XmlTypeConverter; import com.evolveum.midpoint.provisioning.api.ChangeNotificationDispatcher; @@ -58,14 +56,15 @@ import com.evolveum.midpoint.provisioning.api.ProvisioningService; import com.evolveum.midpoint.provisioning.api.ResourceObjectShadowChangeDescription; import com.evolveum.midpoint.repo.api.RepositoryService; +import com.evolveum.midpoint.repo.cache.RepositoryCache; import com.evolveum.midpoint.schema.GetOperationOptions; +import com.evolveum.midpoint.schema.ResultHandler; import com.evolveum.midpoint.schema.SelectorOptions; import com.evolveum.midpoint.schema.constants.SchemaConstants; import com.evolveum.midpoint.schema.processor.ObjectClassComplexTypeDefinition; import com.evolveum.midpoint.schema.result.OperationConstants; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.schema.result.OperationResultStatus; -import com.evolveum.midpoint.schema.util.ObjectQueryUtil; import com.evolveum.midpoint.schema.util.ObjectTypeUtil; import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.task.api.TaskCategory; @@ -81,12 +80,15 @@ import com.evolveum.midpoint.util.exception.ObjectNotFoundException; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.exception.SecurityViolationException; +import com.evolveum.midpoint.util.logging.LoggingUtils; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.FailedOperationTypeType; import com.evolveum.midpoint.xml.ns._public.common.common_3.LayerType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; +import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; /** * The task hander for reconciliation. @@ -534,8 +536,12 @@ private boolean performShadowReconciliation(final PrismObject reso LessFilter timestampFilter = LessFilter.createLess(ShadowType.F_FULL_SYNCHRONIZATION_TIMESTAMP, ShadowType.class, prismContext, XmlTypeConverter.createXMLGregorianCalendar(startTimestamp) , true); - ObjectFilter filter = AndFilter.createAnd(timestampFilter, - RefFilter.createReferenceEqual(ShadowType.F_RESOURCE_REF, ShadowType.class, prismContext, resource.getOid()), + PrismObjectDefinition shadowDef = prismContext.getSchemaRegistry().findObjectDefinitionByCompileTimeClass(ShadowType.class); + EqualFilter nullTimestamptFilter = EqualFilter.createNullEqual(new ItemPath(ShadowType.F_FULL_SYNCHRONIZATION_TIMESTAMP), shadowDef.findPropertyDefinition(ShadowType.F_FULL_SYNCHRONIZATION_TIMESTAMP), null); + OrFilter fullTimestampFilter = OrFilter.createOr(timestampFilter, nullTimestamptFilter); + ObjectReferenceType ref = ObjectTypeUtil.createObjectRef(resource); + ObjectFilter filter = AndFilter.createAnd(fullTimestampFilter, + RefFilter.createReferenceEqual(new ItemPath(ShadowType.F_RESOURCE_REF), ShadowType.class, prismContext, ref.asReferenceValue()), EqualFilter.createEqual(ShadowType.F_OBJECT_CLASS, ShadowType.class, prismContext, objectclassDef.getTypeName())); ObjectQuery query = ObjectQuery.createObjectQuery(filter); diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/SynchronizationServiceImpl.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/SynchronizationServiceImpl.java index 9cebd9644b0..0a1e0dbc5e9 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/SynchronizationServiceImpl.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/SynchronizationServiceImpl.java @@ -193,20 +193,6 @@ public void notifyChange(ResourceObjectShadowChangeDescription change, Task task eventInfo.setOriginalSituation(situation.getSituation()); eventInfo.setNewSituation(situation.getSituation()); // overwritten later (TODO fix this!) -// if (isProtected((PrismObject) currentShadow)){ -// LOGGER.trace("SYNCHRONIZATION skipping {} because it is protected", currentShadow); -// // Just make sure there is no misleading synchronization situation in the shadow -// if (currentShadow.asObjectable().getSynchronizationSituation() != null) { -// ObjectDelta shadowDelta = ObjectDelta.createModificationReplaceProperty(ShadowType.class, currentShadow.getOid(), -// ShadowType.F_SYNCHRONIZATION_SITUATION, prismContext); -// provisioningService.modifyObject(ShadowType.class, currentShadow.getOid(), -// shadowDelta.getModifications(), null, null, task, subResult); -// } -// subResult.recordStatus(OperationResultStatus.NOT_APPLICABLE, "Skipped because it is protected"); -// eventInfo.setProtected(); -// eventInfo.record(task); -// return; -// } if (change.isUnrelatedChange() || Utils.isDryRun(task) || isProtected((PrismObject) currentShadow)){ PrismObject object = null; if (change.getCurrentShadow() != null){ @@ -345,26 +331,24 @@ private boolean isPolicyApplicable(PrismObject currentShad String policyIntent = synchronizationPolicy.getIntent(); ShadowKindType policyKind = synchronizationPolicy.getKind(); + ObjectClassComplexTypeDefinition policyObjectClass = null; + RefinedResourceSchema schema = RefinedResourceSchema.getRefinedSchema(resource); if (policyKind == null && policyIntent == null) { - LOGGER.warn("Neither objectClass nor kind/intent defined for sycnrhonization policy. Could not reliably apply synchronization definition. Skipping..."); - return false; + policyObjectClass = schema.findDefaultObjectClassDefinition(policyKind); } - ObjectClassComplexTypeDefinition policyObjectClass; + if (policyKind != null){ - RefinedResourceSchema schema = RefinedResourceSchema.getRefinedSchema(resource); if (StringUtils.isEmpty(policyIntent)) { policyObjectClass = schema.findDefaultObjectClassDefinition(policyKind); } else { policyObjectClass = schema.findObjectClassDefinition(policyKind, policyIntent); } - if (policyObjectClass != null && policyObjectClass.getTypeName().equals(shadowObjectClass)){ - return true; - } - - return false; } + if (policyObjectClass != null && policyObjectClass.getTypeName().equals(shadowObjectClass)){ + return true; + } } if (policyObjectClasses != null && !policyObjectClasses.isEmpty()) { diff --git a/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestReconScript.java b/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestReconScript.java index 3b54b3a3a38..59a0402146f 100644 --- a/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestReconScript.java +++ b/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestReconScript.java @@ -1,13 +1,26 @@ +/* + * Copyright (c) 2010-2016 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.model.impl.lens; -import java.io.File; - import static com.evolveum.midpoint.test.IntegrationTestTools.display; +import java.io.File; import java.util.ArrayList; import java.util.Collection; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.annotation.DirtiesContext.ClassMode; import org.springframework.test.context.ContextConfiguration; @@ -18,28 +31,24 @@ import com.evolveum.midpoint.model.api.ModelExecuteOptions; import com.evolveum.midpoint.model.impl.AbstractInternalModelIntegrationTest; import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.prism.delta.ItemDelta; import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.prism.delta.PropertyDelta; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.polystring.PolyString; -import com.evolveum.midpoint.prism.util.PrismTestUtil; import com.evolveum.midpoint.schema.constants.SchemaConstants; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.task.api.Task; -import com.evolveum.midpoint.test.IntegrationTestTools; import com.evolveum.midpoint.test.util.TestUtil; import com.evolveum.midpoint.util.QNameUtil; import com.evolveum.midpoint.util.exception.ObjectNotFoundException; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType; import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType; import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; @ContextConfiguration(locations = {"classpath:ctx-model-test-main.xml"}) @DirtiesContext(classMode = ClassMode.AFTER_CLASS) -public class TestReconScript extends AbstractInternalModelIntegrationTest{ +public class TestReconScript extends AbstractInternalModelIntegrationTest { private static final String TASK_RECON_DUMMY_FILENAME = "src/test/resources/common/task-reconcile-dummy.xml"; private static final String TASK_RECON_DUMMY_OID = "10000000-0000-0000-5656-565600000004"; @@ -48,8 +57,7 @@ public class TestReconScript extends AbstractInternalModelIntegrationTest{ private static final String ACCOUNT_BEFORE_SCRIPT_OID = "acc00000-0000-0000-0000-000000001234"; @Test - public void text001testReconcileScriptsWhenProvisioning() throws Exception{ - + public void text001testReconcileScriptsWhenProvisioning() throws Exception{ final String TEST_NAME = "text001testReconcileScriptsWhenProvisioning"; TestUtil.displayTestTile(this, TEST_NAME); @@ -93,7 +101,6 @@ public void text001testReconcileScriptsWhenProvisioning() throws Exception{ @Test public void test002testReconcileScriptsWhenReconciling() throws Exception{ - final String TEST_NAME = "test002testReconcileScriptsWhenReconciling"; TestUtil.displayTestTile(this, TEST_NAME); @@ -110,8 +117,6 @@ public void test002testReconcileScriptsWhenReconciling() throws Exception{ waitForTaskFinish(TASK_RECON_DUMMY_OID, false); - - for (ScriptHistoryEntry script : dummyResource.getScriptHistory()){ String userName = (String) script.getParams().get("midpoint_usercn"); @@ -131,7 +136,6 @@ public void test002testReconcileScriptsWhenReconciling() throws Exception{ @Test public void test003testReconcileScriptsAddUserAction() throws Exception{ - final String TEST_NAME = "test003testReconcileScriptsAddUserAction"; TestUtil.displayTestTile(this, TEST_NAME); @@ -142,7 +146,7 @@ public void test003testReconcileScriptsAddUserAction() throws Exception{ provisioningService.addObject(shadow.asPrismObject(), null, null, task, parentResult); - dummyResource.getScriptHistory().clear(); + dummyResource.getScriptHistory().clear(); // importObjectFromFile(new File(TASK_RECON_DUMMY_FILENAME)); // @@ -187,7 +191,6 @@ public void test003testReconcileScriptsAddUserAction() throws Exception{ @Test public void test005TestDryRunDelete() throws Exception{ - final String TEST_NAME = "test005TestDryRunDelete"; TestUtil.displayTestTile(this, TEST_NAME); @@ -220,11 +223,9 @@ public void test005TestDryRunDelete() throws Exception{ } @Test - public void test005TestReconDelete() throws Exception{ - - final String TEST_NAME = "test005TestDryRunDelete"; + public void test006TestReconDelete() throws Exception{ + final String TEST_NAME = "test006TestReconDelete"; TestUtil.displayTestTile(this, TEST_NAME); - PrismObject task = getTask(TASK_RECON_DUMMY_OID); OperationResult parentResult = new OperationResult(TEST_NAME); diff --git a/model/model-impl/src/test/resources/common/user-elaine.xml b/model/model-impl/src/test/resources/common/user-elaine.xml index cab60f2d902..f16f7de150e 100644 --- a/model/model-impl/src/test/resources/common/user-elaine.xml +++ b/model/model-impl/src/test/resources/common/user-elaine.xml @@ -1,6 +1,6 @@ - + @@ -61,7 +61,7 @@ - + @@ -76,8 +76,8 @@ - - + + diff --git a/model/model-test/src/main/java/com/evolveum/midpoint/model/test/AbstractModelIntegrationTest.java b/model/model-test/src/main/java/com/evolveum/midpoint/model/test/AbstractModelIntegrationTest.java index 82b6eacb009..7e2871549ef 100644 --- a/model/model-test/src/main/java/com/evolveum/midpoint/model/test/AbstractModelIntegrationTest.java +++ b/model/model-test/src/main/java/com/evolveum/midpoint/model/test/AbstractModelIntegrationTest.java @@ -2002,7 +2002,11 @@ public void timeout() { try { Task freshTask = taskManager.getTask(taskOid, waitResult); OperationResult result = freshTask.getResult(); - LOGGER.debug("Result of timed-out task:\n{}", result.debugDump()); + LOGGER.debug("Timed-out task:\n{}", freshTask.debugDump()); + display("Times", "origLastRunStartTimestamp="+longTimeToString(origLastRunStartTimestamp) + + ", origLastRunStartTimestamp=" + longTimeToString(origLastRunStartTimestamp) + + ", freshTask.getLastRunStartTimestamp()=" + longTimeToString(freshTask.getLastRunStartTimestamp()) + + ", freshTask.getLastRunFinishTimestamp()=" + longTimeToString(freshTask.getLastRunFinishTimestamp())); assert false : "Timeout ("+timeout+") while waiting for "+freshTask+" next run. Last result "+result; } catch (ObjectNotFoundException e) { LOGGER.error("Exception during task refresh: {}", e,e); @@ -2012,6 +2016,14 @@ public void timeout() { } }; IntegrationTestTools.waitFor("Waiting for task " + taskOid + " next run", checker, timeout, DEFAULT_TASK_SLEEP_TIME); + + Task freshTask = taskManager.getTask(taskOid, waitResult); + LOGGER.debug("Final task:\n{}", freshTask.debugDump()); + display("Times", "origLastRunStartTimestamp="+longTimeToString(origLastRunStartTimestamp) + + ", origLastRunStartTimestamp=" + longTimeToString(origLastRunStartTimestamp) + + ", freshTask.getLastRunStartTimestamp()=" + longTimeToString(freshTask.getLastRunStartTimestamp()) + + ", freshTask.getLastRunFinishTimestamp()=" + longTimeToString(freshTask.getLastRunFinishTimestamp())); + return taskResultHolder.getValue(); } diff --git a/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/impl/mock/SynchornizationServiceMock.java b/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/impl/mock/SynchornizationServiceMock.java index e90da3dfbfc..61edd950d77 100644 --- a/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/impl/mock/SynchornizationServiceMock.java +++ b/provisioning/provisioning-impl/src/test/java/com/evolveum/midpoint/provisioning/impl/mock/SynchornizationServiceMock.java @@ -16,30 +16,33 @@ package com.evolveum.midpoint.provisioning.impl.mock; -import static org.testng.AssertJUnit.assertNull; 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 javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.Validate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.testng.AssertJUnit; -import com.evolveum.midpoint.prism.delta.ChangeType; -import com.evolveum.midpoint.provisioning.api.ResourceObjectChangeListener; +import com.evolveum.midpoint.prism.PrismProperty; import com.evolveum.midpoint.provisioning.api.ChangeNotificationDispatcher; +import com.evolveum.midpoint.provisioning.api.ResourceObjectChangeListener; import com.evolveum.midpoint.provisioning.api.ResourceObjectShadowChangeDescription; import com.evolveum.midpoint.provisioning.api.ResourceOperationDescription; import com.evolveum.midpoint.provisioning.api.ResourceOperationListener; import com.evolveum.midpoint.repo.api.RepositoryService; +import com.evolveum.midpoint.schema.constants.SchemaConstants; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.schema.util.ShadowUtil; import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.test.ObjectChecker; +import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType; @@ -107,6 +110,11 @@ public void notifyChange(ResourceObjectShadowChangeDescription change, Task task assertTrue("Either current shadow or delta must be present", change.getCurrentShadow() != null || change.getObjectDelta() != null); + + if (change.isUnrelatedChange() || isDryRun(task) || (change.getCurrentShadow() != null && change.getCurrentShadow().asObjectable().isProtectedObject() == Boolean.TRUE)){ + return; + } + if (change.getCurrentShadow() != null) { ShadowType currentShadowType = change.getCurrentShadow().asObjectable(); if (currentShadowType != null) { @@ -164,6 +172,33 @@ public void notifyChange(ResourceObjectShadowChangeDescription change, Task task lastChange = change; } + private static boolean isDryRun(Task task){ + + Validate.notNull(task, "Task must not be null."); + + if (task.getExtension() == null){ + return false; + } + + PrismProperty item = task.getExtensionProperty(SchemaConstants.MODEL_EXTENSION_DRY_RUN); + if (item == null || item.isEmpty()){ + return false; + } + + if (item.getValues().size() > 1){ + return false; +// throw new SchemaException("Unexpected number of values for option 'dry run'."); + } + + Boolean dryRun = item.getValues().iterator().next().getValue(); + + if (dryRun == null){ + return false; + } + + return dryRun.booleanValue(); + } + /* (non-Javadoc) * @see com.evolveum.midpoint.provisioning.api.ResourceObjectChangeListener#notifyFailure(com.evolveum.midpoint.provisioning.api.ResourceObjectShadowFailureDescription, com.evolveum.midpoint.task.api.Task, com.evolveum.midpoint.schema.result.OperationResult) */ diff --git a/samples/resources/sap/assignment/sap-advanced.xml b/samples/resources/sap/assignment/sap-advanced.xml index 087b0a496ae..727cac5ac06 100644 --- a/samples/resources/sap/assignment/sap-advanced.xml +++ b/samples/resources/sap/assignment/sap-advanced.xml @@ -65,13 +65,20 @@ 0 - mr:stringIgnoreCase $user/name + + + + weak $user/name @@ -506,6 +513,7 @@ true + polyStringNorm c:name $account/attributes/icfs:name diff --git a/samples/resources/sap/sap-advanced.xml b/samples/resources/sap/sap-advanced.xml index 6ffc05003ea..3f637c3c4e1 100644 --- a/samples/resources/sap/sap-advanced.xml +++ b/samples/resources/sap/sap-advanced.xml @@ -50,13 +50,20 @@ 0 - mr:stringIgnoreCase $user/name + + + + weak $user/name @@ -384,6 +391,7 @@ true + polyStringNorm c:name $account/attributes/icfs:name diff --git a/samples/resources/sap/sap-medium.xml b/samples/resources/sap/sap-medium.xml index a344786dbe6..45e549e415f 100644 --- a/samples/resources/sap/sap-medium.xml +++ b/samples/resources/sap/sap-medium.xml @@ -50,13 +50,20 @@ 0 - mr:stringIgnoreCase $user/name + + + + weak $user/name @@ -279,6 +286,7 @@ true + polyStringNorm c:name $account/attributes/icfs:name diff --git a/samples/stories/multitenant-idm-saas/readme.txt b/samples/stories/multitenant-idm-saas/readme.txt index 001ae026933..d1e6ed895f5 100644 --- a/samples/stories/multitenant-idm-saas/readme.txt +++ b/samples/stories/multitenant-idm-saas/readme.txt @@ -38,8 +38,10 @@ menu on the left side. To modify organization settings: - click Org. structure on the left side, then Organization tree -- click on the organization name on the right side -- update e.g. Description if necessary +- click the wheel button near the organization name in the tree part of the +page and choose Edit +- click "Show empty fields" icon if necessary +- update attribute(s), e.g. Description if necessary - change password policy which will be applied for all objects in this organization - save the form @@ -48,22 +50,22 @@ Based on your changes, attributes in OpenLDAP will be changed. Password policy if midPoint-only setting, so changing it will not provision changes to OpenLDAP. -To create new administrator for his/her organization: +To create new administrator or user for his/her organization: - click Org. structure on the left side, then Organization tree +- (do not use Users / New user to create user; there is no relationship to +organization and permission will be denied (no attributes will be displayed) -- expand his/her organization (TODO: https://jira.evolveum.com/browse/MID-2795 -to allow only his/her organization to be visible) -- click on the organization on the left side to expand current users -- on the right side, near "Members", click the wheel icon and select "Add -member" +- click the organization name on the left side to expand current users +- on the right side, in the header of "Members" table, click the wheel icon +and select "Create member" and confirm "UserType" to open new user form - fill in the following attributes: - - name (this is login and OpenLDAP uid attribute) + - name (this is midPoint login and OpenLDAP uid attribute) - givenName - familyName - employeeType: click to the field and choose either customer-admin or customer-user - - emailAddress: to send (simulate sending) notification with initial - password + - emailAddress: to send (simulate sending) notification with initial password + - password - save the form Based on the employeeType setting, user will be created either as @@ -96,7 +98,8 @@ will be automatically (un)assigned based on this setting. To assign user a different role using midPoint, click on the user and switch to tab "Assignments": - click on the wheel near "Assignments" header -- click Assign role +- click Assign +- select "RoleType" in "Choose member type" select box - select role(s). For example Customer Power User role - click Assign and then Save @@ -122,25 +125,21 @@ would need to be used (which would also mean all target applications bound with OpenLDAP would need to know which attribute represents the account state). -To Delete user you need to go to Users then List users -(TODO https://jira.evolveum.com/browse/MID-2824). Select the users you wish to +To Delete user you need to go to Users then List users. Select the users you wish to delete and in the wheel choose "Delete" action. User will be deleted from midPoint and the account from OpenLDAP. To allow normal (non-admin) users to change their own password in the -self-service GUI, you need to first to assign them the permission to log in: -Click on the user and switch to tab "Assignments": -- click on the wheel near "Assignments" header -- click Assign role -- select role "Customer End User Role" -- click Assign and then Save +self-service GUI, users first need to have "Customer End Role" role assigned +(this is now automatically assigned by object template for both customer-user +and customer-admin users). From now, the user can login to midPoint using http://localhost:8080/midpoint (the same URL is used for administration) and update his/her password in midPoint and OpenLDAP. Setup: -- tested with Tomcat 7.x, JDK 7.x, git-v3.4devel-515-g6c30887 +- tested with Tomcat 7.x, JDK 7.x, v3.4devel-1465-g49a0f7b - update filePath in the CSV resource before importing data! It must point to your CSV file with customer info! diff --git a/samples/stories/multitenant-idm-saas/roles/role-customer-authz-admin.xml b/samples/stories/multitenant-idm-saas/roles/role-customer-authz-admin.xml index d685d6ec225..c62a2fad173 100644 --- a/samples/stories/multitenant-idm-saas/roles/role-customer-authz-admin.xml +++ b/samples/stories/multitenant-idm-saas/roles/role-customer-authz-admin.xml @@ -120,6 +120,10 @@ name End user + + name + Delegated Administration Role + diff --git a/samples/stories/multitenant-idm-saas/roles/role-customer-authz-enduser.xml b/samples/stories/multitenant-idm-saas/roles/role-customer-authz-enduser.xml index eede8e3417d..acd1865b490 100644 --- a/samples/stories/multitenant-idm-saas/roles/role-customer-authz-enduser.xml +++ b/samples/stories/multitenant-idm-saas/roles/role-customer-authz-enduser.xml @@ -84,8 +84,11 @@ - Read for all resources and roles of roleType=customer and End User + Read for all resources, all organizations and roles of roleType=customer and End User http://midpoint.evolveum.com/xml/ns/public/security/authorization-model-3#read + + OrgType + ResourceType diff --git a/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/TestOpenLdap.java b/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/TestOpenLdap.java index 589c7de738a..8e4f7f7dcfd 100644 --- a/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/TestOpenLdap.java +++ b/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/TestOpenLdap.java @@ -95,6 +95,11 @@ protected int getSearchSizeLimit() { return 500; } + @Override + protected String getPeopleLdapSuffix() { + return "ou=people,"+getLdapSuffix(); + } + @Override protected String getLdapGroupObjectClass() { return "groupOfNames";