Skip to content

Commit

Permalink
Fixing entitlement identifier type conversion
Browse files Browse the repository at this point in the history
  • Loading branch information
semancik committed Oct 22, 2014
1 parent 21e3f4d commit e1dc11b
Show file tree
Hide file tree
Showing 6 changed files with 238 additions and 17 deletions.
Expand Up @@ -17,6 +17,7 @@

import com.evolveum.midpoint.prism.PrismConstants;
import com.evolveum.midpoint.prism.PrismContext;
import com.evolveum.midpoint.prism.PrismProperty;
import com.evolveum.midpoint.prism.PrismPropertyDefinition;
import com.evolveum.midpoint.prism.PrismPropertyValue;
import com.evolveum.midpoint.prism.parser.DomParser;
Expand All @@ -26,6 +27,7 @@
import com.evolveum.midpoint.prism.polystring.PolyStringNormalizer;
import com.evolveum.midpoint.prism.xml.XsdTypeMapper;
import com.evolveum.midpoint.util.DOMUtil;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.prism.xml.ns._public.types_3.PolyStringType;

import org.apache.commons.lang.StringUtils;
Expand All @@ -35,6 +37,7 @@
import org.w3c.dom.NamedNodeMap;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

Expand Down Expand Up @@ -172,4 +175,18 @@ public static <T,X> PrismPropertyValue<X> convertPropertyValue(PrismPropertyValu
}
}

public static <T,X> PrismProperty<X> convertProperty(PrismProperty<T> srcProp, PrismPropertyDefinition<X> targetDef) throws SchemaException {
if (targetDef.getTypeName().equals(srcProp.getDefinition().getTypeName())) {
return (PrismProperty<X>) srcProp;
} else {
PrismProperty<X> targetProp = targetDef.instantiate();
Class<X> expectedJavaType = XsdTypeMapper.toJavaType(targetDef.getTypeName());
for (PrismPropertyValue<T> srcPVal: srcProp.getValues()) {
X convertedRealValue = JavaTypeConverter.convert(expectedJavaType, srcPVal.getValue());
targetProp.add(new PrismPropertyValue<X>(convertedRealValue));
}
return targetProp;
}
}

}
Expand Up @@ -342,6 +342,9 @@ public Collection<String> getAttributeStringValues(ShadowType shadow, javax.xml.
}

public <T> T getIdentifierValue(ShadowType shadow) throws SchemaException {
if (shadow == null) {
return null;
}
Collection<ResourceAttribute<?>> identifiers = ShadowUtil.getIdentifiers(shadow);
if (identifiers.size() == 0) {
return null;
Expand All @@ -358,7 +361,28 @@ public <T> T getIdentifierValue(ShadowType shadow) throws SchemaException {
}
return realValues.iterator().next();
}


public <T> T getSecondaryIdentifierValue(ShadowType shadow) throws SchemaException {
if (shadow == null) {
return null;
}
Collection<ResourceAttribute<?>> identifiers = ShadowUtil.getSecondaryIdentifiers(shadow);
if (identifiers.size() == 0) {
return null;
}
if (identifiers.size() > 1) {
throw new SchemaException("More than one secondary idenfier in "+shadow);
}
Collection<T> realValues = (Collection<T>) identifiers.iterator().next().getRealValues();
if (realValues.size() == 0) {
return null;
}
if (realValues.size() > 1) {
throw new SchemaException("More than one secondary idenfier value in "+shadow);
}
return realValues.iterator().next();
}

public String determineLdapSingleAttributeValue(Collection<String> dns, String attributeName, PrismProperty attribute) throws NamingException {
return determineLdapSingleAttributeValue(dns, attributeName, attribute.getRealValues());
}
Expand Down
Expand Up @@ -310,9 +310,9 @@ private void evaluateKindIntent(OperationResult result) throws SchemaException,

if (refinedObjectClassDefinition == null) {
if (constructionType.getIntent() != null) {
throw new SchemaException("No account type '"+constructionType.getIntent()+"' found in "+ObjectTypeUtil.toShortString(getResource(result))+" as specified in account construction in "+ObjectTypeUtil.toShortString(source));
throw new SchemaException("No "+kind+" type '"+constructionType.getIntent()+"' found in "+getResource(result)+" as specified in construction in "+source);
} else {
throw new SchemaException("No default account type found in " + resource + " as specified in account construction in "+ObjectTypeUtil.toShortString(source));
throw new SchemaException("No default "+kind+" type found in " + resource + " as specified in construction in "+source);
}
}
}
Expand Down
Expand Up @@ -530,7 +530,7 @@ private <T> void collectEntitlementsAsObjectOperation(Map<ResourceObjectDiscrimi
}
}

