From 60328c40b2b99c6cf41ab6ce90145fae941d07bd Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Tue, 24 Mar 2020 19:35:35 +0100 Subject: [PATCH] Fix serialization of raw deltas (MID-6086) 1. CryptoUtil methods no longer fail on tunneled SchemaExceptions from the depths of prism-impl. 2. parseRealValue now correctly parses ObjectReferenceType objects (no longed using BeanUnmarshaller for their parsing) 3. Prism visitor now visits also objects embedded in reference values. 4. JaxbVisitor in RawType visits the value after being parsed. Fix #2 resolves MID-6086. Fixes #3 and #4 are necessary to correctly encrypt passwords in ShadowType objects embedded in linkRef references. --- .../midpoint/common/crypto/CryptoUtil.java | 54 ++++++------ .../midpoint/common/TestCryptoUtil.java | 85 ++++++++++++++++++- .../resources/crypto/task-add-account.xml | 53 ++++++++++++ .../prism/xml/ns/_public/types_3/RawType.java | 21 +++-- .../prism/impl/PrismReferenceValueImpl.java | 9 ++ .../impl/marshaller/BeanUnmarshaller.java | 4 +- .../impl/marshaller/PrismParserImpl.java | 6 +- .../prism/impl/xnode/MapXNodeImpl.java | 11 +-- .../midpoint/prism/PrismInternalTestUtil.java | 6 +- .../midpoint/prism/TestPrismParsing.java | 10 ++- .../common/json/user-jack-adhoc.json | 10 ++- .../common/json/user-jack-object.json | 10 ++- .../common/yaml/user-jack-adhoc.yaml | 6 +- .../common/yaml/user-jack-object.yaml | 6 +- 14 files changed, 233 insertions(+), 58 deletions(-) create mode 100644 infra/common/src/test/resources/crypto/task-add-account.xml diff --git a/infra/common/src/main/java/com/evolveum/midpoint/common/crypto/CryptoUtil.java b/infra/common/src/main/java/com/evolveum/midpoint/common/crypto/CryptoUtil.java index be4124b049e..7e82a460b6c 100644 --- a/infra/common/src/main/java/com/evolveum/midpoint/common/crypto/CryptoUtil.java +++ b/infra/common/src/main/java/com/evolveum/midpoint/common/crypto/CryptoUtil.java @@ -15,12 +15,11 @@ import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.schema.result.OperationResultStatus; import com.evolveum.midpoint.util.Holder; -import com.evolveum.midpoint.util.exception.TunnelException; +import com.evolveum.midpoint.util.MiscUtil; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; import com.evolveum.prism.xml.ns._public.types_3.ProtectedStringType; -import com.evolveum.prism.xml.ns._public.types_3.RawType; import org.jetbrains.annotations.NotNull; import javax.crypto.Cipher; @@ -45,24 +44,24 @@ public class CryptoUtil { /** * Encrypts all encryptable values in the object. + * + * Note: We could use TunnelException here (it would be cleaner) but the tunneled exception could be + * other than EncryptionException! For example, it could come from RawType, carrying a SchemaException. + * See MID-6086. So we use throwExceptionAsUnchecked hack instead. */ + @SuppressWarnings("RedundantThrows") public static void encryptValues(Protector protector, PrismObject object) throws EncryptionException { - try { - object.accept(createEncryptingVisitor(protector)); - } catch (TunnelException e) { - throw (EncryptionException) e.getCause(); - } + //noinspection unchecked + object.accept(createEncryptingVisitor(protector)); } /** * Encrypts all encryptable values in delta. */ + @SuppressWarnings("RedundantThrows") public static void encryptValues(Protector protector, ObjectDelta delta) throws EncryptionException { - try { - delta.accept(createEncryptingVisitor(protector)); - } catch (TunnelException e) { - throw (EncryptionException) e.getCause(); - } + //noinspection unchecked + delta.accept(createEncryptingVisitor(protector)); } @NotNull @@ -76,7 +75,8 @@ private static ProtectedStringProcessor createEncryptingProcessor(Protector prot try { protector.encrypt(protectedString); } catch (EncryptionException e) { - throw new EncryptionException("Failed to encrypt value for field " + propertyName + ": " + e.getMessage(), e); + MiscUtil.throwExceptionAsUnchecked( + new EncryptionException("Failed to encrypt value for field " + propertyName + ": " + e.getMessage(), e)); } } }); @@ -85,6 +85,7 @@ private static ProtectedStringProcessor createEncryptingProcessor(Protector prot // Checks that everything is encrypted public static void checkEncrypted(final PrismObject object) { try { + //noinspection unchecked object.accept(createCheckingVisitor()); } catch (IllegalStateException e) { throw new IllegalStateException(e.getMessage() + " in " + object, e); @@ -95,6 +96,7 @@ public static void checkEncrypted(final PrismObject ob // Checks that everything is encrypted public static void checkEncrypted(final ObjectDelta delta) { try { + //noinspection unchecked delta.accept(createCheckingVisitor()); } catch (IllegalStateException e) { throw new IllegalStateException(e.getMessage() + " in delta " + delta, e); @@ -184,19 +186,18 @@ public static void securitySelfTest(OperationResult parentTestResult) { /** * Re-encrypts all encryptable values in the object. */ + @SuppressWarnings("RedundantThrows") public static int reencryptValues(Protector protector, PrismObject object) throws EncryptionException { - try { - Holder modCountHolder = new Holder<>(0); - object.accept(createVisitor((ps, propName) -> reencryptProtectedStringType(ps, propName, modCountHolder, protector))); - return modCountHolder.getValue(); - } catch (TunnelException e) { - throw (EncryptionException) e.getCause(); - } + Holder modCountHolder = new Holder<>(0); + //noinspection unchecked + object.accept(createVisitor((ps, propName) -> reencryptProtectedStringType(ps, propName, modCountHolder, protector))); + return modCountHolder.getValue(); } @NotNull public static Collection getEncryptionKeyNames(PrismObject object) { Set keys = new HashSet<>(); + //noinspection unchecked object.accept(createVisitor((ps, propName) -> { if (ps.getEncryptedDataType() != null && ps.getEncryptedDataType().getKeyInfo() != null) { keys.add(ps.getEncryptedDataType().getKeyInfo().getKeyName()); @@ -208,6 +209,7 @@ public static Collection getEncryptionKeyNames(Pr @SuppressWarnings("unused") // used externally public static boolean containsCleartext(PrismObject object) { Holder result = new Holder<>(false); + //noinspection unchecked object.accept(createVisitor((ps, propName) -> { if (ps.getClearValue() != null) { result.setValue(true); @@ -219,6 +221,7 @@ public static boolean containsCleartext(PrismObject ob @SuppressWarnings("unused") // used externally public static boolean containsHashedData(PrismObject object) { Holder result = new Holder<>(false); + //noinspection unchecked object.accept(createVisitor((ps, propName) -> { if (ps.getHashedDataType() != null) { result.setValue(true); @@ -237,7 +240,7 @@ private static class CombinedVisitor implements Visitor, JaxbVisitor { private ProtectedStringProcessor processor; private String lastPropName = "?"; - CombinedVisitor(ProtectedStringProcessor processor) { + private CombinedVisitor(ProtectedStringProcessor processor) { this.processor = processor; } @@ -247,7 +250,7 @@ public void visit(JaxbVisitable visitable) { try { processor.apply(((ProtectedStringType) visitable), lastPropName); } catch (EncryptionException e) { - throw new TunnelException(e); + MiscUtil.throwExceptionAsUnchecked(e); } } else { JaxbVisitable.visitPrismStructure(visitable, this); @@ -257,7 +260,7 @@ public void visit(JaxbVisitable visitable) { @Override public void visit(Visitable visitable) { if (visitable instanceof PrismPropertyValue) { - PrismPropertyValue pval = ((PrismPropertyValue) visitable); + PrismPropertyValue pval = (PrismPropertyValue) visitable; Object realValue = pval.getRealValue(); if (realValue instanceof JaxbVisitable) { String oldLastPropName = lastPropName; @@ -290,7 +293,7 @@ private static void reencryptProtectedStringType(ProtectedStringType ps, String protector.encrypt(ps); increment(modCountHolder); } catch (EncryptionException e) { - throw new TunnelException(new EncryptionException("Failed to encrypt value for field " + propName + ": " + e.getMessage(), e)); + MiscUtil.throwExceptionAsUnchecked(new EncryptionException("Failed to encrypt value for field " + propName + ": " + e.getMessage(), e)); } } else if (ps.getEncryptedDataType() != null) { try { @@ -300,7 +303,7 @@ private static void reencryptProtectedStringType(ProtectedStringType ps, String increment(modCountHolder); } } catch (EncryptionException e) { - throw new TunnelException(new EncryptionException("Failed to check/reencrypt value for field " + propName + ": " + e.getMessage(), e)); + MiscUtil.throwExceptionAsUnchecked(new EncryptionException("Failed to check/reencrypt value for field " + propName + ": " + e.getMessage(), e)); } } else { // no clear nor encrypted value @@ -311,6 +314,7 @@ private static void increment(Holder countHolder) { countHolder.setValue(countHolder.getValue() + 1); } + @SuppressWarnings("SameParameterValue") private static void securitySelfTestAlgorithm(String algorithmName, String transformationName, Integer keySize, boolean critical, OperationResult parentResult) { OperationResult subresult = parentResult.createSubresult(CryptoUtil.class.getName()+".securitySelfTest.algorithm."+algorithmName); diff --git a/infra/common/src/test/java/com/evolveum/midpoint/common/TestCryptoUtil.java b/infra/common/src/test/java/com/evolveum/midpoint/common/TestCryptoUtil.java index 50facf859c0..d033ee17663 100644 --- a/infra/common/src/test/java/com/evolveum/midpoint/common/TestCryptoUtil.java +++ b/infra/common/src/test/java/com/evolveum/midpoint/common/TestCryptoUtil.java @@ -20,14 +20,22 @@ import java.util.HashSet; import java.util.Set; +import com.evolveum.midpoint.prism.*; +import com.evolveum.midpoint.prism.delta.ObjectDelta; +import com.evolveum.midpoint.prism.path.ItemPath; + +import com.evolveum.midpoint.schema.DeltaConvertor; +import com.evolveum.midpoint.schema.constants.SchemaConstants; + +import com.evolveum.midpoint.schema.util.ObjectTypeUtil; +import com.evolveum.prism.xml.ns._public.types_3.ObjectDeltaType; + import org.testng.annotations.BeforeSuite; import org.testng.annotations.Listeners; import org.testng.annotations.Test; import org.xml.sax.SAXException; import com.evolveum.midpoint.common.crypto.CryptoUtil; -import com.evolveum.midpoint.prism.PrismContext; -import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.crypto.EncryptionException; import com.evolveum.midpoint.prism.crypto.KeyStoreBasedProtectorBuilder; import com.evolveum.midpoint.prism.crypto.Protector; @@ -43,6 +51,8 @@ import com.evolveum.midpoint.xml.ns._public.common.common_3.*; import com.evolveum.prism.xml.ns._public.types_3.ProtectedStringType; +import javax.xml.namespace.QName; + @Listeners({ com.evolveum.midpoint.tools.testng.AlphabeticalMethodInterceptor.class }) public class TestCryptoUtil extends AbstractUnitTest { @@ -50,6 +60,7 @@ public class TestCryptoUtil extends AbstractUnitTest { private static final File FILE_USER_JACK = new File(TEST_DIR, "user-jack.xml"); private static final File FILE_TASK_MODIFY_JACK_PASSWORD = new File(TEST_DIR, "task-modify-jack-password.xml"); private static final File FILE_TASK_ADD_JACK = new File(TEST_DIR, "task-add-jack.xml"); + private static final File FILE_TASK_ADD_ACCOUNT = new File(TEST_DIR, "task-add-account.xml"); private static final File FILE_SYSTEM_CONFIGURATION = new File(TEST_DIR, "system-configuration.xml"); private static final String KEYSTORE_PATH = TEST_RESOURCES_PATH + "/keystore.jceks"; @@ -107,6 +118,76 @@ public void test120EncryptBulkActionTask() throws Exception { CryptoUtil.checkEncrypted(task); } + /** + * MID-6086 + */ + @Test + public void test125EncryptAddAccountTask() throws Exception { + given(); + PrismContext prismContext = getPrismContext(); + PrismObject task = prismContext.parserFor(FILE_TASK_ADD_ACCOUNT).xml().parse(); + + when(); + CryptoUtil.encryptValues(protector, task); + + then(); + String serialized = prismContext.xmlSerializer().serialize(task); + System.out.println("After encryption:\n" + serialized); + assertFalse("Serialized object contains the password!", serialized.contains(PASSWORD_PLAINTEXT)); + + CryptoUtil.checkEncrypted(task); + } + + /** + * MID-6086 + */ + @Test + public void test127EncryptAddAccountTaskManuallyConstructed() throws Exception { + given(); + PrismContext prismContext = getPrismContext(); + PrismObject task = new TaskType(prismContext) + .name("test127") + .asPrismObject(); + PrismPropertyDefinition deltasDefinition = task.getDefinition() + .findPropertyDefinition(ItemPath.create(TaskType.F_EXTENSION, SchemaConstants.MODEL_EXTENSION_OBJECT_DELTAS)); + PrismProperty deltas = deltasDefinition.instantiate(); + + ShadowType shadow = new ShadowType(prismContext) + .name("some-shadow"); + PrismContainerDefinition attributesDef = shadow.asPrismObject().getDefinition() + .findContainerDefinition(ShadowType.F_ATTRIBUTES); + PrismContainer attributes = attributesDef.instantiate(); + shadow.asPrismObject().add(attributes); + + MutablePrismPropertyDefinition passwordDef = prismContext.definitionFactory() + .createPropertyDefinition( + new QName(SchemaConstants.NS_ICF_SCHEMA, "password"), ProtectedStringType.COMPLEX_TYPE); + PrismProperty password = passwordDef.instantiate(); + ProtectedStringType passwordRealValue = new ProtectedStringType(); + passwordRealValue.setClearValue(PASSWORD_PLAINTEXT); + password.setRealValue(passwordRealValue); + attributes.add(password); + + PrismReferenceValue linkToAdd = ObjectTypeUtil.createObjectRefWithFullObject(shadow, prismContext).asReferenceValue(); + ObjectDelta userDelta = prismContext.deltaFor(UserType.class) + .item(UserType.F_LINK_REF) + .add(linkToAdd) + .asObjectDelta("some-oid"); + + deltas.addRealValue(DeltaConvertor.toObjectDeltaType(userDelta, null)); + task.addExtensionItem(deltas); + + when(); + CryptoUtil.encryptValues(protector, task); + + then(); + String serialized = prismContext.xmlSerializer().serialize(task); + System.out.println("After encryption:\n" + serialized); + assertFalse("Serialized object contains the password!", serialized.contains(PASSWORD_PLAINTEXT)); + + CryptoUtil.checkEncrypted(task); + } + @Test public void test130EncryptUserInDelta() throws Exception { // GIVEN diff --git a/infra/common/src/test/resources/crypto/task-add-account.xml b/infra/common/src/test/resources/crypto/task-add-account.xml new file mode 100644 index 00000000000..5c2133c1bb0 --- /dev/null +++ b/infra/common/src/test/resources/crypto/task-add-account.xml @@ -0,0 +1,53 @@ + + + + + Execute changes + + + modify + c:UserType + 07cc8c14-f94a-4da9-86ab-0246fc63bb6b + + add + c:linkRef + + + + ri:AccountObjectClass + account + default + + pass1234word + + + + + + + false + false + false + + + 1585065525794-0-1 + + + + http://midpoint.evolveum.com/xml/ns/public/gui/channels-3#user + closed + Utility + http://midpoint.evolveum.com/xml/ns/public/model/execute-deltas/handler-3 + single + tight + diff --git a/infra/prism-api/src/main/java/com/evolveum/prism/xml/ns/_public/types_3/RawType.java b/infra/prism-api/src/main/java/com/evolveum/prism/xml/ns/_public/types_3/RawType.java index ed6196f7989..44ab534ed38 100644 --- a/infra/prism-api/src/main/java/com/evolveum/prism/xml/ns/_public/types_3/RawType.java +++ b/infra/prism-api/src/main/java/com/evolveum/prism/xml/ns/_public/types_3/RawType.java @@ -469,21 +469,20 @@ public String guessFormattedValue() throws SchemaException { @Override public void accept(JaxbVisitor visitor) { - visitor.visit(this); - if (isParsed()) { - Object realValue = parsed.getRealValue(); - if (realValue instanceof JaxbVisitable) { - ((JaxbVisitable) realValue).accept(visitor); - } - } else if (explicitTypeName != null) { + Object value; + if (isParsed() || explicitTypeName != null) { + // (Potentially) parsing the value before visiting it. try { - Object value = getValue(true); - if (value instanceof JaxbVisitable) { - ((JaxbVisitable) value).accept(visitor); - } + value = getValue(true); } catch (SchemaException e) { throw new TunnelException(e); } + } else { + value = null; + } + visitor.visit(this); + if (value instanceof JaxbVisitable) { + ((JaxbVisitable) value).accept(visitor); } } } diff --git a/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/PrismReferenceValueImpl.java b/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/PrismReferenceValueImpl.java index cc7aea49c92..d1646392eff 100644 --- a/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/PrismReferenceValueImpl.java +++ b/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/PrismReferenceValueImpl.java @@ -710,4 +710,13 @@ public void shortDump(StringBuilder sb) { } } } + + @Override + public void accept(Visitor visitor) { + super.accept(visitor); + if (object != null) { + //noinspection unchecked + object.accept(visitor); + } + } } diff --git a/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/marshaller/BeanUnmarshaller.java b/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/marshaller/BeanUnmarshaller.java index 90a452cbc8f..f92e5ac09c3 100644 --- a/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/marshaller/BeanUnmarshaller.java +++ b/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/marshaller/BeanUnmarshaller.java @@ -801,8 +801,8 @@ private void computeParamTypeFromSetter(String propName, Class setterParamTyp private void computeParamTypeFromGetter(String propName, Class getterReturnType) throws SchemaException { if (!Collection.class.isAssignableFrom(getterReturnType)) { - throw new SchemaException("Cannot find getter for field " + actualPropertyName + " in " + beanClass - + " does not return collection, cannot use it to set value"); + throw new SchemaException("Cannot find setter for field " + actualPropertyName + " in " + beanClass + + ". The getter was found, but it does not return collection - so it cannot be used to set the value."); } // getter.genericReturnType = Collection<...> Type typeArgument = inspector.getTypeArgument(getter.getGenericReturnType(), diff --git a/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/marshaller/PrismParserImpl.java b/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/marshaller/PrismParserImpl.java index 708c49e3728..ea213d9ada3 100644 --- a/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/marshaller/PrismParserImpl.java +++ b/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/marshaller/PrismParserImpl.java @@ -245,7 +245,11 @@ private T doParseRealValue(Class clazz, RootXNodeImpl root) throws IOExce } // although bean unmarshaller can process containerables as well, prism unmarshaller is better at it - if (clazz != null && !Containerable.class.isAssignableFrom(clazz) && getBeanUnmarshaller().canProcess(clazz)) { + // for referencables, bean unmarshaller cannot parse embedded objects - so we use doParseItemValue instead as well + if (clazz != null + && !Referencable.class.isAssignableFrom(clazz) + && !Containerable.class.isAssignableFrom(clazz) + && getBeanUnmarshaller().canProcess(clazz)) { return getBeanUnmarshaller().unmarshal(root, clazz, context); } else if (clazz != null && Objectable.class.isAssignableFrom(clazz)) { // we need to NOT strip off OID diff --git a/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/xnode/MapXNodeImpl.java b/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/xnode/MapXNodeImpl.java index 0490127c398..2707d9aaad6 100644 --- a/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/xnode/MapXNodeImpl.java +++ b/infra/prism-impl/src/main/java/com/evolveum/midpoint/prism/impl/xnode/MapXNodeImpl.java @@ -7,6 +7,7 @@ package com.evolveum.midpoint.prism.impl.xnode; import java.util.*; +import java.util.stream.Collectors; import javax.xml.namespace.QName; @@ -271,12 +272,12 @@ public String getDesc() { @Override public String toString() { - StringBuilder sb = new StringBuilder("XNode(map:"+subnodes.size()+" entries)"); + StringBuilder sb = new StringBuilder("XNode(map:"+subnodes.size()+" entries) {"); sb.append("\n"); - subnodes.entrySet().forEach(entry -> { - sb.append(entry.toString()); - sb.append("; \n"); - }); + sb.append(subnodes.entrySet().stream() + .map(Object::toString) + .collect(Collectors.joining(";\n"))); + sb.append(" }"); return sb.toString(); } diff --git a/infra/prism-impl/src/test/java/com/evolveum/midpoint/prism/PrismInternalTestUtil.java b/infra/prism-impl/src/test/java/com/evolveum/midpoint/prism/PrismInternalTestUtil.java index 8014277a4b4..8f737de9b6c 100644 --- a/infra/prism-impl/src/test/java/com/evolveum/midpoint/prism/PrismInternalTestUtil.java +++ b/infra/prism-impl/src/test/java/com/evolveum/midpoint/prism/PrismInternalTestUtil.java @@ -270,7 +270,7 @@ public static void assertVisitor(Visitable visitable, int expectedVisits) { @Override public void visit(Visitable visitable) { visits.add(visitable); - System.out.println("Visiting: "+visitable); + System.out.println("#" + visits.size() + ": Visiting: "+visitable); } }; visitable.accept(visitor); @@ -281,7 +281,7 @@ public static void assertPathVisitor(PathVisitable visitable, final ItemPath pat final List visits = new ArrayList<>(); Visitor visitor = visitable1 -> { visits.add(visitable1); - System.out.println("Visiting(path="+path+",recursive="+recursive+"): "+ visitable1); + System.out.println("#" + visits.size() + ": Visiting(path="+path+",recursive="+recursive+"): "+ visitable1); }; visitable.accept(visitor, path, recursive); assertEquals("Wrong number of visits for path "+path, expectedVisits, visits.size()); @@ -296,7 +296,7 @@ public static void assertUserJack(PrismObject user, boolean expectRawI user.assertDefinitions("test"); assertUserJackContent(user, expectRawInConstructions, expectFullPolyName, withIncomplete); assertUserJackExtension(user, withIncomplete); - assertVisitor(user, 71); + assertVisitor(user, 75); assertPathVisitor(user, UserType.F_ASSIGNMENT, true, 9); assertPathVisitor(user, ItemPath.create(UserType.F_ASSIGNMENT, USER_ASSIGNMENT_1_ID), true, 3); diff --git a/infra/prism-impl/src/test/java/com/evolveum/midpoint/prism/TestPrismParsing.java b/infra/prism-impl/src/test/java/com/evolveum/midpoint/prism/TestPrismParsing.java index b94e3878088..454713233a4 100644 --- a/infra/prism-impl/src/test/java/com/evolveum/midpoint/prism/TestPrismParsing.java +++ b/infra/prism-impl/src/test/java/com/evolveum/midpoint/prism/TestPrismParsing.java @@ -150,7 +150,9 @@ private void roundTrip(File file, boolean expectFullPolyName, boolean withIncomp // WHEN // We need to serialize with composite objects during roundtrip, otherwise the result will not be equal - String userXml = prismContext.serializerFor(getOutputFormat()).serialize(originalUser); + String userXml = prismContext.serializerFor(getOutputFormat()) + .options(SerializationOptions.createSerializeCompositeObjects()) + .serialize(originalUser); // THEN System.out.println("Serialized user:"); @@ -193,7 +195,9 @@ private void roundTripAdhoc(File file) throws SchemaException, IOException { // WHEN // We need to serialize with composite objects during roundtrip, otherwise the result will not be equal - String userXml = prismContext.serializeObjectToString(originalUser, getOutputFormat()); + String userXml = prismContext.serializerFor(getOutputFormat()) + .options(SerializationOptions.createSerializeCompositeObjects()) + .serialize(originalUser); // THEN System.out.println("Serialized user:"); @@ -386,7 +390,7 @@ protected void assertUserAdhoc(PrismObject user, boolean expectRawInCo user.checkConsistence(); assertUserJackContent(user, expectRawInConstructions, true, withIncomplete); assertUserExtensionAdhoc(user); - assertVisitor(user, 58); + assertVisitor(user, 62); } private void assertUserExtensionAdhoc(PrismObject user) { diff --git a/infra/prism-impl/src/test/resources/common/json/user-jack-adhoc.json b/infra/prism-impl/src/test/resources/common/json/user-jack-adhoc.json index 0f7901002d7..2b3d40f86db 100644 --- a/infra/prism-impl/src/test/resources/common/json/user-jack-adhoc.json +++ b/infra/prism-impl/src/test/resources/common/json/user-jack-adhoc.json @@ -66,8 +66,14 @@ } }, "accountRef" : [ { - "oid" : "c0c010c0-d34d-b33f-f00d-aaaaaaaa1111", - "type" : "http://midpoint.evolveum.com/xml/ns/test/foo-1.xsd#AccountType" + "oid" : "c0c010c0-d34d-b33f-f00d-aaaaaaaa1113", + "type" : "http://midpoint.evolveum.com/xml/ns/test/foo-1.xsd#AccountType", + "object" : { + "oid" : "c0c010c0-d34d-b33f-f00d-aaaaaaaa1113", + "name" : "jsparrow" + } + }, { + "oid" : "c0c010c0-d34d-b33f-f00d-aaaaaaaa1111" }, { "oid" : "c0c010c0-d34d-b33f-f00d-aaaaaaaa1112", "type" : "http://midpoint.evolveum.com/xml/ns/test/foo-1.xsd#AccountType", diff --git a/infra/prism-impl/src/test/resources/common/json/user-jack-object.json b/infra/prism-impl/src/test/resources/common/json/user-jack-object.json index 52dcd88bac8..69443661829 100644 --- a/infra/prism-impl/src/test/resources/common/json/user-jack-object.json +++ b/infra/prism-impl/src/test/resources/common/json/user-jack-object.json @@ -66,8 +66,14 @@ } }, "accountRef" : [ { - "oid" : "c0c010c0-d34d-b33f-f00d-aaaaaaaa1111", - "type" : "http://midpoint.evolveum.com/xml/ns/test/foo-1.xsd#AccountType" + "oid" : "c0c010c0-d34d-b33f-f00d-aaaaaaaa1113", + "type" : "http://midpoint.evolveum.com/xml/ns/test/foo-1.xsd#AccountType", + "object" : { + "oid" : "c0c010c0-d34d-b33f-f00d-aaaaaaaa1113", + "name" : "jsparrow" + } + }, { + "oid" : "c0c010c0-d34d-b33f-f00d-aaaaaaaa1111" }, { "oid" : "c0c010c0-d34d-b33f-f00d-aaaaaaaa1112", "type" : "http://midpoint.evolveum.com/xml/ns/test/foo-1.xsd#AccountType", diff --git a/infra/prism-impl/src/test/resources/common/yaml/user-jack-adhoc.yaml b/infra/prism-impl/src/test/resources/common/yaml/user-jack-adhoc.yaml index c445e6ea717..44621c94f8e 100644 --- a/infra/prism-impl/src/test/resources/common/yaml/user-jack-adhoc.yaml +++ b/infra/prism-impl/src/test/resources/common/yaml/user-jack-adhoc.yaml @@ -53,8 +53,12 @@ user: cipherData: cipherValue: "blc5OXO2Z4vJW7o/XXhqZzg/rkwsIOwRBK7KLgMqwcrVcYpeZZOjxzgRgFiNw4IB" accountRef: - - oid: "c0c010c0-d34d-b33f-f00d-aaaaaaaa1111" + - oid: "c0c010c0-d34d-b33f-f00d-aaaaaaaa1113" type: "http://midpoint.evolveum.com/xml/ns/test/foo-1.xsd#AccountType" + object: + oid: "c0c010c0-d34d-b33f-f00d-aaaaaaaa1113" + name: "jsparrow" + - oid: "c0c010c0-d34d-b33f-f00d-aaaaaaaa1111" # deliberately without specifying the type, as it should be taken from the definition - oid: "c0c010c0-d34d-b33f-f00d-aaaaaaaa1112" type: "http://midpoint.evolveum.com/xml/ns/test/foo-1.xsd#AccountType" description: "This is a reference with a filter" diff --git a/infra/prism-impl/src/test/resources/common/yaml/user-jack-object.yaml b/infra/prism-impl/src/test/resources/common/yaml/user-jack-object.yaml index 8890b24262f..67f6d5560ef 100644 --- a/infra/prism-impl/src/test/resources/common/yaml/user-jack-object.yaml +++ b/infra/prism-impl/src/test/resources/common/yaml/user-jack-object.yaml @@ -52,8 +52,12 @@ object: !http://midpoint.evolveum.com/xml/ns/test/foo-1.xsd/UserType cipherData: cipherValue: "blc5OXO2Z4vJW7o/XXhqZzg/rkwsIOwRBK7KLgMqwcrVcYpeZZOjxzgRgFiNw4IB" accountRef: - - oid: "c0c010c0-d34d-b33f-f00d-aaaaaaaa1111" + - oid: "c0c010c0-d34d-b33f-f00d-aaaaaaaa1113" type: "http://midpoint.evolveum.com/xml/ns/test/foo-1.xsd#AccountType" + object: + oid: "c0c010c0-d34d-b33f-f00d-aaaaaaaa1113" + name: "jsparrow" + - oid: "c0c010c0-d34d-b33f-f00d-aaaaaaaa1111" # deliberately without specifying the type, as it should be taken from the definition - oid: "c0c010c0-d34d-b33f-f00d-aaaaaaaa1112" type: "http://midpoint.evolveum.com/xml/ns/test/foo-1.xsd#AccountType" description: "This is a reference with a filter"