You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by il...@apache.org on 2019/09/27 13:33:49 UTC
[syncope] branch 2_1_X updated: [SYNCOPE-957] More tests for linked
accounts
This is an automated email from the ASF dual-hosted git repository.
ilgrosso pushed a commit to branch 2_1_X
in repository https://gitbox.apache.org/repos/asf/syncope.git
The following commit(s) were added to refs/heads/2_1_X by this push:
new e06afa6 [SYNCOPE-957] More tests for linked accounts
e06afa6 is described below
commit e06afa66657bf19b7b855ff1d6ea75cd5bd8dfaf
Author: Francesco Chicchiriccò <il...@apache.org>
AuthorDate: Fri Sep 27 14:43:26 2019 +0200
[SYNCOPE-957] More tests for linked accounts
---
.../jpa/dao/DefaultPushCorrelationRule.java | 8 +-
.../jpa/entity/user/JPALinkedAccount.java | 2 +-
.../core/provisioning/api/MappingManager.java | 10 +-
.../core/provisioning/java/MappingManagerImpl.java | 25 ++-
.../core/provisioning/java/VirAttrHandlerImpl.java | 1 -
.../java/data/AbstractAnyDataBinder.java | 1 -
.../provisioning/java/data/UserDataBinderImpl.java | 4 +-
.../java/propagation/DeletingLinkedAccount.java | 187 +++++++++++++++++++++
.../java/propagation/PropagationManagerImpl.java | 119 +++++++------
.../core/spring/security/EncryptorTest.java | 1 -
.../syncope/fit/core/LinkedAccountITCase.java | 110 +++++++++++-
11 files changed, 385 insertions(+), 83 deletions(-)
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/DefaultPushCorrelationRule.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/DefaultPushCorrelationRule.java
index 78cad78..129258e 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/DefaultPushCorrelationRule.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/DefaultPushCorrelationRule.java
@@ -62,7 +62,13 @@ public class DefaultPushCorrelationRule implements PushCorrelationRule {
item -> item.getPurpose() == MappingPurpose.PROPAGATION || item.getPurpose() == MappingPurpose.BOTH).
forEach(item -> {
Pair<String, Attribute> attr = mappingManager.prepareAttr(
- provision, item, any, null, AccountGetter.DEFAULT, PlainAttrGetter.DEFAULT);
+ provision,
+ item,
+ any,
+ null,
+ AccountGetter.DEFAULT,
+ AccountGetter.DEFAULT,
+ PlainAttrGetter.DEFAULT);
if (attr != null && attr.getRight() != null && conf.getSchemas().contains(item.getIntAttrName())) {
filters.add(provision.isIgnoreCaseMatch()
? FilterBuilder.equalsIgnoreCase(attr.getRight())
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPALinkedAccount.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPALinkedAccount.java
index 9175c73..c24a85c 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPALinkedAccount.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPALinkedAccount.java
@@ -186,7 +186,7 @@ public class JPALinkedAccount extends AbstractGeneratedKeyEntity implements Link
@Override
public boolean remove(final LAPlainAttr attr) {
checkType(attr, JPALAPlainAttr.class);
- return getPlainAttrs().remove((JPALAPlainAttr) attr);
+ return plainAttrs.remove((JPALAPlainAttr) attr);
}
@Override
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/MappingManager.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/MappingManager.java
index e5660f7..e970512 100644
--- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/MappingManager.java
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/MappingManager.java
@@ -63,7 +63,7 @@ public interface MappingManager {
* @param intAttrName int attr name
* @param schemaType schema type
* @param any any object
- * @param accountGetter function to get actual account instance
+ * @param usernameAccountGetter function to get actual account instance for username
* @param plainAttrGetter function to get PlainAttr instances
* @return attribute values and their type
*/
@@ -73,7 +73,7 @@ public interface MappingManager {
IntAttrName intAttrName,
AttrSchemaType schemaType,
Any<?> any,
- AccountGetter accountGetter,
+ AccountGetter usernameAccountGetter,
PlainAttrGetter plainAttrGetter);
/**
@@ -83,7 +83,8 @@ public interface MappingManager {
* @param item mapping item
* @param any given any object
* @param password clear-text password
- * @param accountGetter function to get actual account instance
+ * @param usernameAccountGetter function to get actual account instance for username
+ * @param passwordAccountGetter function to get actual account instance for password
* @param plainAttrGetter function to get PlainAttr instances
* @return connObjectLink (if it is the case) + prepared attribute
*/
@@ -91,7 +92,8 @@ public interface MappingManager {
Provision provision,
Item item, Any<?> any,
String password,
- AccountGetter accountGetter,
+ AccountGetter usernameAccountGetter,
+ AccountGetter passwordAccountGetter,
PlainAttrGetter plainAttrGetter);
/**
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 950b8f0..ae90118 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
@@ -208,6 +208,7 @@ public class MappingManagerImpl implements MappingManager {
any,
password,
AccountGetter.DEFAULT,
+ AccountGetter.DEFAULT,
PlainAttrGetter.DEFAULT),
attributes);
if (processedConnObjectKey != null) {
@@ -270,9 +271,8 @@ public class MappingManagerImpl implements MappingManager {
mapItem,
user,
password,
- acct -> account.getUsername() == null
- ? AccountGetter.DEFAULT.apply(acct)
- : account,
+ acct -> account.getUsername() == null ? AccountGetter.DEFAULT.apply(acct) : account,
+ acct -> account.getPassword() == null ? AccountGetter.DEFAULT.apply(acct) : account,
(attributable, schema) -> {
PlainAttr<?> result = null;
if (attributable instanceof User) {
@@ -309,12 +309,6 @@ public class MappingManagerImpl implements MappingManager {
if (account.isSuspended() != null) {
attributes.add(AttributeBuilder.buildEnabled(!BooleanUtils.negate(account.isSuspended())));
}
- if (!changePwd) {
- Attribute pwdAttr = AttributeUtil.find(OperationalAttributes.PASSWORD_NAME, attributes);
- if (pwdAttr != null) {
- attributes.remove(pwdAttr);
- }
- }
return attributes;
}
@@ -416,7 +410,8 @@ public class MappingManagerImpl implements MappingManager {
final Item item,
final Any<?> any,
final String password,
- final AccountGetter accountGetter,
+ final AccountGetter usernameAccountGetter,
+ final AccountGetter passwordAccountGetter,
final PlainAttrGetter plainAttrGetter) {
IntAttrName intAttrName;
@@ -435,7 +430,7 @@ public class MappingManagerImpl implements MappingManager {
: false;
Pair<AttrSchemaType, List<PlainAttrValue>> intValues =
- getIntValues(provision, item, intAttrName, schemaType, any, accountGetter, plainAttrGetter);
+ getIntValues(provision, item, intAttrName, schemaType, any, usernameAccountGetter, plainAttrGetter);
schemaType = intValues.getLeft();
List<PlainAttrValue> values = intValues.getRight();
@@ -473,7 +468,8 @@ public class MappingManagerImpl implements MappingManager {
if (item.isConnObjectKey()) {
result = Pair.of(objValues.isEmpty() ? null : objValues.iterator().next().toString(), null);
} else if (item.isPassword() && any instanceof User) {
- String passwordAttrValue = getPasswordAttrValue(provision, accountGetter.apply((User) any), password);
+ String passwordAttrValue =
+ getPasswordAttrValue(provision, passwordAccountGetter.apply((User) any), password);
if (passwordAttrValue == null) {
result = null;
} else {
@@ -498,7 +494,7 @@ public class MappingManagerImpl implements MappingManager {
final IntAttrName intAttrName,
final AttrSchemaType schemaType,
final Any<?> any,
- final AccountGetter accountGetter,
+ final AccountGetter usernameAccountGetter,
final PlainAttrGetter plainAttrGetter) {
LOG.debug("Get internal values for {} as '{}' on {}", any, mapItem.getIntAttrName(), provision.getResource());
@@ -581,7 +577,7 @@ public class MappingManagerImpl implements MappingManager {
case "username":
if (ref instanceof Account) {
- attrValue.setStringValue(accountGetter.apply((Account) ref).getUsername());
+ attrValue.setStringValue(usernameAccountGetter.apply((Account) ref).getUsername());
values.add(attrValue);
}
break;
@@ -757,6 +753,7 @@ public class MappingManagerImpl implements MappingManager {
any,
null,
AccountGetter.DEFAULT,
+ AccountGetter.DEFAULT,
PlainAttrGetter.DEFAULT);
}
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/VirAttrHandlerImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/VirAttrHandlerImpl.java
index 2af9933..6bc8db3 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/VirAttrHandlerImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/VirAttrHandlerImpl.java
@@ -186,5 +186,4 @@ public class VirAttrHandlerImpl implements VirAttrHandler {
anyUtilsFactory.getInstance(any).dao().findAllowedSchemas(any, VirSchema.class).
getForMembership(membership.getRightEnd()));
}
-
}
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java
index 4d957c6..7560a5a 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java
@@ -423,7 +423,6 @@ abstract class AbstractAnyDataBinder {
((PlainAttr) attr).setOwner(any);
attr.setSchema(schema);
any.add(attr);
-
}
}
if (attr != null) {
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java
index a55b48a..6342a80 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java
@@ -581,7 +581,7 @@ public class UserDataBinderImpl extends AbstractAnyDataBinder implements UserDat
user.getLinkedAccounts().remove(account);
account.setOwner(null);
- account.getPlainAttrs().forEach(attr -> {
+ account.getPlainAttrs().stream().collect(Collectors.toSet()).forEach(attr -> {
account.remove(attr);
attr.setOwner(null);
attr.setAccount(null);
@@ -608,7 +608,7 @@ public class UserDataBinderImpl extends AbstractAnyDataBinder implements UserDat
ResourceOperation.CREATE,
Pair.of(account.getResource().getKey(), account.getConnObjectName()));
});
-
+
// finalize resource management
reasons.entrySet().stream().
filter(entry -> entry.getValue().isEmpty()).
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/DeletingLinkedAccount.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/DeletingLinkedAccount.java
new file mode 100644
index 0000000..331aa84
--- /dev/null
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/DeletingLinkedAccount.java
@@ -0,0 +1,187 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.provisioning.java.propagation;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+import org.apache.commons.lang3.builder.EqualsBuilder;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+import org.apache.syncope.common.lib.types.CipherAlgorithm;
+import org.apache.syncope.core.persistence.api.entity.Privilege;
+import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
+import org.apache.syncope.core.persistence.api.entity.user.LAPlainAttr;
+import org.apache.syncope.core.persistence.api.entity.user.LinkedAccount;
+import org.apache.syncope.core.persistence.api.entity.user.User;
+
+public class DeletingLinkedAccount implements LinkedAccount {
+
+ private static final long serialVersionUID = -6828106363047119713L;
+
+ private final User user;
+
+ private final ExternalResource resource;
+
+ private final String connObjectName;
+
+ public DeletingLinkedAccount(final User user, final ExternalResource resource, final String connObjectName) {
+ this.user = user;
+ this.resource = resource;
+ this.connObjectName = connObjectName;
+ }
+
+ @Override
+ public String getKey() {
+ return null;
+ }
+
+ @Override
+ public String getConnObjectName() {
+ return connObjectName;
+ }
+
+ @Override
+ public void setConnObjectName(final String connObjectName) {
+ // unsupported
+ }
+
+ @Override
+ public User getOwner() {
+ return user;
+ }
+
+ @Override
+ public void setOwner(final User owner) {
+ // unsupported
+ }
+
+ @Override
+ public ExternalResource getResource() {
+ return resource;
+ }
+
+ @Override
+ public void setResource(final ExternalResource resource) {
+ // unsupported
+ }
+
+ @Override
+ public boolean add(final Privilege privilege) {
+ return false;
+ }
+
+ @Override
+ public Set<? extends Privilege> getPrivileges() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public String getUsername() {
+ return null;
+ }
+
+ @Override
+ public void setUsername(final String username) {
+ // unsupported
+ }
+
+ @Override
+ public CipherAlgorithm getCipherAlgorithm() {
+ return null;
+ }
+
+ @Override
+ public boolean canDecodePassword() {
+ return false;
+ }
+
+ @Override
+ public String getPassword() {
+ return null;
+ }
+
+ @Override
+ public void setEncodedPassword(final String password, final CipherAlgorithm cipherAlgoritm) {
+ // unsupported
+ }
+
+ @Override
+ public void setPassword(final String password, final CipherAlgorithm cipherAlgoritm) {
+ // unsupported
+ }
+
+ @Override
+ public Boolean isSuspended() {
+ return null;
+ }
+
+ @Override
+ public void setSuspended(final Boolean suspended) {
+ //
+ }
+
+ @Override
+ public boolean add(final LAPlainAttr attr) {
+ return false;
+ }
+
+ @Override
+ public boolean remove(final LAPlainAttr attr) {
+ return false;
+ }
+
+ @Override
+ public Optional<? extends LAPlainAttr> getPlainAttr(final String plainSchema) {
+ return Optional.empty();
+ }
+
+ @Override
+ public List<? extends LAPlainAttr> getPlainAttrs() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public int hashCode() {
+ return new HashCodeBuilder().
+ append(user.getKey()).
+ append(resource).
+ append(connObjectName).
+ build();
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final DeletingLinkedAccount other = (DeletingLinkedAccount) obj;
+ return new EqualsBuilder().
+ append(user.getKey(), other.user.getKey()).
+ append(resource, other.resource).
+ append(connObjectName, other.connObjectName).
+ build();
+ }
+}
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/PropagationManagerImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/PropagationManagerImpl.java
index 4b23adf..f519640 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/PropagationManagerImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/PropagationManagerImpl.java
@@ -53,6 +53,7 @@ import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
import org.apache.syncope.core.persistence.api.entity.resource.Item;
import org.apache.syncope.core.persistence.api.entity.resource.OrgUnit;
import org.apache.syncope.core.persistence.api.entity.resource.Provision;
+import org.apache.syncope.core.persistence.api.entity.user.LinkedAccount;
import org.apache.syncope.core.persistence.api.entity.user.User;
import org.apache.syncope.core.provisioning.api.MappingManager;
import org.apache.syncope.core.provisioning.api.UserWorkflowResult;
@@ -66,6 +67,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
/**
* Manage the data propagation to external resources.
@@ -223,20 +225,20 @@ public class PropagationManagerImpl implements PropagationManager {
return getUpdateTasks(
userDAO.authFind(wfResult.getResult().getLeft().getKey()),
- wfResult.getResult().getKey().getPassword() == null
+ wfResult.getResult().getLeft().getPassword() == null
? null
- : wfResult.getResult().getKey().getPassword().getValue(),
+ : wfResult.getResult().getLeft().getPassword().getValue(),
changePwd,
- wfResult.getResult().getValue(),
+ wfResult.getResult().getRight(),
wfResult.getPropByRes(),
wfResult.getPropByLinkedAccount(),
- wfResult.getResult().getKey().getVirAttrs(),
+ wfResult.getResult().getLeft().getVirAttrs(),
noPropResourceKeys);
}
@Override
public List<PropagationTaskInfo> getUserUpdateTasks(final UserWorkflowResult<Pair<UserPatch, Boolean>> wfResult) {
- UserPatch userPatch = wfResult.getResult().getKey();
+ UserPatch userPatch = wfResult.getResult().getLeft();
// Propagate password update only to requested resources
List<PropagationTaskInfo> tasks;
@@ -308,7 +310,7 @@ public class PropagationManagerImpl implements PropagationManager {
enable,
false,
propByRes == null ? new PropagationByResource<>() : propByRes,
- null,
+ propByLinkedAccount,
vAttrs);
}
@@ -329,11 +331,6 @@ public class PropagationManagerImpl implements PropagationManager {
final PropagationByResource<Pair<String, String>> propByLinkedAccount,
final Collection<String> noPropResourceKeys) {
- if (noPropResourceKeys != null) {
- propByLinkedAccount.get(ResourceOperation.DELETE).
- removeIf(account -> noPropResourceKeys.contains(account.getLeft()));
- }
-
return getDeleteTasks(userDAO.authFind(key), propByRes, propByLinkedAccount, noPropResourceKeys);
}
@@ -378,32 +375,32 @@ public class PropagationManagerImpl implements PropagationManager {
task.setEntityKey(any.getKey());
}
task.setOperation(operation);
- task.setConnObjectKey(preparedAttrs.getKey());
+ task.setConnObjectKey(preparedAttrs.getLeft());
// Check if any of mandatory attributes (in the mapping) is missing or not received any value:
// if so, add special attributes that will be evaluated by PropagationTaskExecutor
List<String> mandatoryMissing = new ArrayList<>();
List<String> mandatoryNullOrEmpty = new ArrayList<>();
mappingItems.stream().filter(item -> (!item.isConnObjectKey()
- && JexlUtils.evaluateMandatoryCondition(item.getMandatoryCondition(), any))).
- forEach(item -> {
- Attribute attr = AttributeUtil.find(item.getExtAttrName(), preparedAttrs.getValue());
- if (attr == null) {
- mandatoryMissing.add(item.getExtAttrName());
- } else if (attr.getValue() == null || attr.getValue().isEmpty()) {
- mandatoryNullOrEmpty.add(item.getExtAttrName());
- }
- });
+ && JexlUtils.evaluateMandatoryCondition(item.getMandatoryCondition(), any))).forEach(item -> {
+
+ Attribute attr = AttributeUtil.find(item.getExtAttrName(), preparedAttrs.getRight());
+ if (attr == null) {
+ mandatoryMissing.add(item.getExtAttrName());
+ } else if (CollectionUtils.isEmpty(attr.getValue())) {
+ mandatoryNullOrEmpty.add(item.getExtAttrName());
+ }
+ });
if (!mandatoryMissing.isEmpty()) {
- preparedAttrs.getValue().add(AttributeBuilder.build(
+ preparedAttrs.getRight().add(AttributeBuilder.build(
PropagationTaskExecutor.MANDATORY_MISSING_ATTR_NAME, mandatoryMissing));
}
if (!mandatoryNullOrEmpty.isEmpty()) {
- preparedAttrs.getValue().add(AttributeBuilder.build(
+ preparedAttrs.getRight().add(AttributeBuilder.build(
PropagationTaskExecutor.MANDATORY_NULL_OR_EMPTY_ATTR_NAME, mandatoryNullOrEmpty));
}
- task.setAttributes(POJOHelper.serialize(preparedAttrs.getValue()));
+ task.setAttributes(POJOHelper.serialize(preparedAttrs.getRight()));
return task;
}
@@ -494,7 +491,7 @@ public class PropagationManagerImpl implements PropagationManager {
Pair<String, Set<Attribute>> preparedAttrs =
mappingManager.prepareAttrs(any, password, changePwd, enable, provision);
if (vAttrMap.containsKey(resourceKey)) {
- preparedAttrs.getValue().addAll(vAttrMap.get(resourceKey));
+ preparedAttrs.getRight().addAll(vAttrMap.get(resourceKey));
}
PropagationTaskInfo task = newTask(
@@ -514,34 +511,46 @@ public class PropagationManagerImpl implements PropagationManager {
if (any instanceof User && propByLinkedAccount != null) {
User user = (User) any;
propByLinkedAccount.asMap().forEach((accountInfo, operation) -> {
- user.getLinkedAccount(accountInfo.getLeft(), accountInfo.getRight()).ifPresent(account -> {
- Provision provision = account.getResource().getProvision(AnyTypeKind.USER.name()).orElse(null);
- List<? extends Item> mappingItems = provision == null
- ? Collections.<Item>emptyList()
- : MappingUtils.getPropagationItems(provision.getMapping().getItems());
-
- if (provision == null) {
- LOG.error("No provision specified on resource {} for type {}, ignoring...",
- account.getResource(), AnyTypeKind.USER.name());
- } else if (mappingItems.isEmpty()) {
- LOG.warn("Requesting propagation for {} but no propagation mapping provided for {}",
- AnyTypeKind.USER.name(), account.getResource());
- } else {
- PropagationTaskInfo accountTask = newTask(
- user,
- account.getResource().getKey(),
- operation,
- provision,
- deleteOnResource,
- mappingItems,
- Pair.of(account.getConnObjectName(),
- mappingManager.prepareAttrs(user, account, password, changePwd, provision)));
- tasks.add(accountTask);
-
- LOG.debug("PropagationTask created for Linked Account {}: {}",
- account.getConnObjectName(), accountTask);
- }
- });
+ LinkedAccount account = user.getLinkedAccount(accountInfo.getLeft(), accountInfo.getRight()).
+ orElse(null);
+ if (account == null && operation == ResourceOperation.DELETE) {
+ account = new DeletingLinkedAccount(
+ user, resourceDAO.find(accountInfo.getLeft()), accountInfo.getRight());
+ }
+
+ Provision provision = account == null || account.getResource() == null
+ ? null
+ : account.getResource().getProvision(AnyTypeKind.USER.name()).orElse(null);
+ List<? extends Item> mappingItems = provision == null
+ ? Collections.<Item>emptyList()
+ : MappingUtils.getPropagationItems(provision.getMapping().getItems());
+
+ if (account == null) {
+ LOG.error("Invalid operation {} on deleted account {} on resource {}, ignoring...",
+ operation, accountInfo.getRight(), accountInfo.getLeft());
+ } else if (account.getResource() == null) {
+ LOG.error("Invalid resource name specified: {}, ignoring...", accountInfo.getLeft());
+ } else if (provision == null) {
+ LOG.error("No provision specified on resource {} for type {}, ignoring...",
+ account.getResource(), AnyTypeKind.USER.name());
+ } else if (mappingItems.isEmpty()) {
+ LOG.warn("Requesting propagation for {} but no propagation mapping provided for {}",
+ AnyTypeKind.USER.name(), account.getResource());
+ } else {
+ PropagationTaskInfo accountTask = newTask(
+ user,
+ account.getResource().getKey(),
+ operation,
+ provision,
+ deleteOnResource,
+ mappingItems,
+ Pair.of(account.getConnObjectName(),
+ mappingManager.prepareAttrs(user, account, password, changePwd, provision)));
+ tasks.add(accountTask);
+
+ LOG.debug("PropagationTask created for Linked Account {}: {}",
+ account.getConnObjectName(), accountTask);
+ }
});
}
@@ -586,8 +595,8 @@ public class PropagationManagerImpl implements PropagationManager {
task.setOldConnObjectKey(propByRes.getOldConnObjectKey(resource.getKey()));
Pair<String, Set<Attribute>> preparedAttrs = mappingManager.prepareAttrs(realm, orgUnit);
- task.setConnObjectKey(preparedAttrs.getKey());
- task.setAttributes(POJOHelper.serialize(preparedAttrs.getValue()));
+ task.setConnObjectKey(preparedAttrs.getLeft());
+ task.setAttributes(POJOHelper.serialize(preparedAttrs.getRight()));
tasks.add(task);
diff --git a/core/spring/src/test/java/org/apache/syncope/core/spring/security/EncryptorTest.java b/core/spring/src/test/java/org/apache/syncope/core/spring/security/EncryptorTest.java
index 4ec78b9..f7fb603 100644
--- a/core/spring/src/test/java/org/apache/syncope/core/spring/security/EncryptorTest.java
+++ b/core/spring/src/test/java/org/apache/syncope/core/spring/security/EncryptorTest.java
@@ -74,7 +74,6 @@ public class EncryptorTest {
@Test
public void testSaltedHash() throws Exception {
String encPassword = encryptor.encode(password, CipherAlgorithm.SSHA256);
- // System.out.println("ENC: " + encPassword);
assertNotNull(encPassword);
assertTrue(encryptor.verify(password, CipherAlgorithm.SSHA256, encPassword));
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/LinkedAccountITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/LinkedAccountITCase.java
index 8c6a7c4..57d86bc 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/LinkedAccountITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/LinkedAccountITCase.java
@@ -20,35 +20,139 @@ package org.apache.syncope.fit.core;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import java.util.Optional;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import javax.naming.ldap.LdapContext;
import org.apache.commons.lang3.RandomStringUtils;
+import org.apache.syncope.common.lib.patch.LinkedAccountPatch;
+import org.apache.syncope.common.lib.patch.UserPatch;
import org.apache.syncope.common.lib.to.LinkedAccountTO;
+import org.apache.syncope.common.lib.to.PagedResult;
+import org.apache.syncope.common.lib.to.PropagationTaskTO;
import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.ExecStatus;
+import org.apache.syncope.common.lib.types.PatchOperation;
+import org.apache.syncope.common.lib.types.ResourceOperation;
+import org.apache.syncope.common.lib.types.TaskType;
+import org.apache.syncope.common.rest.api.beans.TaskQuery;
import org.apache.syncope.fit.AbstractITCase;
import org.junit.jupiter.api.Test;
public class LinkedAccountITCase extends AbstractITCase {
@Test
- public void createWithLinkedAccount() throws NamingException {
+ public void createWithLinkedAccountThenRemove() throws NamingException {
+ // 1. create user with linked account
UserTO user = UserITCase.getSampleTO(
"linkedAccount" + RandomStringUtils.randomNumeric(5) + "@syncope.apache.org");
+ String connObjectName = "uid=" + user.getUsername() + ",ou=People,o=isp";
+ String privilege = applicationService.read("mightyApp").getPrivileges().get(0).getKey();
LinkedAccountTO account = new LinkedAccountTO.Builder().
- connObjectName("uid=" + user.getUsername() + ",ou=People,o=isp").
+ connObjectName(connObjectName).
resource(RESOURCE_NAME_LDAP).
build();
account.getPlainAttrs().add(attrTO("surname", "LINKED_SURNAME"));
+ account.getPrivileges().add(privilege);
user.getLinkedAccounts().add(account);
user = createUser(user).getEntity();
assertNotNull(user.getKey());
+ assertEquals(privilege, user.getLinkedAccounts().get(0).getPrivileges().iterator().next());
+
+ // 2. verify that propagation task was generated and that account is found on resource
+ PagedResult<PropagationTaskTO> tasks = taskService.search(
+ new TaskQuery.Builder(TaskType.PROPAGATION).resource(RESOURCE_NAME_LDAP).
+ anyTypeKind(AnyTypeKind.USER).entityKey(user.getKey()).build());
+ assertEquals(1, tasks.getTotalCount());
+ assertEquals(connObjectName, tasks.getResult().get(0).getConnObjectKey());
+ assertEquals(ResourceOperation.CREATE, tasks.getResult().get(0).getOperation());
+ assertEquals(ExecStatus.SUCCESS.name(), tasks.getResult().get(0).getLatestExecStatus());
+
+ LdapContext ldapObj = (LdapContext) getLdapRemoteObject(
+ RESOURCE_LDAP_ADMIN_DN, RESOURCE_LDAP_ADMIN_PWD, connObjectName);
+ assertNotNull(ldapObj);
+
+ Attributes ldapAttrs = ldapObj.getAttributes("");
+ assertEquals(
+ user.getPlainAttr("email").get().getValues().get(0),
+ ldapAttrs.get("mail").getAll().next().toString());
+ assertEquals("LINKED_SURNAME", ldapAttrs.get("sn").getAll().next().toString());
+
+ // 3. remove linked account from user
+ UserPatch userPatch = new UserPatch();
+ userPatch.setKey(user.getKey());
+ userPatch.getLinkedAccounts().add(new LinkedAccountPatch.Builder().
+ operation(PatchOperation.DELETE).
+ linkedAccountTO(user.getLinkedAccounts().get(0)).build());
+
+ user = updateUser(userPatch).getEntity();
+ assertTrue(user.getLinkedAccounts().isEmpty());
+
+ // 4. verify that propagation task was generated and that account is not any more on resource
+ tasks = taskService.search(
+ new TaskQuery.Builder(TaskType.PROPAGATION).resource(RESOURCE_NAME_LDAP).
+ anyTypeKind(AnyTypeKind.USER).entityKey(user.getKey()).build());
+ assertEquals(2, tasks.getTotalCount());
+
+ Optional<PropagationTaskTO> deletTask =
+ tasks.getResult().stream().filter(task -> task.getOperation() == ResourceOperation.DELETE).findFirst();
+ assertTrue(deletTask.isPresent());
+ assertEquals(connObjectName, deletTask.get().getConnObjectKey());
+ assertEquals(ExecStatus.SUCCESS.name(), deletTask.get().getLatestExecStatus());
+
+ assertNull(getLdapRemoteObject(RESOURCE_LDAP_ADMIN_DN, RESOURCE_LDAP_ADMIN_PWD, connObjectName));
+ }
+
+ @Test
+ public void createWithoutLinkedAccountThenAdd() throws NamingException {
+ // 1. create user without linked account
+ UserTO user = UserITCase.getSampleTO(
+ "linkedAccount" + RandomStringUtils.randomNumeric(5) + "@syncope.apache.org");
+ String connObjectName = "uid=" + user.getUsername() + ",ou=People,o=isp";
+
+ user = createUser(user).getEntity();
+ assertNotNull(user.getKey());
+ assertTrue(user.getLinkedAccounts().isEmpty());
+
+ PagedResult<PropagationTaskTO> tasks = taskService.search(
+ new TaskQuery.Builder(TaskType.PROPAGATION).resource(RESOURCE_NAME_LDAP).
+ anyTypeKind(AnyTypeKind.USER).entityKey(user.getKey()).build());
+ assertEquals(0, tasks.getTotalCount());
+
+ assertNull(getLdapRemoteObject(RESOURCE_LDAP_ADMIN_DN, RESOURCE_LDAP_ADMIN_PWD, connObjectName));
+
+ // 2. add linked account to user
+ UserPatch userPatch = new UserPatch();
+ userPatch.setKey(user.getKey());
+
+ LinkedAccountTO account = new LinkedAccountTO.Builder().
+ connObjectName(connObjectName).
+ resource(RESOURCE_NAME_LDAP).
+ build();
+ account.getPlainAttrs().add(attrTO("surname", "LINKED_SURNAME"));
+ account.setPassword("Password123");
+ userPatch.getLinkedAccounts().add(new LinkedAccountPatch.Builder().linkedAccountTO(account).build());
+
+ user = updateUser(userPatch).getEntity();
+ assertEquals(1, user.getLinkedAccounts().size());
+
+ // 3. verify that propagation task was generated and that account is found on resource
+ tasks = taskService.search(
+ new TaskQuery.Builder(TaskType.PROPAGATION).resource(RESOURCE_NAME_LDAP).
+ anyTypeKind(AnyTypeKind.USER).entityKey(user.getKey()).build());
+ assertEquals(1, tasks.getTotalCount());
+ assertEquals(connObjectName, tasks.getResult().get(0).getConnObjectKey());
+ assertEquals(ResourceOperation.CREATE, tasks.getResult().get(0).getOperation());
+ assertEquals(ExecStatus.SUCCESS.name(), tasks.getResult().get(0).getLatestExecStatus());
LdapContext ldapObj = (LdapContext) getLdapRemoteObject(
- RESOURCE_LDAP_ADMIN_DN, RESOURCE_LDAP_ADMIN_PWD, account.getConnObjectName());
+ RESOURCE_LDAP_ADMIN_DN, RESOURCE_LDAP_ADMIN_PWD, connObjectName);
assertNotNull(ldapObj);
Attributes ldapAttrs = ldapObj.getAttributes("");