diff --git a/build-system/pom.xml b/build-system/pom.xml
index aaf561f3b18..057e40f7977 100644
--- a/build-system/pom.xml
+++ b/build-system/pom.xml
@@ -83,7 +83,7 @@
5.22.0
1.3
2.0.6
- 1.4.3.41
+ 1.4.3.43
6.5.0
10.11.1.1
1.8.0
diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/PageTaskController.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/PageTaskController.java
index 573128e6f5a..a3460a73f73 100644
--- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/PageTaskController.java
+++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/PageTaskController.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2017 Evolveum
+ * Copyright (c) 2010-2018 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -78,7 +78,7 @@ public void deleteSyncTokenPerformed(AjaxRequestTarget target) {
if (property == null) {
result.recordWarning("Token is not present in this task."); // should be treated by isVisible
} else {
- final ObjectDelta extends ObjectType> delta = (ObjectDelta extends ObjectType>)
+ final ObjectDelta extends ObjectType> delta =
DeltaBuilder.deltaFor(TaskType.class, parentPage.getPrismContext())
.item(new ItemPath(TaskType.F_EXTENSION, SchemaConstants.SYNC_TOKEN), property.getDefinition()).replace()
.asObjectDelta(parentPage.getTaskDto().getOid());
diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskBasicTabPanel.html b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskBasicTabPanel.html
index 197c13f92fd..c089569fdd4 100644
--- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskBasicTabPanel.html
+++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskBasicTabPanel.html
@@ -23,44 +23,46 @@
diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskSchedulingTabPanel.html b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskSchedulingTabPanel.html
index c9e85bcfa13..f1c08c93ecd 100644
--- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskSchedulingTabPanel.html
+++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/TaskSchedulingTabPanel.html
@@ -22,94 +22,98 @@
-
-
- |
- |
-
-
- |
- |
-
-
- |
- |
-
-
- |
- |
-
-
+
+
+
+ |
+ |
+
+
+ |
+ |
+
+
+ |
+ |
+
+
+ |
+ |
+
+
+
diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/handlers/DefaultHandlerPanel.html b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/handlers/DefaultHandlerPanel.html
index 6d00e5c1d25..89251fb65a9 100644
--- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/handlers/DefaultHandlerPanel.html
+++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/handlers/DefaultHandlerPanel.html
@@ -21,13 +21,15 @@
diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/handlers/QueryBasedHandlerPanel.html b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/handlers/QueryBasedHandlerPanel.html
index bb1e72e599d..f4d379ea137 100644
--- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/handlers/QueryBasedHandlerPanel.html
+++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/handlers/QueryBasedHandlerPanel.html
@@ -21,17 +21,19 @@
diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/handlers/ResourceRelatedHandlerPanel.html b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/handlers/ResourceRelatedHandlerPanel.html
index 4d2c916c9a6..c73e721f6e1 100644
--- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/handlers/ResourceRelatedHandlerPanel.html
+++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/handlers/ResourceRelatedHandlerPanel.html
@@ -21,34 +21,36 @@
diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/handlers/ScannerHandlerPanel.html b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/handlers/ScannerHandlerPanel.html
index 7cfc4ebf242..0c820175ceb 100644
--- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/handlers/ScannerHandlerPanel.html
+++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/handlers/ScannerHandlerPanel.html
@@ -21,12 +21,14 @@
diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/handlers/ScriptExecutionHandlerPanel.html b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/handlers/ScriptExecutionHandlerPanel.html
index c2c6a7b0f35..bd93bcd2ef7 100644
--- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/handlers/ScriptExecutionHandlerPanel.html
+++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/server/handlers/ScriptExecutionHandlerPanel.html
@@ -21,12 +21,14 @@
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 a5cc62910e4..47fee87865a 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
@@ -23,6 +23,7 @@
import org.identityconnectors.framework.common.exceptions.ConnectorException;
import org.identityconnectors.framework.common.exceptions.ConnectorIOException;
import org.identityconnectors.framework.common.exceptions.InvalidAttributeValueException;
+import org.identityconnectors.framework.common.exceptions.InvalidPasswordException;
import org.identityconnectors.framework.common.exceptions.UnknownUidException;
import org.identityconnectors.framework.common.objects.*;
@@ -390,7 +391,8 @@ public Schema schema() {
throw new UnsupportedOperationException();
}
- SchemaBuilder builder = new SchemaBuilder(AbstractDummyConnector.class);
+ SchemaBuilder builder = new SchemaBuilder(this.getClass());
+ log.ok("Building schema for {0}", this.getClass());
try {
@@ -418,11 +420,17 @@ public Schema schema() {
builder.defineOperationOption(OperationOptionInfoBuilder.buildPageSize(), SearchOp.class);
builder.defineOperationOption(OperationOptionInfoBuilder.buildSortKeys(), SearchOp.class);
}
+
+ extendSchema(builder);
log.info("schema::end");
return builder.build();
}
+ protected void extendSchema(SchemaBuilder builder) {
+ // for subclasses
+ }
+
private String getAccountObjectClassName() {
if (configuration.getUseLegacySchema()) {
return ObjectClass.ACCOUNT_NAME;
@@ -1598,6 +1606,32 @@ private boolean attributesToGetHasAttribute(Collection attributesToGet,
}
return attributesToGet.contains(attrName);
}
+
+ protected void applyModifyMetadata(DummyObject object, OperationOptions options) throws ConnectException, FileNotFoundException, SchemaViolationException, ConflictException {
+ String runAsUser = options.getRunAsUser();
+ if (runAsUser != null) {
+ if (!configuration.getSupportRunAs()) {
+ throw new UnsupportedOperationException("runAsUser option is not supported");
+ }
+ DummyAccount runAsAccount = resource.getAccountByUsername(runAsUser);
+ if (runAsAccount == null) {
+ new ConfigurationException("No runAsUser "+runAsUser);
+ }
+ GuardedString runWithPassword = options.getRunWithPassword();
+ if (runWithPassword != null) {
+ runWithPassword.access((clearChars) -> {
+ if (!runAsAccount.getPassword().equals(new String(clearChars))) {
+ throw new InvalidPasswordException("Wrong runWithPassword");
+ }
+ });
+ } else {
+ throw new InvalidPasswordException("No runWithPassword");
+ }
+ object.setLastModifier(runAsAccount.getName());
+ } else {
+ object.setLastModifier(null);
+ }
+ }
public void validate(ObjectClass oc) {
if (oc == null) {
diff --git a/icf-connectors/dummy-connector/src/main/java/com/evolveum/icf/dummy/connector/DummyConfiguration.java b/icf-connectors/dummy-connector/src/main/java/com/evolveum/icf/dummy/connector/DummyConfiguration.java
index 0e6a3788027..c816942e080 100644
--- a/icf-connectors/dummy-connector/src/main/java/com/evolveum/icf/dummy/connector/DummyConfiguration.java
+++ b/icf-connectors/dummy-connector/src/main/java/com/evolveum/icf/dummy/connector/DummyConfiguration.java
@@ -45,6 +45,7 @@ public class DummyConfiguration extends AbstractConfiguration {
private boolean supportSchema = true;
private boolean supportActivation = true;
private boolean supportValidity = false;
+ private boolean supportRunAs = true;
private String uidMode = UID_MODE_NAME;
private boolean enforceUniqueName = true;
private String passwordReadabilityMode = PASSWORD_READABILITY_MODE_UNREADABLE;
@@ -126,6 +127,16 @@ public boolean getSupportValidity() {
public void setSupportValidity(boolean supportValidity) {
this.supportValidity = supportValidity;
}
+
+ @ConfigurationProperty(displayMessageKey = "UI_SUPPORT_RUN_AS",
+ helpMessageKey = "UI_SUPPORT_RUN_AS_HELP")
+ public boolean getSupportRunAs() {
+ return supportRunAs;
+ }
+
+ public void setSupportRunAs(boolean supportRunAs) {
+ this.supportRunAs = supportRunAs;
+ }
@ConfigurationProperty(displayMessageKey = "UI_UID_MODE",
helpMessageKey = "UI_UID_MODE_HELP")
diff --git a/icf-connectors/dummy-connector/src/main/java/com/evolveum/icf/dummy/connector/DummyConnector.java b/icf-connectors/dummy-connector/src/main/java/com/evolveum/icf/dummy/connector/DummyConnector.java
index 51c1fd8eaff..df5e37a839d 100644
--- a/icf-connectors/dummy-connector/src/main/java/com/evolveum/icf/dummy/connector/DummyConnector.java
+++ b/icf-connectors/dummy-connector/src/main/java/com/evolveum/icf/dummy/connector/DummyConnector.java
@@ -23,6 +23,7 @@
import org.identityconnectors.framework.common.exceptions.ConnectorException;
import org.identityconnectors.framework.common.exceptions.ConnectorIOException;
import org.identityconnectors.framework.common.exceptions.InvalidAttributeValueException;
+import org.identityconnectors.framework.common.exceptions.InvalidPasswordException;
import org.identityconnectors.framework.common.exceptions.UnknownUidException;
import org.identityconnectors.framework.common.objects.*;
@@ -125,6 +126,7 @@ public Set updateDelta(final ObjectClass objectClass, final Uid
if (account == null) {
throw new UnknownUidException("Account with UID "+uid+" does not exist on resource");
}
+ applyModifyMetadata(account, options);
// we do this before setting attribute values, in case when description itself would be changed
resource.changeDescriptionIfNeeded(account);
@@ -174,6 +176,7 @@ public Set updateDelta(final ObjectClass objectClass, final Uid
}
}
+
} else if (ObjectClass.GROUP.is(objectClass.getObjectClassValue())) {
@@ -188,6 +191,7 @@ public Set updateDelta(final ObjectClass objectClass, final Uid
if (group == null) {
throw new UnknownUidException("Group with UID "+uid+" does not exist on resource");
}
+ applyModifyMetadata(group, options);
for (AttributeDelta delta : modifications) {
if (delta.is(Name.NAME)) {
@@ -219,6 +223,7 @@ public Set updateDelta(final ObjectClass objectClass, final Uid
applyOrdinaryAttributeDelta(group, delta, valuesTransformer);
}
}
+
} else if (objectClass.is(OBJECTCLASS_PRIVILEGE_NAME)) {
@@ -233,6 +238,7 @@ public Set updateDelta(final ObjectClass objectClass, final Uid
if (priv == null) {
throw new UnknownUidException("Privilege with UID "+uid+" does not exist on resource");
}
+ applyModifyMetadata(priv, options);
for (AttributeDelta delta : modifications) {
if (delta.is(Name.NAME)) {
@@ -257,6 +263,7 @@ public Set updateDelta(final ObjectClass objectClass, final Uid
applyOrdinaryAttributeDelta(priv, delta, null);
}
}
+
} else if (objectClass.is(OBJECTCLASS_ORG_NAME)) {
@@ -271,6 +278,7 @@ public Set updateDelta(final ObjectClass objectClass, final Uid
if (org == null) {
throw new UnknownUidException("Org with UID "+uid+" does not exist on resource");
}
+ applyModifyMetadata(org, options);
for (AttributeDelta delta : modifications) {
if (delta.is(Name.NAME)) {
@@ -295,7 +303,7 @@ public Set updateDelta(final ObjectClass objectClass, final Uid
applyOrdinaryAttributeDelta(org, delta, null);
}
}
-
+
} else {
throw new ConnectorException("Unknown object class "+objectClass);
@@ -321,7 +329,7 @@ public Set updateDelta(final ObjectClass objectClass, final Uid
log.info("update::end {0}", instanceName);
return sideEffectChanges;
}
-
+
private void applyAuxiliaryObjectClassDelta(DummyObject dummyObject, AttributeDelta delta) {
List replaceValues = getReplaceValues(delta, String.class);
if (replaceValues != null) {
@@ -490,4 +498,15 @@ protected void addAdditionalCommonAttributes(ConnectorObjectBuilder builder, Dum
}
}
+ @Override
+ protected void extendSchema(SchemaBuilder builder) {
+ super.extendSchema(builder);
+
+ if (configuration.getSupportRunAs()) {
+ log.ok("Adding runAs options to schema");
+ builder.defineOperationOption(OperationOptionInfoBuilder.buildRunWithUser(), UpdateDeltaOp.class);
+ builder.defineOperationOption(OperationOptionInfoBuilder.buildRunWithPassword(), UpdateDeltaOp.class);
+ }
+ }
+
}
diff --git a/icf-connectors/dummy-connector/src/main/java/com/evolveum/icf/dummy/connector/DummyConnectorLegacyUpdate.java b/icf-connectors/dummy-connector/src/main/java/com/evolveum/icf/dummy/connector/DummyConnectorLegacyUpdate.java
index 046ccc3505c..f3d1c2eef8a 100644
--- a/icf-connectors/dummy-connector/src/main/java/com/evolveum/icf/dummy/connector/DummyConnectorLegacyUpdate.java
+++ b/icf-connectors/dummy-connector/src/main/java/com/evolveum/icf/dummy/connector/DummyConnectorLegacyUpdate.java
@@ -116,6 +116,7 @@ public Uid update(ObjectClass objectClass, Uid uid, Set replaceAttrib
if (account == null) {
throw new UnknownUidException("Account with UID "+uid+" does not exist on resource");
}
+ applyModifyMetadata(account, options);
// we do this before setting attribute values, in case when description itself would be changed
resource.changeDescriptionIfNeeded(account);
@@ -179,6 +180,7 @@ public Uid update(ObjectClass objectClass, Uid uid, Set replaceAttrib
if (group == null) {
throw new UnknownUidException("Group with UID "+uid+" does not exist on resource");
}
+ applyModifyMetadata(group, options);
for (Attribute attr : replaceAttributes) {
if (attr.is(Name.NAME)) {
@@ -229,6 +231,7 @@ public Uid update(ObjectClass objectClass, Uid uid, Set replaceAttrib
if (priv == null) {
throw new UnknownUidException("Privilege with UID "+uid+" does not exist on resource");
}
+ applyModifyMetadata(priv, options);
for (Attribute attr : replaceAttributes) {
if (attr.is(Name.NAME)) {
@@ -271,6 +274,7 @@ public Uid update(ObjectClass objectClass, Uid uid, Set replaceAttrib
if (org == null) {
throw new UnknownUidException("Org with UID "+uid+" does not exist on resource");
}
+ applyModifyMetadata(org, options);
for (Attribute attr : replaceAttributes) {
if (attr.is(Name.NAME)) {
@@ -346,6 +350,7 @@ public Uid addAttributeValues(ObjectClass objectClass, Uid uid, Set v
if (account == null) {
throw new UnknownUidException("Account with UID "+uid+" does not exist on resource");
}
+ applyModifyMetadata(account, options);
// we could change the description here, but don't do that not to collide with ADD operation
// TODO add the functionality if needed
@@ -391,6 +396,7 @@ public Uid addAttributeValues(ObjectClass objectClass, Uid uid, Set v
if (group == null) {
throw new UnknownUidException("Group with UID "+uid+" does not exist on resource");
}
+ applyModifyMetadata(group, options);
for (Attribute attr : valuesToAdd) {
@@ -435,6 +441,7 @@ public Uid addAttributeValues(ObjectClass objectClass, Uid uid, Set v
if (priv == null) {
throw new UnknownUidException("Privilege with UID "+uid+" does not exist on resource");
}
+ applyModifyMetadata(priv, options);
for (Attribute attr : valuesToAdd) {
@@ -471,6 +478,7 @@ public Uid addAttributeValues(ObjectClass objectClass, Uid uid, Set v
if (org == null) {
throw new UnknownUidException("Org with UID "+uid+" does not exist on resource");
}
+ applyModifyMetadata(org, options);
for (Attribute attr : valuesToAdd) {
@@ -538,6 +546,7 @@ public Uid removeAttributeValues(ObjectClass objectClass, Uid uid, Set auxiliaryObjectClassNames = new HashSet<>();
@@ -117,6 +118,14 @@ public void setValidTo(Date validTo) throws ConnectException, FileNotFoundExcept
recordModify();
}
+ public String getLastModifier() {
+ return lastModifier;
+ }
+
+ public void setLastModifier(String lastModifier) {
+ this.lastModifier = lastModifier;
+ }
+
public BreakMode getModifyBreakMode() {
return modifyBreakMode;
}
@@ -460,11 +469,6 @@ protected String toStringContent() {
return "name=" + name + ", attributes=" + attributes + ", enabled=" + enabled;
}
- @Override
- public String debugDump() {
- return debugDump(0);
- }
-
@Override
public String debugDump(int indent) {
StringBuilder sb = new StringBuilder();
@@ -483,6 +487,8 @@ public String debugDump(int indent) {
sb.append(" ").append(PrettyPrinter.prettyPrint(validFrom)).append(" - ").append(PrettyPrinter.prettyPrint(validTo));
}
sb.append("\n");
+ DebugUtil.debugDumpWithLabel(sb, "lastModifier", lastModifier, indent + 1);
+ sb.append("\n");
DebugUtil.debugDumpWithLabel(sb, "Attributes", attributes, indent + 1);
extendDebugDump(sb, indent);
return sb.toString();
diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/builder/DeltaBuilder.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/builder/DeltaBuilder.java
index 6eadc1e9af3..1af1aab7ded 100644
--- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/builder/DeltaBuilder.java
+++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/builder/DeltaBuilder.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2015 Evolveum
+ * Copyright (c) 2010-2018 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -199,6 +199,14 @@ public S_ValuesEntry oldRealValues(Collection> realValues) {
}
return this;
}
+
+ @Override
+ public S_ValuesEntry oldRealValue(T realValue) {
+ if (realValue != null) {
+ currentDelta.addEstimatedOldValue(toPrismValue(currentDelta, realValue));
+ }
+ return this;
+ }
@Override
public S_ValuesEntry old(PrismValue... values) {
diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/builder/S_ItemEntry.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/builder/S_ItemEntry.java
index ee323185ee1..34e869b4504 100644
--- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/builder/S_ItemEntry.java
+++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/builder/S_ItemEntry.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2015 Evolveum
+ * Copyright (c) 2010-2018 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,7 +36,7 @@ public interface S_ItemEntry {
S_ValuesEntry item(ItemPath path, ItemDefinition itemDefinition);
List> asObjectDeltas(String oid);
- ObjectDelta> asObjectDelta(String oid);
+ ObjectDelta asObjectDelta(String oid);
// TEMPORARY HACK
@SuppressWarnings("unchecked")
diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/builder/S_ValuesEntry.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/builder/S_ValuesEntry.java
index 25237c86a6d..7973340c7aa 100644
--- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/builder/S_ValuesEntry.java
+++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/delta/builder/S_ValuesEntry.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2015 Evolveum
+ * Copyright (c) 2010-2018 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -44,6 +44,7 @@ public interface S_ValuesEntry {
S_ItemEntry replace(Collection extends PrismValue> values);
S_ValuesEntry old(Object... realValues);
S_ValuesEntry oldRealValues(Collection> realValues);
+ S_ValuesEntry oldRealValue(T realValue);
S_ValuesEntry old(PrismValue... values);
S_ValuesEntry old(Collection extends PrismValue> values);
}
diff --git a/infra/schema/src/main/java/com/evolveum/midpoint/schema/constants/SchemaConstants.java b/infra/schema/src/main/java/com/evolveum/midpoint/schema/constants/SchemaConstants.java
index 58e5f65b884..53881c8e404 100644
--- a/infra/schema/src/main/java/com/evolveum/midpoint/schema/constants/SchemaConstants.java
+++ b/infra/schema/src/main/java/com/evolveum/midpoint/schema/constants/SchemaConstants.java
@@ -399,12 +399,24 @@ public abstract class SchemaConstants {
public static final String NS_GUI = NS_MIDPOINT_PUBLIC + "/gui";
public static final String NS_GUI_CHANNEL = NS_GUI + "/channels-3";
+
+ // Init channel, used when system is initializing itself
public static final QName CHANNEL_GUI_INIT_QNAME = new QName(NS_GUI_CHANNEL, "init");
public static final String CHANNEL_GUI_INIT_URI = QNameUtil.qNameToUri(CHANNEL_GUI_INIT_QNAME);
+
public static final QName CHANNEL_GUI_SELF_REGISTRATION_QNAME = new QName(NS_GUI_CHANNEL, "selfRegistration");
public static final String CHANNEL_GUI_SELF_REGISTRATION_URI = QNameUtil.qNameToUri(CHANNEL_GUI_SELF_REGISTRATION_QNAME);
+
+ // Channel for self-service part of the user interface. These are the pages when user is changing his own data.
+ // E.g. update of his own profile and password change are considered to be self-service.
+ public static final QName CHANNEL_GUI_SELF_SERVICE_QNAME = new QName(NS_GUI_CHANNEL, "selfService");
+ public static final String CHANNEL_GUI_SELF_SERVICE_URI = QNameUtil.qNameToUri(CHANNEL_GUI_SELF_SERVICE_QNAME);
+
+ // Password reset channel. This is *reset*, which means that the user does not know the old password and cannot log in.
public static final QName CHANNEL_GUI_RESET_PASSWORD_QNAME = new QName(NS_GUI_CHANNEL, "resetPassword");
public static final String CHANNEL_GUI_RESET_PASSWORD_URI = QNameUtil.qNameToUri(CHANNEL_GUI_RESET_PASSWORD_QNAME);
+
+ // Catch-all channel for all user operations in user interface.
public static final QName CHANNEL_GUI_USER_QNAME = new QName(NS_GUI_CHANNEL, "user");
public static final String CHANNEL_GUI_USER_URI = QNameUtil.qNameToUri(CHANNEL_GUI_USER_QNAME);
diff --git a/infra/schema/src/main/java/com/evolveum/midpoint/schema/processor/ResourceObjectIdentification.java b/infra/schema/src/main/java/com/evolveum/midpoint/schema/processor/ResourceObjectIdentification.java
index 2c1d699c67b..c2a4ccf8003 100644
--- a/infra/schema/src/main/java/com/evolveum/midpoint/schema/processor/ResourceObjectIdentification.java
+++ b/infra/schema/src/main/java/com/evolveum/midpoint/schema/processor/ResourceObjectIdentification.java
@@ -1,5 +1,5 @@
/**
- * Copyright (c) 2015-2016 Evolveum
+ * Copyright (c) 2015-2018 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.List;
import com.evolveum.midpoint.schema.util.ShadowUtil;
import com.evolveum.midpoint.util.PrettyPrinter;
@@ -72,6 +73,19 @@ public ResourceAttribute getSecondaryIdentifier() throws SchemaException
return (ResourceAttribute) secondaryIdentifiers.iterator().next();
}
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public Collection extends ResourceAttribute>> getAllIdentifiers() {
+ if (primaryIdentifiers == null) {
+ return secondaryIdentifiers;
+ }
+ if (secondaryIdentifiers == null) {
+ return primaryIdentifiers;
+ }
+ List allIdentifiers = new ArrayList<>(primaryIdentifiers.size() + secondaryIdentifiers.size());
+ allIdentifiers.addAll(primaryIdentifiers);
+ allIdentifiers.addAll(secondaryIdentifiers);
+ return allIdentifiers;
+ }
public ObjectClassComplexTypeDefinition getObjectClassDefinition() {
return objectClassDefinition;
diff --git a/infra/schema/src/main/resources/xml/ns/public/resource/capabilities-3.xsd b/infra/schema/src/main/resources/xml/ns/public/resource/capabilities-3.xsd
index 1a59a093334..ea7ab029782 100644
--- a/infra/schema/src/main/resources/xml/ns/public/resource/capabilities-3.xsd
+++ b/infra/schema/src/main/resources/xml/ns/public/resource/capabilities-3.xsd
@@ -1,6 +1,6 @@
+
+
+
+
+
+
+
diff --git a/infra/schema/src/test/java/com/evolveum/midpoint/schema/TestParseDiffPatch.java b/infra/schema/src/test/java/com/evolveum/midpoint/schema/TestParseDiffPatch.java
index f3b6d074786..32d3a8e905e 100644
--- a/infra/schema/src/test/java/com/evolveum/midpoint/schema/TestParseDiffPatch.java
+++ b/infra/schema/src/test/java/com/evolveum/midpoint/schema/TestParseDiffPatch.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2017 Evolveum
+ * Copyright (c) 2010-2018 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -903,7 +903,7 @@ public void testCampaign() throws SchemaException, SAXException, IOException, JA
triggerToDelete.setHandlerUri("http://midpoint.evolveum.com/xml/ns/public/certification/trigger/close-stage/handler-3");
@SuppressWarnings({"unchecked", "raw"})
- ObjectDelta delta = (ObjectDelta)
+ ObjectDelta delta =
DeltaBuilder.deltaFor(AccessCertificationCampaignType.class, getPrismContext())
.item(AccessCertificationCampaignType.F_TRIGGER).delete(triggerToDelete)
.asObjectDelta(campaign.getOid());
diff --git a/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/TestAdHocCertification.java b/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/TestAdHocCertification.java
index e1c018cd1d8..a9ace748634 100644
--- a/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/TestAdHocCertification.java
+++ b/model/certification-impl/src/test/java/com/evolveum/midpoint/certification/test/TestAdHocCertification.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2017 Evolveum
+ * Copyright (c) 2010-2018 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -115,7 +115,7 @@ public void test020ModifyIndigo() throws Exception {
// WHEN
TestUtil.displayWhen(TEST_NAME);
@SuppressWarnings({ "unchecked", "raw" })
- ObjectDelta delta = (ObjectDelta) DeltaBuilder.deltaFor(UserType.class, prismContext)
+ ObjectDelta delta = DeltaBuilder.deltaFor(UserType.class, prismContext)
.item(UserType.F_DESCRIPTION).replace("new description")
.item(UserType.F_ACTIVATION, ActivationType.F_ADMINISTRATIVE_STATUS).replace(ActivationStatusType.DISABLED)
.asObjectDelta(USER_INDIGO_OID);
diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/ChangeExecutor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/ChangeExecutor.java
index b3de8c25cbd..28553178c8f 100644
--- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/ChangeExecutor.java
+++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/ChangeExecutor.java
@@ -63,7 +63,9 @@
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.schema.result.OperationResultStatus;
import com.evolveum.midpoint.schema.util.ShadowUtil;
+import com.evolveum.midpoint.security.api.MidPointPrincipal;
import com.evolveum.midpoint.security.api.OwnerResolver;
+import com.evolveum.midpoint.security.api.SecurityContextManager;
import com.evolveum.midpoint.security.enforcer.api.AuthorizationParameters;
import com.evolveum.midpoint.security.enforcer.api.SecurityEnforcer;
import com.evolveum.midpoint.task.api.Task;
@@ -77,6 +79,7 @@
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;
+import com.evolveum.prism.xml.ns._public.types_3.ProtectedStringType;
import com.evolveum.prism.xml.ns._public.types_3.RawType;
import org.apache.commons.lang.BooleanUtils;
@@ -116,6 +119,7 @@ public class ChangeExecutor {
@Autowired private PrismContext prismContext;
@Autowired private ExpressionFactory expressionFactory;
@Autowired private SecurityEnforcer securityEnforcer;
+ @Autowired private SecurityContextManager securityContextManager;
@Autowired private Clock clock;
@Autowired private ModelObjectResolver objectResolver;
@Autowired private OperationalDataManager metadataManager;
@@ -1165,11 +1169,16 @@ private ProvisioningOperationOptions copyFromModelOptions(ModelExecuteOptions op
}
private ProvisioningOperationOptions getProvisioningOptions(LensContext context,
- ModelExecuteOptions modelOptions) {
+ ModelExecuteOptions modelOptions, PrismObject existingShadow, ObjectDelta delta) throws SecurityViolationException {
if (modelOptions == null && context != null) {
modelOptions = context.getOptions();
}
ProvisioningOperationOptions provisioningOptions = copyFromModelOptions(modelOptions);
+
+ if (executeAsSelf(context, modelOptions, existingShadow, delta)) {
+ LOGGER.trace("Setting 'execute as self' provisioning option for {}", existingShadow);
+ provisioningOptions.setRunAsAccountOid(existingShadow.getOid());
+ }
if (context != null && context.getChannel() != null) {
@@ -1188,6 +1197,62 @@ private ProvisioningOperationOptions getProvisioningOptio
return provisioningOptions;
}
+
+ // This is a bit of black magic. We only want to execute as self if there a user is changing its own password
+ // and we also have old password value.
+ // Later, this should be improved. Maybe we need special model operation option for this? Or maybe it should be somehow
+ // automatically detected based on resource capabilities? We do not know yet. Therefore let's do the simplest possible
+ // thing. Otherwise we might do something that we will later regret.
+ private boolean executeAsSelf(LensContext context,
+ ModelExecuteOptions modelOptions, PrismObject existingShadow, ObjectDelta delta) throws SecurityViolationException {
+ if (existingShadow == null) {
+ return false;
+ }
+
+ if (!SchemaConstants.CHANNEL_GUI_SELF_SERVICE_URI.equals(context.getChannel())) {
+ return false;
+ }
+
+ if (delta == null) {
+ return false;
+ }
+ if (!delta.isModify()) {
+ return false;
+ }
+ PropertyDelta passwordDelta = delta.findPropertyDelta(SchemaConstants.PATH_PASSWORD_VALUE);
+ if (passwordDelta == null) {
+ return false;
+ }
+ if (passwordDelta.getEstimatedOldValues() == null || passwordDelta.getEstimatedOldValues().isEmpty()) {
+ return false;
+ }
+ ProtectedStringType oldPassword = passwordDelta.getEstimatedOldValues().iterator().next().getValue();
+ if (!oldPassword.canGetCleartext()) {
+ return false;
+ }
+
+ LensFocusContext focusContext = context.getFocusContext();
+ if (focusContext == null) {
+ return false;
+ }
+ if (!focusContext.canRepresent(UserType.class)) {
+ return false;
+ }
+
+ MidPointPrincipal principal = securityContextManager.getPrincipal();
+ if (principal == null) {
+ return false;
+ }
+ UserType loggedInUser = principal.getUser();
+ if (loggedInUser == null) {
+ return false;
+ }
+
+ if (!loggedInUser.getOid().equals(focusContext.getOid())) {
+ return false;
+ }
+ return true;
+ }
private void logDeltaExecution(ObjectDelta objectDelta,
LensContext context, ResourceType resource, OperationResult result, Task task) {
@@ -1268,7 +1333,8 @@ private PrismObject executeAddit
throw new UnsupportedOperationException("NodeType cannot be added using model interface");
} else if (ObjectTypes.isManagedByProvisioning(objectTypeToAdd)) {
- ProvisioningOperationOptions provisioningOptions = getProvisioningOptions(context, options);
+ ProvisioningOperationOptions provisioningOptions = getProvisioningOptions(context, options,
+ (PrismObject)objectContext.getObjectCurrent(), (ObjectDelta)change);
oid = addProvisioningObject(objectToAdd, context, objectContext, provisioningOptions,
resource, task, result);
@@ -1319,7 +1385,8 @@ private PrismObject executeDelet
} else if (NodeType.class.isAssignableFrom(objectTypeClass)) {
taskManager.deleteNode(oid, result);
} else if (ObjectTypes.isClassManagedByProvisioning(objectTypeClass)) {
- ProvisioningOperationOptions provisioningOptions = getProvisioningOptions(context, options);
+ ProvisioningOperationOptions provisioningOptions = getProvisioningOptions(context, options,
+ (PrismObject)objectContext.getObjectCurrent(), (ObjectDelta)change);
try {
objectAfterModification = deleteProvisioningObject(objectTypeClass, oid, context, objectContext,
provisioningOptions, resource, task, result);
@@ -1387,7 +1454,8 @@ private void executeModification(Ob
} else if (NodeType.class.isAssignableFrom(objectTypeClass)) {
throw new UnsupportedOperationException("NodeType is not modifiable using model interface");
} else if (ObjectTypes.isClassManagedByProvisioning(objectTypeClass)) {
- ProvisioningOperationOptions provisioningOptions = getProvisioningOptions(context, options);
+ ProvisioningOperationOptions provisioningOptions = getProvisioningOptions(context, options,
+ (PrismObject)objectContext.getObjectCurrent(), (ObjectDelta)delta);
String oid = modifyProvisioningObject(objectTypeClass, delta.getOid(),
delta.getModifications(), context, objectContext, provisioningOptions, resource,
task, result);
diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/MappingEvaluator.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/MappingEvaluator.java
index 7b1bb9b77eb..c565aa18be7 100644
--- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/MappingEvaluator.java
+++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/MappingEvaluator.java
@@ -473,10 +473,13 @@ public boolean isMeaningful(PrismValueDeltaSetTriple mappingOutputTriple) {
+ private void applyEstematedOldValueInReplaceCase(ItemDelta targetItemDelta,
+ PrismValueDeltaSetTriple outputTriple) {
+ Collection nonPositiveValues = outputTriple.getNonPositiveValues();
+ if (nonPositiveValues == null || nonPositiveValues.isEmpty()) {
+ return;
+ }
+ targetItemDelta.setEstimatedOldValues(PrismValue.cloneCollection(nonPositiveValues));
+ }
+
+ private boolean isMeaningful(PrismValueDeltaSetTriple mappingOutputTriple) {
if (mappingOutputTriple == null) {
// this means: mapping not applicable
return false;
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 c4ffd52b4f2..78f1515d4ce 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
@@ -190,7 +190,7 @@ private void processProjectionPasswordMapping(LensContext<
boolean evaluateWeak = getEvaluateWeak(projCtx);
- final ItemDeltaItem, PrismPropertyDefinition> userPasswordIdi = focusContext
+ final ItemDeltaItem, PrismPropertyDefinition> userPasswordIdi = focusContext
.getObjectDeltaObject().findIdi(SchemaConstants.PATH_PASSWORD_VALUE);
ValuePolicyResolver stringPolicyResolver = new ValuePolicyResolver() {
@@ -249,6 +249,30 @@ public ValuePolicyType resolve() {
}
}
}
+
+ Collection> minusSet = outputTriple.getMinusSet();
+ if (minusSet != null && !minusSet.isEmpty()) {
+ if (!canGetCleartext(minusSet)) {
+ // We have hashed values in minus set. That is not great, we won't be able to get
+ // cleartext from that if we need it (e.g. for runAs in provisioning).
+ // Therefore try to get old value from user password delta. If that matches with
+ // hashed value then we have the cleartext.
+ ProtectedStringType oldProjectionPassword = minusSet.iterator().next().getRealValue();
+ PropertyDelta userPasswordDelta = (PropertyDelta) userPasswordIdi.getDelta();
+ Collection> userPasswordDeltaOldValues = userPasswordDelta.getEstimatedOldValues();
+ if (userPasswordDeltaOldValues != null && !userPasswordDeltaOldValues.isEmpty()) {
+ ProtectedStringType oldUserPassword = userPasswordDeltaOldValues.iterator().next().getRealValue();
+ try {
+ if (oldUserPassword.canGetCleartext() && protector.compare(oldUserPassword, oldProjectionPassword)) {
+ outputTriple.clearMinusSet();
+ outputTriple.addToMinusSet(new PrismPropertyValue<>(oldUserPassword));
+ }
+ } catch (EncryptionException e) {
+ throw new SystemException(e.getMessage(), e);
+ }
+ }
+ }
+ }
return true;
};
diff --git a/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestAssignmentProcessor2.java b/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestAssignmentProcessor2.java
index 082a64ded58..ba6e6a8c2c8 100644
--- a/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestAssignmentProcessor2.java
+++ b/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestAssignmentProcessor2.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2017 Evolveum
+ * Copyright (c) 2010-2018 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -374,7 +374,7 @@ public void test050JackDeputyOfBarbossa() throws Exception {
rule.setName("barbossa-0");
policyRuleAssignment.setPolicyRule(rule);
@SuppressWarnings({"unchecked", "raw" })
- ObjectDelta objectDelta = (ObjectDelta) DeltaBuilder.deltaFor(UserType.class, prismContext)
+ ObjectDelta objectDelta = deltaFor(UserType.class)
.item(UserType.F_ASSIGNMENT).add(
ObjectTypeUtil.createAssignmentTo(ROLE_R1_OID, ObjectTypes.ROLE, prismContext),
policyRuleAssignment)
@@ -459,7 +459,7 @@ public void test060JackDeputyOfGuybrushDeputyOfBarbossa() throws Exception {
rule.setName("guybrush-0");
policyRuleAssignment.setPolicyRule(rule);
@SuppressWarnings({"unchecked", "raw" })
- ObjectDelta objectDelta = (ObjectDelta) DeltaBuilder.deltaFor(UserType.class, prismContext)
+ ObjectDelta objectDelta = deltaFor(UserType.class)
.item(UserType.F_ASSIGNMENT).add(deputyOfBarbossaAssignment, policyRuleAssignment)
.asObjectDelta(USER_GUYBRUSH_OID);
executeChangesAssertSuccess(objectDelta, null, task, result);
diff --git a/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyRules.java b/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyRules.java
index 4a2893b8947..59db6d44d1f 100644
--- a/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyRules.java
+++ b/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyRules.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2017 Evolveum
+ * Copyright (c) 2010-2018 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -630,7 +630,7 @@ public void test300DrakeChangeEmployeeType() throws Exception {
// WHEN
TestUtil.displayWhen(TEST_NAME);
- ObjectDelta extends ObjectType> delta = (ObjectDelta extends ObjectType>) DeltaBuilder.deltaFor(UserType.class, prismContext)
+ ObjectDelta extends ObjectType> delta = deltaFor(UserType.class)
.item(UserType.F_ASSIGNMENT)
.add(ObjectTypeUtil.createAssignmentTo(ROLE_JUDGE_OID, ObjectTypes.ROLE, prismContext))
.item(UserType.F_EMPLOYEE_TYPE).replace("T")
diff --git a/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyRules2.java b/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyRules2.java
index f68c8729b0d..cd63e124e9b 100644
--- a/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyRules2.java
+++ b/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/lens/TestPolicyRules2.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2017 Evolveum
+ * Copyright (c) 2010-2018 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -244,7 +244,7 @@ public void test120JackAttemptToMoveTo1900AndAssignRoleStudent() throws Exceptio
fillContextWithUser(context, USER_JACK_OID, result);
AssignmentType assignment = ObjectTypeUtil.createAssignmentTo(roleStudentOid, ObjectTypes.ROLE, prismContext);
assignment.beginActivation().validTo("2099-01-01T00:00:00");
- context.getFocusContext().addPrimaryDelta((ObjectDelta) DeltaBuilder.deltaFor(UserType.class, prismContext)
+ context.getFocusContext().addPrimaryDelta(DeltaBuilder.deltaFor(UserType.class, prismContext)
.item(UserType.F_ASSIGNMENT).add(assignment)
.item(UserType.F_COST_CENTER).replace("1900")
.asObjectDelta(USER_JACK_OID));
@@ -297,7 +297,7 @@ public void test130JackMoveTo1900AndAssignRoleStudent() throws Exception {
fillContextWithUser(context, USER_JACK_OID, result);
AssignmentType assignment = ObjectTypeUtil.createAssignmentTo(roleStudentOid, ObjectTypes.ROLE, prismContext);
assignment.beginActivation().validTo("2099-01-01T00:00:00");
- context.getFocusContext().addPrimaryDelta((ObjectDelta) DeltaBuilder.deltaFor(UserType.class, prismContext)
+ context.getFocusContext().addPrimaryDelta(DeltaBuilder.deltaFor(UserType.class, prismContext)
.item(UserType.F_ASSIGNMENT).add(assignment)
.item(UserType.F_COST_CENTER).replace("1900")
.asObjectDelta(USER_JACK_OID));
@@ -353,7 +353,7 @@ public void test135JackChangeValidTo() throws Exception {
LensContext context = createUserLensContext();
fillContextWithUser(context, USER_JACK_OID, result);
- context.getFocusContext().addPrimaryDelta((ObjectDelta) DeltaBuilder.deltaFor(UserType.class, prismContext)
+ context.getFocusContext().addPrimaryDelta(DeltaBuilder.deltaFor(UserType.class, prismContext)
.item(UserType.F_ASSIGNMENT, assignmentId, AssignmentType.F_ACTIVATION, ActivationType.F_VALID_TO).replace()
.asObjectDelta(USER_JACK_OID));
display("Input context", context);
@@ -501,7 +501,7 @@ public void test150FrankAttemptToAssignRoleStudentButDisabled() throws Exception
LensContext context = createUserLensContext();
fillContextWithUser(context, userFrankOid, result);
- context.getFocusContext().addPrimaryDelta((ObjectDelta) DeltaBuilder.deltaFor(UserType.class, prismContext)
+ context.getFocusContext().addPrimaryDelta(DeltaBuilder.deltaFor(UserType.class, prismContext)
.item(UserType.F_ASSIGNMENT).add(
ObjectTypeUtil.createAssignmentTo(roleStudentOid, ObjectTypes.ROLE, prismContext)
.beginActivation()
diff --git a/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/visualizer/TestVisualizer.java b/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/visualizer/TestVisualizer.java
index d68a41a774f..6b86cbb83ad 100644
--- a/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/visualizer/TestVisualizer.java
+++ b/model/model-impl/src/test/java/com/evolveum/midpoint/model/impl/visualizer/TestVisualizer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2017 Evolveum
+ * Copyright (c) 2010-2018 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -138,7 +138,7 @@ public void test200UserDeltaBasic() throws Exception {
final String TEST_NAME = "test200UserDeltaBasic";
Task task = createTask(TEST_NAME);
- ObjectDelta> delta = DeltaBuilder.deltaFor(UserType.class, prismContext)
+ ObjectDelta> delta = deltaFor(UserType.class)
.item(UserType.F_NAME).replace("admin")
.asObjectDelta(USER_ADMINISTRATOR_OID);
@@ -164,7 +164,7 @@ public void test210UserDeltaContainers() throws Exception {
ass1.getActivation().setValidTo(XmlTypeConverter.createXMLGregorianCalendar(2017, 1, 1, 0, 0, 0));
ass1.setTargetRef(createObjectRef(ROLE_SUPERUSER_OID, ROLE));
- ObjectDelta> delta = DeltaBuilder.deltaFor(UserType.class, prismContext)
+ ObjectDelta> delta = deltaFor(UserType.class)
.item(UserType.F_NAME).replace("admin")
.item(UserType.F_ACTIVATION, ActivationType.F_ADMINISTRATIVE_STATUS).replace(ActivationStatusType.ENABLED)
.item(UserType.F_ASSIGNMENT, 1, AssignmentType.F_TARGET_REF).replace(createObjectRef("123", ROLE).asReferenceValue())
@@ -188,7 +188,7 @@ public void test212UserDeltaContainerSimple() throws Exception {
final String TEST_NAME = "test212UserDeltaContainerSimple";
Task task = createTask(TEST_NAME);
- ObjectDelta> delta = DeltaBuilder.deltaFor(UserType.class, prismContext)
+ ObjectDelta> delta = deltaFor(UserType.class)
.item(UserType.F_ACTIVATION, ActivationType.F_EFFECTIVE_STATUS).replace(ActivationStatusType.ENABLED)
.item(UserType.F_ACTIVATION, ActivationType.F_ENABLE_TIMESTAMP).replace(XmlTypeConverter.createXMLGregorianCalendar(new Date()))
.asObjectDelta(USER_ADMINISTRATOR_OID);
@@ -218,7 +218,7 @@ public void test220UserContainerReplace() throws Exception {
ActivationType act1 = new ActivationType(prismContext);
act1.setAdministrativeStatus(ActivationStatusType.DISABLED);
- ObjectDelta> delta = DeltaBuilder.deltaFor(UserType.class, prismContext)
+ ObjectDelta> delta = deltaFor(UserType.class)
.item(UserType.F_NAME).replace("admin")
.item(UserType.F_ACTIVATION).replace(act1)
.item(UserType.F_ASSIGNMENT).replace(ass1)
@@ -246,7 +246,7 @@ public void test230UserContainerDelete() throws Exception {
AssignmentType ass2 = new AssignmentType(prismContext);
ass2.setId(99999L);
- ObjectDelta> delta = DeltaBuilder.deltaFor(UserType.class, prismContext)
+ ObjectDelta> delta = deltaFor(UserType.class)
.item(UserType.F_NAME).replace("admin")
.item(UserType.F_ASSIGNMENT).delete(ass1, ass2)
.asObjectDelta(USER_ADMINISTRATOR_OID);
@@ -274,7 +274,7 @@ public void test300UserAssignmentPreview() throws Exception {
ass1.setConstruction(new ConstructionType(prismContext));
ass1.getConstruction().setResourceRef(createObjectRef(RESOURCE_DUMMY_OID, RESOURCE));
- ObjectDelta delta = (ObjectDelta) DeltaBuilder.deltaFor(UserType.class, prismContext)
+ ObjectDelta delta = deltaFor(UserType.class)
.item(UserType.F_ASSIGNMENT).add(ass1)
.asObjectDelta(USER_JACK_OID);
@@ -309,7 +309,7 @@ public void test305UserAssignmentAdd() throws Exception {
ass1.setConstruction(new ConstructionType());
ass1.getConstruction().setResourceRef(createObjectRef(RESOURCE_DUMMY_OID, RESOURCE));
- ObjectDelta delta = (ObjectDelta) DeltaBuilder.deltaFor(UserType.class, prismContext)
+ ObjectDelta delta = deltaFor(UserType.class)
.item(UserType.F_ASSIGNMENT).add(ass1)
.asObjectDelta(USER_JACK_OID);
@@ -332,7 +332,7 @@ public void test307UserDisablePreview() throws Exception {
final String TEST_NAME = "test307UserDisablePreview";
Task task = createTask(TEST_NAME);
- ObjectDelta delta = (ObjectDelta) DeltaBuilder.deltaFor(UserType.class, prismContext)
+ ObjectDelta delta = deltaFor(UserType.class)
.item(UserType.F_ACTIVATION, ActivationType.F_ADMINISTRATIVE_STATUS).replace(ActivationStatusType.DISABLED)
.asObjectDelta(USER_JACK_OID);
@@ -381,7 +381,7 @@ public void test310UserLinkRefDelete() throws Exception {
assertEquals("wrong # of linkrefs", 1, jack.getLinkRef().size());
dummyAccountOid = jack.getLinkRef().get(0).getOid();
- ObjectDelta delta = (ObjectDelta) DeltaBuilder.deltaFor(UserType.class, prismContext)
+ ObjectDelta delta = deltaFor(UserType.class)
.item(UserType.F_LINK_REF).delete(createObjectRef(dummyAccountOid, SHADOW).asReferenceValue())
.asObjectDelta(USER_JACK_OID);
@@ -401,7 +401,7 @@ public void test320UserLinkRefAdd() throws Exception {
final String TEST_NAME = "test320UserLinkRefAdd";
Task task = createTask(TEST_NAME);
- ObjectDelta delta = (ObjectDelta) DeltaBuilder.deltaFor(UserType.class, prismContext)
+ ObjectDelta delta = deltaFor(UserType.class)
.item(UserType.F_LINK_REF).add(createObjectRef(dummyAccountOid, SHADOW).asReferenceValue())
.asObjectDelta(USER_JACK_OID);
@@ -421,7 +421,7 @@ public void test330UserLinkRefReplaceNoOp() throws Exception {
final String TEST_NAME = "test330UserLinkRefReplaceNoOp";
Task task = createTask(TEST_NAME);
- ObjectDelta delta = (ObjectDelta) DeltaBuilder.deltaFor(UserType.class, prismContext)
+ ObjectDelta delta = deltaFor(UserType.class)
.item(UserType.F_LINK_REF).replace(createObjectRef(dummyAccountOid, SHADOW).asReferenceValue())
.asObjectDelta(USER_JACK_OID);
@@ -441,7 +441,7 @@ public void test340UserLinkRefReplaceOp() throws Exception {
final String TEST_NAME = "test340UserLinkRefReplaceOp";
Task task = createTask(TEST_NAME);
- ObjectDelta delta = (ObjectDelta) DeltaBuilder.deltaFor(UserType.class, prismContext)
+ ObjectDelta delta = deltaFor(UserType.class)
.item(UserType.F_LINK_REF).replace(createObjectRef("777", SHADOW).asReferenceValue())
.asObjectDelta(USER_JACK_OID);
diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/AbstractConfiguredModelIntegrationTest.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/AbstractConfiguredModelIntegrationTest.java
index 13bb1d23e5a..d648332103b 100644
--- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/AbstractConfiguredModelIntegrationTest.java
+++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/AbstractConfiguredModelIntegrationTest.java
@@ -297,6 +297,9 @@ public class AbstractConfiguredModelIntegrationTest extends AbstractModelIntegra
protected static final File ROLE_ADMINS_FILE = new File(COMMON_DIR, "role-admins.xml");
protected static final String ROLE_ADMINS_OID = "be835a70-e3f4-11e6-82cb-9b47ecb57v15";
+ protected static final File ROLE_END_USER_FILE = new File(COMMON_DIR, "role-end-user.xml");
+ protected static final String ROLE_END_USER_OID = "00000000-0000-0000-0000-00000000aa0f";
+
public static final File USER_JACK_FILE = new File(COMMON_DIR, "user-jack.xml");
public static final String USER_JACK_OID = "c0c010c0-d34d-b33f-f00d-111111111111";
public static final String USER_JACK_USERNAME = "jack";
diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestConsistencySimple.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestConsistencySimple.java
index df98cd94e6d..b12c3cf4ba9 100644
--- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestConsistencySimple.java
+++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestConsistencySimple.java
@@ -175,7 +175,7 @@ private void executeTest(final String TEST_NAME, FocusOperation focusOperation,
if (shadowOperation != ShadowOperation.KEEP) {
@SuppressWarnings("unchecked")
- ObjectDelta removeLinkRefDelta = (ObjectDelta) DeltaBuilder.deltaFor(UserType.class, prismContext)
+ ObjectDelta removeLinkRefDelta = deltaFor(UserType.class)
.item(UserType.F_LINK_REF).replace()
.asObjectDelta(USER_JACK_OID);
executeChanges(removeLinkRefDelta, ModelExecuteOptions.createRaw(), task, result);
@@ -188,7 +188,7 @@ private void executeTest(final String TEST_NAME, FocusOperation focusOperation,
} else {
if (shadowOperation == ShadowOperation.UNLINK_AND_TOMBSTONE) {
@SuppressWarnings("unchecked")
- ObjectDelta markAsDead = (ObjectDelta) DeltaBuilder.deltaFor(ShadowType.class, prismContext)
+ ObjectDelta markAsDead = deltaFor(ShadowType.class)
.item(ShadowType.F_DEAD).replace(Boolean.TRUE)
.asObjectDelta(shadowBefore.getOid());
executeChanges(markAsDead, ModelExecuteOptions.createRaw(), task, result);
@@ -280,7 +280,7 @@ private void cleanUpBeforeTest(Task task, OperationResult result) throws Excepti
for (ObjectReferenceType ref : jack.asObjectable().getLinkRef()) {
deleteObject(ShadowType.class, ref.getOid());
}
- ObjectDelta killLinkRefDelta = (ObjectDelta) DeltaBuilder.deltaFor(UserType.class, prismContext)
+ ObjectDelta killLinkRefDelta = deltaFor(UserType.class)
.item(UserType.F_LINK_REF).replace().asObjectDelta(USER_JACK_OID);
executeChanges(killLinkRefDelta, ModelExecuteOptions.createRaw(), task, result);
}
diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestRaceConditions.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestRaceConditions.java
index f96d8af30b1..00ea556eadf 100644
--- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestRaceConditions.java
+++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestRaceConditions.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2017 Evolveum
+ * Copyright (c) 2010-2018 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -70,7 +70,7 @@ public void test100AssignRoles() throws Exception {
// WHEN
TestUtil.displayWhen(TEST_NAME);
@SuppressWarnings({"unchecked", "raw"})
- ObjectDelta objectDelta = (ObjectDelta) DeltaBuilder.deltaFor(UserType.class, prismContext)
+ ObjectDelta objectDelta = deltaFor(UserType.class)
.item(UserType.F_ASSIGNMENT).add(
ObjectTypeUtil.createAssignmentTo(ROLE_PIRATE_OID, ObjectTypes.ROLE, prismContext),
ObjectTypeUtil.createAssignmentTo(ROLE_SAILOR_OID, ObjectTypes.ROLE, prismContext))
@@ -131,7 +131,7 @@ private void deleteAssignment(PrismObject user, int index, Task task,
try {
login(userAdministrator);
@SuppressWarnings({ "unchecked", "raw" })
- ObjectDelta objectDelta = (ObjectDelta) DeltaBuilder.deltaFor(UserType.class, prismContext)
+ ObjectDelta objectDelta = deltaFor(UserType.class)
.item(FocusType.F_ASSIGNMENT).delete(user.asObjectable().getAssignment().get(index).clone())
.asObjectDelta(USER_JACK_OID);
modelService.executeChanges(Collections.singletonList(objectDelta), null, task,
diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/password/AbstractPasswordTest.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/password/AbstractPasswordTest.java
index 9241b041645..36c453b25a3 100644
--- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/password/AbstractPasswordTest.java
+++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/password/AbstractPasswordTest.java
@@ -27,6 +27,7 @@
import com.evolveum.midpoint.prism.delta.builder.DeltaBuilder;
import com.evolveum.midpoint.test.DummyResourceContoller;
import com.evolveum.midpoint.test.IntegrationTestTools;
+import com.evolveum.midpoint.test.asserter.UserAsserter;
import com.evolveum.midpoint.test.util.MidPointTestConstants;
import com.evolveum.midpoint.util.exception.*;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;
@@ -80,6 +81,8 @@ public abstract class AbstractPasswordTest extends AbstractInitializedModelInteg
protected static final String USER_PASSWORD_VALID_2 = "abcd223";
protected static final String USER_PASSWORD_VALID_3 = "abcd323";
protected static final String USER_PASSWORD_VALID_4 = "abcd423";
+ protected static final String USER_PASSWORD_VALID_5 = "abcd523";
+ protected static final String USER_PASSWORD_VALID_6 = "abcd623";
// Very long and very simple password. This is meant to violate the policies.
protected static final String USER_PASSWORD_LLL_CLEAR = "lllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll";
@@ -152,6 +155,8 @@ public void initSystem(Task initTask, OperationResult initResult) throws Excepti
repoAddObjectFromFile(USER_THREE_HEADED_MONKEY_FILE, UserType.class, true, initResult);
+ repoAddObjectFromFile(ROLE_END_USER_FILE, initResult);
+
importObjectFromFile(PASSWORD_POLICY_MAVERICK_FILE);
initDummyResourcePirate(RESOURCE_DUMMY_MAVERICK_NAME, RESOURCE_DUMMY_MAVERICK_FILE, RESOURCE_DUMMY_MAVERICK_OID, initTask, initResult);
@@ -1280,8 +1285,7 @@ public void test222ModifyUserJackPasswordBadContainer() throws Exception {
}
// THEN
- result.computeStatus();
- TestUtil.assertFailure(result);
+ assertFailure(result);
assertJackPasswordsWithHistory(USER_PASSWORD_VALID_1, USER_PASSWORD_AA_CLEAR);
assertNoUserPasswordNotifications();
@@ -1391,8 +1395,7 @@ private void doTestModifyUserJackPasswordSuccessWithHistory(final String TEST_NA
modifyUserChangePassword(USER_JACK_OID, newPassword, task, result);
// THEN
- result.computeStatus();
- TestUtil.assertSuccess(result);
+ assertSuccess(result);
lastPasswordChangeEnd = clock.currentTimeXMLGregorianCalendar();
@@ -1426,8 +1429,7 @@ private void doTestModifyUserJackPasswordFailureWithHistory(final String TEST_NA
}
// THEN
- result.computeStatus();
- TestUtil.assertFailure(result);
+ assertFailure(result);
assertJackPasswordsWithHistory(oldPassword, expectedPasswordHistory);
@@ -1478,7 +1480,7 @@ public void test300TwoParentOrgRefs() throws Exception {
display("jack", jack);
assertEquals("Wrong # of parentOrgRefs", 2, jack.getParentOrgRef().size());
- ObjectDelta orgDelta = (ObjectDelta) DeltaBuilder.deltaFor(OrgType.class, prismContext)
+ ObjectDelta orgDelta = DeltaBuilder.deltaFor(OrgType.class, prismContext)
.item(OrgType.F_PASSWORD_POLICY_REF).replace(new PrismReferenceValue(PASSWORD_POLICY_GLOBAL_OID))
.asObjectDelta(ORG_GOVERNOR_OFFICE_OID);
executeChanges(orgDelta, null, task, result);
@@ -1498,8 +1500,7 @@ public void test300TwoParentOrgRefs() throws Exception {
}
// THEN
- result.computeStatus();
- TestUtil.assertFailure(result);
+ assertFailure(result);
PrismObject userJack = getUser(USER_JACK_OID);
display("User after change execution", userJack);
@@ -1779,8 +1780,8 @@ public void test316UserRecompute() throws Exception {
}
/**
- * Change password again so we have predictable password instead of
- * randomly-generated one.
+ * Change password to set predictable password instead of randomly-generated one.
+ * That will be nicer for future tests.
*/
@Test
public void test318ChangeUserPassword() throws Exception {
@@ -1791,27 +1792,33 @@ public void test318ChangeUserPassword() throws Exception {
Task task = createTask(TEST_NAME);
OperationResult result = task.getResult();
prepareTest();
-
+
// WHEN
- TestUtil.displayWhen(TEST_NAME);
+ displayWhen(TEST_NAME);
modifyUserChangePassword(USER_JACK_OID, USER_PASSWORD_VALID_3, task, result);
// THEN
- TestUtil.displayThen(TEST_NAME);
- result.computeStatus();
- TestUtil.assertSuccess(result);
-
- PrismObject userAfter = getUser(USER_JACK_OID);
- display("User after change execution", userAfter);
- assertUserPassword(userAfter, USER_PASSWORD_VALID_3);
- assertLinks(userAfter, 4);
-
- // password mapping is normal
- assertDummyPassword(ACCOUNT_JACK_DUMMY_USERNAME, USER_PASSWORD_VALID_3);
+ displayThen(TEST_NAME);
+ assertSuccess(result);
- // password mapping is strong
- assertDummyAccount(RESOURCE_DUMMY_RED_NAME, ACCOUNT_JACK_DUMMY_USERNAME, USER_JACK_FULL_NAME, true);
- assertDummyPassword(RESOURCE_DUMMY_RED_NAME, ACCOUNT_JACK_DUMMY_USERNAME, USER_PASSWORD_VALID_3);
+ PrismObject userAfter = assertUserAfter(USER_JACK_OID)
+ .assertPassword(USER_PASSWORD_VALID_3, getPasswordStorageType())
+ .assertLinks(4)
+ .getObject();
+
+ // default password mapping is normal
+ assertDummyAccountByUsername(null, ACCOUNT_JACK_DUMMY_USERNAME)
+ .assertPassword(USER_PASSWORD_VALID_3)
+ // Admin password reset, no runAs
+ .assertLastModifier(null);
+
+ // RED password mapping is strong
+ assertDummyAccountByUsername(RESOURCE_DUMMY_RED_NAME, ACCOUNT_JACK_DUMMY_USERNAME)
+ .assertFullName(USER_JACK_FULL_NAME)
+ .assertEnabled()
+ .assertPassword(USER_PASSWORD_VALID_3)
+ // and RED resource has no runAs capability
+ .assertLastModifier(null);
// password mapping is weak
assertDummyAccount(RESOURCE_DUMMY_BLUE_NAME, ACCOUNT_JACK_DUMMY_USERNAME, USER_JACK_FULL_NAME, true);
@@ -3486,7 +3493,237 @@ private void testJackManyPasswordChangesAttempt(String TEST_NAME, String passwor
assertDummyPassword(ACCOUNT_JACK_DUMMY_USERNAME, newPassword);
assertDummyPassword(RESOURCE_DUMMY_RED_NAME, ACCOUNT_JACK_DUMMY_USERNAME, newPassword);
}
+
+ /**
+ * Jack changing his own password. He does it as an admin
+ * and there is no old password specified. RunAs should NOT be used.
+ *
+ * This also sets predictable password for next test.
+ *
+ * MID-4661
+ */
+ @Test
+ public void test560ChangeJackPasswordSuperuser() throws Exception {
+ final String TEST_NAME = "test560ChangeJackPasswordSuperuser";
+ displayTestTitle(TEST_NAME);
+
+ // GIVEN
+ prepareTest();
+
+ assignRole(USER_JACK_OID, ROLE_SUPERUSER_OID);
+
+ // preconditions
+ assertUserBefore(USER_JACK_OID)
+ .displayWithProjections()
+ .assertLinks(4);
+
+ assertDummyAccountByUsername(null, ACCOUNT_JACK_DUMMY_USERNAME)
+ .assertLastModifier(null);
+
+ login(USER_JACK_USERNAME);
+
+ Task task = createTask(TEST_NAME, getSecurityContextPrincipal());
+ task.setChannel(SchemaConstants.CHANNEL_GUI_USER_URI);
+ OperationResult result = task.getResult();
+
+ // WHEN
+ displayWhen(TEST_NAME);
+ modifyUserChangePassword(USER_JACK_OID, USER_PASSWORD_VALID_4, task, result);
+
+ // THEN
+ displayThen(TEST_NAME);
+ login(USER_ADMINISTRATOR_USERNAME);
+ assertSuccess(result);
+
+ assertUserAfter(USER_JACK_OID)
+ .assertPassword(USER_PASSWORD_VALID_4, getPasswordStorageType())
+ .assertLinks(4)
+ .getObject();
+
+ // default password mapping is normal
+ assertDummyAccountByUsername(null, ACCOUNT_JACK_DUMMY_USERNAME)
+ .assertPassword(USER_PASSWORD_VALID_4)
+ .assertLastModifier(null);
+
+ // RED password mapping is strong
+ assertDummyAccountByUsername(RESOURCE_DUMMY_RED_NAME, ACCOUNT_JACK_DUMMY_USERNAME)
+ .assertFullName(USER_JACK_FULL_NAME)
+ .assertEnabled()
+ .assertPassword(USER_PASSWORD_VALID_4)
+ // and RED resource has no runAs capability
+ .assertLastModifier(null);
+
+ // BLUE password mapping is weak, we do not really care about password change here
+ // we do not really care about ugly resource either
+
+ displayAccountPasswordNotifications();
+ assertAccountPasswordNotifications(2);
+ assertHasAccountPasswordNotification(null, USER_JACK_USERNAME, USER_PASSWORD_VALID_4);
+ assertHasAccountPasswordNotification(RESOURCE_DUMMY_RED_NAME, USER_JACK_USERNAME, USER_PASSWORD_VALID_4);
+ // not BLUE, it already has a password
+ assertSingleUserPasswordNotification(USER_JACK_USERNAME, USER_PASSWORD_VALID_4);
+ }
+
+ private ObjectDelta createOldNewPasswordDelta(String oid, String oldPassword, String newPassword) throws SchemaException {
+ ProtectedStringType oldPasswordPs = new ProtectedStringType();
+ oldPasswordPs.setClearValue(oldPassword);
+
+ ProtectedStringType newPasswordPs = new ProtectedStringType();
+ newPasswordPs.setClearValue(newPassword);
+
+ return deltaFor(UserType.class)
+ .item(PASSWORD_VALUE_PATH)
+ .oldRealValue(oldPasswordPs)
+ .replace(newPasswordPs)
+ .asObjectDelta(USER_JACK_OID);
+ }
+
+ /**
+ * Self-service password change. User's own identity should be used
+ * to change password on resource that have runAs capability.
+ *
+ * MID-4661
+ */
+ @Test
+ public void test562ChangeJackPasswordSelfService() throws Exception {
+ final String TEST_NAME = "test562ChangeJackPasswordSelfService";
+ displayTestTitle(TEST_NAME);
+
+ // GIVEN
+ prepareTest();
+
+ // preconditions
+ assertUserBefore(USER_JACK_OID)
+ .displayWithProjections()
+ .assertLinks(4);
+
+ assertDummyAccountByUsername(null, ACCOUNT_JACK_DUMMY_USERNAME)
+ .assertPassword(USER_PASSWORD_VALID_4)
+ .assertLastModifier(null);
+
+ login(USER_JACK_USERNAME);
+
+ Task task = createTask(TEST_NAME, getSecurityContextPrincipal());
+ task.setChannel(SchemaConstants.CHANNEL_GUI_SELF_SERVICE_URI);
+ OperationResult result = task.getResult();
+
+ ObjectDelta objectDelta = createOldNewPasswordDelta(USER_JACK_OID,
+ USER_PASSWORD_VALID_4, USER_PASSWORD_VALID_5);
+
+ // WHEN
+ displayWhen(TEST_NAME);
+ executeChanges(objectDelta, null, task, result);
+
+ // THEN
+ displayThen(TEST_NAME);
+ login(USER_ADMINISTRATOR_USERNAME);
+ assertSuccess(result);
+
+ assertUserAfter(USER_JACK_OID)
+ .assertPassword(USER_PASSWORD_VALID_5, getPasswordStorageType())
+ .assertLinks(4)
+ .getObject();
+
+ // default password mapping is normal
+ assertDummyAccountByUsername(null, ACCOUNT_JACK_DUMMY_USERNAME)
+ .assertPassword(USER_PASSWORD_VALID_5)
+ .assertLastModifier(ACCOUNT_JACK_DUMMY_USERNAME);
+
+ // RED password mapping is strong
+ assertDummyAccountByUsername(RESOURCE_DUMMY_RED_NAME, ACCOUNT_JACK_DUMMY_USERNAME)
+ .assertFullName(USER_JACK_FULL_NAME)
+ .assertEnabled()
+ .assertPassword(USER_PASSWORD_VALID_5)
+ // and RED resource has no runAs capability
+ .assertLastModifier(null);
+
+ // BLUE password mapping is weak, we do not really care about password change here
+ // we do not really care about ugly resource either
+
+ displayAccountPasswordNotifications();
+ assertAccountPasswordNotifications(2);
+ assertHasAccountPasswordNotification(null, USER_JACK_USERNAME, USER_PASSWORD_VALID_5);
+ assertHasAccountPasswordNotification(RESOURCE_DUMMY_RED_NAME, USER_JACK_USERNAME, USER_PASSWORD_VALID_5);
+ // not BLUE, it already has a password
+ assertSingleUserPasswordNotification(USER_JACK_USERNAME, USER_PASSWORD_VALID_5);
+ }
+
+ /**
+ * Admin is changing Jack's password.
+ * Old password is (strangely) specified.
+ * But as this is not user changing its own password then RunAs
+ * should NOT be used.
+ *
+ * MID-4661
+ */
+ @Test
+ public void test564ChangeJackPasswordAdmin() throws Exception {
+ final String TEST_NAME = "test564ChangeJackPasswordAdmin";
+ displayTestTitle(TEST_NAME);
+
+ // GIVEN
+
+ prepareTest();
+
+ // preconditions
+ assertUserBefore(USER_JACK_OID)
+ .displayWithProjections()
+ .assertLinks(4);
+
+ assertDummyAccountByUsername(null, ACCOUNT_JACK_DUMMY_USERNAME)
+ .assertPassword(USER_PASSWORD_VALID_5)
+ .assertLastModifier(ACCOUNT_JACK_DUMMY_USERNAME);
+
+ login(USER_ADMINISTRATOR_USERNAME);
+
+ Task task = createTask(TEST_NAME, getSecurityContextPrincipal());
+ task.setChannel(SchemaConstants.CHANNEL_GUI_USER_URI);
+ OperationResult result = task.getResult();
+
+ ObjectDelta objectDelta = createOldNewPasswordDelta(USER_JACK_OID,
+ USER_PASSWORD_VALID_5, USER_PASSWORD_VALID_6);
+
+ // WHEN
+ displayWhen(TEST_NAME);
+ executeChanges(objectDelta, null, task, result);
+
+ // THEN
+ displayThen(TEST_NAME);
+ login(USER_ADMINISTRATOR_USERNAME);
+ assertSuccess(result);
+
+ assertUserAfter(USER_JACK_OID)
+ .assertPassword(USER_PASSWORD_VALID_6, getPasswordStorageType())
+ .assertLinks(4)
+ .getObject();
+
+ // default password mapping is normal
+ assertDummyAccountByUsername(null, ACCOUNT_JACK_DUMMY_USERNAME)
+ .assertPassword(USER_PASSWORD_VALID_6)
+ .assertLastModifier(null);
+
+ // RED password mapping is strong
+ assertDummyAccountByUsername(RESOURCE_DUMMY_RED_NAME, ACCOUNT_JACK_DUMMY_USERNAME)
+ .assertFullName(USER_JACK_FULL_NAME)
+ .assertEnabled()
+ .assertPassword(USER_PASSWORD_VALID_6)
+ // and RED resource has no runAs capability
+ .assertLastModifier(null);
+
+ // BLUE password mapping is weak, we do not really care about password change here
+ // we do not really care about ugly resource either
+
+ displayAccountPasswordNotifications();
+ assertAccountPasswordNotifications(2);
+ assertHasAccountPasswordNotification(null, USER_JACK_USERNAME, USER_PASSWORD_VALID_6);
+ assertHasAccountPasswordNotification(RESOURCE_DUMMY_RED_NAME, USER_JACK_USERNAME, USER_PASSWORD_VALID_6);
+ // not BLUE, it already has a password
+ assertSingleUserPasswordNotification(USER_JACK_USERNAME, USER_PASSWORD_VALID_6);
+ }
+
+
+
protected ObjectDelta createAccountInitializationDelta(String accountOid, String newAccountPassword) {
ObjectDelta shadowDelta = ObjectDelta.createEmptyModifyDelta(ShadowType.class, accountOid, prismContext);
ProtectedStringType passwordPs = new ProtectedStringType();
diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/security/AbstractSecurityTest.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/security/AbstractSecurityTest.java
index b3edd4562b4..4821aced12f 100644
--- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/security/AbstractSecurityTest.java
+++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/security/AbstractSecurityTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2017 Evolveum
+ * Copyright (c) 2010-2018 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -254,9 +254,6 @@ public abstract class AbstractSecurityTest extends AbstractInitializedModelInteg
protected static final File ROLE_FILTER_OBJECT_USER_TYPE_SHADOWS_FILE = new File(TEST_DIR, "role-filter-object-user-type-shadow.xml");
protected static final String ROLE_FILTER_OBJECT_USER_TYPE_SHADOWS_OID = "00000000-0000-0000-0000-00000000aa0h";
- protected static final File ROLE_END_USER_FILE = new File(TEST_DIR, "role-end-user.xml");
- protected static final String ROLE_END_USER_OID = "00000000-0000-0000-0000-00000000aa0f";
-
protected static final File ROLE_MODIFY_USER_FILE = new File(TEST_DIR, "role-modify-user.xml");
protected static final String ROLE_MODIFY_USER_OID = "00000000-0000-0000-0000-00000000aa0g";
diff --git a/model/model-intest/src/test/resources/common/resource-dummy-red.xml b/model/model-intest/src/test/resources/common/resource-dummy-red.xml
index e16bdd305a2..43a4893a2fd 100644
--- a/model/model-intest/src/test/resources/common/resource-dummy-red.xml
+++ b/model/model-intest/src/test/resources/common/resource-dummy-red.xml
@@ -1,6 +1,6 @@
+ has mostly STRONG mappings, therefore it is used in strong mapping tests. Also:
+ * has pre-create and delayed delete configuration.
+ * does NOT support runAs
+ -->
red
+ false
useless
diff --git a/model/model-intest/src/test/resources/security/role-end-user.xml b/model/model-intest/src/test/resources/common/role-end-user.xml
similarity index 100%
rename from model/model-intest/src/test/resources/security/role-end-user.xml
rename to model/model-intest/src/test/resources/common/role-end-user.xml
diff --git a/model/model-intest/src/test/resources/logback-test.xml b/model/model-intest/src/test/resources/logback-test.xml
index 34fd61718ea..648dc2323dc 100644
--- a/model/model-intest/src/test/resources/logback-test.xml
+++ b/model/model-intest/src/test/resources/logback-test.xml
@@ -68,7 +68,7 @@
-
+
@@ -97,8 +97,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 48fe34455f6..4c8a19b22a4 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
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2017 Evolveum
+ * Copyright (c) 2010-2018 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -717,7 +717,7 @@ protected void modifyUserSetPassword(String userOid, String newPassword, Task ta
userPasswordPs.setClearValue(newPassword);
PasswordType passwordType = new PasswordType();
passwordType.setValue(userPasswordPs);
- ObjectDelta delta = (ObjectDelta) DeltaBuilder.deltaFor(UserType.class, prismContext)
+ ObjectDelta delta = DeltaBuilder.deltaFor(UserType.class, prismContext)
.item(SchemaConstants.PATH_PASSWORD).add(passwordType)
.asObjectDelta(userOid);
executeChanges(delta, null, task, result);
@@ -5368,6 +5368,7 @@ protected PendingOperationType findPendingOperation(PrismObject shad
protected void initializeAsserter(AbstractAsserter> asserter) {
asserter.setPrismContext(prismContext);
asserter.setObjectResolver(repoSimpleObjectResolver);
+ asserter.setProtector(protector);
}
protected UserAsserter assertUserAfter(String oid) throws ObjectNotFoundException, SchemaException, SecurityViolationException, CommunicationException, ConfigurationException, ExpressionEvaluationException {
diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/entitlements/AddAssociationAspect.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/entitlements/AddAssociationAspect.java
index d1253941b4e..c00d19db439 100644
--- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/entitlements/AddAssociationAspect.java
+++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/entitlements/AddAssociationAspect.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2015 Evolveum
+ * Copyright (c) 2010-2018 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -270,7 +270,7 @@ private ObjectTreeDeltas associationAdditionToDelta(ModelContext> modelContext
ResourceShadowDiscriminator shadowDiscriminator =
ResourceShadowDiscriminator.fromResourceShadowDiscriminatorType(addition.getResourceShadowDiscriminator());
String projectionOid = modelContext.findProjectionContext(shadowDiscriminator).getOid();
- ObjectDelta objectDelta = (ObjectDelta) DeltaBuilder.deltaFor(ShadowType.class, prismContext)
+ ObjectDelta objectDelta = DeltaBuilder.deltaFor(ShadowType.class, prismContext)
.item(ShadowType.F_ASSOCIATION).add(addition.getAssociation().clone())
.asObjectDelta(projectionOid);
diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/policy/AssignmentPolicyAspectPart.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/policy/AssignmentPolicyAspectPart.java
index e129f9648e4..cdb5d69ad23 100644
--- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/policy/AssignmentPolicyAspectPart.java
+++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/policy/AssignmentPolicyAspectPart.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2017 Evolveum
+ * Copyright (c) 2010-2018 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -348,7 +348,7 @@ private ObjectDelta extends FocusType> assignmentToDelta(Class extends Objec
S_ValuesEntry item = DeltaBuilder.deltaFor(focusClass, prismContext)
.item(FocusType.F_ASSIGNMENT);
S_ItemEntry op = assignmentRemoved ? item.delete(value) : item.add(value);
- return (ObjectDelta extends FocusType>) op.asObjectDelta(objectOid);
+ return op.asObjectDelta(objectOid);
}
}
diff --git a/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/policy/assignments/AbstractTestAssignmentApproval.java b/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/policy/assignments/AbstractTestAssignmentApproval.java
index eaff8805155..48ebb5ee65a 100644
--- a/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/policy/assignments/AbstractTestAssignmentApproval.java
+++ b/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/policy/assignments/AbstractTestAssignmentApproval.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2017 Evolveum
+ * Copyright (c) 2010-2018 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -100,7 +100,7 @@ public void test020DeleteRole1Assignment() throws Exception {
LensContext context = createUserLensContext();
fillContextWithUser(context, userJackOid, result);
addFocusDeltaToContext(context,
- (ObjectDelta) DeltaBuilder.deltaFor(UserType.class, prismContext)
+ DeltaBuilder.deltaFor(UserType.class, prismContext)
.item(UserType.F_ASSIGNMENT).delete(createAssignmentTo(getRoleOid(1), ObjectTypes.ROLE, prismContext))
.asObjectDelta(userJackOid));
clockwork.run(context, task, result);
@@ -288,7 +288,7 @@ private void executeAssignRole1ToJack(String TEST_NAME, boolean immediate, boole
PrismObject jack = getUser(userJackOid);
AssignmentType assignment = createAssignmentTo(getRoleOid(1), ObjectTypes.ROLE, prismContext);
assignment.getTargetRef().setRelation(relation);
- ObjectDelta addRole1Delta = (ObjectDelta) DeltaBuilder
+ ObjectDelta addRole1Delta = DeltaBuilder
.deltaFor(UserType.class, prismContext)
.item(UserType.F_ASSIGNMENT).add(assignment)
.asObjectDelta(userJackOid);
@@ -387,27 +387,27 @@ protected void assertActiveWorkItems(String approverOid, int expectedCount) thro
private void executeAssignRoles123ToJack(String TEST_NAME, boolean immediate, boolean approve1, boolean approve2, boolean approve3) throws Exception {
PrismObject jack = getUser(userJackOid);
@SuppressWarnings("unchecked")
- ObjectDelta addRole1Delta = (ObjectDelta) DeltaBuilder
+ ObjectDelta addRole1Delta = DeltaBuilder
.deltaFor(UserType.class, prismContext)
.item(UserType.F_ASSIGNMENT).add(createAssignmentTo(getRoleOid(1), ObjectTypes.ROLE, prismContext))
.asObjectDelta(userJackOid);
@SuppressWarnings("unchecked")
- ObjectDelta addRole2Delta = (ObjectDelta) DeltaBuilder
+ ObjectDelta addRole2Delta = DeltaBuilder
.deltaFor(UserType.class, prismContext)
.item(UserType.F_ASSIGNMENT).add(createAssignmentTo(getRoleOid(2), ObjectTypes.ROLE, prismContext))
.asObjectDelta(userJackOid);
@SuppressWarnings("unchecked")
- ObjectDelta addRole3Delta = (ObjectDelta) DeltaBuilder
+ ObjectDelta addRole3Delta = DeltaBuilder
.deltaFor(UserType.class, prismContext)
.item(UserType.F_ASSIGNMENT).add(createAssignmentTo(getRoleOid(3), ObjectTypes.ROLE, prismContext))
.asObjectDelta(userJackOid);
@SuppressWarnings("unchecked")
- ObjectDelta addRole4Delta = (ObjectDelta) DeltaBuilder
+ ObjectDelta addRole4Delta = DeltaBuilder
.deltaFor(UserType.class, prismContext)
.item(UserType.F_ASSIGNMENT).add(createAssignmentTo(getRoleOid(4), ObjectTypes.ROLE, prismContext))
.asObjectDelta(userJackOid);
@SuppressWarnings("unchecked")
- ObjectDelta changeDescriptionDelta = (ObjectDelta) DeltaBuilder
+ ObjectDelta changeDescriptionDelta = DeltaBuilder
.deltaFor(UserType.class, prismContext)
.item(UserType.F_DESCRIPTION).replace(TEST_NAME)
.asObjectDelta(userJackOid);
diff --git a/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/policy/assignments/metarole/TestAssignmentsWithDifferentMetaroles.java b/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/policy/assignments/metarole/TestAssignmentsWithDifferentMetaroles.java
index 5c4eb308ad2..1c922e6b4ac 100644
--- a/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/policy/assignments/metarole/TestAssignmentsWithDifferentMetaroles.java
+++ b/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/policy/assignments/metarole/TestAssignmentsWithDifferentMetaroles.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2017 Evolveum
+ * Copyright (c) 2010-2018 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1044,22 +1044,22 @@ private void executeAssignRoles123ToJack(String TEST_NAME, boolean immediate,
Task task = createTask("executeAssignRoles123ToJack");
PrismObject jack = getUser(userJackOid);
@SuppressWarnings("unchecked")
- ObjectDelta addRole1Delta = (ObjectDelta) DeltaBuilder
+ ObjectDelta addRole1Delta = DeltaBuilder
.deltaFor(UserType.class, prismContext)
.item(UserType.F_ASSIGNMENT).add(createAssignmentTo(roleRole21Oid, ObjectTypes.ROLE, prismContext))
.asObjectDelta(userJackOid);
@SuppressWarnings("unchecked")
- ObjectDelta addRole2Delta = (ObjectDelta) DeltaBuilder
+ ObjectDelta addRole2Delta = DeltaBuilder
.deltaFor(UserType.class, prismContext)
.item(UserType.F_ASSIGNMENT).add(createAssignmentTo(roleRole22Oid, ObjectTypes.ROLE, prismContext))
.asObjectDelta(userJackOid);
@SuppressWarnings("unchecked")
- ObjectDelta addRole3Delta = (ObjectDelta) DeltaBuilder
+ ObjectDelta addRole3Delta = DeltaBuilder
.deltaFor(UserType.class, prismContext)
.item(UserType.F_ASSIGNMENT).add(createAssignmentTo(roleRole23Oid, ObjectTypes.ROLE, prismContext))
.asObjectDelta(userJackOid);
@SuppressWarnings("unchecked")
- ObjectDelta changeDescriptionDelta = (ObjectDelta) DeltaBuilder
+ ObjectDelta changeDescriptionDelta = DeltaBuilder
.deltaFor(UserType.class, prismContext)
.item(UserType.F_DESCRIPTION).replace(TEST_NAME)
.asObjectDelta(userJackOid);
@@ -1194,7 +1194,7 @@ private void previewAssignRolesToJack(String TEST_NAME, boolean immediate, boole
assignmentsToAdd.add(createAssignmentTo(roleRole24Oid, ObjectTypes.ROLE, prismContext));
}
@SuppressWarnings("unchecked")
- ObjectDelta primaryDelta = (ObjectDelta) DeltaBuilder
+ ObjectDelta primaryDelta = DeltaBuilder
.deltaFor(UserType.class, prismContext)
.item(UserType.F_ASSIGNMENT).addRealValues(assignmentsToAdd)
.item(UserType.F_DESCRIPTION).replace(TEST_NAME)
@@ -1307,22 +1307,22 @@ private void executeUnassignRoles123ToJack(String TEST_NAME, boolean immediate,
AssignmentType del2 = toDelete(a2, byId);
AssignmentType del3 = toDelete(a3, byId);
@SuppressWarnings("unchecked")
- ObjectDelta deleteRole1Delta = has1and2 ? (ObjectDelta) DeltaBuilder
+ ObjectDelta deleteRole1Delta = has1and2 ? DeltaBuilder
.deltaFor(UserType.class, prismContext)
.item(UserType.F_ASSIGNMENT).delete(del1)
.asObjectDelta(userJackOid) : null;
@SuppressWarnings("unchecked")
- ObjectDelta deleteRole2Delta = has1and2 ? (ObjectDelta) DeltaBuilder
+ ObjectDelta deleteRole2Delta = has1and2 ? DeltaBuilder
.deltaFor(UserType.class, prismContext)
.item(UserType.F_ASSIGNMENT).delete(del2)
.asObjectDelta(userJackOid) : null;
@SuppressWarnings("unchecked")
- ObjectDelta deleteRole3Delta = (ObjectDelta) DeltaBuilder
+ ObjectDelta deleteRole3Delta = DeltaBuilder
.deltaFor(UserType.class, prismContext)
.item(UserType.F_ASSIGNMENT).delete(del3)
.asObjectDelta(userJackOid);
@SuppressWarnings("unchecked")
- ObjectDelta changeDescriptionDelta = (ObjectDelta) DeltaBuilder
+ ObjectDelta changeDescriptionDelta = DeltaBuilder
.deltaFor(UserType.class, prismContext)
.item(UserType.F_DESCRIPTION).replace(TEST_NAME)
.asObjectDelta(userJackOid);
diff --git a/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/policy/assignments/plain/TestAssignmentApprovalPlainExplicit.java b/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/policy/assignments/plain/TestAssignmentApprovalPlainExplicit.java
index 2538494e6e5..682a6847afd 100644
--- a/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/policy/assignments/plain/TestAssignmentApprovalPlainExplicit.java
+++ b/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/policy/assignments/plain/TestAssignmentApprovalPlainExplicit.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2017 Evolveum
+ * Copyright (c) 2010-2018 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -59,7 +59,7 @@ protected String getRoleName(int number) {
@Override
protected void importLead10(Task task, OperationResult result) throws Exception {
super.importLead10(task, result);
- executeChangesAssertSuccess((ObjectDelta) DeltaBuilder.deltaFor(RoleType.class, prismContext)
+ executeChangesAssertSuccess(DeltaBuilder.deltaFor(RoleType.class, prismContext)
.item(RoleType.F_APPROVER_REF)
.add(prv(userLead10Oid))
.asObjectDelta(getRoleOid(10)), null, task, result);
diff --git a/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/policy/lifecycle/AbstractTestLifecycle.java b/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/policy/lifecycle/AbstractTestLifecycle.java
index 8fd1c7c2f10..aea7b322898 100644
--- a/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/policy/lifecycle/AbstractTestLifecycle.java
+++ b/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/policy/lifecycle/AbstractTestLifecycle.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2017 Evolveum
+ * Copyright (c) 2010-2018 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -103,7 +103,7 @@ public void test010CreateRolePirate() throws Exception {
PrismReferenceValue pirateOwner = new PrismReferenceValue(rolePirateOid, RoleType.COMPLEX_TYPE);
pirateOwner.setRelation(SchemaConstants.ORG_OWNER);
- executeChanges((ObjectDelta) DeltaBuilder.deltaFor(UserType.class, prismContext)
+ executeChanges(DeltaBuilder.deltaFor(UserType.class, prismContext)
.item(UserType.F_ASSIGNMENT).add(ObjectTypeUtil.createAssignmentTo(pirateOwner, prismContext))
.asObjectDelta(userPirateOwnerOid),
null, task, result);
@@ -128,7 +128,7 @@ public void test100ModifyRolePirateDescription() throws Exception {
TestUtil.displayTestTitle(this, TEST_NAME);
login(userAdministrator);
- ObjectDelta descriptionDelta = (ObjectDelta) DeltaBuilder.deltaFor(RoleType.class, prismContext)
+ ObjectDelta descriptionDelta = DeltaBuilder.deltaFor(RoleType.class, prismContext)
.item(RoleType.F_DESCRIPTION).replace("Bloody pirate")
.asObjectDelta(rolePirateOid);
ObjectDelta delta0 = ObjectDelta.createModifyDelta(rolePirateOid, Collections.emptyList(), RoleType.class, prismContext);
diff --git a/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/policy/object/TestObjectConstraints.java b/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/policy/object/TestObjectConstraints.java
index 8ca75daa07f..306c5ac0186 100644
--- a/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/policy/object/TestObjectConstraints.java
+++ b/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/policy/object/TestObjectConstraints.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2017 Evolveum
+ * Copyright (c) 2010-2018 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -177,7 +177,7 @@ protected Boolean decideOnApproval(String executionId, org.activiti.engine.task.
roleEmployeeOid = searchObjectByName(RoleType.class, "employee").getOid();
PrismReferenceValue employeeOwner = new PrismReferenceValue(roleEmployeeOid, RoleType.COMPLEX_TYPE).relation(SchemaConstants.ORG_OWNER);
- executeChanges((ObjectDelta) DeltaBuilder.deltaFor(UserType.class, prismContext)
+ executeChanges(DeltaBuilder.deltaFor(UserType.class, prismContext)
.item(UserType.F_ASSIGNMENT).add(ObjectTypeUtil.createAssignmentTo(employeeOwner, prismContext))
.asObjectDelta(userEmployeeOwnerOid),
null, task, result);
@@ -195,7 +195,7 @@ public void test020ActivateIncompleteRole() throws Exception {
OperationResult result = task.getResult();
@SuppressWarnings({"unchecked", "raw"})
- ObjectDelta activateRoleDelta = (ObjectDelta) DeltaBuilder.deltaFor(RoleType.class, prismContext)
+ ObjectDelta activateRoleDelta = DeltaBuilder.deltaFor(RoleType.class, prismContext)
.item(RoleType.F_LIFECYCLE_STATE).replace(SchemaConstants.LIFECYCLE_ACTIVE)
.asObjectDelta(roleEmployeeOid);
@@ -230,7 +230,7 @@ public void test030ActivateIncompleteRoleAgain() throws Exception {
OperationResult result = task.getResult();
@SuppressWarnings({"unchecked", "raw"})
- ObjectDelta activateRoleDelta = (ObjectDelta) DeltaBuilder.deltaFor(RoleType.class, prismContext)
+ ObjectDelta activateRoleDelta = DeltaBuilder.deltaFor(RoleType.class, prismContext)
.item(RoleType.F_LIFECYCLE_STATE).replace(SchemaConstants.LIFECYCLE_ACTIVE)
.item(RoleType.F_DESCRIPTION).replace("hi")
.asObjectDelta(roleEmployeeOid);
@@ -278,7 +278,7 @@ public void test045ActivateCompleteRole() throws Exception {
OperationResult result = task.getResult();
@SuppressWarnings({"unchecked", "raw"})
- ObjectDelta activateRoleDelta = (ObjectDelta) DeltaBuilder.deltaFor(RoleType.class, prismContext)
+ ObjectDelta activateRoleDelta = DeltaBuilder.deltaFor(RoleType.class, prismContext)
.item(RoleType.F_LIFECYCLE_STATE).replace(SchemaConstants.LIFECYCLE_ACTIVE)
.item(RoleType.F_DESCRIPTION).replace("hi")
.asObjectDelta(roleEmployeeOid);
diff --git a/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/policy/other/TestMiscellaneous.java b/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/policy/other/TestMiscellaneous.java
index eb154717ec3..8aeb0ca66d0 100644
--- a/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/policy/other/TestMiscellaneous.java
+++ b/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/policy/other/TestMiscellaneous.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2017 Evolveum
+ * Copyright (c) 2010-2018 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -315,7 +315,7 @@ public void test250SkippingApprovals() throws Exception {
// WHEN
@SuppressWarnings({"raw", "unchecked"})
ObjectDelta extends ObjectType> delta =
- (ObjectDelta extends ObjectType>) DeltaBuilder.deltaFor(UserType.class, prismContext)
+ DeltaBuilder.deltaFor(UserType.class, prismContext)
.item(UserType.F_ASSIGNMENT)
.add(ObjectTypeUtil.createAssignmentTo(roleRole1aOid, ObjectTypes.ROLE, prismContext))
.asObjectDelta(userJackOid);
diff --git a/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/policy/sod/AbstractTestSoD.java b/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/policy/sod/AbstractTestSoD.java
index d1bcb70b502..cd36bf8641d 100644
--- a/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/policy/sod/AbstractTestSoD.java
+++ b/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/policy/sod/AbstractTestSoD.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2017 Evolveum
+ * Copyright (c) 2010-2018 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -119,12 +119,12 @@ public void test020AssignRolePirate() throws Exception {
String originalDescription = jack.asObjectable().getDescription();
@SuppressWarnings("unchecked")
- ObjectDelta addPirateDelta = (ObjectDelta) DeltaBuilder
+ ObjectDelta addPirateDelta = DeltaBuilder
.deltaFor(UserType.class, prismContext)
.item(UserType.F_ASSIGNMENT).add(createAssignmentTo(rolePirateOid, ObjectTypes.ROLE, prismContext))
.asObjectDelta(userJackOid);
@SuppressWarnings("unchecked")
- ObjectDelta changeDescriptionDelta = (ObjectDelta) DeltaBuilder
+ ObjectDelta changeDescriptionDelta = DeltaBuilder
.deltaFor(UserType.class, prismContext)
.item(UserType.F_DESCRIPTION).replace("Pirate Judge")
.asObjectDelta(userJackOid);
@@ -240,7 +240,7 @@ public void test030AssignRoleRespectable() throws Exception {
// WHEN+THEN
PrismObject jack = getUser(userJackOid);
@SuppressWarnings("unchecked")
- ObjectDelta addRespectableDelta = (ObjectDelta) DeltaBuilder
+ ObjectDelta addRespectableDelta = DeltaBuilder
.deltaFor(UserType.class, prismContext)
.item(UserType.F_ASSIGNMENT).add(createAssignmentTo(roleRespectableOid, ObjectTypes.ROLE, prismContext))
.asObjectDelta(userJackOid);
diff --git a/provisioning/provisioning-api/src/main/java/com/evolveum/midpoint/provisioning/api/ProvisioningOperationOptions.java b/provisioning/provisioning-api/src/main/java/com/evolveum/midpoint/provisioning/api/ProvisioningOperationOptions.java
index 48da97ad134..ee9f54eecd0 100644
--- a/provisioning/provisioning-api/src/main/java/com/evolveum/midpoint/provisioning/api/ProvisioningOperationOptions.java
+++ b/provisioning/provisioning-api/src/main/java/com/evolveum/midpoint/provisioning/api/ProvisioningOperationOptions.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2017 Evolveum
+ * Copyright (c) 2010-2018 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -37,6 +37,24 @@ public class ProvisioningOperationOptions implements Serializable {
private Boolean overwrite;
+ /**
+ * Run the operations on resource using the specified identity.
+ * The value is a OID of an account shadow.
+ *
+ * This option should be considered a suggestion, not a command.
+ * Therefore if the connector can run operation as specified user
+ * the it should run it. But if it is not capable to run such
+ * operation as specified user but it can run it as administrator
+ * then it should run the operation as administrator.
+ * That case may happen e.g. if account cleartext password is not
+ * known at that time.
+ *
+ * Note: maybe later we need some kind of flag that makes this
+ * option "critical", i.e. that an error is thrown if the
+ * operation cannot be executed as specified identity.
+ */
+ private String runAsAccountOid;
+
public Boolean getCompletePostponed() {
return completePostponed;
}
@@ -182,6 +200,20 @@ public static ProvisioningOperationOptions createRaw() {
opts.setRaw(true);
return opts;
}
+
+ public String getRunAsAccountOid() {
+ return runAsAccountOid;
+ }
+
+ public void setRunAsAccountOid(String runAsAccountOid) {
+ this.runAsAccountOid = runAsAccountOid;
+ }
+
+ public static ProvisioningOperationOptions createRunAsAccountOid(String runAsAccountOid) {
+ ProvisioningOperationOptions opts = new ProvisioningOperationOptions();
+ opts.setRunAsAccountOid(runAsAccountOid);
+ return opts;
+ }
@Override
public String toString() {
@@ -192,6 +224,9 @@ public String toString() {
appendFlag(sb, "postpone", postpone);
appendFlag(sb, "doNotDiscovery", doNotDiscovery);
appendFlag(sb, "overwrite", overwrite);
+ if (runAsAccountOid != null) {
+ sb.append("runAsAccountOid=").append(runAsAccountOid).append(",");
+ }
if (sb.charAt(sb.length() - 1) == ',') {
sb.deleteCharAt(sb.length() - 1);
}
diff --git a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ProvisioningContext.java b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ProvisioningContext.java
index e5506c70308..9993432a2d5 100644
--- a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ProvisioningContext.java
+++ b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ProvisioningContext.java
@@ -24,6 +24,7 @@
import com.evolveum.midpoint.schema.SelectorOptions;
import com.evolveum.midpoint.schema.processor.ObjectClassComplexTypeDefinition;
import com.evolveum.midpoint.schema.result.OperationResult;
+import com.evolveum.midpoint.schema.util.ResourceTypeUtil;
import com.evolveum.midpoint.task.api.StateReporter;
import com.evolveum.midpoint.util.exception.*;
import com.evolveum.midpoint.util.logging.Trace;
@@ -313,7 +314,11 @@ private ConnectorInstance getConnectorInstance(Class<
throw e;
}
}
-
+
+ public T getResourceEffectiveCapability(Class capabilityClass) throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException, ExpressionEvaluationException {
+ return ResourceTypeUtil.getEffectiveCapability(getResource(), capabilityClass);
+ }
+
public CapabilitiesType getConnectorCapabilities(Class operationCapabilityClass) {
return resourceManager.getConnectorCapabilities(resource.asPrismObject(), operationCapabilityClass);
}
diff --git a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ResourceObjectConverter.java b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ResourceObjectConverter.java
index 5d6957fc1a8..059b30baa3d 100644
--- a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ResourceObjectConverter.java
+++ b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/impl/ResourceObjectConverter.java
@@ -31,6 +31,7 @@
import com.evolveum.midpoint.prism.util.JavaTypeConverter;
import com.evolveum.midpoint.prism.util.PrismUtil;
import com.evolveum.midpoint.provisioning.api.GenericConnectorException;
+import com.evolveum.midpoint.provisioning.api.ProvisioningOperationOptions;
import com.evolveum.midpoint.provisioning.ucf.api.*;
import com.evolveum.midpoint.provisioning.util.ProvisioningUtil;
import com.evolveum.midpoint.repo.cache.RepositoryCache;
@@ -234,9 +235,10 @@ private boolean hasAllIdentifiers(Collection extends ResourceAttribute>> att
public AsynchronousOperationReturnValue> addResourceObject(ProvisioningContext ctx,
- PrismObject shadow, OperationProvisioningScriptsType scripts, boolean skipExplicitUniquenessCheck, OperationResult parentResult)
- throws ObjectNotFoundException, SchemaException, CommunicationException,
- ObjectAlreadyExistsException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException {
+ PrismObject shadow, OperationProvisioningScriptsType scripts, ConnectorOperationOptions connOptions,
+ boolean skipExplicitUniquenessCheck, OperationResult parentResult)
+ throws ObjectNotFoundException, SchemaException, CommunicationException,
+ ObjectAlreadyExistsException, ConfigurationException, SecurityViolationException, ExpressionEvaluationException {
OperationResult result = parentResult.createSubresult(OPERATION_ADD_RESOURCE_OBJECT);
@@ -308,7 +310,7 @@ public AsynchronousOperationReturnValue> addResourceObje
}
// Execute entitlement modification on other objects (if needed)
- executeEntitlementChangesAdd(ctx, shadowClone, scripts, result);
+ executeEntitlementChangesAdd(ctx, shadowClone, scripts, connOptions, result);
LOGGER.trace("Added resource object {}", shadow);
@@ -375,7 +377,7 @@ private void checkForAddConflicts(ProvisioningContext ctx, PrismObject shadow,
- OperationProvisioningScriptsType scripts, OperationResult parentResult)
+ OperationProvisioningScriptsType scripts, ConnectorOperationOptions connOptions, OperationResult parentResult)
throws ObjectNotFoundException, SchemaException, CommunicationException, ConfigurationException,
SecurityViolationException, ExpressionEvaluationException {
@@ -404,7 +406,7 @@ public AsynchronousOperationResult deleteResourceObject(ProvisioningContext ctx,
}
// Execute entitlement modification on other objects (if needed)
- executeEntitlementChangesDelete(ctx, shadow, scripts, result);
+ executeEntitlementChangesDelete(ctx, shadow, scripts, connOptions, result);
Collection additionalOperations = new ArrayList<>();
addExecuteScriptOperation(additionalOperations, ProvisioningOperationTypeType.DELETE, scripts, ctx.getResource(),
@@ -483,6 +485,7 @@ public AsynchronousOperationReturnValue repoShadow,
OperationProvisioningScriptsType scripts,
+ ConnectorOperationOptions connOptions,
Collection extends ItemDelta> itemDeltas,
XMLGregorianCalendar now,
OperationResult parentResult)
@@ -608,7 +611,7 @@ public AsynchronousOperationReturnValue> convertToPropertyDelta(
@SuppressWarnings("rawtypes")
private AsynchronousOperationReturnValue> executeModify(ProvisioningContext ctx,
PrismObject currentShadow, Collection extends ResourceAttribute>> identifiers,
- Collection operations, OperationResult parentResult)
+ Collection operations, ConnectorOperationOptions connOptions, OperationResult parentResult)
throws ObjectNotFoundException, CommunicationException, SchemaException, SecurityViolationException, ConfigurationException, ObjectAlreadyExistsException, ExpressionEvaluationException {
Collection sideEffectChanges = new HashSet<>();
@@ -816,7 +819,8 @@ private AsynchronousOperationReturnValue sideEffects = connectorAsyncOpRet.getReturnValue();
if (sideEffects != null) {
sideEffectChanges.addAll(sideEffects);
@@ -1100,21 +1104,22 @@ private boolean isIdentifierDelta(ProvisioningContext ctx, PropertyDelta
ctx.getObjectClassDefinition().isSecondaryIdentifier(propertyDelta.getElementName());
}
- private PrismObject executeEntitlementChangesAdd(ProvisioningContext ctx, PrismObject shadow, OperationProvisioningScriptsType scripts,
+ private PrismObject executeEntitlementChangesAdd(ProvisioningContext ctx, PrismObject shadow,
+ OperationProvisioningScriptsType scripts, ConnectorOperationOptions connOptions,
OperationResult parentResult) throws SchemaException, ObjectNotFoundException, CommunicationException, SecurityViolationException, ConfigurationException, ObjectAlreadyExistsException, ExpressionEvaluationException {
Map roMap = new HashMap<>();
shadow = entitlementConverter.collectEntitlementsAsObjectOperationInShadowAdd(ctx, roMap, shadow, parentResult);
- executeEntitlements(ctx, roMap, parentResult);
+ executeEntitlements(ctx, roMap, connOptions, parentResult);
return shadow;
}
private PrismObject executeEntitlementChangesModify(ProvisioningContext ctx, PrismObject subjectShadowBefore,
PrismObject subjectShadowAfter,
- OperationProvisioningScriptsType scripts, Collection extends ItemDelta> subjectDeltas, OperationResult parentResult) throws SchemaException, ObjectNotFoundException, CommunicationException, SecurityViolationException, ConfigurationException, ObjectAlreadyExistsException, ExpressionEvaluationException {
+ OperationProvisioningScriptsType scripts, ConnectorOperationOptions connOptions, Collection extends ItemDelta> subjectDeltas, OperationResult parentResult) throws SchemaException, ObjectNotFoundException, CommunicationException, SecurityViolationException, ConfigurationException, ObjectAlreadyExistsException, ExpressionEvaluationException {
Map roMap = new HashMap<>();
@@ -1177,13 +1182,13 @@ private PrismObject