[midPoint] Working around a constraint violation in user name?
Mikko Pekkarinen
mikko.pekkarinen at datactica.fi
Tue Mar 28 15:56:42 CEST 2017
Hello,
I'm trying to synchronize users into midPoint. The names of the users are generated from the email address. The shadows are correlated to users using a separate GUID field in an extension.
Problem: when the resource contains 2 user accounts whose normalized email addresses are equal, my mappings fail. If there are accounts with identical emails, the iteration works as expected. That is:
- Import 2 accounts with different GUIDs but same email "sauli.ahtisaari at rosvo.fi" => 2 midPoint users created, with names
"sauli.ahtisaari at rosvo.fi" and "sauli.ahtisaari+1 at rosvo.fi".
- Import a third account with email "sauliahtisaari at rosvo.fi" (differs by a missing '.') => user is not created. Instead, getting an exception:
2017-03-28 12:55:31,177 [] [midPointScheduler_Worker-10] ERROR (com.evolveum.midpoint.model.impl.sync.SynchronizationServiceImpl): SYNCHRONIZATION: Error in synchronization on resource:43ec8c33-1d9d-4129-8ee4-80cfbac8eb46(Feikki-SAHA) for situation UNMATCHED: ObjectAlreadyExistsException: Conflicting object already exists (violated constraint 'uc_user_name'). Change was ResourceObjectShadowChangeDescription(objectDelta=null, currentShadow=shadow:584ddb51-9555-4f44-883d-72d1e97eee9b(c41bd105-73ec-515c-bb91-e57229fb0ac8), oldShadow=shadow:584ddb51-9555-4f44-883d-72d1e97eee9b(c41bd105-73ec-515c-bb91-e57229fb0ac8), sourceChannel=http://midpoint.evolveum.com/xml/ns/public/provisioning/channels-3#liveSync, resource=resource:43ec8c33-1d9d-4129-8ee4-80cfbac8eb46(Feikki-SAHA))
com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException: Conflicting object already exists (violated constraint 'uc_user_name')
...
Caused by: org.hibernate.exception.ConstraintViolationException: could not execute statement
at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:129) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final]
...
Caused by: org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "uc_user_name"
Detail: Key (name_norm)=(sauliahtisaarirosvofi) already exists.
...
Some config:
Inbound mapping:
<inbound>
<name>User Name</name>
<description>"name" is a mandatory attribute for midPoint Users. Getting error "No name in new object null as produced by template null in iteration 0, we cannot process an object without a name" if it's not set." Therefore, setting it. Furthermore, the database schema requires that the field is unique => email is likely the best choice here.</description>
<authoritative>true</authoritative>
<exclusive>false</exclusive>
<strength>weak</strength>
<expression>
<script>
<code>return basic.toAscii(input)?.replaceFirst('@', sprintf("+%x@", new Random().nextInt(10000)));</code>
</script>
</expression>
<target>
<c:path>name</c:path>
</target>
</inbound>
(Putting a random token in the value here, or else the user creation fails already here, before the user template is processed.
I know, this fails with probability 1/10000, but I can live with that. Iteration would be better, but that's not supported in inbound mappings?)
Object template:
<mapping>
<name>Generate unique midPoint username</name>
<strength>strong</strength>
<source>
<c:path>emailAddress</c:path>
</source>
<expression>
<script>
<code>
tmp = basic.toAscii(emailAddress);
if (basic.isEmpty(iterationToken) || !tmp.contains('@')) {
return tmp + iterationToken;
} else {
return tmp.replaceFirst('@', "+$iterationToken@");
}
</code>
</script>
</expression>
<target>
<c:path>name</c:path>
</target>
<condition>
<script>
<code>emailAddress != null</code>
</script>
</condition>
It seems that the iteration is only checking if the name is already in use, but it does not consider the unique constraint "uc_user_name" at all.
As a workaround I could probably use midpoint.searchObjects to check if a conflicting user already exists, but that seems expensive.
Any better ideas?
Mikko
More information about the midPoint
mailing list