You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by an...@apache.org on 2019/05/21 14:00:07 UTC
[syncope] branch 2_1_X updated: [SYNCOPE-1472] fixed multiple
entries creation in relationship tables through list checks and constraints
on many yo many relationships
This is an automated email from the ASF dual-hosted git repository.
andreapatricelli 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 5664ec9 [SYNCOPE-1472] fixed multiple entries creation in relationship tables through list checks and constraints on many yo many relationships
5664ec9 is described below
commit 5664ec94ccb233c6acc59748863dc09b386a2604
Author: Andrea Patricelli <an...@apache.org>
AuthorDate: Tue May 21 09:45:28 2019 +0200
[SYNCOPE-1472] fixed multiple entries creation in relationship tables through list checks and constraints on many yo many relationships
---
.../core/persistence/jpa/entity/JPAAnyType.java | 7 ++-
.../core/persistence/jpa/entity/JPARealm.java | 9 ++--
.../core/persistence/jpa/entity/JPAReport.java | 5 ++-
.../core/persistence/jpa/entity/JPARole.java | 17 +++++---
.../jpa/entity/anyobject/JPAAnyObject.java | 11 +++--
.../persistence/jpa/entity/group/JPAGroup.java | 11 +++--
.../jpa/entity/group/JPATypeExtension.java | 3 +-
.../jpa/entity/policy/JPAAccountPolicy.java | 9 +++-
.../jpa/entity/policy/JPAPasswordPolicy.java | 5 ++-
.../jpa/entity/resource/JPAExternalResource.java | 5 ++-
.../jpa/entity/resource/JPAMappingItem.java | 5 ++-
.../jpa/entity/resource/JPAOrgUnitItem.java | 5 ++-
.../jpa/entity/resource/JPAProvision.java | 4 +-
.../persistence/jpa/entity/task/JPAPullTask.java | 5 ++-
.../persistence/jpa/entity/task/JPAPushTask.java | 5 ++-
.../core/persistence/jpa/entity/user/JPAUser.java | 14 +++---
.../jpa/entity/JPAOIDCProviderItem.java | 8 +++-
.../persistence/jpa/entity/JPASAML2IdPItem.java | 8 +++-
.../apache/syncope/fit/core/AnyObjectITCase.java | 33 ++++++++++++++
.../org/apache/syncope/fit/core/AnyTypeITCase.java | 19 ++++++++
.../org/apache/syncope/fit/core/GroupITCase.java | 36 +++++++++++++++
.../org/apache/syncope/fit/core/RealmITCase.java | 19 ++++++++
.../org/apache/syncope/fit/core/RoleITCase.java | 28 ++++++++++++
.../apache/syncope/fit/core/UserIssuesITCase.java | 51 ++++++++++++++++++++++
24 files changed, 284 insertions(+), 38 deletions(-)
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAnyType.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAnyType.java
index d9025bc..1af918d 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAnyType.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAnyType.java
@@ -29,6 +29,7 @@ import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
import javax.validation.constraints.NotNull;
import org.apache.syncope.common.lib.types.AnyTypeKind;
import org.apache.syncope.core.persistence.api.entity.AnyType;
@@ -53,7 +54,9 @@ public class JPAAnyType extends AbstractProvidedKeyEntity implements AnyType {
@JoinTable(joinColumns =
@JoinColumn(name = "anyType_id", referencedColumnName = "id"),
inverseJoinColumns =
- @JoinColumn(name = "anyTypeClass_id", referencedColumnName = "id"))
+ @JoinColumn(name = "anyTypeClass_id", referencedColumnName = "id"),
+ uniqueConstraints =
+ @UniqueConstraint(columnNames = { "anyType_id", "anyTypeClass_id" }))
private List<JPAAnyTypeClass> classes = new ArrayList<>();
@Override
@@ -69,7 +72,7 @@ public class JPAAnyType extends AbstractProvidedKeyEntity implements AnyType {
@Override
public boolean add(final AnyTypeClass anyTypeClass) {
checkType(anyTypeClass, JPAAnyTypeClass.class);
- return this.classes.add((JPAAnyTypeClass) anyTypeClass);
+ return classes.contains((JPAAnyTypeClass) anyTypeClass) || this.classes.add((JPAAnyTypeClass) anyTypeClass);
}
@Override
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPARealm.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPARealm.java
index 49bb739..7e1a476 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPARealm.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPARealm.java
@@ -77,7 +77,9 @@ public class JPARealm extends AbstractGeneratedKeyEntity implements Realm {
joinColumns =
@JoinColumn(name = "realm_id"),
inverseJoinColumns =
- @JoinColumn(name = "implementation_id"))
+ @JoinColumn(name = "implementation_id"),
+ uniqueConstraints =
+ @UniqueConstraint(columnNames = { "realm_id", "implementation_id" }))
private List<JPAImplementation> actions = new ArrayList<>();
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "realm")
@@ -87,7 +89,8 @@ public class JPARealm extends AbstractGeneratedKeyEntity implements Realm {
@JoinTable(joinColumns =
@JoinColumn(name = "realm_id"),
inverseJoinColumns =
- @JoinColumn(name = "resource_id"))
+ @JoinColumn(name = "resource_id"),
+ uniqueConstraints = @UniqueConstraint(columnNames = { "realm_id", "resource_id" }))
private List<JPAExternalResource> resources = new ArrayList<>();
@Override
@@ -173,7 +176,7 @@ public class JPARealm extends AbstractGeneratedKeyEntity implements Realm {
@Override
public boolean add(final ExternalResource resource) {
checkType(resource, JPAExternalResource.class);
- return resources.add((JPAExternalResource) resource);
+ return resources.contains((JPAExternalResource) resource) || resources.add((JPAExternalResource) resource);
}
@Override
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAReport.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAReport.java
index bed6e36..df3317f 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAReport.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAReport.java
@@ -30,6 +30,7 @@ import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
import javax.validation.constraints.NotNull;
import org.apache.syncope.common.lib.types.ImplementationType;
import org.apache.syncope.core.persistence.api.entity.Implementation;
@@ -55,7 +56,9 @@ public class JPAReport extends AbstractGeneratedKeyEntity implements Report {
joinColumns =
@JoinColumn(name = "report_id"),
inverseJoinColumns =
- @JoinColumn(name = "implementation_id"))
+ @JoinColumn(name = "implementation_id"),
+ uniqueConstraints =
+ @UniqueConstraint(columnNames = { "report_id", "implementation_id" }))
private List<JPAImplementation> reportlets = new ArrayList<>();
private String cronExpression;
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPARole.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPARole.java
index 4dbddbf..2a0269a 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPARole.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPARole.java
@@ -36,6 +36,7 @@ import javax.persistence.Lob;
import javax.persistence.ManyToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
import javax.validation.Valid;
import org.apache.syncope.core.persistence.api.entity.Application;
import org.apache.syncope.core.persistence.api.entity.user.DynRoleMembership;
@@ -67,7 +68,9 @@ public class JPARole extends AbstractProvidedKeyEntity implements Role {
@JoinTable(joinColumns =
@JoinColumn(name = "role_id"),
inverseJoinColumns =
- @JoinColumn(name = "realm_id"))
+ @JoinColumn(name = "realm_id"),
+ uniqueConstraints =
+ @UniqueConstraint(columnNames = { "role_id", "realm_id" }))
@Valid
private List<JPARealm> realms = new ArrayList<>();
@@ -75,7 +78,9 @@ public class JPARole extends AbstractProvidedKeyEntity implements Role {
@JoinTable(joinColumns =
@JoinColumn(name = "role_id"),
inverseJoinColumns =
- @JoinColumn(name = "dynamicRealm_id"))
+ @JoinColumn(name = "dynamicRealm_id"),
+ uniqueConstraints =
+ @UniqueConstraint(columnNames = { "role_id", "dynamicRealm_id" }))
@Valid
private List<JPADynRealm> dynRealms = new ArrayList<>();
@@ -90,7 +95,9 @@ public class JPARole extends AbstractProvidedKeyEntity implements Role {
@JoinTable(joinColumns =
@JoinColumn(name = "role_id"),
inverseJoinColumns =
- @JoinColumn(name = "privilege_id"))
+ @JoinColumn(name = "privilege_id"),
+ uniqueConstraints =
+ @UniqueConstraint(columnNames = { "role_id", "privilege_id" }))
@Valid
private Set<JPAPrivilege> privileges = new HashSet<>();
@@ -102,7 +109,7 @@ public class JPARole extends AbstractProvidedKeyEntity implements Role {
@Override
public boolean add(final Realm realm) {
checkType(realm, JPARealm.class);
- return realms.add((JPARealm) realm);
+ return realms.contains((JPARealm) realm) || realms.add((JPARealm) realm);
}
@Override
@@ -113,7 +120,7 @@ public class JPARole extends AbstractProvidedKeyEntity implements Role {
@Override
public boolean add(final DynRealm dynamicRealm) {
checkType(dynamicRealm, JPADynRealm.class);
- return dynRealms.add((JPADynRealm) dynamicRealm);
+ return dynRealms.contains((JPADynRealm) dynamicRealm) || dynRealms.add((JPADynRealm) dynamicRealm);
}
@Override
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAnyObject.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAnyObject.java
index 0a04e01..91af63a 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAnyObject.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAnyObject.java
@@ -32,6 +32,7 @@ import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import org.apache.syncope.core.persistence.api.entity.AnyType;
@@ -75,14 +76,16 @@ public class JPAAnyObject
@JoinTable(joinColumns =
@JoinColumn(name = "anyObject_id"),
inverseJoinColumns =
- @JoinColumn(name = "resource_id"))
+ @JoinColumn(name = "resource_id"),
+ uniqueConstraints = @UniqueConstraint(columnNames = { "anyObject_id", "resource_id" }))
private List<JPAExternalResource> resources = new ArrayList<>();
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(joinColumns =
@JoinColumn(name = "anyObject_id"),
inverseJoinColumns =
- @JoinColumn(name = "anyTypeClass_id"))
+ @JoinColumn(name = "anyTypeClass_id"),
+ uniqueConstraints = @UniqueConstraint(columnNames = { "anyObject_id", "anyTypeClass_id" }))
private List<JPAAnyTypeClass> auxClasses = new ArrayList<>();
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "leftEnd")
@@ -117,7 +120,7 @@ public class JPAAnyObject
@Override
public boolean add(final ExternalResource resource) {
checkType(resource, JPAExternalResource.class);
- return resources.add((JPAExternalResource) resource);
+ return resources.contains((JPAExternalResource) resource) || resources.add((JPAExternalResource) resource);
}
@Override
@@ -139,7 +142,7 @@ public class JPAAnyObject
@Override
public boolean add(final AnyTypeClass auxClass) {
checkType(auxClass, JPAAnyTypeClass.class);
- return this.auxClasses.add((JPAAnyTypeClass) auxClass);
+ return auxClasses.contains((JPAAnyTypeClass) auxClass) || this.auxClasses.add((JPAAnyTypeClass) auxClass);
}
@Override
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGroup.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGroup.java
index 7c6724a..5f1da30 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGroup.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGroup.java
@@ -32,6 +32,7 @@ import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import org.apache.syncope.core.spring.ApplicationContextProvider;
@@ -79,14 +80,16 @@ public class JPAGroup extends AbstractAny<GPlainAttr> implements Group {
@JoinTable(joinColumns =
@JoinColumn(name = "group_id"),
inverseJoinColumns =
- @JoinColumn(name = "resource_id"))
+ @JoinColumn(name = "resource_id"),
+ uniqueConstraints = @UniqueConstraint(columnNames = { "group_id", "resource_id" }))
private List<JPAExternalResource> resources = new ArrayList<>();
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(joinColumns =
@JoinColumn(name = "group_id"),
inverseJoinColumns =
- @JoinColumn(name = "anyTypeClass_id"))
+ @JoinColumn(name = "anyTypeClass_id"),
+ uniqueConstraints = @UniqueConstraint(columnNames = { "group_id", "anyTypeClass_id" }))
private List<JPAAnyTypeClass> auxClasses = new ArrayList<>();
@OneToOne(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "group")
@@ -122,7 +125,7 @@ public class JPAGroup extends AbstractAny<GPlainAttr> implements Group {
@Override
public boolean add(final ExternalResource resource) {
checkType(resource, JPAExternalResource.class);
- return resources.add((JPAExternalResource) resource);
+ return resources.contains((JPAExternalResource) resource) || resources.add((JPAExternalResource) resource);
}
@Override
@@ -190,7 +193,7 @@ public class JPAGroup extends AbstractAny<GPlainAttr> implements Group {
@Override
public boolean add(final AnyTypeClass auxClass) {
checkType(auxClass, JPAAnyTypeClass.class);
- return this.auxClasses.add((JPAAnyTypeClass) auxClass);
+ return auxClasses.contains((JPAAnyTypeClass) auxClass) || this.auxClasses.add((JPAAnyTypeClass) auxClass);
}
@Override
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPATypeExtension.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPATypeExtension.java
index 648436e..207096a 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPATypeExtension.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPATypeExtension.java
@@ -54,7 +54,8 @@ public class JPATypeExtension extends AbstractGeneratedKeyEntity implements Type
@JoinTable(joinColumns =
@JoinColumn(name = "typeExtension_id"),
inverseJoinColumns =
- @JoinColumn(name = "anyTypeClass_id"))
+ @JoinColumn(name = "anyTypeClass_id"),
+ uniqueConstraints = @UniqueConstraint(columnNames = { "typeExtension_id", "anyTypeClass_id" }))
private List<JPAAnyTypeClass> auxClasses = new ArrayList<>();
@Override
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAAccountPolicy.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAAccountPolicy.java
index 24b1a2e..b3dd6a0 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAAccountPolicy.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAAccountPolicy.java
@@ -28,6 +28,7 @@ import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
import javax.validation.constraints.NotNull;
import org.apache.syncope.common.lib.types.ImplementationType;
import org.apache.syncope.core.persistence.api.entity.Implementation;
@@ -54,7 +55,9 @@ public class JPAAccountPolicy extends AbstractPolicy implements AccountPolicy {
joinColumns =
@JoinColumn(name = "policy_id"),
inverseJoinColumns =
- @JoinColumn(name = "implementation_id"))
+ @JoinColumn(name = "implementation_id"),
+ uniqueConstraints =
+ @UniqueConstraint(columnNames = { "policy_id", "implementation_id" }))
private List<JPAImplementation> rules = new ArrayList<>();
/**
@@ -64,7 +67,9 @@ public class JPAAccountPolicy extends AbstractPolicy implements AccountPolicy {
@JoinTable(joinColumns =
@JoinColumn(name = "accountPolicy_id"),
inverseJoinColumns =
- @JoinColumn(name = "resource_id"))
+ @JoinColumn(name = "resource_id"),
+ uniqueConstraints =
+ @UniqueConstraint(columnNames = { "accountPolicy_id", "resource_id" }))
private Set<JPAExternalResource> resources = new HashSet<>();
@Override
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPasswordPolicy.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPasswordPolicy.java
index c3de4e2..2e2ba98 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPasswordPolicy.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPasswordPolicy.java
@@ -26,6 +26,7 @@ import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
import javax.validation.constraints.NotNull;
import org.apache.syncope.common.lib.types.ImplementationType;
import org.apache.syncope.core.persistence.api.entity.Implementation;
@@ -50,7 +51,9 @@ public class JPAPasswordPolicy extends AbstractPolicy implements PasswordPolicy
joinColumns =
@JoinColumn(name = "policy_id"),
inverseJoinColumns =
- @JoinColumn(name = "implementation_id"))
+ @JoinColumn(name = "implementation_id"),
+ uniqueConstraints =
+ @UniqueConstraint(columnNames = { "policy_id", "implementation_id" }))
private List<JPAImplementation> rules = new ArrayList<>();
@Override
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAExternalResource.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAExternalResource.java
index b44035e..5af5c09 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAExternalResource.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAExternalResource.java
@@ -41,6 +41,7 @@ import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
import javax.validation.constraints.NotNull;
import org.apache.commons.lang3.StringUtils;
import org.apache.syncope.common.lib.types.ConnConfProperty;
@@ -159,7 +160,9 @@ public class JPAExternalResource extends AbstractProvidedKeyEntity implements Ex
joinColumns =
@JoinColumn(name = "resource_id"),
inverseJoinColumns =
- @JoinColumn(name = "implementation_id"))
+ @JoinColumn(name = "implementation_id"),
+ uniqueConstraints =
+ @UniqueConstraint(columnNames = { "resource_id", "implementation_id" }))
private List<JPAImplementation> propagationActions = new ArrayList<>();
@Override
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMappingItem.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMappingItem.java
index 1f55c8d..8cfa6b1 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMappingItem.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMappingItem.java
@@ -28,6 +28,7 @@ import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
import org.apache.syncope.common.lib.types.ImplementationType;
import org.apache.syncope.core.persistence.api.entity.Implementation;
import org.apache.syncope.core.persistence.api.entity.resource.Mapping;
@@ -51,7 +52,9 @@ public class JPAMappingItem extends AbstractItem implements MappingItem {
joinColumns =
@JoinColumn(name = "item_id"),
inverseJoinColumns =
- @JoinColumn(name = "implementation_id"))
+ @JoinColumn(name = "implementation_id"),
+ uniqueConstraints =
+ @UniqueConstraint(columnNames = { "item_id", "implementation_id" }))
private List<JPAImplementation> transformers = new ArrayList<>();
@Override
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAOrgUnitItem.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAOrgUnitItem.java
index 49b8cdd..9911d39 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAOrgUnitItem.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAOrgUnitItem.java
@@ -28,6 +28,7 @@ import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
import org.apache.syncope.common.lib.types.ImplementationType;
import org.apache.syncope.core.persistence.api.entity.Implementation;
import org.apache.syncope.core.persistence.api.entity.resource.OrgUnit;
@@ -51,7 +52,9 @@ public class JPAOrgUnitItem extends AbstractItem implements OrgUnitItem {
joinColumns =
@JoinColumn(name = "item_id"),
inverseJoinColumns =
- @JoinColumn(name = "implementation_id"))
+ @JoinColumn(name = "implementation_id"),
+ uniqueConstraints =
+ @UniqueConstraint(columnNames = { "item_id", "implementation_id" }))
private List<JPAImplementation> transformers = new ArrayList<>();
@Override
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAProvision.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAProvision.java
index df194b4..331e68b 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAProvision.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAProvision.java
@@ -69,7 +69,9 @@ public class JPAProvision extends AbstractGeneratedKeyEntity implements Provisio
@JoinTable(joinColumns =
@JoinColumn(name = "provision_id"),
inverseJoinColumns =
- @JoinColumn(name = "anyTypeClass_id"))
+ @JoinColumn(name = "anyTypeClass_id"),
+ uniqueConstraints =
+ @UniqueConstraint(columnNames = { "provision_id", "anyTypeClass_id" }))
private List<JPAAnyTypeClass> auxClasses = new ArrayList<>();
@Lob
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAPullTask.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAPullTask.java
index 3dc7ee6..fdc4221 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAPullTask.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAPullTask.java
@@ -33,6 +33,7 @@ import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
+import javax.persistence.UniqueConstraint;
import javax.validation.constraints.NotNull;
import org.apache.syncope.common.lib.types.ImplementationType;
import org.apache.syncope.common.lib.types.PullMode;
@@ -65,7 +66,9 @@ public class JPAPullTask extends AbstractProvisioningTask implements PullTask {
joinColumns =
@JoinColumn(name = "task_id"),
inverseJoinColumns =
- @JoinColumn(name = "implementation_id"))
+ @JoinColumn(name = "implementation_id"),
+ uniqueConstraints =
+ @UniqueConstraint(columnNames = { "task_id", "implementation_id" }))
private List<JPAImplementation> actions = new ArrayList<>();
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "pullTask")
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAPushTask.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAPushTask.java
index abadd8c..b899212 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAPushTask.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAPushTask.java
@@ -30,6 +30,7 @@ import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
+import javax.persistence.UniqueConstraint;
import org.apache.syncope.common.lib.types.ImplementationType;
import org.apache.syncope.core.persistence.api.entity.AnyType;
import org.apache.syncope.core.persistence.api.entity.Implementation;
@@ -53,7 +54,9 @@ public class JPAPushTask extends AbstractProvisioningTask implements PushTask {
joinColumns =
@JoinColumn(name = "task_id"),
inverseJoinColumns =
- @JoinColumn(name = "implementation_id"))
+ @JoinColumn(name = "implementation_id"),
+ uniqueConstraints =
+ @UniqueConstraint(columnNames = { "task_id", "implementation_id" }))
private List<JPAImplementation> actions = new ArrayList<>();
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "pushTask")
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUser.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUser.java
index 4d91360..f580e91 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUser.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUser.java
@@ -42,6 +42,7 @@ import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
+import javax.persistence.UniqueConstraint;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import org.apache.syncope.common.lib.types.CipherAlgorithm;
@@ -88,7 +89,8 @@ public class JPAUser
@JoinTable(joinColumns =
@JoinColumn(name = "user_id"),
inverseJoinColumns =
- @JoinColumn(name = "role_id"))
+ @JoinColumn(name = "role_id"),
+ uniqueConstraints = @UniqueConstraint(columnNames = { "user_id", "role_id" }))
private List<JPARole> roles = new ArrayList<>();
@OneToMany(cascade = CascadeType.ALL, mappedBy = "owner")
@@ -152,14 +154,16 @@ public class JPAUser
@JoinTable(joinColumns =
@JoinColumn(name = "user_id"),
inverseJoinColumns =
- @JoinColumn(name = "resource_id"))
+ @JoinColumn(name = "resource_id"),
+ uniqueConstraints = @UniqueConstraint(columnNames = { "user_id", "resource_id" }))
private List<JPAExternalResource> resources = new ArrayList<>();
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(joinColumns =
@JoinColumn(name = "user_id"),
inverseJoinColumns =
- @JoinColumn(name = "anyTypeClass_id"))
+ @JoinColumn(name = "anyTypeClass_id"),
+ uniqueConstraints = @UniqueConstraint(columnNames = { "user_id", "anyTypeClass_id" }))
private List<JPAAnyTypeClass> auxClasses = new ArrayList<>();
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "leftEnd")
@@ -189,7 +193,7 @@ public class JPAUser
@Override
public boolean add(final ExternalResource resource) {
checkType(resource, JPAExternalResource.class);
- return resources.add((JPAExternalResource) resource);
+ return resources.contains((JPAExternalResource) resource) || resources.add((JPAExternalResource) resource);
}
@Override
@@ -419,7 +423,7 @@ public class JPAUser
@Override
public boolean add(final AnyTypeClass auxClass) {
checkType(auxClass, JPAAnyTypeClass.class);
- return this.auxClasses.add((JPAAnyTypeClass) auxClass);
+ return auxClasses.contains((JPAAnyTypeClass) auxClass) || this.auxClasses.add((JPAAnyTypeClass) auxClass);
}
@Override
diff --git a/ext/oidcclient/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAOIDCProviderItem.java b/ext/oidcclient/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAOIDCProviderItem.java
index 69268cb..f4d2123 100644
--- a/ext/oidcclient/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAOIDCProviderItem.java
+++ b/ext/oidcclient/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAOIDCProviderItem.java
@@ -28,6 +28,7 @@ import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
import org.apache.syncope.common.lib.types.ImplementationType;
import org.apache.syncope.core.persistence.api.entity.Implementation;
import org.apache.syncope.core.persistence.api.entity.OIDCProvider;
@@ -62,14 +63,17 @@ public class JPAOIDCProviderItem extends AbstractItem implements OIDCProviderIte
joinColumns =
@JoinColumn(name = "item_id"),
inverseJoinColumns =
- @JoinColumn(name = "implementation_id"))
+ @JoinColumn(name = "implementation_id"),
+ uniqueConstraints =
+ @UniqueConstraint(columnNames = { "item_id", "implementation_id" }))
private List<JPAImplementation> transformers = new ArrayList<>();
@Override
public boolean add(final Implementation transformer) {
checkType(transformer, JPAImplementation.class);
checkImplementationType(transformer, ImplementationType.ITEM_TRANSFORMER);
- return this.transformers.add((JPAImplementation) transformer);
+ return transformers.contains((JPAImplementation) transformer)
+ || this.transformers.add((JPAImplementation) transformer);
}
@Override
diff --git a/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPASAML2IdPItem.java b/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPASAML2IdPItem.java
index 6e22a43..75f1cdc 100644
--- a/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPASAML2IdPItem.java
+++ b/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPASAML2IdPItem.java
@@ -28,6 +28,7 @@ import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
import org.apache.syncope.common.lib.types.ImplementationType;
import org.apache.syncope.core.persistence.api.entity.Implementation;
import org.apache.syncope.core.persistence.api.entity.SAML2IdP;
@@ -51,7 +52,9 @@ public class JPASAML2IdPItem extends AbstractItem implements SAML2IdPItem {
joinColumns =
@JoinColumn(name = "item_id"),
inverseJoinColumns =
- @JoinColumn(name = "implementation_id"))
+ @JoinColumn(name = "implementation_id"),
+ uniqueConstraints =
+ @UniqueConstraint(columnNames = { "item_id", "implementation_id" }))
private List<JPAImplementation> transformers = new ArrayList<>();
@Override
@@ -69,7 +72,8 @@ public class JPASAML2IdPItem extends AbstractItem implements SAML2IdPItem {
public boolean add(final Implementation transformer) {
checkType(transformer, JPAImplementation.class);
checkImplementationType(transformer, ImplementationType.ITEM_TRANSFORMER);
- return this.transformers.add((JPAImplementation) transformer);
+ return transformers.contains((JPAImplementation) transformer)
+ || this.transformers.add((JPAImplementation) transformer);
}
@Override
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AnyObjectITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AnyObjectITCase.java
index 36cd40f..4d1dc89 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AnyObjectITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AnyObjectITCase.java
@@ -31,6 +31,7 @@ import org.apache.syncope.client.lib.SyncopeClient;
import org.apache.syncope.common.lib.SyncopeClientException;
import org.apache.syncope.common.lib.SyncopeConstants;
import org.apache.syncope.common.lib.patch.AnyObjectPatch;
+import org.apache.syncope.common.lib.patch.StringPatchItem;
import org.apache.syncope.common.lib.to.ConnObjectTO;
import org.apache.syncope.common.lib.to.AnyObjectTO;
import org.apache.syncope.common.lib.to.AttrTO;
@@ -39,6 +40,7 @@ import org.apache.syncope.common.lib.to.PagedResult;
import org.apache.syncope.common.lib.to.RelationshipTO;
import org.apache.syncope.common.lib.types.AnyTypeKind;
import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.apache.syncope.common.lib.types.PatchOperation;
import org.apache.syncope.common.lib.types.SchemaType;
import org.apache.syncope.common.rest.api.beans.AnyQuery;
import org.apache.syncope.fit.AbstractITCase;
@@ -211,4 +213,35 @@ public class AnyObjectITCase extends AbstractITCase {
assertEquals(ClientExceptionType.InvalidAnyType, e.getType());
}
}
+
+ @Test
+ public void issueSYNCOPE1472() {
+ // 1. assign resource-db-scripted again to Canon MF 8030cn and update twice
+ AnyObjectPatch anyObjectPatch = new AnyObjectPatch();
+ anyObjectPatch.setKey("8559d14d-58c2-46eb-a2d4-a7d35161e8f8");
+ anyObjectPatch.getResources().add(new StringPatchItem.Builder().value(RESOURCE_NAME_DBSCRIPTED).build());
+ anyObjectPatch.getAuxClasses().add(new StringPatchItem.Builder().value("csv").build());
+
+ for (int i = 0; i < 2; i++) {
+ updateAnyObject(anyObjectPatch);
+ }
+
+ // 2. remove resources and auxiliary classes
+ anyObjectPatch.getResources().clear();
+ anyObjectPatch.getResources().add(new StringPatchItem.Builder()
+ .value(RESOURCE_NAME_DBSCRIPTED)
+ .operation(PatchOperation.DELETE)
+ .build());
+ anyObjectPatch.getAuxClasses().clear();
+ anyObjectPatch.getAuxClasses().add(new StringPatchItem.Builder()
+ .value("csv")
+ .operation(PatchOperation.DELETE)
+ .build());
+
+ updateAnyObject(anyObjectPatch);
+
+ AnyObjectTO printer = anyObjectService.read("8559d14d-58c2-46eb-a2d4-a7d35161e8f8");
+ assertFalse(printer.getResources().contains(RESOURCE_NAME_DBSCRIPTED), "Should not contain removed resources");
+ assertFalse(printer.getAuxClasses().contains("csv"), "Should not contain removed auxiliary classes");
+ }
}
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AnyTypeITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AnyTypeITCase.java
index 28ae442..e5eb88d 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AnyTypeITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AnyTypeITCase.java
@@ -178,4 +178,23 @@ public class AnyTypeITCase extends AbstractITCase {
anyTypeService.update(group);
}
}
+
+ @Test
+ public void issueSYNCOPE1472() {
+ // 1. add any type class csv twice to PRINTER any type
+ AnyTypeTO anyTypeTO = anyTypeService.read("PRINTER");
+ anyTypeTO.getClasses().clear();
+ anyTypeTO.getClasses().add("minimal printer");
+ anyTypeTO.getClasses().add("csv");
+ anyTypeTO.getClasses().add("csv");
+ anyTypeService.update(anyTypeTO);
+
+ // 2. read again and remove any type class
+ anyTypeTO = anyTypeService.read("PRINTER");
+ anyTypeTO.getClasses().remove("csv");
+ anyTypeService.update(anyTypeTO);
+
+ assertFalse(anyTypeService.read("PRINTER").getClasses().contains("csv"),
+ "Should not contain removed any type classes");
+ }
}
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/GroupITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/GroupITCase.java
index 33cbe38..95071aa 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/GroupITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/GroupITCase.java
@@ -1155,4 +1155,40 @@ public class GroupITCase extends AbstractITCase {
}
}
}
+
+ @Test
+ public void issueSYNCOPE1472() {
+ // 1. update group artDirector by assigning twice resource-testdb and auxiliary class csv
+ GroupPatch groupPatch = new GroupPatch();
+ groupPatch.setKey("ece66293-8f31-4a84-8e8d-23da36e70846");
+ groupPatch.getResources().add(new StringPatchItem.Builder()
+ .value(RESOURCE_NAME_TESTDB)
+ .operation(PatchOperation.ADD_REPLACE)
+ .build());
+ groupPatch.getAuxClasses().add(new StringPatchItem.Builder()
+ .operation(PatchOperation.ADD_REPLACE)
+ .value("csv")
+ .build());
+ for (int i = 0; i < 2; i++) {
+ updateGroup(groupPatch);
+ }
+
+ // 2. remove resources and auxiliary classes
+ groupPatch.getResources().clear();
+ groupPatch.getResources().add(new StringPatchItem.Builder()
+ .value(RESOURCE_NAME_TESTDB)
+ .operation(PatchOperation.DELETE)
+ .build());
+ groupPatch.getAuxClasses().clear();
+ groupPatch.getAuxClasses().add(new StringPatchItem.Builder()
+ .value("csv")
+ .operation(PatchOperation.DELETE)
+ .build());
+
+ updateGroup(groupPatch);
+
+ GroupTO groupTO = groupService.read("ece66293-8f31-4a84-8e8d-23da36e70846");
+ assertFalse(groupTO.getResources().contains(RESOURCE_NAME_TESTDB), "Should not contain removed resources");
+ assertFalse(groupTO.getAuxClasses().contains("csv"), "Should not contain removed auxiliary classes");
+ }
}
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RealmITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RealmITCase.java
index f62f2f9..c250c47 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RealmITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RealmITCase.java
@@ -268,4 +268,23 @@ public class RealmITCase extends AbstractITCase {
assertNull(
getLdapRemoteObject(RESOURCE_LDAP_ADMIN_DN, RESOURCE_LDAP_ADMIN_PWD, "ou=test,o=isp"));
}
+
+ @Test
+ public void issueSYNCOPE1472() {
+ // 1. assign twice resource-ldap-orgunit to /odd
+ RealmTO realmTO = realmService.list("/odd").get(0);
+ realmTO.getResources().clear();
+ realmTO.getResources().add("resource-ldap-orgunit");
+ realmTO.getResources().add("resource-ldap-orgunit");
+ realmTO = realmService.update(realmTO).readEntity(new GenericType<ProvisioningResult<RealmTO>>() {
+ }).getEntity();
+
+ // 2. remove resource-ldap-orgunit resource
+ realmTO.getResources().remove("resource-ldap-orgunit");
+
+ realmTO = realmService.update(realmTO).readEntity(new GenericType<ProvisioningResult<RealmTO>>() {
+ }).getEntity();
+
+ assertFalse(realmTO.getResources().contains("resource-ldap-orgunit"), "Should not contain removed resources");
+ }
}
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RoleITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RoleITCase.java
index 44a3d5c..82649fc 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RoleITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RoleITCase.java
@@ -28,8 +28,10 @@ import java.util.List;
import javax.ws.rs.core.Response;
import org.apache.syncope.common.lib.SyncopeClientException;
import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.to.DynRealmTO;
import org.apache.syncope.common.lib.to.RoleTO;
import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
import org.apache.syncope.common.lib.types.ClientExceptionType;
import org.apache.syncope.common.lib.types.FlowableEntitlement;
import org.apache.syncope.common.lib.types.StandardEntitlement;
@@ -146,4 +148,30 @@ public class RoleITCase extends AbstractITCase {
assertTrue(bellini.getDynMemberships().isEmpty());
assertTrue(bellini.getPrivileges().isEmpty());
}
+
+ @Test
+ public void issueSYNCOPE1472() {
+ final DynRealmTO dynRealmTO = new DynRealmTO();
+ dynRealmTO.setKey("dynRealm");
+ dynRealmTO.getDynMembershipConds().put(AnyTypeKind.USER.name(), "username=~rossini");
+ dynRealmService.create(dynRealmTO);
+
+ // 1. associate role Other again to /odd realm and twice to dynRealm
+ RoleTO roleTO = roleService.read("Other");
+ roleTO.getRealms().add("/odd");
+ roleTO.getDynRealms().add("dynRealm");
+ roleTO.getDynRealms().add("dynRealm");
+ roleService.update(roleTO);
+
+ // 2. update by removing realm and dynamic realm
+ roleTO = roleService.read("Other");
+ roleTO.getRealms().remove("/odd");
+ roleTO.getDynRealms().remove("dynRealm");
+ roleService.update(roleTO);
+
+ roleTO = roleService.read("Other");
+
+ assertFalse(roleTO.getRealms().contains("/odd"), "Should not contain removed realms");
+ assertFalse(roleTO.getDynRealms().contains("dynRealm"), "Should not contain removed dynamic realms");
+ }
}
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserIssuesITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserIssuesITCase.java
index b86fa94..9d2a101 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserIssuesITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserIssuesITCase.java
@@ -1520,4 +1520,55 @@ public class UserIssuesITCase extends AbstractITCase {
configurationService.set(original);
}
}
+
+ @Test
+ public void issueSYNCOPE1472() {
+ // 1. update user rossini by assigning twice resource-testdb2 and auxiliary class csv
+ UserPatch userPatch = new UserPatch();
+ userPatch.setKey("1417acbe-cbf6-4277-9372-e75e04f97000");
+ userPatch.setPassword(new PasswordPatch.Builder()
+ .onSyncope(false)
+ .resource(RESOURCE_NAME_TESTDB)
+ .value("Password123")
+ .build());
+ userPatch.getResources().add(new StringPatchItem.Builder()
+ .value(RESOURCE_NAME_TESTDB)
+ .operation(PatchOperation.ADD_REPLACE)
+ .build());
+ userPatch.getAuxClasses().add(new StringPatchItem.Builder()
+ .operation(PatchOperation.ADD_REPLACE)
+ .value("csv")
+ .build());
+ userPatch.getRoles().add(new StringPatchItem.Builder()
+ .operation(PatchOperation.ADD_REPLACE)
+ .value("Other")
+ .build());
+
+ for (int i = 0; i < 2; i++) {
+ updateUser(userPatch);
+ }
+
+ // 2. remove resources, auxiliary classes and roles
+ userPatch.getResources().clear();
+ userPatch.getResources().add(new StringPatchItem.Builder()
+ .value(RESOURCE_NAME_TESTDB)
+ .operation(PatchOperation.DELETE)
+ .build());
+ userPatch.getAuxClasses().clear();
+ userPatch.getAuxClasses().add(new StringPatchItem.Builder()
+ .value("csv")
+ .operation(PatchOperation.DELETE)
+ .build());
+ userPatch.getRoles().clear();
+ userPatch.getRoles().add(new StringPatchItem.Builder()
+ .value("Other")
+ .operation(PatchOperation.DELETE)
+ .build());
+ updateUser(userPatch);
+
+ UserTO userTO = userService.read("1417acbe-cbf6-4277-9372-e75e04f97000");
+ assertFalse(userTO.getResources().contains(RESOURCE_NAME_TESTDB), "Should not contain removed resources");
+ assertFalse(userTO.getAuxClasses().contains("csv"), "Should not contain removed auxiliary classes");
+ assertFalse(userTO.getRoles().contains("Other"),"Should not contain removed roles");
+ }
}