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 2015/08/13 17:18:07 UTC
[25/26] syncope git commit: [SYNCOPE-119] Adding test for delegated
admin (user) CRUD
[SYNCOPE-119] Adding test for delegated admin (user) CRUD
Project: http://git-wip-us.apache.org/repos/asf/syncope/repo
Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/bcb9a0d7
Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/bcb9a0d7
Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/bcb9a0d7
Branch: refs/heads/master
Commit: bcb9a0d7b0a792eba87046853510376cf4e58131
Parents: 5cf6aae
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Tue Aug 11 12:51:57 2015 +0200
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Thu Aug 13 17:16:51 2015 +0200
----------------------------------------------------------------------
.../syncope/common/lib/types/Entitlement.java | 2 -
.../syncope/core/logic/AbstractAnyLogic.java | 25 +++-
.../syncope/core/logic/AnyObjectLogic.java | 114 ++++++++++------
.../apache/syncope/core/logic/GroupLogic.java | 134 +++++++++++++------
.../apache/syncope/core/logic/UserLogic.java | 108 ++++++++++++---
.../apache/syncope/core/misc/RealmUtils.java | 4 +-
.../misc/security/UnauthorizedException.java | 5 +-
.../core/persistence/jpa/dao/JPARoleDAO.java | 9 ++
.../core/persistence/jpa/outer/RoleTest.java | 33 +++++
.../rest/cxf/service/UserSelfServiceImpl.java | 6 +-
.../core/reference/AuthenticationITCase.java | 91 ++++++++++++-
11 files changed, 426 insertions(+), 105 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/syncope/blob/bcb9a0d7/common/lib/src/main/java/org/apache/syncope/common/lib/types/Entitlement.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/types/Entitlement.java b/common/lib/src/main/java/org/apache/syncope/common/lib/types/Entitlement.java
index 85befc6..bf87c89 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/types/Entitlement.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/types/Entitlement.java
@@ -108,8 +108,6 @@ public final class Entitlement {
public static final String USER_DELETE = "USER_DELETE";
- public static final String USER_VIEW = "USER_VIEW";
-
public static final String GROUP_SEARCH = "GROUP_SEARCH";
public static final String GROUP_CREATE = "GROUP_CREATE";
http://git-wip-us.apache.org/repos/asf/syncope/blob/bcb9a0d7/core/logic/src/main/java/org/apache/syncope/core/logic/AbstractAnyLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/AbstractAnyLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/AbstractAnyLogic.java
index 6f66113..7a6cfdd 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/AbstractAnyLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/AbstractAnyLogic.java
@@ -26,7 +26,9 @@ import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.Predicate;
import org.apache.syncope.common.lib.mod.AnyMod;
import org.apache.syncope.common.lib.to.AnyTO;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
import org.apache.syncope.core.misc.RealmUtils;
+import org.apache.syncope.core.misc.security.UnauthorizedException;
import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
@@ -57,8 +59,8 @@ public abstract class AbstractAnyLogic<TO extends AnyTO, MOD extends AnyMod>
protected Set<String> getEffectiveRealms(
final Set<String> allowedRealms, final Collection<String> requestedRealms) {
- final Set<String> allowed = RealmUtils.normalize(allowedRealms);
- final Set<String> requested = RealmUtils.normalize(requestedRealms);
+ Set<String> allowed = RealmUtils.normalize(allowedRealms);
+ Set<String> requested = RealmUtils.normalize(requestedRealms);
Set<String> effective = new HashSet<>();
CollectionUtils.select(requested, new StartsWithPredicate(allowed), effective);
@@ -67,6 +69,25 @@ public abstract class AbstractAnyLogic<TO extends AnyTO, MOD extends AnyMod>
return effective;
}
+ protected void securityChecks(final Set<String> effectiveRealms, final String realm, final Long key) {
+ if (!CollectionUtils.exists(effectiveRealms, new Predicate<String>() {
+
+ @Override
+ public boolean evaluate(final String ownedRealm) {
+ return realm.startsWith(ownedRealm);
+ }
+ })) {
+
+ throw new UnauthorizedException(
+ this instanceof UserLogic
+ ? AnyTypeKind.USER
+ : this instanceof GroupLogic
+ ? AnyTypeKind.GROUP
+ : AnyTypeKind.ANY_OBJECT,
+ key);
+ }
+ }
+
public abstract TO read(Long key);
public abstract int count(List<String> realms);
http://git-wip-us.apache.org/repos/asf/syncope/blob/bcb9a0d7/core/logic/src/main/java/org/apache/syncope/core/logic/AnyObjectLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/AnyObjectLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/AnyObjectLogic.java
index 38927ce..0b0cb74 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/AnyObjectLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/AnyObjectLogic.java
@@ -22,6 +22,7 @@ import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -46,9 +47,7 @@ import org.apache.syncope.core.provisioning.api.data.AnyObjectDataBinder;
import org.apache.syncope.core.provisioning.api.propagation.PropagationManager;
import org.apache.syncope.core.provisioning.api.propagation.PropagationTaskExecutor;
import org.apache.syncope.core.misc.security.AuthContextUtils;
-import org.apache.syncope.core.misc.security.UnauthorizedException;
import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
-import org.apache.syncope.core.persistence.api.dao.NotFoundException;
import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
import org.apache.syncope.core.provisioning.api.AnyTransformer;
import org.springframework.beans.factory.annotation.Autowired;
@@ -90,8 +89,8 @@ public class AnyObjectLogic extends AbstractAnyLogic<AnyObjectTO, AnyObjectMod>
@PreAuthorize("hasRole('" + Entitlement.ANY_OBJECT_READ + "')")
@Transactional(readOnly = true)
@Override
- public AnyObjectTO read(final Long anyObjectKey) {
- return binder.getAnyObjectTO(anyObjectKey);
+ public AnyObjectTO read(final Long key) {
+ return binder.getAnyObjectTO(key);
}
@PreAuthorize("isAuthenticated()")
@@ -164,12 +163,11 @@ public class AnyObjectLogic extends AbstractAnyLogic<AnyObjectTO, AnyObjectMod>
if (anyObjectTO.getRealm() == null) {
throw SyncopeClientException.build(ClientExceptionType.InvalidRealm);
}
+ // security checks
Set<String> effectiveRealms = getEffectiveRealms(
AuthContextUtils.getAuthorizations().get(Entitlement.ANY_OBJECT_CREATE),
Collections.singleton(anyObjectTO.getRealm()));
- if (effectiveRealms.isEmpty()) {
- throw new UnauthorizedException(AnyTypeKind.ANY_OBJECT, null);
- }
+ securityChecks(effectiveRealms, anyObjectTO.getRealm(), null);
// Any transformation (if configured)
AnyObjectTO actual = attrTransformer.transform(anyObjectTO);
@@ -191,21 +189,25 @@ public class AnyObjectLogic extends AbstractAnyLogic<AnyObjectTO, AnyObjectMod>
@PreAuthorize("hasRole('" + Entitlement.ANY_OBJECT_UPDATE + "')")
@Override
public AnyObjectTO update(final AnyObjectMod anyObjectMod) {
- AnyObject anyObject = anyObjectDAO.authFind(anyObjectMod.getKey());
- if (anyObject == null) {
- throw new NotFoundException("AnyObject with key " + anyObjectMod.getKey());
+ // Any transformation (if configured)
+ AnyObjectMod actual = attrTransformer.transform(anyObjectMod);
+ LOG.debug("Transformed: {}", actual);
+
+ // security checks
+ AnyObjectTO toUpdate = binder.getAnyObjectTO(anyObjectMod.getKey());
+ Set<String> requestedRealms = new HashSet<>();
+ requestedRealms.add(toUpdate.getRealm());
+ if (StringUtils.isNotBlank(actual.getRealm())) {
+ requestedRealms.add(actual.getRealm());
}
Set<String> effectiveRealms = getEffectiveRealms(
AuthContextUtils.getAuthorizations().get(Entitlement.ANY_OBJECT_UPDATE),
- Collections.singleton(anyObject.getRealm().getFullPath()));
- if (effectiveRealms.isEmpty()) {
- throw new UnauthorizedException(AnyTypeKind.ANY_OBJECT, anyObject.getKey());
+ requestedRealms);
+ securityChecks(effectiveRealms, toUpdate.getRealm(), toUpdate.getKey());
+ if (StringUtils.isNotBlank(actual.getRealm())) {
+ securityChecks(effectiveRealms, actual.getRealm(), toUpdate.getKey());
}
- // Any transformation (if configured)
- AnyObjectMod actual = attrTransformer.transform(anyObjectMod);
- LOG.debug("Transformed: {}", actual);
-
Map.Entry<Long, List<PropagationStatus>> updated = provisioningManager.update(anyObjectMod);
AnyObjectTO updatedTO = binder.getAnyObjectTO(updated.getKey());
@@ -215,22 +217,18 @@ public class AnyObjectLogic extends AbstractAnyLogic<AnyObjectTO, AnyObjectMod>
@PreAuthorize("hasRole('" + Entitlement.ANY_OBJECT_DELETE + "')")
@Override
- public AnyObjectTO delete(final Long anyObjectKey) {
- AnyObject anyObject = anyObjectDAO.authFind(anyObjectKey);
- if (anyObject == null) {
- throw new NotFoundException("AnyObject with key " + anyObjectKey);
- }
+ public AnyObjectTO delete(final Long key) {
+ // security checks
+ AnyObjectTO toDelete = binder.getAnyObjectTO(key);
Set<String> effectiveRealms = getEffectiveRealms(
- AuthContextUtils.getAuthorizations().get(Entitlement.ANY_OBJECT_UPDATE),
- Collections.singleton(anyObject.getRealm().getFullPath()));
- if (effectiveRealms.isEmpty()) {
- throw new UnauthorizedException(AnyTypeKind.ANY_OBJECT, anyObject.getKey());
- }
+ AuthContextUtils.getAuthorizations().get(Entitlement.ANY_OBJECT_DELETE),
+ Collections.singleton(toDelete.getRealm()));
+ securityChecks(effectiveRealms, toDelete.getRealm(), toDelete.getKey());
- List<PropagationStatus> statuses = provisioningManager.delete(anyObjectKey);
+ List<PropagationStatus> statuses = provisioningManager.delete(key);
AnyObjectTO anyObjectTO = new AnyObjectTO();
- anyObjectTO.setKey(anyObjectKey);
+ anyObjectTO.setKey(key);
anyObjectTO.getPropagationStatusTOs().addAll(statuses);
@@ -239,9 +237,16 @@ public class AnyObjectLogic extends AbstractAnyLogic<AnyObjectTO, AnyObjectMod>
@PreAuthorize("hasRole('" + Entitlement.ANY_OBJECT_UPDATE + "')")
@Override
- public AnyObjectTO unlink(final Long anyObjectKey, final Collection<String> resources) {
+ public AnyObjectTO unlink(final Long key, final Collection<String> resources) {
+ // security checks
+ AnyObjectTO anyObject = binder.getAnyObjectTO(key);
+ Set<String> effectiveRealms = getEffectiveRealms(
+ AuthContextUtils.getAuthorizations().get(Entitlement.ANY_OBJECT_UPDATE),
+ Collections.singleton(anyObject.getRealm()));
+ securityChecks(effectiveRealms, anyObject.getRealm(), anyObject.getKey());
+
AnyObjectMod anyObjectMod = new AnyObjectMod();
- anyObjectMod.setKey(anyObjectKey);
+ anyObjectMod.setKey(key);
anyObjectMod.getResourcesToRemove().addAll(resources);
return binder.getAnyObjectTO(provisioningManager.unlink(anyObjectMod));
@@ -249,9 +254,16 @@ public class AnyObjectLogic extends AbstractAnyLogic<AnyObjectTO, AnyObjectMod>
@PreAuthorize("hasRole('" + Entitlement.ANY_OBJECT_UPDATE + "')")
@Override
- public AnyObjectTO link(final Long anyObjectKey, final Collection<String> resources) {
+ public AnyObjectTO link(final Long key, final Collection<String> resources) {
+ // security checks
+ AnyObjectTO anyObject = binder.getAnyObjectTO(key);
+ Set<String> effectiveRealms = getEffectiveRealms(
+ AuthContextUtils.getAuthorizations().get(Entitlement.ANY_OBJECT_UPDATE),
+ Collections.singleton(anyObject.getRealm()));
+ securityChecks(effectiveRealms, anyObject.getRealm(), anyObject.getKey());
+
AnyObjectMod anyObjectMod = new AnyObjectMod();
- anyObjectMod.setKey(anyObjectKey);
+ anyObjectMod.setKey(key);
anyObjectMod.getResourcesToAdd().addAll(resources);
return binder.getAnyObjectTO(provisioningManager.link(anyObjectMod));
@@ -259,9 +271,16 @@ public class AnyObjectLogic extends AbstractAnyLogic<AnyObjectTO, AnyObjectMod>
@PreAuthorize("hasRole('" + Entitlement.ANY_OBJECT_UPDATE + "')")
@Override
- public AnyObjectTO unassign(final Long anyObjectKey, final Collection<String> resources) {
+ public AnyObjectTO unassign(final Long key, final Collection<String> resources) {
+ // security checks
+ AnyObjectTO anyObject = binder.getAnyObjectTO(key);
+ Set<String> effectiveRealms = getEffectiveRealms(
+ AuthContextUtils.getAuthorizations().get(Entitlement.ANY_OBJECT_UPDATE),
+ Collections.singleton(anyObject.getRealm()));
+ securityChecks(effectiveRealms, anyObject.getRealm(), anyObject.getKey());
+
AnyObjectMod anyObjectMod = new AnyObjectMod();
- anyObjectMod.setKey(anyObjectKey);
+ anyObjectMod.setKey(key);
anyObjectMod.getResourcesToRemove().addAll(resources);
return update(anyObjectMod);
}
@@ -274,6 +293,13 @@ public class AnyObjectLogic extends AbstractAnyLogic<AnyObjectTO, AnyObjectMod>
final boolean changepwd,
final String password) {
+ // security checks
+ AnyObjectTO anyObject = binder.getAnyObjectTO(key);
+ Set<String> effectiveRealms = getEffectiveRealms(
+ AuthContextUtils.getAuthorizations().get(Entitlement.ANY_OBJECT_UPDATE),
+ Collections.singleton(anyObject.getRealm()));
+ securityChecks(effectiveRealms, anyObject.getRealm(), anyObject.getKey());
+
AnyObjectMod anyObjectMod = new AnyObjectMod();
anyObjectMod.setKey(key);
anyObjectMod.getResourcesToAdd().addAll(resources);
@@ -284,6 +310,13 @@ public class AnyObjectLogic extends AbstractAnyLogic<AnyObjectTO, AnyObjectMod>
@PreAuthorize("hasRole('" + Entitlement.ANY_OBJECT_UPDATE + "')")
@Override
public AnyObjectTO deprovision(final Long key, final Collection<String> resources) {
+ // security checks
+ AnyObjectTO anyObject = binder.getAnyObjectTO(key);
+ Set<String> effectiveRealms = getEffectiveRealms(
+ AuthContextUtils.getAuthorizations().get(Entitlement.ANY_OBJECT_UPDATE),
+ Collections.singleton(anyObject.getRealm()));
+ securityChecks(effectiveRealms, anyObject.getRealm(), anyObject.getKey());
+
List<PropagationStatus> statuses = provisioningManager.deprovision(key, resources);
AnyObjectTO updatedTO = binder.getAnyObjectTO(key);
@@ -299,10 +332,15 @@ public class AnyObjectLogic extends AbstractAnyLogic<AnyObjectTO, AnyObjectMod>
final boolean changePwd,
final String password) {
- AnyObjectTO original = binder.getAnyObjectTO(key);
- original.getPropagationStatusTOs().addAll(provisioningManager.provision(key, resources));
+ // security checks
+ AnyObjectTO anyObject = binder.getAnyObjectTO(key);
+ Set<String> effectiveRealms = getEffectiveRealms(
+ AuthContextUtils.getAuthorizations().get(Entitlement.ANY_OBJECT_UPDATE),
+ Collections.singleton(anyObject.getRealm()));
+ securityChecks(effectiveRealms, anyObject.getRealm(), anyObject.getKey());
- return original;
+ anyObject.getPropagationStatusTOs().addAll(provisioningManager.provision(key, resources));
+ return anyObject;
}
@Override
http://git-wip-us.apache.org/repos/asf/syncope/blob/bcb9a0d7/core/logic/src/main/java/org/apache/syncope/core/logic/GroupLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/GroupLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/GroupLogic.java
index 33b0447..1c3d7f5 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/GroupLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/GroupLogic.java
@@ -22,13 +22,16 @@ import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.Resource;
import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.Predicate;
import org.apache.commons.collections4.Transformer;
import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.StringUtils;
import org.apache.syncope.common.lib.SyncopeClientException;
import org.apache.syncope.common.lib.SyncopeConstants;
import org.apache.syncope.common.lib.mod.GroupMod;
@@ -50,7 +53,6 @@ import org.apache.syncope.core.provisioning.api.propagation.PropagationTaskExecu
import org.apache.syncope.core.misc.security.AuthContextUtils;
import org.apache.syncope.core.misc.security.UnauthorizedException;
import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
-import org.apache.syncope.core.persistence.api.dao.NotFoundException;
import org.apache.syncope.core.provisioning.api.AnyTransformer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
@@ -91,11 +93,25 @@ public class GroupLogic extends AbstractAnyLogic<GroupTO, GroupMod> {
@Autowired
protected GroupProvisioningManager provisioningManager;
+ @Override
+ protected void securityChecks(final Set<String> effectiveRealms, final String realm, final Long key) {
+ if (!CollectionUtils.exists(effectiveRealms, new Predicate<String>() {
+
+ @Override
+ public boolean evaluate(final String ownedRealm) {
+ return realm.startsWith(ownedRealm) || ownedRealm.equals(RealmUtils.getGroupOwnerRealm(realm, key));
+ }
+ })) {
+
+ throw new UnauthorizedException(AnyTypeKind.GROUP, key);
+ }
+ }
+
@PreAuthorize("hasRole('" + Entitlement.GROUP_READ + "')")
@Transactional(readOnly = true)
@Override
- public GroupTO read(final Long groupKey) {
- return binder.getGroupTO(groupKey);
+ public GroupTO read(final Long key) {
+ return binder.getGroupTO(key);
}
@PreAuthorize("isAuthenticated() and not(hasRole('" + Entitlement.ANONYMOUS + "'))")
@@ -153,7 +169,7 @@ public class GroupLogic extends AbstractAnyLogic<GroupTO, GroupMod> {
public List<GroupTO> search(final SearchCond searchCondition, final int page, final int size,
final List<OrderByClause> orderBy, final List<String> realms, final boolean details) {
- final List<Group> matchingGroups = searchDAO.search(
+ List<Group> matchingGroups = searchDAO.search(
getEffectiveRealms(AuthContextUtils.getAuthorizations().get(Entitlement.GROUP_SEARCH), realms),
searchCondition, page, size, orderBy, AnyTypeKind.GROUP);
return CollectionUtils.collect(matchingGroups, new Transformer<Group, GroupTO>() {
@@ -169,15 +185,13 @@ public class GroupLogic extends AbstractAnyLogic<GroupTO, GroupMod> {
@Override
public GroupTO create(final GroupTO groupTO) {
if (groupTO.getRealm() == null) {
- SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidRealm);
- throw sce;
+ throw SyncopeClientException.build(ClientExceptionType.InvalidRealm);
}
+ // security checks
Set<String> effectiveRealms = getEffectiveRealms(
AuthContextUtils.getAuthorizations().get(Entitlement.GROUP_CREATE),
Collections.singleton(groupTO.getRealm()));
- if (effectiveRealms.isEmpty()) {
- throw new UnauthorizedException(AnyTypeKind.GROUP, null);
- }
+ securityChecks(effectiveRealms, groupTO.getRealm(), null);
// Any transformation (if configured)
GroupTO actual = attrTransformer.transform(groupTO);
@@ -195,21 +209,25 @@ public class GroupLogic extends AbstractAnyLogic<GroupTO, GroupMod> {
@PreAuthorize("hasRole('" + Entitlement.GROUP_UPDATE + "')")
@Override
public GroupTO update(final GroupMod groupMod) {
- Group group = groupDAO.authFind(groupMod.getKey());
- if (group == null) {
- throw new NotFoundException("Group with key " + groupMod.getKey());
+ // Any transformation (if configured)
+ GroupMod actual = attrTransformer.transform(groupMod);
+ LOG.debug("Transformed: {}", actual);
+
+ // security checks
+ GroupTO toUpdate = binder.getGroupTO(groupMod.getKey());
+ Set<String> requestedRealms = new HashSet<>();
+ requestedRealms.add(toUpdate.getRealm());
+ if (StringUtils.isNotBlank(actual.getRealm())) {
+ requestedRealms.add(actual.getRealm());
}
Set<String> effectiveRealms = getEffectiveRealms(
AuthContextUtils.getAuthorizations().get(Entitlement.GROUP_UPDATE),
- Collections.singleton(RealmUtils.getGroupOwnerRealm(group.getRealm().getFullPath(), group.getKey())));
- if (effectiveRealms.isEmpty()) {
- throw new UnauthorizedException(AnyTypeKind.GROUP, group.getKey());
+ requestedRealms);
+ securityChecks(effectiveRealms, toUpdate.getRealm(), toUpdate.getKey());
+ if (StringUtils.isNotBlank(actual.getRealm())) {
+ securityChecks(effectiveRealms, actual.getRealm(), toUpdate.getKey());
}
- // Any transformation (if configured)
- GroupMod actual = attrTransformer.transform(groupMod);
- LOG.debug("Transformed: {}", actual);
-
Map.Entry<Long, List<PropagationStatus>> updated = provisioningManager.update(groupMod);
GroupTO updatedTO = binder.getGroupTO(updated.getKey());
@@ -219,19 +237,15 @@ public class GroupLogic extends AbstractAnyLogic<GroupTO, GroupMod> {
@PreAuthorize("hasRole('" + Entitlement.GROUP_DELETE + "')")
@Override
- public GroupTO delete(final Long groupKey) {
- Group group = groupDAO.authFind(groupKey);
- if (group == null) {
- throw new NotFoundException("Group with key " + groupKey);
- }
+ public GroupTO delete(final Long key) {
+ // security checks
+ GroupTO toDelete = binder.getGroupTO(key);
Set<String> effectiveRealms = getEffectiveRealms(
AuthContextUtils.getAuthorizations().get(Entitlement.GROUP_DELETE),
- Collections.singleton(RealmUtils.getGroupOwnerRealm(group.getRealm().getFullPath(), group.getKey())));
- if (effectiveRealms.isEmpty()) {
- throw new UnauthorizedException(AnyTypeKind.GROUP, group.getKey());
- }
+ Collections.singleton(toDelete.getRealm()));
+ securityChecks(effectiveRealms, toDelete.getRealm(), toDelete.getKey());
- List<Group> ownedGroups = groupDAO.findOwnedByGroup(groupKey);
+ List<Group> ownedGroups = groupDAO.findOwnedByGroup(key);
if (!ownedGroups.isEmpty()) {
SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.GroupOwnership);
sce.getElements().addAll(CollectionUtils.collect(ownedGroups, new Transformer<Group, String>() {
@@ -244,10 +258,10 @@ public class GroupLogic extends AbstractAnyLogic<GroupTO, GroupMod> {
throw sce;
}
- List<PropagationStatus> statuses = provisioningManager.delete(groupKey);
+ List<PropagationStatus> statuses = provisioningManager.delete(key);
GroupTO groupTO = new GroupTO();
- groupTO.setKey(groupKey);
+ groupTO.setKey(key);
groupTO.getPropagationStatusTOs().addAll(statuses);
@@ -256,9 +270,16 @@ public class GroupLogic extends AbstractAnyLogic<GroupTO, GroupMod> {
@PreAuthorize("hasRole('" + Entitlement.GROUP_UPDATE + "')")
@Override
- public GroupTO unlink(final Long groupKey, final Collection<String> resources) {
+ public GroupTO unlink(final Long key, final Collection<String> resources) {
+ // security checks
+ GroupTO group = binder.getGroupTO(key);
+ Set<String> effectiveRealms = getEffectiveRealms(
+ AuthContextUtils.getAuthorizations().get(Entitlement.GROUP_UPDATE),
+ Collections.singleton(group.getRealm()));
+ securityChecks(effectiveRealms, group.getRealm(), group.getKey());
+
GroupMod groupMod = new GroupMod();
- groupMod.setKey(groupKey);
+ groupMod.setKey(key);
groupMod.getResourcesToRemove().addAll(resources);
return binder.getGroupTO(provisioningManager.unlink(groupMod));
@@ -266,9 +287,16 @@ public class GroupLogic extends AbstractAnyLogic<GroupTO, GroupMod> {
@PreAuthorize("hasRole('" + Entitlement.GROUP_UPDATE + "')")
@Override
- public GroupTO link(final Long groupKey, final Collection<String> resources) {
+ public GroupTO link(final Long key, final Collection<String> resources) {
+ // security checks
+ GroupTO group = binder.getGroupTO(key);
+ Set<String> effectiveRealms = getEffectiveRealms(
+ AuthContextUtils.getAuthorizations().get(Entitlement.GROUP_UPDATE),
+ Collections.singleton(group.getRealm()));
+ securityChecks(effectiveRealms, group.getRealm(), group.getKey());
+
GroupMod groupMod = new GroupMod();
- groupMod.setKey(groupKey);
+ groupMod.setKey(key);
groupMod.getResourcesToAdd().addAll(resources);
return binder.getGroupTO(provisioningManager.link(groupMod));
@@ -276,9 +304,16 @@ public class GroupLogic extends AbstractAnyLogic<GroupTO, GroupMod> {
@PreAuthorize("hasRole('" + Entitlement.GROUP_UPDATE + "')")
@Override
- public GroupTO unassign(final Long groupKey, final Collection<String> resources) {
+ public GroupTO unassign(final Long key, final Collection<String> resources) {
+ // security checks
+ GroupTO group = binder.getGroupTO(key);
+ Set<String> effectiveRealms = getEffectiveRealms(
+ AuthContextUtils.getAuthorizations().get(Entitlement.GROUP_UPDATE),
+ Collections.singleton(group.getRealm()));
+ securityChecks(effectiveRealms, group.getRealm(), group.getKey());
+
GroupMod groupMod = new GroupMod();
- groupMod.setKey(groupKey);
+ groupMod.setKey(key);
groupMod.getResourcesToRemove().addAll(resources);
return update(groupMod);
}
@@ -291,6 +326,13 @@ public class GroupLogic extends AbstractAnyLogic<GroupTO, GroupMod> {
final boolean changepwd,
final String password) {
+ // security checks
+ GroupTO group = binder.getGroupTO(key);
+ Set<String> effectiveRealms = getEffectiveRealms(
+ AuthContextUtils.getAuthorizations().get(Entitlement.GROUP_UPDATE),
+ Collections.singleton(group.getRealm()));
+ securityChecks(effectiveRealms, group.getRealm(), group.getKey());
+
GroupMod groupMod = new GroupMod();
groupMod.setKey(key);
groupMod.getResourcesToAdd().addAll(resources);
@@ -301,6 +343,13 @@ public class GroupLogic extends AbstractAnyLogic<GroupTO, GroupMod> {
@PreAuthorize("hasRole('" + Entitlement.GROUP_UPDATE + "')")
@Override
public GroupTO deprovision(final Long key, final Collection<String> resources) {
+ // security checks
+ GroupTO group = binder.getGroupTO(key);
+ Set<String> effectiveRealms = getEffectiveRealms(
+ AuthContextUtils.getAuthorizations().get(Entitlement.GROUP_UPDATE),
+ Collections.singleton(group.getRealm()));
+ securityChecks(effectiveRealms, group.getRealm(), group.getKey());
+
List<PropagationStatus> statuses = provisioningManager.deprovision(key, resources);
GroupTO updatedTO = binder.getGroupTO(key);
@@ -316,10 +365,15 @@ public class GroupLogic extends AbstractAnyLogic<GroupTO, GroupMod> {
final boolean changePwd,
final String password) {
- GroupTO original = binder.getGroupTO(key);
- original.getPropagationStatusTOs().addAll(provisioningManager.provision(key, resources));
+ // security checks
+ GroupTO group = binder.getGroupTO(key);
+ Set<String> effectiveRealms = getEffectiveRealms(
+ AuthContextUtils.getAuthorizations().get(Entitlement.GROUP_UPDATE),
+ Collections.singleton(group.getRealm()));
+ securityChecks(effectiveRealms, group.getRealm(), group.getKey());
- return original;
+ group.getPropagationStatusTOs().addAll(provisioningManager.provision(key, resources));
+ return group;
}
@Override
http://git-wip-us.apache.org/repos/asf/syncope/blob/bcb9a0d7/core/logic/src/main/java/org/apache/syncope/core/logic/UserLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/UserLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/UserLogic.java
index 28e7401..ff87d6b 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/UserLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/UserLogic.java
@@ -23,12 +23,14 @@ import java.security.AccessControlException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.Transformer;
import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.syncope.common.lib.SyncopeClientException;
@@ -51,7 +53,6 @@ import org.apache.syncope.core.provisioning.api.data.UserDataBinder;
import org.apache.syncope.core.provisioning.api.propagation.PropagationManager;
import org.apache.syncope.core.provisioning.api.propagation.PropagationTaskExecutor;
import org.apache.syncope.core.misc.security.AuthContextUtils;
-import org.apache.syncope.core.misc.security.UnauthorizedException;
import org.apache.syncope.core.misc.serialization.POJOHelper;
import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
import org.apache.syncope.core.provisioning.api.AnyTransformer;
@@ -180,7 +181,7 @@ public class UserLogic extends AbstractAnyLogic<UserTO, UserMod> {
}
@PreAuthorize("isAnonymous() or hasRole('" + Entitlement.ANONYMOUS + "')")
- public UserTO createSelf(final UserTO userTO, final boolean storePassword) {
+ public UserTO selfCreate(final UserTO userTO, final boolean storePassword) {
return doCreate(userTO, storePassword);
}
@@ -193,15 +194,13 @@ public class UserLogic extends AbstractAnyLogic<UserTO, UserMod> {
@PreAuthorize("hasRole('" + Entitlement.USER_CREATE + "')")
public UserTO create(final UserTO userTO, final boolean storePassword) {
if (userTO.getRealm() == null) {
- SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidRealm);
- throw sce;
+ throw SyncopeClientException.build(ClientExceptionType.InvalidRealm);
}
+ // security checks
Set<String> effectiveRealms = getEffectiveRealms(
AuthContextUtils.getAuthorizations().get(Entitlement.USER_CREATE),
Collections.singleton(userTO.getRealm()));
- if (effectiveRealms.isEmpty()) {
- throw new UnauthorizedException(AnyTypeKind.USER, null);
- }
+ securityChecks(effectiveRealms, userTO.getRealm(), null);
return doCreate(userTO, storePassword);
}
@@ -219,14 +218,14 @@ public class UserLogic extends AbstractAnyLogic<UserTO, UserMod> {
}
@PreAuthorize("isAuthenticated() and not(hasRole('" + Entitlement.ANONYMOUS + "'))")
- public UserTO updateSelf(final UserMod userMod) {
+ public UserTO selfUpdate(final UserMod userMod) {
UserTO userTO = binder.getAuthenticatedUserTO();
if (userTO.getKey() != userMod.getKey()) {
throw new AccessControlException("Not allowed for user with key " + userMod.getKey());
}
- return update(userMod);
+ return doUpdate(userMod);
}
@PreAuthorize("hasRole('" + Entitlement.USER_UPDATE + "')")
@@ -236,7 +235,26 @@ public class UserLogic extends AbstractAnyLogic<UserTO, UserMod> {
UserMod actual = anyTransformer.transform(userMod);
LOG.debug("Transformed: {}", actual);
- Map.Entry<Long, List<PropagationStatus>> updated = provisioningManager.update(actual);
+ // security checks
+ UserTO toUpdate = binder.getUserTO(userMod.getKey());
+ Set<String> requestedRealms = new HashSet<>();
+ requestedRealms.add(toUpdate.getRealm());
+ if (StringUtils.isNotBlank(actual.getRealm())) {
+ requestedRealms.add(actual.getRealm());
+ }
+ Set<String> effectiveRealms = getEffectiveRealms(
+ AuthContextUtils.getAuthorizations().get(Entitlement.USER_UPDATE),
+ requestedRealms);
+ securityChecks(effectiveRealms, toUpdate.getRealm(), toUpdate.getKey());
+ if (StringUtils.isNotBlank(actual.getRealm())) {
+ securityChecks(effectiveRealms, actual.getRealm(), toUpdate.getKey());
+ }
+
+ return doUpdate(actual);
+ }
+
+ protected UserTO doUpdate(final UserMod userMod) {
+ Map.Entry<Long, List<PropagationStatus>> updated = provisioningManager.update(userMod);
UserTO updatedTO = binder.getUserTO(updated.getKey());
updatedTO.getPropagationStatusTOs().addAll(updated.getValue());
@@ -267,8 +285,15 @@ public class UserLogic extends AbstractAnyLogic<UserTO, UserMod> {
@PreAuthorize("hasRole('" + Entitlement.USER_UPDATE + "')")
public UserTO status(final StatusMod statusMod) {
+ // security checks
+ UserTO toUpdate = binder.getUserTO(statusMod.getKey());
+ Set<String> effectiveRealms = getEffectiveRealms(
+ AuthContextUtils.getAuthorizations().get(Entitlement.USER_UPDATE),
+ Collections.singleton(toUpdate.getRealm()));
+ securityChecks(effectiveRealms, toUpdate.getRealm(), toUpdate.getKey());
+
Map.Entry<Long, List<PropagationStatus>> updated = setStatusOnWfAdapter(statusMod);
- final UserTO savedTO = binder.getUserTO(updated.getKey());
+ UserTO savedTO = binder.getUserTO(updated.getKey());
savedTO.getPropagationStatusTOs().addAll(updated.getValue());
return savedTO;
}
@@ -305,15 +330,26 @@ public class UserLogic extends AbstractAnyLogic<UserTO, UserMod> {
}
@PreAuthorize("isAuthenticated() and not(hasRole('" + Entitlement.ANONYMOUS + "'))")
- public UserTO deleteSelf() {
+ public UserTO selfDelete() {
UserTO userTO = binder.getAuthenticatedUserTO();
- return delete(userTO.getKey());
+ return doDelete(userTO.getKey());
}
@PreAuthorize("hasRole('" + Entitlement.USER_DELETE + "')")
@Override
public UserTO delete(final Long key) {
+ // security checks
+ UserTO toDelete = binder.getUserTO(key);
+ Set<String> effectiveRealms = getEffectiveRealms(
+ AuthContextUtils.getAuthorizations().get(Entitlement.USER_DELETE),
+ Collections.singleton(toDelete.getRealm()));
+ securityChecks(effectiveRealms, toDelete.getRealm(), toDelete.getKey());
+
+ return doDelete(key);
+ }
+
+ protected UserTO doDelete(final Long key) {
List<Group> ownedGroups = groupDAO.findOwnedByUser(key);
if (!ownedGroups.isEmpty()) {
SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.GroupOwnership);
@@ -344,6 +380,13 @@ public class UserLogic extends AbstractAnyLogic<UserTO, UserMod> {
@PreAuthorize("hasRole('" + Entitlement.USER_UPDATE + "')")
@Override
public UserTO unlink(final Long key, final Collection<String> resources) {
+ // security checks
+ UserTO user = binder.getUserTO(key);
+ Set<String> effectiveRealms = getEffectiveRealms(
+ AuthContextUtils.getAuthorizations().get(Entitlement.USER_UPDATE),
+ Collections.singleton(user.getRealm()));
+ securityChecks(effectiveRealms, user.getRealm(), user.getKey());
+
UserMod userMod = new UserMod();
userMod.setKey(key);
userMod.getResourcesToRemove().addAll(resources);
@@ -354,6 +397,13 @@ public class UserLogic extends AbstractAnyLogic<UserTO, UserMod> {
@PreAuthorize("hasRole('" + Entitlement.USER_UPDATE + "')")
@Override
public UserTO link(final Long key, final Collection<String> resources) {
+ // security checks
+ UserTO user = binder.getUserTO(key);
+ Set<String> effectiveRealms = getEffectiveRealms(
+ AuthContextUtils.getAuthorizations().get(Entitlement.USER_UPDATE),
+ Collections.singleton(user.getRealm()));
+ securityChecks(effectiveRealms, user.getRealm(), user.getKey());
+
UserMod userMod = new UserMod();
userMod.setKey(key);
userMod.getResourcesToAdd().addAll(resources);
@@ -364,6 +414,13 @@ public class UserLogic extends AbstractAnyLogic<UserTO, UserMod> {
@PreAuthorize("hasRole('" + Entitlement.USER_UPDATE + "')")
@Override
public UserTO unassign(final Long key, final Collection<String> resources) {
+ // security checks
+ UserTO user = binder.getUserTO(key);
+ Set<String> effectiveRealms = getEffectiveRealms(
+ AuthContextUtils.getAuthorizations().get(Entitlement.USER_UPDATE),
+ Collections.singleton(user.getRealm()));
+ securityChecks(effectiveRealms, user.getRealm(), user.getKey());
+
UserMod userMod = new UserMod();
userMod.setKey(key);
userMod.getResourcesToRemove().addAll(resources);
@@ -378,6 +435,13 @@ public class UserLogic extends AbstractAnyLogic<UserTO, UserMod> {
final boolean changepwd,
final String password) {
+ // security checks
+ UserTO user = binder.getUserTO(key);
+ Set<String> effectiveRealms = getEffectiveRealms(
+ AuthContextUtils.getAuthorizations().get(Entitlement.USER_UPDATE),
+ Collections.singleton(user.getRealm()));
+ securityChecks(effectiveRealms, user.getRealm(), user.getKey());
+
UserMod userMod = new UserMod();
userMod.setKey(key);
userMod.getResourcesToAdd().addAll(resources);
@@ -396,6 +460,13 @@ public class UserLogic extends AbstractAnyLogic<UserTO, UserMod> {
@PreAuthorize("hasRole('" + Entitlement.USER_UPDATE + "')")
@Override
public UserTO deprovision(final Long key, final Collection<String> resources) {
+ // security checks
+ UserTO user = binder.getUserTO(key);
+ Set<String> effectiveRealms = getEffectiveRealms(
+ AuthContextUtils.getAuthorizations().get(Entitlement.USER_UPDATE),
+ Collections.singleton(user.getRealm()));
+ securityChecks(effectiveRealms, user.getRealm(), user.getKey());
+
List<PropagationStatus> statuses = provisioningManager.deprovision(key, resources);
UserTO updatedTO = binder.getUserTO(key);
@@ -411,10 +482,15 @@ public class UserLogic extends AbstractAnyLogic<UserTO, UserMod> {
final boolean changePwd,
final String password) {
- UserTO original = binder.getUserTO(key);
- original.getPropagationStatusTOs().addAll(provisioningManager.provision(key, changePwd, password, resources));
+ // security checks
+ UserTO user = binder.getUserTO(key);
+ Set<String> effectiveRealms = getEffectiveRealms(
+ AuthContextUtils.getAuthorizations().get(Entitlement.USER_UPDATE),
+ Collections.singleton(user.getRealm()));
+ securityChecks(effectiveRealms, user.getRealm(), user.getKey());
- return original;
+ user.getPropagationStatusTOs().addAll(provisioningManager.provision(key, changePwd, password, resources));
+ return user;
}
@Override
http://git-wip-us.apache.org/repos/asf/syncope/blob/bcb9a0d7/core/misc/src/main/java/org/apache/syncope/core/misc/RealmUtils.java
----------------------------------------------------------------------
diff --git a/core/misc/src/main/java/org/apache/syncope/core/misc/RealmUtils.java b/core/misc/src/main/java/org/apache/syncope/core/misc/RealmUtils.java
index 7a921ee..d8bacdb 100644
--- a/core/misc/src/main/java/org/apache/syncope/core/misc/RealmUtils.java
+++ b/core/misc/src/main/java/org/apache/syncope/core/misc/RealmUtils.java
@@ -24,8 +24,8 @@ import java.util.Set;
public final class RealmUtils {
- public static String getGroupOwnerRealm(final String realmPath, final Long groupId) {
- return realmPath + "@" + groupId;
+ public static String getGroupOwnerRealm(final String realmPath, final Long groupKey) {
+ return realmPath + "@" + groupKey;
}
public static boolean normalizingAddTo(final Set<String> realms, final String newRealm) {
http://git-wip-us.apache.org/repos/asf/syncope/blob/bcb9a0d7/core/misc/src/main/java/org/apache/syncope/core/misc/security/UnauthorizedException.java
----------------------------------------------------------------------
diff --git a/core/misc/src/main/java/org/apache/syncope/core/misc/security/UnauthorizedException.java b/core/misc/src/main/java/org/apache/syncope/core/misc/security/UnauthorizedException.java
index e5c2815..b2054cb 100644
--- a/core/misc/src/main/java/org/apache/syncope/core/misc/security/UnauthorizedException.java
+++ b/core/misc/src/main/java/org/apache/syncope/core/misc/security/UnauthorizedException.java
@@ -25,6 +25,9 @@ public class UnauthorizedException extends RuntimeException {
private static final long serialVersionUID = 7540587364235915081L;
public UnauthorizedException(final AnyTypeKind type, final Long key) {
- super("Missing entitlement or realm administration for " + type + " " + key);
+ super("Missing entitlement or realm administration for "
+ + (key == null
+ ? "new " + type
+ : type + " " + key));
}
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/bcb9a0d7/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARoleDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARoleDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARoleDAO.java
index 6fb5ec3..168241f 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARoleDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARoleDAO.java
@@ -30,6 +30,7 @@ import org.apache.syncope.core.persistence.api.entity.Realm;
import org.apache.syncope.core.persistence.api.entity.Role;
import org.apache.syncope.core.persistence.api.entity.user.User;
import org.apache.syncope.core.persistence.jpa.entity.JPARole;
+import org.apache.syncope.core.persistence.jpa.entity.user.JPAUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
@@ -95,6 +96,14 @@ public class JPARoleDAO extends AbstractDAO<Role, Long> implements RoleDAO {
@Override
public void delete(final Role role) {
+ TypedQuery<User> query = entityManager().createQuery(
+ "SELECT e FROM " + JPAUser.class.getSimpleName() + " e WHERE :role MEMBER OF e.roles", User.class);
+ query.setParameter("role", role);
+
+ for (User user : query.getResultList()) {
+ user.remove(role);
+ }
+
entityManager().remove(role);
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/bcb9a0d7/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/RoleTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/RoleTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/RoleTest.java
index c9c7ef2..9764e07 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/RoleTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/RoleTest.java
@@ -160,4 +160,37 @@ public class RoleTest extends AbstractTest {
dynRoleMemberships = findDynRoleMemberships(user);
assertTrue(dynRoleMemberships.isEmpty());
}
+
+ @Test
+ public void delete() {
+ // 0. create role
+ Role role = entityFactory.newEntity(Role.class);
+ role.setName("new");
+ role.addRealm(realmDAO.getRoot());
+ role.addRealm(realmDAO.find("/even/two"));
+ role.getEntitlements().add(Entitlement.LOG_LIST);
+ role.getEntitlements().add(Entitlement.LOG_SET_LEVEL);
+
+ role = roleDAO.save(role);
+ assertNotNull(role);
+
+ // 1. create user and assign that role
+ User user = entityFactory.newEntity(User.class);
+ user.setUsername("username");
+ user.setRealm(realmDAO.find("/even/two"));
+ user.add(role);
+
+ user = userDAO.save(user);
+ assertNotNull(user);
+
+ // 2. remove role
+ roleDAO.delete(role);
+
+ userDAO.flush();
+
+ // 3. verify that role was removed from user
+ user = userDAO.find(user.getKey());
+ assertNotNull(user);
+ assertTrue(user.getRoles().isEmpty());
+ }
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/bcb9a0d7/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserSelfServiceImpl.java
----------------------------------------------------------------------
diff --git a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserSelfServiceImpl.java b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserSelfServiceImpl.java
index 18013d2..4930bbb 100644
--- a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserSelfServiceImpl.java
+++ b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserSelfServiceImpl.java
@@ -48,7 +48,7 @@ public class UserSelfServiceImpl extends AbstractServiceImpl implements UserSelf
throw sce;
}
- UserTO created = logic.createSelf(userTO, storePassword);
+ UserTO created = logic.selfCreate(userTO, storePassword);
return createResponse(created.getKey(), created);
}
@@ -64,13 +64,13 @@ public class UserSelfServiceImpl extends AbstractServiceImpl implements UserSelf
@Override
public Response update(final UserMod userMod) {
- UserTO updated = logic.updateSelf(userMod);
+ UserTO updated = logic.selfUpdate(userMod);
return modificationResponse(updated);
}
@Override
public Response delete() {
- UserTO deleted = logic.deleteSelf();
+ UserTO deleted = logic.selfDelete();
return modificationResponse(deleted);
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/bcb9a0d7/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/AuthenticationITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/AuthenticationITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/AuthenticationITCase.java
index 6378631..cdfd1b1 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/AuthenticationITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/AuthenticationITCase.java
@@ -28,7 +28,7 @@ import java.security.AccessControlException;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
-
+import javax.ws.rs.core.Response;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.Predicate;
import org.apache.commons.collections4.Transformer;
@@ -54,6 +54,7 @@ import org.apache.syncope.common.lib.types.ResourceDeassociationActionType;
import org.apache.syncope.common.lib.types.SchemaType;
import org.apache.syncope.common.lib.wrap.ResourceKey;
import org.apache.syncope.common.rest.api.CollectionWrapper;
+import org.apache.syncope.common.rest.api.RESTHeaders;
import org.apache.syncope.common.rest.api.service.SchemaService;
import org.apache.syncope.common.rest.api.service.UserService;
import org.apache.syncope.core.misc.security.Encryptor;
@@ -234,6 +235,94 @@ public class AuthenticationITCase extends AbstractITCase {
}
@Test
+ public void delegatedUserCRUD() {
+ Long roleKey = null;
+ Long delegatedAdminKey = null;
+ try {
+ // 1. create role for full user administration, under realm /even/two
+ RoleTO role = new RoleTO();
+ role.setName("Delegated user admin");
+ role.getEntitlements().add(Entitlement.USER_CREATE);
+ role.getEntitlements().add(Entitlement.USER_UPDATE);
+ role.getEntitlements().add(Entitlement.USER_DELETE);
+ role.getEntitlements().add(Entitlement.USER_LIST);
+ role.getEntitlements().add(Entitlement.USER_READ);
+ role.getRealms().add("/even/two");
+
+ roleKey = Long.valueOf(roleService.create(role).getHeaderString(RESTHeaders.RESOURCE_KEY));
+ assertNotNull(roleKey);
+
+ // 2. as admin, create delegated admin user, and assign the role just created
+ UserTO delegatedAdmin = UserITCase.getUniqueSampleTO("admin@syncope.apache.org");
+ delegatedAdmin.getRoles().add(roleKey);
+ delegatedAdmin = createUser(delegatedAdmin);
+ delegatedAdminKey = delegatedAdmin.getKey();
+
+ // 3. instantiate a delegate user service client, for further operatins
+ UserService delegatedUserService =
+ clientFactory.create(delegatedAdmin.getUsername(), "password123").getService(UserService.class);
+
+ // 4. as delegated, create user under realm / -> fail
+ UserTO user = UserITCase.getUniqueSampleTO("delegated@syncope.apache.org");
+ try {
+ delegatedUserService.create(user);
+ fail();
+ } catch (SyncopeClientException e) {
+ assertEquals(ClientExceptionType.Unauthorized, e.getType());
+ }
+
+ // 5. set realm to /even/two -> succeed
+ user.setRealm("/even/two");
+
+ Response response = delegatedUserService.create(user);
+ assertEquals(Response.Status.CREATED.getStatusCode(), response.getStatus());
+
+ user = response.readEntity(UserTO.class);
+ assertEquals("surname", user.getPlainAttrMap().get("surname").getValues().get(0));
+
+ // 5. as delegated, update user attempting to move under realm / -> fail
+ UserMod userMod = new UserMod();
+ userMod.setKey(user.getKey());
+ userMod.setRealm("/odd");
+ userMod.getPlainAttrsToRemove().add("surname");
+ userMod.getPlainAttrsToUpdate().add(attrMod("surname", "surname2"));
+
+ try {
+ delegatedUserService.update(userMod);
+ fail();
+ } catch (SyncopeClientException e) {
+ assertEquals(ClientExceptionType.Unauthorized, e.getType());
+ }
+
+ // 6. revert realm change -> succeed
+ userMod.setRealm(null);
+
+ response = delegatedUserService.update(userMod);
+ assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
+
+ user = response.readEntity(UserTO.class);
+ assertEquals("surname2", user.getPlainAttrMap().get("surname").getValues().get(0));
+
+ // 7. as delegated, delete user
+ delegatedUserService.delete(user.getKey());
+
+ try {
+ userService.read(user.getKey());
+ fail();
+ } catch (SyncopeClientException e) {
+ assertEquals(ClientExceptionType.NotFound, e.getType());
+ }
+ } finally {
+ if (roleKey != null) {
+ roleService.delete(roleKey);
+ }
+ if (delegatedAdminKey != null) {
+ userService.delete(delegatedAdminKey);
+ }
+ }
+ }
+
+ @Test
public void checkFailedLogins() {
UserTO userTO = UserITCase.getUniqueSampleTO("checkFailedLogin@syncope.apache.org");
userTO.getRoles().add(2L);