private <T> void collectEntitlementAsObjectOperation(Map<ResourceObjectDiscriminator, Collection<Operation>> roMap,
private <TV,TA> void collectEntitlementAsObjectOperation(Map<ResourceObjectDiscriminator, Collection<Operation>> roMap,
PrismContainerValue<ShadowAssociationType> associationCVal, RefinedObjectClassDefinition objectClassDefinition,
PrismObject<ShadowType> shadowBefore, PrismObject<ShadowType> shadowAfter, RefinedResourceSchema rSchema, ResourceType resource, ModificationType modificationType)
throws SchemaException {
Expand Down Expand Up @@ -608,13 +608,13 @@ private <T> void collectEntitlementAsObjectOperation(Map<ResourceObjectDiscrimin
}
}

ResourceAttribute<T> valueAttr = ShadowUtil.getAttribute(shadow, valueAttrName);
ResourceAttribute<TV> valueAttr = ShadowUtil.getAttribute(shadow, valueAttrName);
if (valueAttr == null) {
// TODO: check schema and try to fetch full shadow if necessary
throw new SchemaException("No value attribute "+valueAttrName+" in shadow");
}

PropertyDelta<T> attributeDelta = null;
PropertyDelta<TA> attributeDelta = null;
for(Operation operation: operations) {
if (operation instanceof PropertyModificationOperation) {
PropertyModificationOperation propOp = (PropertyModificationOperation)operation;
Expand All @@ -629,13 +629,15 @@ private <T> void collectEntitlementAsObjectOperation(Map<ResourceObjectDiscrimin
operations.add(attributeModification);
}

PrismProperty<TA> changedAssocAttr = PrismUtil.convertProperty(valueAttr, assocAttrDef);

if (modificationType == ModificationType.ADD) {
attributeDelta.addValuesToAdd(valueAttr.getClonedValues());
attributeDelta.addValuesToAdd(changedAssocAttr.getClonedValues());
} else if (modificationType == ModificationType.DELETE) {
attributeDelta.addValuesToDelete(valueAttr.getClonedValues());
attributeDelta.addValuesToDelete(changedAssocAttr.getClonedValues());
} else if (modificationType == ModificationType.REPLACE) {
// TODO: check if already exists
attributeDelta.setValuesToReplace(valueAttr.getClonedValues());
attributeDelta.setValuesToReplace(changedAssocAttr.getClonedValues());
}
}

Expand Down
185 changes: 181 additions & 4 deletions samples/demo-rs/resource-ldap-openldap.xml
Expand Up @@ -72,9 +72,11 @@ It also contains inbound mappings and definition to enable synchronization.
<icfcldap:host>localhost</icfcldap:host>
<icfcldap:baseContexts>dc=example,dc=com</icfcldap:baseContexts>
<icfcldap:principal>uid=idm,ou=Administrators,dc=example,dc=com</icfcldap:principal>
<icfcldap:credentials>
<clearValue>secret</clearValue>
</icfcldap:credentials>
<icfcldap:credentials>
<clearValue>secret</clearValue>
</icfcldap:credentials>
<icfcldap:passwordHashAlgorithm>SSHA</icfcldap:passwordHashAlgorithm>
<icfcldap:groupMemberAttribute>member</icfcldap:groupMemberAttribute>
<icfcldap:modifiersNamesToFilterOut>uid=idm,ou=Administrators,dc=example,dc=com</icfcldap:modifiersNamesToFilterOut>
<icfcldap:vlvSortAttribute>uid</icfcldap:vlvSortAttribute>
<icfcldap:useBlocks>true</icfcldap:useBlocks>
Expand Down Expand Up @@ -254,6 +256,26 @@ It also contains inbound mappings and definition to enable synchronization.
</outbound>
</attribute>

<association>
<ref>ri:group</ref>
<displayName>LDAP Group Membership</displayName>
<kind>entitlement</kind>
<intent>ldapGroup</intent>
<direction>objectToSubject</direction>
<associationAttribute>ri:member</associationAttribute>
<valueAttribute>icfs:name</valueAttribute>
</association>

<association>
<ref>ri:customerProject</ref>
<displayName>Customer Project Group Membership</displayName>
<kind>entitlement</kind>
<intent>customerProject</intent>
<direction>objectToSubject</direction>
<associationAttribute>ri:member</associationAttribute>
<valueAttribute>icfs:name</valueAttribute>
</association>

<iteration>
<maxIterations>5</maxIterations>
</iteration>
Expand Down Expand Up @@ -291,6 +313,156 @@ It also contains inbound mappings and definition to enable synchronization.
</credentials>

</objectType>

<objectType>
<kind>entitlement</kind>
<intent>ldapGroup</intent>
<displayName>LDAP Group</displayName>
<objectClass>ri:CustomgroupOfNamesObjectClass</objectClass>
<attribute>
<ref>icfs:name</ref>
<matchingRule>mr:stringIgnoreCase</matchingRule>
<outbound>
<source>
<path>$focus/name</path>
</source>
<expression>
<script>
<code>
import javax.naming.ldap.Rdn
import javax.naming.ldap.LdapName

dn = new LdapName('ou=groups,dc=example,dc=com')
dn.add(new Rdn('cn', name.toString()))
return dn.toString()
</code>
</script>
</expression>
</outbound>
</attribute>
<attribute>
<ref>ri:cn</ref>
<matchingRule>mr:stringIgnoreCase</matchingRule>
<outbound>
<strength>weak</strength>
<source>
<path>$focus/name</path>
</source>
</outbound>
</attribute>
<attribute>
<ref>ri:description</ref>
<outbound>
<source>
<path>description</path>
</source>
</outbound>
</attribute>
</objectType>

<objectType>
<kind>generic</kind>
<intent>customer</intent>
<displayName>Customer</displayName>
<objectClass>ri:CustomorganizationalUnitObjectClass</objectClass>
<attribute>
<ref>icfs:name</ref>
<matchingRule>mr:stringIgnoreCase</matchingRule>
<outbound>
<source>
<path>$focus/name</path>
</source>
<expression>
<script>
<code>
import javax.naming.ldap.Rdn
import javax.naming.ldap.LdapName

dn = new LdapName('ou=customers,dc=example,dc=com')
dn.add(new Rdn('ou', name.toString()))
return dn.toString()
</code>
</script>
</expression>
</outbound>
</attribute>
<attribute>
<ref>ri:ou</ref>
<matchingRule>mr:stringIgnoreCase</matchingRule>
<outbound>
<strength>weak</strength>
<source>
<path>$focus/name</path>
</source>
</outbound>
</attribute>
<attribute>
<ref>ri:description</ref>
<outbound>
<source>
<path>description</path>
</source>
</outbound>
</attribute>
</objectType>

<objectType>
<kind>entitlement</kind>
<intent>customerProject</intent>
<displayName>Customer Project Group</displayName>
<objectClass>ri:CustomgroupOfNamesObjectClass</objectClass>
<attribute>
<ref>icfs:name</ref>
<matchingRule>mr:stringIgnoreCase</matchingRule>
<outbound>
<source>
<path>$focus/name</path>
</source>
<expression>
<script>
<code>
import javax.naming.ldap.Rdn
import javax.naming.ldap.LdapName

dn = new LdapName('ou=customers,dc=example,dc=com')
customerName = midpoint.getParentOrgByOrgType(focus,'customer').getName().toString()
dn.add(new Rdn('ou', customerName))
dn.add(new Rdn('cn', name.toString()))
return dn.toString()
</code>
</script>
</expression>
</outbound>
</attribute>
<attribute>
<ref>ri:cn</ref>
<matchingRule>mr:stringIgnoreCase</matchingRule>
<outbound>
<strength>weak</strength>
<source>
<path>$focus/name</path>
</source>
</outbound>
</attribute>
<attribute>
<ref>ri:description</ref>
<outbound>
<source>
<path>description</path>
</source>
</outbound>
</attribute>
<attribute>
<ref>ri:member</ref>
<outbound>
<strength>weak</strength>
<expression>
<value>uid=nobody,dc=example,dc=com</value>
</expression>
</outbound>
</attribute>
</objectType>

</schemaHandling>

<!--
Expand All @@ -306,7 +478,12 @@ It also contains inbound mappings and definition to enable synchronization.
</configured>
</capabilities>
-->
<!--

<consistency>
<avoidDuplicateValues>true</avoidDuplicateValues>
</consistency>

<!--
Synchronization section describes the synchronization policy, timing,
reactions and similar synchronization settings.
-->
Expand Down
9 changes: 5 additions & 4 deletions samples/resources/openldap/openldap-localhost-medium.xml
Expand Up @@ -72,10 +72,11 @@ It also contains inbound mappings and definition to enable synchronization.
<icfcldap:host>localhost</icfcldap:host>
<icfcldap:baseContexts>dc=example,dc=com</icfcldap:baseContexts>
<icfcldap:principal>uid=idm,ou=Administrators,dc=example,dc=com</icfcldap:principal>
<icfcldap:credentials>
<clearValue>secret</clearValue>
</icfcldap:credentials>
<icfcldap:passwordHashAlgorithm>SSHA</icfcldap:passwordHashAlgorithm>
<icfcldap:credentials>
<clearValue>secret</clearValue>
</icfcldap:credentials>
<icfcldap:passwordHashAlgorithm>SSHA</icfcldap:passwordHashAlgorithm>
<icfcldap:groupMemberAttribute>member</icfcldap:groupMemberAttribute>
<icfcldap:modifiersNamesToFilterOut>uid=idm,ou=Administrators,dc=example,dc=com</icfcldap:modifiersNamesToFilterOut>
<icfcldap:vlvSortAttribute>uid</icfcldap:vlvSortAttribute>
<icfcldap:useBlocks>true</icfcldap:useBlocks>
Expand Down

0 comments on commit e1dc11b

Please sign in to comment.