You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by sk...@apache.org on 2018/04/12 13:22:13 UTC
syncope git commit: [SYNCOPE-1302] Added new expression model in
mapping for internal attributes to access user relationships
Repository: syncope
Updated Branches:
refs/heads/2_0_X 73fab3dee -> 02b6d4eb6
[SYNCOPE-1302] Added new expression model in mapping for internal attributes to access user relationships
Project: http://git-wip-us.apache.org/repos/asf/syncope/repo
Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/02b6d4eb
Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/02b6d4eb
Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/02b6d4eb
Branch: refs/heads/2_0_X
Commit: 02b6d4eb6f6d0eaa993e00ef6d86c9f7c4411850
Parents: 73fab3d
Author: skylark17 <ma...@tirasa.net>
Authored: Thu Apr 12 15:21:30 2018 +0200
Committer: skylark17 <ma...@tirasa.net>
Committed: Thu Apr 12 15:21:58 2018 +0200
----------------------------------------------------------------------
.../NotificationWizardBuilder.java | 4 +-
.../console/wizards/AbstractMappingPanel.java | 4 +-
.../core/provisioning/api/IntAttrName.java | 30 ++
.../provisioning/java/IntAttrNameParser.java | 24 +-
.../provisioning/java/MappingManagerImpl.java | 306 +++++++++++--------
.../java/data/ResourceDataBinderImpl.java | 15 +
.../java/IntAttrNameParserTest.java | 59 ++++
.../concepts/externalresources.adoc | 4 +
8 files changed, 316 insertions(+), 130 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/syncope/blob/02b6d4eb/client/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationWizardBuilder.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationWizardBuilder.java b/client/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationWizardBuilder.java
index 3ccfab0..bd9c503 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationWizardBuilder.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationWizardBuilder.java
@@ -358,7 +358,9 @@ public class NotificationWizardBuilder extends AjaxWizardBuilder<NotificationWra
recipientAttrName.addRequiredLabel();
recipientAttrName.setTitle(getString("intAttrNameInfo.help")
+ "<code>groups[groupName].attribute</code>, "
- + "<code>anyObjects[anyObjectName].attribute</code> or "
+ + "<code>users[userName].attribute</code>, "
+ + "<code>anyObjects[anyObjectName].attribute</code>, "
+ + "<code>relationships[relationshipType][anyType].attribute</code> or "
+ "<code>memberships[groupName].attribute</code>", true);
add(recipientAttrName);
http://git-wip-us.apache.org/repos/asf/syncope/blob/02b6d4eb/client/console/src/main/java/org/apache/syncope/client/console/wizards/AbstractMappingPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wizards/AbstractMappingPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/wizards/AbstractMappingPanel.java
index 42475c0..38e5579 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/wizards/AbstractMappingPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wizards/AbstractMappingPanel.java
@@ -153,7 +153,9 @@ public abstract class AbstractMappingPanel extends Panel {
Model.<String>of(),
Model.of(getString("intAttrNameInfo.help")
+ "<code>groups[groupName].attribute</code>, "
- + "<code>anyObjects[anyObjectName].attribute</code> or "
+ + "<code>users[userName].attribute</code>, "
+ + "<code>anyObjects[anyObjectName].attribute</code>, "
+ + "<code>relationships[relationshipType][anyType].attribute</code> or "
+ "<code>memberships[groupName].attribute</code>"),
new PopoverConfig().withHtml(true).withPlacement(TooltipConfig.Placement.right)) {
http://git-wip-us.apache.org/repos/asf/syncope/blob/02b6d4eb/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/IntAttrName.java
----------------------------------------------------------------------
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/IntAttrName.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/IntAttrName.java
index f46384e..a243bad 100644
--- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/IntAttrName.java
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/IntAttrName.java
@@ -35,10 +35,16 @@ public class IntAttrName {
private String enclosingGroup;
+ private String relatedUser;
+
private String relatedAnyObject;
private String membershipOfGroup;
+ private String relationshipType;
+
+ private String relationshipAnyType;
+
public AnyTypeKind getAnyTypeKind() {
return anyTypeKind;
}
@@ -79,6 +85,14 @@ public class IntAttrName {
this.enclosingGroup = enclosingGroup;
}
+ public String getRelatedUser() {
+ return relatedUser;
+ }
+
+ public void setRelatedUser(final String relatedUser) {
+ this.relatedUser = relatedUser;
+ }
+
public String getRelatedAnyObject() {
return relatedAnyObject;
}
@@ -95,6 +109,22 @@ public class IntAttrName {
this.membershipOfGroup = membershipOfGroup;
}
+ public String getRelationshipType() {
+ return relationshipType;
+ }
+
+ public void setRelationshipType(final String relationshipType) {
+ this.relationshipType = relationshipType;
+ }
+
+ public String getRelationshipAnyType() {
+ return relationshipAnyType;
+ }
+
+ public void setRelationshipAnyType(final String relationshipAnyType) {
+ this.relationshipAnyType = relationshipAnyType;
+ }
+
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE);
http://git-wip-us.apache.org/repos/asf/syncope/blob/02b6d4eb/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/IntAttrNameParser.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/IntAttrNameParser.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/IntAttrNameParser.java
index 2b77a61..27dd988 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/IntAttrNameParser.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/IntAttrNameParser.java
@@ -38,12 +38,19 @@ public class IntAttrNameParser {
private static final Pattern ENCLOSING_GROUP_PATTERN = Pattern.compile(
"^groups\\[(" + SyncopeConstants.NAME_PATTERN + ")\\]\\.(.+)");
+ private static final Pattern RELATED_USER_PATTERN = Pattern.compile(
+ "^users\\[(" + SyncopeConstants.NAME_PATTERN + ")\\]\\.(.+)");
+
private static final Pattern RELATED_ANY_OBJECT_PATTERN = Pattern.compile(
"^anyObjects\\[(" + SyncopeConstants.NAME_PATTERN + ")\\]\\.(.+)");
private static final Pattern MEMBERSHIP_PATTERN = Pattern.compile(
"^memberships\\[(" + SyncopeConstants.NAME_PATTERN + ")\\]\\.(.+)");
+ private static final Pattern RELATIONSHIP_PATTERN = Pattern.compile(
+ "^relationships\\[(" + SyncopeConstants.NAME_PATTERN + ")\\]"
+ + "\\[(" + SyncopeConstants.NAME_PATTERN + ")\\]\\.(.+)");
+
@Autowired
private PlainSchemaDAO plainSchemaDAO;
@@ -114,7 +121,22 @@ public class IntAttrNameParser {
result.setMembershipOfGroup(matcher.group(1));
setFieldOrSchemaName(matcher.group(2), result.getAnyTypeKind(), result);
} else {
- throw new ParseException("Unparsable expression: " + intAttrName, 0);
+ matcher = RELATED_USER_PATTERN.matcher(intAttrName);
+ if (matcher.matches()) {
+ result.setAnyTypeKind(AnyTypeKind.USER);
+ result.setRelatedUser(matcher.group(1));
+ setFieldOrSchemaName(matcher.group(2), result.getAnyTypeKind(), result);
+ } else {
+ matcher = RELATIONSHIP_PATTERN.matcher(intAttrName);
+ if (matcher.matches()) {
+ result.setAnyTypeKind(AnyTypeKind.ANY_OBJECT);
+ result.setRelationshipType(matcher.group(1));
+ result.setRelationshipAnyType(matcher.group(2));
+ setFieldOrSchemaName(matcher.group(3), result.getAnyTypeKind(), result);
+ } else {
+ throw new ParseException("Unparsable expression: " + intAttrName, 0);
+ }
+ }
}
}
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/02b6d4eb/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/MappingManagerImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/MappingManagerImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/MappingManagerImpl.java
index ac63ad7..66c1652 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/MappingManagerImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/MappingManagerImpl.java
@@ -27,6 +27,7 @@ import java.util.List;
import java.util.Set;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.ListUtils;
+import org.apache.commons.collections4.Predicate;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.reflect.FieldUtils;
@@ -40,6 +41,7 @@ import org.apache.syncope.common.lib.to.GroupableRelatableTO;
import org.apache.syncope.common.lib.to.MembershipTO;
import org.apache.syncope.common.lib.to.RealmTO;
import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
import org.apache.syncope.common.lib.types.AttrSchemaType;
import org.apache.syncope.core.persistence.api.attrvalue.validation.ParsingValidationException;
import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
@@ -48,8 +50,11 @@ import org.apache.syncope.core.persistence.api.dao.DerSchemaDAO;
import org.apache.syncope.core.persistence.api.dao.GroupDAO;
import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO;
import org.apache.syncope.core.persistence.api.dao.RealmDAO;
+import org.apache.syncope.core.persistence.api.dao.RelationshipTypeDAO;
+import org.apache.syncope.core.persistence.api.dao.UserDAO;
import org.apache.syncope.core.persistence.api.dao.VirSchemaDAO;
import org.apache.syncope.core.persistence.api.entity.Any;
+import org.apache.syncope.core.persistence.api.entity.AnyType;
import org.apache.syncope.core.persistence.api.entity.AnyUtils;
import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
import org.apache.syncope.core.persistence.api.entity.DerSchema;
@@ -59,6 +64,8 @@ import org.apache.syncope.core.persistence.api.entity.PlainAttr;
import org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
import org.apache.syncope.core.persistence.api.entity.PlainSchema;
import org.apache.syncope.core.persistence.api.entity.Realm;
+import org.apache.syncope.core.persistence.api.entity.Relationship;
+import org.apache.syncope.core.persistence.api.entity.RelationshipType;
import org.apache.syncope.core.persistence.api.entity.Schema;
import org.apache.syncope.core.persistence.api.entity.VirSchema;
import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
@@ -119,6 +126,12 @@ public class MappingManagerImpl implements MappingManager {
private GroupDAO groupDAO;
@Autowired
+ private UserDAO userDAO;
+
+ @Autowired
+ private RelationshipTypeDAO relationshipTypeDAO;
+
+ @Autowired
private RealmDAO realmDAO;
@Autowired
@@ -401,10 +414,14 @@ public class MappingManagerImpl implements MappingManager {
LOG.debug("Get internal values for {} as '{}' on {}", any, mapItem.getIntAttrName(), provision.getResource());
- Any<?> reference = null;
+ List<Any<?>> references = new ArrayList<>();
Membership<?> membership = null;
- if (intAttrName.getEnclosingGroup() == null && intAttrName.getRelatedAnyObject() == null) {
- reference = any;
+ if (intAttrName.getEnclosingGroup() == null
+ && intAttrName.getRelatedAnyObject() == null
+ && intAttrName.getRelationshipAnyType() == null
+ && intAttrName.getRelationshipType() == null
+ && intAttrName.getRelatedUser() == null) {
+ references.add(any);
}
if (any instanceof GroupableRelatable) {
GroupableRelatable<?, ?, ?, ?, ?> groupableRelatable = (GroupableRelatable<?, ?, ?, ?, ?>) any;
@@ -415,7 +432,17 @@ public class MappingManagerImpl implements MappingManager {
LOG.warn("No membership for {} in {}, ignoring",
intAttrName.getEnclosingGroup(), groupableRelatable);
} else {
- reference = group;
+ references.add(group);
+ }
+ } else if (intAttrName.getRelatedUser() != null) {
+ User user = userDAO.findByUsername(intAttrName.getRelatedUser());
+ if (user == null || user.getRelationships(groupableRelatable.getKey()).isEmpty()) {
+ LOG.warn("No relationship for {} in {}, ignoring",
+ intAttrName.getRelatedUser(), groupableRelatable);
+ } else if (groupableRelatable.getType().getKind() == AnyTypeKind.USER) {
+ LOG.warn("Users cannot have relationship with other users, ignoring");
+ } else {
+ references.add(user);
}
} else if (intAttrName.getRelatedAnyObject() != null) {
AnyObject anyObject = anyObjectDAO.findByName(intAttrName.getRelatedAnyObject());
@@ -423,14 +450,37 @@ public class MappingManagerImpl implements MappingManager {
LOG.warn("No relationship for {} in {}, ignoring",
intAttrName.getRelatedAnyObject(), groupableRelatable);
} else {
- reference = anyObject;
+ references.add(anyObject);
+ }
+ } else if (intAttrName.getRelationshipAnyType() != null && intAttrName.getRelationshipType() != null) {
+ RelationshipType relationshipType = relationshipTypeDAO.find(intAttrName.getRelationshipType());
+ final AnyType anyType = anyTypeDAO.find(intAttrName.getRelationshipAnyType());
+ if (relationshipType == null || groupableRelatable.getRelationships(relationshipType).isEmpty()) {
+ LOG.warn("No relationship for type {} in {}, ignoring",
+ intAttrName.getRelationshipType(), groupableRelatable);
+ } else if (anyType == null) {
+ LOG.warn("No anyType {}, ignoring", intAttrName.getRelationshipAnyType());
+ } else {
+ @SuppressWarnings("unchecked")
+ List<Relationship<?, ?>> results = (List<Relationship<?, ?>>) ListUtils.select(
+ groupableRelatable.getRelationships(relationshipType),
+ new Predicate<Relationship<?, ?>>() {
+
+ @Override
+ public boolean evaluate(final Relationship<?, ?> relationship) {
+ return anyType.equals(relationship.getRightEnd().getType());
+ }
+ });
+ for (Relationship<?, ?> result : results) {
+ references.add(result.getRightEnd());
+ }
}
} else if (intAttrName.getMembershipOfGroup() != null) {
Group group = groupDAO.findByName(intAttrName.getMembershipOfGroup());
membership = groupableRelatable.getMembership(group.getKey());
}
}
- if (reference == null) {
+ if (references.isEmpty()) {
LOG.warn("Could not determine the reference instance for {}", mapItem.getIntAttrName());
return Collections.emptyList();
}
@@ -438,143 +488,145 @@ public class MappingManagerImpl implements MappingManager {
List<PlainAttrValue> values = new ArrayList<>();
boolean transform = true;
- AnyUtils anyUtils = anyUtilsFactory.getInstance(reference);
- if (intAttrName.getField() != null) {
- PlainAttrValue attrValue = anyUtils.newPlainAttrValue();
-
- switch (intAttrName.getField()) {
- case "key":
- attrValue.setStringValue(reference.getKey());
- values.add(attrValue);
- break;
+ for (Any<?> reference : references) {
+ AnyUtils anyUtils = anyUtilsFactory.getInstance(reference);
+ if (intAttrName.getField() != null) {
+ PlainAttrValue attrValue = anyUtils.newPlainAttrValue();
- case "realm":
- attrValue.setStringValue(reference.getRealm().getFullPath());
- values.add(attrValue);
- break;
+ switch (intAttrName.getField()) {
+ case "key":
+ attrValue.setStringValue(reference.getKey());
+ values.add(attrValue);
+ break;
- case "password":
- // ignore
- break;
+ case "realm":
+ attrValue.setStringValue(reference.getRealm().getFullPath());
+ values.add(attrValue);
+ break;
+
+ case "password":
+ // ignore
+ break;
+
+ case "userOwner":
+ case "groupOwner":
+ Mapping uMapping = provision.getAnyType().equals(anyTypeDAO.findUser())
+ ? provision.getMapping()
+ : null;
+ Mapping gMapping = provision.getAnyType().equals(anyTypeDAO.findGroup())
+ ? provision.getMapping()
+ : null;
+
+ if (reference instanceof Group) {
+ Group group = (Group) reference;
+ String groupOwnerValue = null;
+ if (group.getUserOwner() != null && uMapping != null) {
+ groupOwnerValue = getGroupOwnerValue(provision, group.getUserOwner());
+ }
+ if (group.getGroupOwner() != null && gMapping != null) {
+ groupOwnerValue = getGroupOwnerValue(provision, group.getGroupOwner());
+ }
- case "userOwner":
- case "groupOwner":
- Mapping uMapping = provision.getAnyType().equals(anyTypeDAO.findUser())
- ? provision.getMapping()
- : null;
- Mapping gMapping = provision.getAnyType().equals(anyTypeDAO.findGroup())
- ? provision.getMapping()
- : null;
-
- if (reference instanceof Group) {
- Group group = (Group) reference;
- String groupOwnerValue = null;
- if (group.getUserOwner() != null && uMapping != null) {
- groupOwnerValue = getGroupOwnerValue(provision, group.getUserOwner());
- }
- if (group.getGroupOwner() != null && gMapping != null) {
- groupOwnerValue = getGroupOwnerValue(provision, group.getGroupOwner());
+ if (StringUtils.isNotBlank(groupOwnerValue)) {
+ attrValue.setStringValue(groupOwnerValue);
+ values.add(attrValue);
+ }
}
+ break;
- if (StringUtils.isNotBlank(groupOwnerValue)) {
- attrValue.setStringValue(groupOwnerValue);
+ case "suspended":
+ if (reference instanceof User) {
+ attrValue.setBooleanValue(((User) reference).isSuspended());
values.add(attrValue);
}
- }
- break;
+ break;
- case "suspended":
- if (reference instanceof User) {
- attrValue.setBooleanValue(((User) reference).isSuspended());
- values.add(attrValue);
- }
- break;
-
- case "mustChangePassword":
- if (reference instanceof User) {
- attrValue.setBooleanValue(((User) reference).isMustChangePassword());
- values.add(attrValue);
- }
- break;
+ case "mustChangePassword":
+ if (reference instanceof User) {
+ attrValue.setBooleanValue(((User) reference).isMustChangePassword());
+ values.add(attrValue);
+ }
+ break;
- default:
- try {
- Object fieldValue = FieldUtils.readField(reference, intAttrName.getField(), true);
- if (fieldValue instanceof Date) {
- // needed because ConnId does not natively supports the Date type
- attrValue.setStringValue(DateFormatUtils.ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.
- format((Date) fieldValue));
- } else if (Boolean.TYPE.isInstance(fieldValue)) {
- attrValue.setBooleanValue((Boolean) fieldValue);
- } else if (Double.TYPE.isInstance(fieldValue) || Float.TYPE.isInstance(fieldValue)) {
- attrValue.setDoubleValue((Double) fieldValue);
- } else if (Long.TYPE.isInstance(fieldValue) || Integer.TYPE.isInstance(fieldValue)) {
- attrValue.setLongValue((Long) fieldValue);
+ default:
+ try {
+ Object fieldValue = FieldUtils.readField(reference, intAttrName.getField(), true);
+ if (fieldValue instanceof Date) {
+ // needed because ConnId does not natively supports the Date type
+ attrValue.setStringValue(DateFormatUtils.ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.
+ format((Date) fieldValue));
+ } else if (Boolean.TYPE.isInstance(fieldValue)) {
+ attrValue.setBooleanValue((Boolean) fieldValue);
+ } else if (Double.TYPE.isInstance(fieldValue) || Float.TYPE.isInstance(fieldValue)) {
+ attrValue.setDoubleValue((Double) fieldValue);
+ } else if (Long.TYPE.isInstance(fieldValue) || Integer.TYPE.isInstance(fieldValue)) {
+ attrValue.setLongValue((Long) fieldValue);
+ } else {
+ attrValue.setStringValue(fieldValue.toString());
+ }
+ values.add(attrValue);
+ } catch (Exception e) {
+ LOG.error("Could not read value of '{}' from {}", intAttrName.getField(), reference, e);
+ }
+ }
+ } else if (intAttrName.getSchemaType() != null) {
+ switch (intAttrName.getSchemaType()) {
+ case PLAIN:
+ PlainAttr<?> attr;
+ if (membership == null) {
+ attr = reference.getPlainAttr(intAttrName.getSchemaName());
} else {
- attrValue.setStringValue(fieldValue.toString());
+ attr = ((GroupableRelatable<?, ?, ?, ?, ?>) reference).getPlainAttr(
+ intAttrName.getSchemaName(), membership);
}
- values.add(attrValue);
- } catch (Exception e) {
- LOG.error("Could not read value of '{}' from {}", intAttrName.getField(), reference, e);
- }
- }
- } else if (intAttrName.getSchemaType() != null) {
- switch (intAttrName.getSchemaType()) {
- case PLAIN:
- PlainAttr<?> attr;
- if (membership == null) {
- attr = reference.getPlainAttr(intAttrName.getSchemaName());
- } else {
- attr = ((GroupableRelatable<?, ?, ?, ?, ?>) reference).getPlainAttr(
- intAttrName.getSchemaName(), membership);
- }
- if (attr != null) {
- if (attr.getUniqueValue() != null) {
- values.add(anyUtils.clonePlainAttrValue(attr.getUniqueValue()));
- } else if (attr.getValues() != null) {
- for (PlainAttrValue value : attr.getValues()) {
- values.add(anyUtils.clonePlainAttrValue(value));
+ if (attr != null) {
+ if (attr.getUniqueValue() != null) {
+ values.add(anyUtils.clonePlainAttrValue(attr.getUniqueValue()));
+ } else if (attr.getValues() != null) {
+ for (PlainAttrValue value : attr.getValues()) {
+ values.add(anyUtils.clonePlainAttrValue(value));
+ }
}
}
- }
- break;
-
- case DERIVED:
- DerSchema derSchema = derSchemaDAO.find(intAttrName.getSchemaName());
- if (derSchema != null) {
- String value = membership == null
- ? derAttrHandler.getValue(reference, derSchema)
- : derAttrHandler.getValue(reference, membership, derSchema);
- if (value != null) {
- PlainAttrValue attrValue = anyUtils.newPlainAttrValue();
- attrValue.setStringValue(value);
- values.add(attrValue);
+ break;
+
+ case DERIVED:
+ DerSchema derSchema = derSchemaDAO.find(intAttrName.getSchemaName());
+ if (derSchema != null) {
+ String value = membership == null
+ ? derAttrHandler.getValue(reference, derSchema)
+ : derAttrHandler.getValue(reference, membership, derSchema);
+ if (value != null) {
+ PlainAttrValue attrValue = anyUtils.newPlainAttrValue();
+ attrValue.setStringValue(value);
+ values.add(attrValue);
+ }
}
- }
- break;
-
- case VIRTUAL:
- // virtual attributes don't get transformed
- transform = false;
-
- VirSchema virSchema = virSchemaDAO.find(intAttrName.getSchemaName());
- if (virSchema != null) {
- LOG.debug("Expire entry cache {}-{}", reference, intAttrName.getSchemaName());
- virAttrCache.expire(
- reference.getType().getKey(), reference.getKey(), intAttrName.getSchemaName());
-
- List<String> virValues = membership == null
- ? virAttrHandler.getValues(reference, virSchema)
- : virAttrHandler.getValues(reference, membership, virSchema);
- for (String value : virValues) {
- PlainAttrValue attrValue = anyUtils.newPlainAttrValue();
- attrValue.setStringValue(value);
- values.add(attrValue);
+ break;
+
+ case VIRTUAL:
+ // virtual attributes don't get transformed
+ transform = false;
+
+ VirSchema virSchema = virSchemaDAO.find(intAttrName.getSchemaName());
+ if (virSchema != null) {
+ LOG.debug("Expire entry cache {}-{}", reference, intAttrName.getSchemaName());
+ virAttrCache.expire(
+ reference.getType().getKey(), reference.getKey(), intAttrName.getSchemaName());
+
+ List<String> virValues = membership == null
+ ? virAttrHandler.getValues(reference, virSchema)
+ : virAttrHandler.getValues(reference, membership, virSchema);
+ for (String value : virValues) {
+ PlainAttrValue attrValue = anyUtils.newPlainAttrValue();
+ attrValue.setStringValue(value);
+ values.add(attrValue);
+ }
}
- }
- break;
+ break;
- default:
+ default:
+ }
}
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/02b6d4eb/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java
index d4c4a76..294dbc1 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java
@@ -480,6 +480,21 @@ public class ResourceDataBinderImpl implements ResourceDataBinder {
"No need to map virtual schema on linking resource");
}
}
+ if (intAttrName.getRelatedUser() != null
+ && item.getPurpose() != MappingPurpose.PROPAGATION) {
+
+ invalidMapping.getElements().add(
+ "Only " + MappingPurpose.PROPAGATION.name()
+ + " allowed when referring to users");
+ }
+ if ((intAttrName.getRelationshipType() != null
+ || intAttrName.getRelationshipAnyType() != null)
+ && item.getPurpose() != MappingPurpose.PROPAGATION) {
+
+ invalidMapping.getElements().add(
+ "Only " + MappingPurpose.PROPAGATION.name()
+ + " allowed when referring to relationships");
+ }
} else {
LOG.error("'{}' not allowed", itemTO.getIntAttrName());
invalidMapping.getElements().add("'" + itemTO.getIntAttrName() + "' not allowed");
http://git-wip-us.apache.org/repos/asf/syncope/blob/02b6d4eb/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/IntAttrNameParserTest.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/IntAttrNameParserTest.java b/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/IntAttrNameParserTest.java
index adf2871..334a162 100644
--- a/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/IntAttrNameParserTest.java
+++ b/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/IntAttrNameParserTest.java
@@ -49,6 +49,9 @@ public class IntAttrNameParserTest extends AbstractTest {
assertNull(intAttrName.getEnclosingGroup());
assertNull(intAttrName.getMembershipOfGroup());
assertNull(intAttrName.getRelatedAnyObject());
+ assertNull(intAttrName.getRelationshipAnyType());
+ assertNull(intAttrName.getRelationshipType());
+ assertNull(intAttrName.getRelatedUser());
intAttrName = intAttrNameParser.parse("name", AnyTypeKind.GROUP);
assertNotNull(intAttrName);
@@ -60,6 +63,9 @@ public class IntAttrNameParserTest extends AbstractTest {
assertNull(intAttrName.getEnclosingGroup());
assertNull(intAttrName.getMembershipOfGroup());
assertNull(intAttrName.getRelatedAnyObject());
+ assertNull(intAttrName.getRelationshipAnyType());
+ assertNull(intAttrName.getRelationshipType());
+ assertNull(intAttrName.getRelatedUser());
intAttrName = intAttrNameParser.parse("userOwner", AnyTypeKind.GROUP);
assertNotNull(intAttrName);
@@ -71,6 +77,9 @@ public class IntAttrNameParserTest extends AbstractTest {
assertNull(intAttrName.getEnclosingGroup());
assertNull(intAttrName.getMembershipOfGroup());
assertNull(intAttrName.getRelatedAnyObject());
+ assertNull(intAttrName.getRelationshipAnyType());
+ assertNull(intAttrName.getRelationshipType());
+ assertNull(intAttrName.getRelatedUser());
intAttrName = intAttrNameParser.parse("name", AnyTypeKind.USER);
assertNotNull(intAttrName);
@@ -89,6 +98,9 @@ public class IntAttrNameParserTest extends AbstractTest {
assertNull(intAttrName.getEnclosingGroup());
assertNull(intAttrName.getMembershipOfGroup());
assertNull(intAttrName.getRelatedAnyObject());
+ assertNull(intAttrName.getRelationshipAnyType());
+ assertNull(intAttrName.getRelationshipType());
+ assertNull(intAttrName.getRelatedUser());
intAttrName = intAttrNameParser.parse("cn", AnyTypeKind.ANY_OBJECT);
assertNotNull(intAttrName);
@@ -99,6 +111,9 @@ public class IntAttrNameParserTest extends AbstractTest {
assertNull(intAttrName.getEnclosingGroup());
assertNull(intAttrName.getMembershipOfGroup());
assertNull(intAttrName.getRelatedAnyObject());
+ assertNull(intAttrName.getRelationshipAnyType());
+ assertNull(intAttrName.getRelationshipType());
+ assertNull(intAttrName.getRelatedUser());
intAttrName = intAttrNameParser.parse("rvirtualdata", AnyTypeKind.ANY_OBJECT);
assertNotNull(intAttrName);
@@ -109,6 +124,9 @@ public class IntAttrNameParserTest extends AbstractTest {
assertNull(intAttrName.getEnclosingGroup());
assertNull(intAttrName.getMembershipOfGroup());
assertNull(intAttrName.getRelatedAnyObject());
+ assertNull(intAttrName.getRelationshipAnyType());
+ assertNull(intAttrName.getRelationshipType());
+ assertNull(intAttrName.getRelatedUser());
}
@Test
@@ -122,6 +140,25 @@ public class IntAttrNameParserTest extends AbstractTest {
assertEquals("readers", intAttrName.getEnclosingGroup());
assertNull(intAttrName.getMembershipOfGroup());
assertNull(intAttrName.getRelatedAnyObject());
+ assertNull(intAttrName.getRelationshipAnyType());
+ assertNull(intAttrName.getRelationshipType());
+ assertNull(intAttrName.getRelatedUser());
+ }
+
+ @Test
+ public void relatedUser() throws ParseException {
+ IntAttrName intAttrName = intAttrNameParser.parse("users[bellini].firstname", AnyTypeKind.USER);
+ assertNotNull(intAttrName);
+ assertEquals(AnyTypeKind.USER, intAttrName.getAnyTypeKind());
+ assertNull(intAttrName.getField());
+ assertEquals("firstname", intAttrName.getSchemaName());
+ assertEquals(SchemaType.PLAIN, intAttrName.getSchemaType());
+ assertEquals("bellini", intAttrName.getRelatedUser());
+ assertNull(intAttrName.getEnclosingGroup());
+ assertNull(intAttrName.getMembershipOfGroup());
+ assertNull(intAttrName.getRelatedAnyObject());
+ assertNull(intAttrName.getRelationshipAnyType());
+ assertNull(intAttrName.getRelationshipType());
}
@Test
@@ -135,6 +172,9 @@ public class IntAttrNameParserTest extends AbstractTest {
assertNull(intAttrName.getEnclosingGroup());
assertEquals("hp", intAttrName.getRelatedAnyObject());
assertNull(intAttrName.getMembershipOfGroup());
+ assertNull(intAttrName.getRelationshipAnyType());
+ assertNull(intAttrName.getRelationshipType());
+ assertNull(intAttrName.getRelatedUser());
}
@Test
@@ -148,6 +188,25 @@ public class IntAttrNameParserTest extends AbstractTest {
assertNull(intAttrName.getEnclosingGroup());
assertEquals("top", intAttrName.getMembershipOfGroup());
assertNull(intAttrName.getRelatedAnyObject());
+ assertNull(intAttrName.getRelationshipAnyType());
+ assertNull(intAttrName.getRelationshipType());
+ assertNull(intAttrName.getRelatedUser());
+ }
+
+ @Test
+ public void relationship() throws ParseException {
+ IntAttrName intAttrName = intAttrNameParser.parse("relationships[inclusion][PRINTER].location",
+ AnyTypeKind.USER);
+ assertNotNull(intAttrName);
+ assertEquals(AnyTypeKind.ANY_OBJECT, intAttrName.getAnyTypeKind());
+ assertNull(intAttrName.getField());
+ assertEquals("location", intAttrName.getSchemaName());
+ assertEquals(SchemaType.PLAIN, intAttrName.getSchemaType());
+ assertEquals("inclusion", intAttrName.getRelationshipType());
+ assertEquals("PRINTER", intAttrName.getRelationshipAnyType());
+ assertNull(intAttrName.getEnclosingGroup());
+ assertNull(intAttrName.getRelatedAnyObject());
+ assertNull(intAttrName.getRelatedUser());
}
@Test
http://git-wip-us.apache.org/repos/asf/syncope/blob/02b6d4eb/src/main/asciidoc/reference-guide/concepts/externalresources.adoc
----------------------------------------------------------------------
diff --git a/src/main/asciidoc/reference-guide/concepts/externalresources.adoc b/src/main/asciidoc/reference-guide/concepts/externalresources.adoc
index d886191..b22eb9a 100644
--- a/src/main/asciidoc/reference-guide/concepts/externalresources.adoc
+++ b/src/main/asciidoc/reference-guide/concepts/externalresources.adoc
@@ -122,8 +122,12 @@ specified by an expression matching one of the following models:
** `schema` - resolves to the attribute for the given `schema`, owned by the mapped entity (user, group, any object)
** `groups[groupName].schema` - resolves to the attribute for the given `schema`, owned by the group with name
`groupName`, if a membership for the mapped entity exists
+** `users[userName].schema` - resolves to the attribute for the given `schema`, owned by the user with name
+`userName`, if a relationship with the mapped entity exists
** `anyObjects[anyObjectName].schema` - resolves to the attribute for the given `schema`, owned by the any object with
name `anyObjectName`, if a relationship with the mapped entity exists
+** `relationships[relationshipType][relationshipAnyType].schema` - resolves to the attribute for the given `schema`,
+owned by the any object of type `relationshipAnyType`, if a relationship with the mapped entity and type `relationshipType` exists
** `memberships[groupName].schema` - resolves to the attribute for the given `schema`, owned by the membership for group
`groupName` of the mapped entity (user, any object), if such a membership exists
* external attribute - the name of the attribute on the Identity Store