You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by md...@apache.org on 2015/08/14 10:30:52 UTC
[23/31] syncope git commit: [SYNCOPE-652] Now account lockout is
working properly again
[SYNCOPE-652] Now account lockout is working properly again
Project: http://git-wip-us.apache.org/repos/asf/syncope/repo
Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/5cf6aae8
Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/5cf6aae8
Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/5cf6aae8
Branch: refs/heads/SYNCOPE-156
Commit: 5cf6aae8274d8e10b884ec9faeca54f623234836
Parents: 6dfedd8
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Tue Aug 11 08:18:54 2015 +0200
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Thu Aug 13 17:16:51 2015 +0200
----------------------------------------------------------------------
.../client/console/rest/UserRestClient.java | 6 +-
.../syncope/common/lib/mod/StatusMod.java | 2 +
.../common/rest/api/service/UserService.java | 2 +-
.../core/misc/security/AuthDataAccessor.java | 282 +++++++++++++++++++
.../security/SyncopeAuthenticationProvider.java | 276 +++++++-----------
.../security/SyncopeUserDetailsService.java | 88 +-----
.../misc/src/main/resources/securityContext.xml | 2 +
.../core/persistence/api/dao/UserDAO.java | 3 +
.../core/persistence/jpa/dao/JPADomainDAO.java | 2 +
.../core/persistence/jpa/dao/JPAUserDAO.java | 21 +-
.../api/UserProvisioningManager.java | 3 +-
.../core/provisioning/api/UserSuspender.java | 26 --
.../java/DefaultUserProvisioningManager.java | 13 +-
.../provisioning/java/UserSuspenderImpl.java | 51 ----
.../java/data/UserDataBinderImpl.java | 2 +-
.../core/rest/cxf/service/UserServiceImpl.java | 5 +-
.../activiti/ActivitiUserWorkflowAdapter.java | 15 +-
.../core/workflow/api/UserWorkflowAdapter.java | 9 +-
.../java/AbstractUserWorkflowAdapter.java | 54 +++-
.../camel/AbstractCamelProvisioningManager.java | 4 +-
.../camel/CamelUserProvisioningManager.java | 10 +-
.../processor/UserInnerSuspendProcessor.java | 61 ----
.../processor/UserInternalSuspendProcessor.java | 61 ++++
.../src/main/resources/userRoutes.xml | 12 +-
.../core/reference/AuthenticationITCase.java | 5 +-
.../syncope/fit/core/reference/UserITCase.java | 33 ++-
.../fit/core/reference/VirAttrITCase.java | 6 +-
pom.xml | 2 +-
28 files changed, 559 insertions(+), 497 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/syncope/blob/5cf6aae8/client/console/src/main/java/org/apache/syncope/client/console/rest/UserRestClient.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/rest/UserRestClient.java b/client/console/src/main/java/org/apache/syncope/client/console/rest/UserRestClient.java
index 5c5c062..d161658 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/rest/UserRestClient.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/rest/UserRestClient.java
@@ -124,20 +124,22 @@ public class UserRestClient extends AbstractAnyRestClient {
public void suspend(final String etag, final long userKey, final List<StatusBean> statuses) {
StatusMod statusMod = StatusUtils.buildStatusMod(statuses, false);
+ statusMod.setKey(userKey);
statusMod.setType(StatusMod.ModType.SUSPEND);
synchronized (this) {
UserService service = getService(etag, UserService.class);
- service.status(userKey, statusMod);
+ service.status(statusMod);
resetClient(UserService.class);
}
}
public void reactivate(final String etag, final long userKey, final List<StatusBean> statuses) {
StatusMod statusMod = StatusUtils.buildStatusMod(statuses, true);
+ statusMod.setKey(userKey);
statusMod.setType(StatusMod.ModType.REACTIVATE);
synchronized (this) {
UserService service = getService(etag, UserService.class);
- service.status(userKey, statusMod);
+ service.status(statusMod);
resetClient(UserService.class);
}
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/5cf6aae8/common/lib/src/main/java/org/apache/syncope/common/lib/mod/StatusMod.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/mod/StatusMod.java b/common/lib/src/main/java/org/apache/syncope/common/lib/mod/StatusMod.java
index 082b6f8..f989ecf 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/mod/StatusMod.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/mod/StatusMod.java
@@ -21,6 +21,7 @@ package org.apache.syncope.common.lib.mod;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.ArrayList;
import java.util.List;
+import javax.ws.rs.PathParam;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlEnum;
@@ -66,6 +67,7 @@ public class StatusMod extends AbstractBaseBean {
*/
private final List<String> resourceNames = new ArrayList<>();
+ @PathParam("key")
public long getKey() {
return key;
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/5cf6aae8/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserService.java
----------------------------------------------------------------------
diff --git a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserService.java b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserService.java
index bf1e6b7..6dbb56c 100644
--- a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserService.java
+++ b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserService.java
@@ -107,5 +107,5 @@ public interface UserService extends AnyService<UserTO, UserMod> {
@Path("{key}/status")
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
- Response status(@NotNull @PathParam("key") Long key, @NotNull StatusMod statusMod);
+ Response status(@NotNull StatusMod statusMod);
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/5cf6aae8/core/misc/src/main/java/org/apache/syncope/core/misc/security/AuthDataAccessor.java
----------------------------------------------------------------------
diff --git a/core/misc/src/main/java/org/apache/syncope/core/misc/security/AuthDataAccessor.java b/core/misc/src/main/java/org/apache/syncope/core/misc/security/AuthDataAccessor.java
new file mode 100644
index 0000000..7643f9d
--- /dev/null
+++ b/core/misc/src/main/java/org/apache/syncope/core/misc/security/AuthDataAccessor.java
@@ -0,0 +1,282 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.misc.security;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import javax.annotation.Resource;
+import org.apache.commons.collections4.Closure;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.IteratorUtils;
+import org.apache.commons.collections4.PredicateUtils;
+import org.apache.commons.collections4.SetUtils;
+import org.apache.commons.collections4.Transformer;
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.types.AuditElements;
+import org.apache.syncope.common.lib.types.Entitlement;
+import org.apache.syncope.core.misc.AuditManager;
+import org.apache.syncope.core.misc.MappingUtils;
+import org.apache.syncope.core.misc.RealmUtils;
+import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
+import org.apache.syncope.core.persistence.api.dao.ConfDAO;
+import org.apache.syncope.core.persistence.api.dao.DomainDAO;
+import org.apache.syncope.core.persistence.api.dao.GroupDAO;
+import org.apache.syncope.core.persistence.api.dao.NotFoundException;
+import org.apache.syncope.core.persistence.api.dao.RealmDAO;
+import org.apache.syncope.core.persistence.api.dao.UserDAO;
+import org.apache.syncope.core.persistence.api.entity.Domain;
+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.conf.CPlainAttr;
+import org.apache.syncope.core.persistence.api.entity.group.Group;
+import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
+import org.apache.syncope.core.persistence.api.entity.user.User;
+import org.apache.syncope.core.provisioning.api.ConnectorFactory;
+import org.identityconnectors.framework.common.objects.Uid;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.authentication.DisabledException;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.transaction.annotation.Transactional;
+
+public class AuthDataAccessor {
+
+ protected static final Logger LOG = LoggerFactory.getLogger(AuthDataAccessor.class);
+
+ @Resource(name = "adminUser")
+ protected String adminUser;
+
+ @Resource(name = "anonymousUser")
+ protected String anonymousUser;
+
+ @Autowired
+ protected DomainDAO domainDAO;
+
+ @Autowired
+ protected ConfDAO confDAO;
+
+ @Autowired
+ protected RealmDAO realmDAO;
+
+ @Autowired
+ protected UserDAO userDAO;
+
+ @Autowired
+ protected GroupDAO groupDAO;
+
+ @Autowired
+ protected AnyTypeDAO anyTypeDAO;
+
+ @Autowired
+ protected ConnectorFactory connFactory;
+
+ @Autowired
+ protected AuditManager auditManager;
+
+ protected final Encryptor encryptor = Encryptor.getInstance();
+
+ @Transactional(readOnly = true)
+ public Domain findDomain(final String key) {
+ Domain domain = domainDAO.find(key);
+ if (domain == null) {
+ throw new NotFoundException("Could not find domain " + key);
+ }
+ return domain;
+ }
+
+ @Transactional(noRollbackFor = DisabledException.class)
+ public Pair<Long, Boolean> authenticate(final Authentication authentication) {
+ Long key = null;
+ Boolean authenticated = false;
+
+ User user = userDAO.find(authentication.getName());
+ if (user != null) {
+ key = user.getKey();
+
+ if (user.isSuspended() != null && user.isSuspended()) {
+ throw new DisabledException("User " + user.getUsername() + " is suspended");
+ }
+
+ CPlainAttr authStatuses = confDAO.find("authentication.statuses");
+ if (authStatuses != null && !authStatuses.getValuesAsStrings().contains(user.getStatus())) {
+ throw new DisabledException("User " + user.getUsername() + " not allowed to authenticate");
+ }
+
+ boolean userModified = false;
+ authenticated = authenticate(user, authentication.getCredentials().toString());
+ if (authenticated) {
+ if (confDAO.find("log.lastlogindate", Boolean.toString(true)).getValues().get(0).getBooleanValue()) {
+ user.setLastLoginDate(new Date());
+ userModified = true;
+ }
+
+ if (user.getFailedLogins() != 0) {
+ user.setFailedLogins(0);
+ userModified = true;
+ }
+
+ } else {
+ user.setFailedLogins(user.getFailedLogins() + 1);
+ userModified = true;
+ }
+
+ if (userModified) {
+ userDAO.save(user);
+ }
+ }
+
+ return ImmutablePair.of(key, authenticated);
+ }
+
+ protected boolean authenticate(final User user, final String password) {
+ boolean authenticated = encryptor.verify(password, user.getCipherAlgorithm(), user.getPassword());
+ LOG.debug("{} authenticated on internal storage: {}", user.getUsername(), authenticated);
+
+ for (Iterator<? extends ExternalResource> itor = getPassthroughResources(user).iterator();
+ itor.hasNext() && !authenticated;) {
+
+ ExternalResource resource = itor.next();
+ String connObjectKey = null;
+ try {
+ connObjectKey = MappingUtils.getConnObjectKeyValue(user, resource.getProvision(anyTypeDAO.findUser()));
+ Uid uid = connFactory.getConnector(resource).authenticate(connObjectKey, password, null);
+ if (uid != null) {
+ authenticated = true;
+ }
+ } catch (Exception e) {
+ LOG.debug("Could not authenticate {} on {}", user.getUsername(), resource.getKey(), e);
+ }
+ LOG.debug("{} authenticated on {} as {}: {}",
+ user.getUsername(), resource.getKey(), connObjectKey, authenticated);
+ }
+
+ return authenticated;
+ }
+
+ protected Set<? extends ExternalResource> getPassthroughResources(final User user) {
+ Set<? extends ExternalResource> result = null;
+
+ // 1. look for assigned resources, pick the ones whose account policy has authentication resources
+ for (ExternalResource resource : userDAO.findAllResources(user)) {
+ if (resource.getAccountPolicy() != null && !resource.getAccountPolicy().getResources().isEmpty()) {
+ if (result == null) {
+ result = resource.getAccountPolicy().getResources();
+ } else {
+ result.retainAll(resource.getAccountPolicy().getResources());
+ }
+ }
+ }
+
+ // 2. look for realms, pick the ones whose account policy has authentication resources
+ for (Realm realm : realmDAO.findAncestors(user.getRealm())) {
+ if (realm.getAccountPolicy() != null && !realm.getAccountPolicy().getResources().isEmpty()) {
+ if (result == null) {
+ result = realm.getAccountPolicy().getResources();
+ } else {
+ result.retainAll(realm.getAccountPolicy().getResources());
+ }
+ }
+ }
+
+ return SetUtils.emptyIfNull(result);
+ }
+
+ @Transactional(readOnly = true)
+ public void audit(
+ final AuditElements.EventCategoryType type,
+ final String category,
+ final String subcategory,
+ final String event,
+ final AuditElements.Result result,
+ final Object before,
+ final Object output,
+ final Object... input) {
+
+ auditManager.audit(type, category, subcategory, event, result, before, output, input);
+ }
+
+ @Transactional
+ public Set<SyncopeGrantedAuthority> load(final String username) {
+ final Set<SyncopeGrantedAuthority> authorities = new HashSet<>();
+ if (anonymousUser.equals(username)) {
+ authorities.add(new SyncopeGrantedAuthority(Entitlement.ANONYMOUS));
+ } else if (adminUser.equals(username)) {
+ CollectionUtils.collect(IteratorUtils.filteredIterator(Entitlement.values().iterator(),
+ PredicateUtils.notPredicate(PredicateUtils.equalPredicate(Entitlement.ANONYMOUS))),
+ new Transformer<String, SyncopeGrantedAuthority>() {
+
+ @Override
+ public SyncopeGrantedAuthority transform(final String entitlement) {
+ return new SyncopeGrantedAuthority(entitlement, SyncopeConstants.ROOT_REALM);
+ }
+ },
+ authorities);
+ } else {
+ User user = userDAO.find(username);
+ if (user == null) {
+ throw new UsernameNotFoundException("Could not find any user with id " + username);
+ }
+
+ // Give entitlements as assigned by roles (with realms, where applicable) - assigned either
+ // statically and dynamically
+ for (final Role role : userDAO.findAllRoles(user)) {
+ CollectionUtils.forAllDo(role.getEntitlements(), new Closure<String>() {
+
+ @Override
+ public void execute(final String entitlement) {
+ SyncopeGrantedAuthority authority = new SyncopeGrantedAuthority(entitlement);
+ authorities.add(authority);
+
+ List<String> realmFullPahs = new ArrayList<>();
+ CollectionUtils.collect(role.getRealms(), new Transformer<Realm, String>() {
+
+ @Override
+ public String transform(final Realm realm) {
+ return realm.getFullPath();
+ }
+ }, realmFullPahs);
+ authority.addRealms(realmFullPahs);
+ }
+ });
+ }
+
+ // Give group entitlements for owned groups
+ for (Group group : groupDAO.findOwnedByUser(user.getKey())) {
+ for (String entitlement : Arrays.asList(
+ Entitlement.GROUP_READ, Entitlement.GROUP_UPDATE, Entitlement.GROUP_DELETE)) {
+
+ SyncopeGrantedAuthority authority = new SyncopeGrantedAuthority(entitlement);
+ authority.addRealm(RealmUtils.getGroupOwnerRealm(group.getRealm().getFullPath(), group.getKey()));
+ authorities.add(authority);
+ }
+ }
+ }
+
+ return authorities;
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/5cf6aae8/core/misc/src/main/java/org/apache/syncope/core/misc/security/SyncopeAuthenticationProvider.java
----------------------------------------------------------------------
diff --git a/core/misc/src/main/java/org/apache/syncope/core/misc/security/SyncopeAuthenticationProvider.java b/core/misc/src/main/java/org/apache/syncope/core/misc/security/SyncopeAuthenticationProvider.java
index f452128..c8fa53d 100644
--- a/core/misc/src/main/java/org/apache/syncope/core/misc/security/SyncopeAuthenticationProvider.java
+++ b/core/misc/src/main/java/org/apache/syncope/core/misc/security/SyncopeAuthenticationProvider.java
@@ -18,44 +18,26 @@
*/
package org.apache.syncope.core.misc.security;
-import java.util.Date;
-import java.util.Iterator;
-import java.util.Set;
import javax.annotation.Resource;
-import org.apache.commons.collections4.SetUtils;
import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.tuple.Pair;
import org.apache.syncope.common.lib.SyncopeConstants;
import org.apache.syncope.common.lib.types.AuditElements;
import org.apache.syncope.common.lib.types.AuditElements.Result;
import org.apache.syncope.common.lib.types.CipherAlgorithm;
-import org.apache.syncope.core.persistence.api.dao.ConfDAO;
-import org.apache.syncope.core.persistence.api.dao.PolicyDAO;
-import org.apache.syncope.core.persistence.api.dao.UserDAO;
-import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
-import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
-import org.apache.syncope.core.persistence.api.entity.conf.CPlainAttr;
-import org.apache.syncope.core.persistence.api.entity.user.User;
-import org.apache.syncope.core.provisioning.api.ConnectorFactory;
-import org.apache.syncope.core.misc.AuditManager;
-import org.apache.syncope.core.misc.MappingUtils;
-import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
-import org.apache.syncope.core.persistence.api.dao.DomainDAO;
-import org.apache.syncope.core.persistence.api.dao.NotFoundException;
-import org.apache.syncope.core.persistence.api.dao.RealmDAO;
import org.apache.syncope.core.persistence.api.entity.Domain;
-import org.apache.syncope.core.persistence.api.entity.Realm;
-import org.identityconnectors.framework.common.objects.Uid;
+import org.apache.syncope.core.provisioning.api.UserProvisioningManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
-import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContext;
+import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetailsService;
-import org.springframework.transaction.annotation.Transactional;
@Configurable
public class SyncopeAuthenticationProvider implements AuthenticationProvider {
@@ -63,31 +45,10 @@ public class SyncopeAuthenticationProvider implements AuthenticationProvider {
protected static final Logger LOG = LoggerFactory.getLogger(SyncopeAuthenticationProvider.class);
@Autowired
- protected AuditManager auditManager;
+ protected AuthDataAccessor dataAccessor;
@Autowired
- protected DomainDAO domainDAO;
-
- @Autowired
- protected ConfDAO confDAO;
-
- @Autowired
- protected RealmDAO realmDAO;
-
- @Autowired
- protected UserDAO userDAO;
-
- @Autowired
- protected PolicyDAO policyDAO;
-
- @Autowired
- protected AnyTypeDAO anyTypeDAO;
-
- @Autowired
- protected ConnectorFactory connFactory;
-
- @Autowired
- protected AnyUtilsFactory attrUtilsFactory;
+ protected UserProvisioningManager provisioningManager;
@Resource(name = "adminUser")
protected String adminUser;
@@ -130,19 +91,26 @@ public class SyncopeAuthenticationProvider implements AuthenticationProvider {
this.userDetailsService = syncopeUserDetailsService;
}
+ protected <T> T execWithAuthContext(final String domainKey, final Executable<T> executable) {
+ SecurityContext ctx = SecurityContextHolder.getContext();
+ AuthContextUtils.setFakeAuth(domainKey);
+ try {
+ return executable.exec();
+ } finally {
+ AuthContextUtils.clearFakeAuth();
+ SecurityContextHolder.setContext(ctx);
+ }
+ }
+
@Override
- @Transactional(noRollbackFor = { BadCredentialsException.class, DisabledException.class })
public Authentication authenticate(final Authentication authentication) {
- boolean authenticated = false;
-
- String domainKey = authentication.getDetails() instanceof SyncopeAuthenticationDetails
- ? SyncopeAuthenticationDetails.class.cast(authentication.getDetails()).getDomain()
- : null;
+ String domainKey = SyncopeAuthenticationDetails.class.cast(authentication.getDetails()).getDomain();
if (StringUtils.isBlank(domainKey)) {
domainKey = SyncopeConstants.MASTER_DOMAIN;
}
SyncopeAuthenticationDetails.class.cast(authentication.getDetails()).setDomain(domainKey);
+ boolean authenticated;
if (anonymousUser.equals(authentication.getName())) {
authenticated = authentication.getCredentials().toString().equals(anonymousKey);
} else if (adminUser.equals(authentication.getName())) {
@@ -152,67 +120,90 @@ public class SyncopeAuthenticationProvider implements AuthenticationProvider {
CipherAlgorithm.valueOf(adminPasswordAlgorithm),
adminPassword);
} else {
- Domain domain = domainDAO.find(domainKey);
- if (domain == null) {
- throw new NotFoundException("Could not find domain " + domainKey);
- }
-
- authenticated = encryptor.verify(
- authentication.getCredentials().toString(),
- domain.getAdminCipherAlgorithm(),
- domain.getAdminPwd());
+ final String domainToFind = domainKey;
+ authenticated = execWithAuthContext(SyncopeConstants.MASTER_DOMAIN, new Executable<Boolean>() {
+
+ @Override
+ public Boolean exec() {
+ Domain domain = dataAccessor.findDomain(domainToFind);
+
+ return encryptor.verify(
+ authentication.getCredentials().toString(),
+ domain.getAdminCipherAlgorithm(),
+ domain.getAdminPwd());
+ }
+ });
}
} else {
- User user = userDAO.find(authentication.getName());
-
- if (user != null) {
- if (user.isSuspended() != null && user.isSuspended()) {
- throw new DisabledException("User " + user.getUsername() + " is suspended");
- }
-
- CPlainAttr authStatuses = confDAO.find("authentication.statuses");
- if (authStatuses != null && !authStatuses.getValuesAsStrings().contains(user.getStatus())) {
- throw new DisabledException("User " + user.getUsername() + " not allowed to authenticate");
- }
-
- authenticated = authenticate(user, authentication.getCredentials().toString());
-
- updateLoginAttributes(user, authenticated);
+ final Pair<Long, Boolean> authResult =
+ execWithAuthContext(domainKey, new Executable<Pair<Long, Boolean>>() {
+
+ @Override
+ public Pair<Long, Boolean> exec() {
+ return dataAccessor.authenticate(authentication);
+ }
+ });
+ authenticated = authResult.getValue();
+ if (!authenticated) {
+ execWithAuthContext(domainKey, new Executable<Void>() {
+
+ @Override
+ public Void exec() {
+ provisioningManager.internalSuspend(authResult.getKey());
+ return null;
+ }
+ });
}
}
+ final boolean isAuthenticated = authenticated;
UsernamePasswordAuthenticationToken token;
- if (authenticated) {
- token = new UsernamePasswordAuthenticationToken(
- authentication.getPrincipal(),
- null,
- userDetailsService.loadUserByUsername(authentication.getPrincipal().toString()).getAuthorities());
- token.setDetails(authentication.getDetails());
-
- auditManager.audit(
- AuditElements.EventCategoryType.REST,
- AuditElements.AUTHENTICATION_CATEGORY,
- null,
- AuditElements.LOGIN_EVENT,
- Result.SUCCESS,
- null,
- authenticated,
- authentication,
- "Successfully authenticated, with entitlements: " + token.getAuthorities());
+ if (isAuthenticated) {
+ token = execWithAuthContext(domainKey, new Executable<UsernamePasswordAuthenticationToken>() {
+
+ @Override
+ public UsernamePasswordAuthenticationToken exec() {
+ UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
+ authentication.getPrincipal(),
+ null,
+ userDetailsService.loadUserByUsername(authentication.getPrincipal().toString()).
+ getAuthorities());
+ token.setDetails(authentication.getDetails());
+
+ dataAccessor.audit(
+ AuditElements.EventCategoryType.REST,
+ AuditElements.AUTHENTICATION_CATEGORY,
+ null,
+ AuditElements.LOGIN_EVENT,
+ Result.SUCCESS,
+ null,
+ isAuthenticated,
+ authentication,
+ "Successfully authenticated, with entitlements: " + token.getAuthorities());
+ return token;
+ }
+ });
LOG.debug("User {} successfully authenticated, with groups {}",
authentication.getPrincipal(), token.getAuthorities());
} else {
- auditManager.audit(
- AuditElements.EventCategoryType.REST,
- AuditElements.AUTHENTICATION_CATEGORY,
- null,
- AuditElements.LOGIN_EVENT,
- Result.FAILURE,
- null,
- authenticated,
- authentication,
- "User " + authentication.getPrincipal() + " not authenticated");
+ execWithAuthContext(domainKey, new Executable<Void>() {
+
+ @Override
+ public Void exec() {
+ dataAccessor.audit(
+ AuditElements.EventCategoryType.REST,
+ AuditElements.AUTHENTICATION_CATEGORY,
+ null,
+ AuditElements.LOGIN_EVENT,
+ Result.FAILURE,
+ null,
+ isAuthenticated,
+ authentication,
+ "User " + authentication.getPrincipal() + " not authenticated");
+ return null;
+ }
+ });
LOG.debug("User {} not authenticated", authentication.getPrincipal());
@@ -222,84 +213,13 @@ public class SyncopeAuthenticationProvider implements AuthenticationProvider {
return token;
}
- protected void updateLoginAttributes(final User user, final boolean authenticated) {
- boolean userModified = false;
-
- if (authenticated) {
- if (confDAO.find("log.lastlogindate", Boolean.toString(true)).getValues().get(0).getBooleanValue()) {
- user.setLastLoginDate(new Date());
- userModified = true;
- }
-
- if (user.getFailedLogins() != 0) {
- user.setFailedLogins(0);
- userModified = true;
- }
- } else {
- user.setFailedLogins(user.getFailedLogins() + 1);
- userModified = true;
- }
-
- if (userModified) {
- userDAO.save(user);
- }
- }
-
- protected Set<? extends ExternalResource> getPassthroughResources(final User user) {
- Set<? extends ExternalResource> result = null;
-
- // 1. look for assigned resources, pick the ones whose account policy has authentication resources
- for (ExternalResource resource : userDAO.findAllResources(user)) {
- if (resource.getAccountPolicy() != null && !resource.getAccountPolicy().getResources().isEmpty()) {
- if (result == null) {
- result = resource.getAccountPolicy().getResources();
- } else {
- result.retainAll(resource.getAccountPolicy().getResources());
- }
- }
- }
-
- // 2. look for realms, pick the ones whose account policy has authentication resources
- for (Realm realm : realmDAO.findAncestors(user.getRealm())) {
- if (realm.getAccountPolicy() != null && !realm.getAccountPolicy().getResources().isEmpty()) {
- if (result == null) {
- result = realm.getAccountPolicy().getResources();
- } else {
- result.retainAll(realm.getAccountPolicy().getResources());
- }
- }
- }
-
- return SetUtils.emptyIfNull(result);
- }
-
- protected boolean authenticate(final User user, final String password) {
- boolean authenticated = encryptor.verify(password, user.getCipherAlgorithm(), user.getPassword());
- LOG.debug("{} authenticated on internal storage: {}", user.getUsername(), authenticated);
-
- for (Iterator<? extends ExternalResource> itor = getPassthroughResources(user).iterator();
- itor.hasNext() && !authenticated;) {
-
- ExternalResource resource = itor.next();
- String connObjectKey = null;
- try {
- connObjectKey = MappingUtils.getConnObjectKeyValue(user, resource.getProvision(anyTypeDAO.findUser()));
- Uid uid = connFactory.getConnector(resource).authenticate(connObjectKey, password, null);
- if (uid != null) {
- authenticated = true;
- }
- } catch (Exception e) {
- LOG.debug("Could not authenticate {} on {}", user.getUsername(), resource.getKey(), e);
- }
- LOG.debug("{} authenticated on {} as {}: {}",
- user.getUsername(), resource.getKey(), connObjectKey, authenticated);
- }
-
- return authenticated;
- }
-
@Override
public boolean supports(final Class<? extends Object> type) {
return type.equals(UsernamePasswordAuthenticationToken.class);
}
+
+ protected interface Executable<T> {
+
+ T exec();
+ }
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/5cf6aae8/core/misc/src/main/java/org/apache/syncope/core/misc/security/SyncopeUserDetailsService.java
----------------------------------------------------------------------
diff --git a/core/misc/src/main/java/org/apache/syncope/core/misc/security/SyncopeUserDetailsService.java b/core/misc/src/main/java/org/apache/syncope/core/misc/security/SyncopeUserDetailsService.java
index a179e75..70ec6ac 100644
--- a/core/misc/src/main/java/org/apache/syncope/core/misc/security/SyncopeUserDetailsService.java
+++ b/core/misc/src/main/java/org/apache/syncope/core/misc/security/SyncopeUserDetailsService.java
@@ -18,104 +18,20 @@
*/
package org.apache.syncope.core.misc.security;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import javax.annotation.Resource;
-import org.apache.commons.collections4.Closure;
-import org.apache.commons.collections4.CollectionUtils;
-import org.apache.commons.collections4.IteratorUtils;
-import org.apache.commons.collections4.PredicateUtils;
-import org.apache.commons.collections4.Transformer;
-import org.apache.syncope.common.lib.SyncopeConstants;
-import org.apache.syncope.common.lib.types.Entitlement;
-import org.apache.syncope.core.misc.RealmUtils;
-import org.apache.syncope.core.persistence.api.dao.GroupDAO;
-import org.apache.syncope.core.persistence.api.dao.UserDAO;
-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.group.Group;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
-import org.springframework.security.core.userdetails.UsernameNotFoundException;
@Configurable
public class SyncopeUserDetailsService implements UserDetailsService {
@Autowired
- protected UserDAO userDAO;
-
- @Autowired
- protected GroupDAO groupDAO;
-
- @Resource(name = "adminUser")
- protected String adminUser;
-
- @Resource(name = "anonymousUser")
- protected String anonymousUser;
+ protected AuthDataAccessor dataAccessor;
@Override
public UserDetails loadUserByUsername(final String username) {
- final Set<SyncopeGrantedAuthority> authorities = new HashSet<>();
- if (anonymousUser.equals(username)) {
- authorities.add(new SyncopeGrantedAuthority(Entitlement.ANONYMOUS));
- } else if (adminUser.equals(username)) {
- CollectionUtils.collect(IteratorUtils.filteredIterator(Entitlement.values().iterator(),
- PredicateUtils.notPredicate(PredicateUtils.equalPredicate(Entitlement.ANONYMOUS))),
- new Transformer<String, SyncopeGrantedAuthority>() {
-
- @Override
- public SyncopeGrantedAuthority transform(final String entitlement) {
- return new SyncopeGrantedAuthority(entitlement, SyncopeConstants.ROOT_REALM);
- }
- },
- authorities);
- } else {
- org.apache.syncope.core.persistence.api.entity.user.User user = userDAO.find(username);
- if (user == null) {
- throw new UsernameNotFoundException("Could not find any user with id " + username);
- }
-
- // Give entitlements as assigned by roles (with realms, where applicable) - assigned either
- // statically and dynamically
- for (final Role role : userDAO.findAllRoles(user)) {
- CollectionUtils.forAllDo(role.getEntitlements(), new Closure<String>() {
-
- @Override
- public void execute(final String entitlement) {
- SyncopeGrantedAuthority authority = new SyncopeGrantedAuthority(entitlement);
- authorities.add(authority);
-
- List<String> realmFullPahs = new ArrayList<>();
- CollectionUtils.collect(role.getRealms(), new Transformer<Realm, String>() {
-
- @Override
- public String transform(final Realm realm) {
- return realm.getFullPath();
- }
- }, realmFullPahs);
- authority.addRealms(realmFullPahs);
- }
- });
- }
-
- // Give group entitlements for owned groups
- for (Group group : groupDAO.findOwnedByUser(user.getKey())) {
- for (String entitlement : Arrays.asList(
- Entitlement.GROUP_READ, Entitlement.GROUP_UPDATE, Entitlement.GROUP_DELETE)) {
-
- SyncopeGrantedAuthority authority = new SyncopeGrantedAuthority(entitlement);
- authority.addRealm(RealmUtils.getGroupOwnerRealm(group.getRealm().getFullPath(), group.getKey()));
- authorities.add(authority);
- }
- }
- }
-
- return new User(username, "<PASSWORD_PLACEHOLDER>", authorities);
+ return new User(username, "<PASSWORD_PLACEHOLDER>", dataAccessor.load(username));
}
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/5cf6aae8/core/misc/src/main/resources/securityContext.xml
----------------------------------------------------------------------
diff --git a/core/misc/src/main/resources/securityContext.xml b/core/misc/src/main/resources/securityContext.xml
index 57b1980..1022815 100644
--- a/core/misc/src/main/resources/securityContext.xml
+++ b/core/misc/src/main/resources/securityContext.xml
@@ -62,6 +62,8 @@ under the License.
<security:csrf disabled="true"/>
</security:http>
+ <bean class="org.apache.syncope.core.misc.security.AuthDataAccessor"/>
+
<bean id="syncopeUserDetailsService" class="org.apache.syncope.core.misc.security.SyncopeUserDetailsService"/>
<bean id="syncopeAuthenticationProvider" class="org.apache.syncope.core.misc.security.SyncopeAuthenticationProvider">
http://git-wip-us.apache.org/repos/asf/syncope/blob/5cf6aae8/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/UserDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/UserDAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/UserDAO.java
index a1e4d09..3fc9b99 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/UserDAO.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/UserDAO.java
@@ -20,6 +20,7 @@ package org.apache.syncope.core.persistence.api.dao;
import java.util.Collection;
import java.util.List;
+import org.apache.commons.lang3.tuple.Pair;
import org.apache.syncope.core.persistence.api.entity.Role;
import org.apache.syncope.core.persistence.api.entity.group.Group;
import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
@@ -49,4 +50,6 @@ public interface UserDAO extends AnyDAO<User> {
Collection<ExternalResource> findAllResources(User user);
Collection<String> findAllResourceNames(User user);
+
+ Pair<Boolean, Boolean> enforcePolicies(User user);
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/5cf6aae8/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADomainDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADomainDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADomainDAO.java
index b3bb188..eeee97c 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADomainDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADomainDAO.java
@@ -24,10 +24,12 @@ import org.apache.syncope.core.persistence.api.dao.DomainDAO;
import org.apache.syncope.core.persistence.api.entity.Domain;
import org.apache.syncope.core.persistence.jpa.entity.JPADomain;
import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
@Repository
public class JPADomainDAO extends AbstractDAO<Domain, String> implements DomainDAO {
+ @Transactional(readOnly = true)
@Override
public Domain find(final String key) {
return entityManager().find(JPADomain.class, key);
http://git-wip-us.apache.org/repos/asf/syncope/blob/5cf6aae8/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAUserDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAUserDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAUserDAO.java
index 50564f2..4e9afe1 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAUserDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAUserDAO.java
@@ -63,7 +63,6 @@ import org.apache.syncope.core.persistence.api.entity.user.UMembership;
import org.apache.syncope.core.persistence.jpa.entity.JPAAnyUtilsFactory;
import org.apache.syncope.core.persistence.jpa.entity.user.JPADynRoleMembership;
import org.apache.syncope.core.persistence.jpa.entity.user.JPAUDynGroupMembership;
-import org.apache.syncope.core.provisioning.api.UserSuspender;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
@@ -96,9 +95,6 @@ public class JPAUserDAO extends AbstractAnyDAO<User> implements UserDAO {
@Autowired
private AccountPolicyEnforcer apEnforcer;
- @Autowired(required = false)
- private UserSuspender suspender;
-
@Override
protected AnyUtils init() {
return new JPAAnyUtilsFactory().getInstance(AnyTypeKind.USER);
@@ -210,11 +206,9 @@ public class JPAUserDAO extends AbstractAnyDAO<User> implements UserDAO {
private List<AccountPolicy> getAccountPolicies(final User user) {
List<AccountPolicy> policies = new ArrayList<>();
- AccountPolicy policy;
-
// add resource policies
for (ExternalResource resource : findAllResources(user)) {
- policy = resource.getAccountPolicy();
+ AccountPolicy policy = resource.getAccountPolicy();
if (policy != null) {
policies.add(policy);
}
@@ -222,7 +216,7 @@ public class JPAUserDAO extends AbstractAnyDAO<User> implements UserDAO {
// add realm policies
for (Realm realm : realmDAO.findAncestors(user.getRealm())) {
- policy = realm.getAccountPolicy();
+ AccountPolicy policy = realm.getAccountPolicy();
if (policy != null) {
policies.add(policy);
}
@@ -231,7 +225,9 @@ public class JPAUserDAO extends AbstractAnyDAO<User> implements UserDAO {
return policies;
}
- private Pair<Boolean, Boolean> enforcePolicies(final User user) {
+ @Transactional(readOnly = true)
+ @Override
+ public Pair<Boolean, Boolean> enforcePolicies(final User user) {
// ------------------------------
// Verify password policies
// ------------------------------
@@ -310,18 +306,13 @@ public class JPAUserDAO extends AbstractAnyDAO<User> implements UserDAO {
JPAUser.class.cast(merged).setClearPassword(clearPwd);
// 4. enforce password and account policies
- Pair<Boolean, Boolean> enforceSuspend = null;
try {
- enforceSuspend = enforcePolicies(merged);
+ enforcePolicies(merged);
} catch (InvalidEntityException e) {
entityManager().remove(merged);
throw e;
}
- if (suspender != null && enforceSuspend.getKey()) {
- suspender.suspend(user, enforceSuspend.getValue());
- }
-
roleDAO.refreshDynMemberships(merged);
groupDAO.refreshDynMemberships(merged);
http://git-wip-us.apache.org/repos/asf/syncope/blob/5cf6aae8/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/UserProvisioningManager.java
----------------------------------------------------------------------
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/UserProvisioningManager.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/UserProvisioningManager.java
index 3378707..21acad2 100644
--- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/UserProvisioningManager.java
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/UserProvisioningManager.java
@@ -26,7 +26,6 @@ import org.apache.syncope.common.lib.mod.StatusMod;
import org.apache.syncope.common.lib.mod.UserMod;
import org.apache.syncope.common.lib.to.PropagationStatus;
import org.apache.syncope.common.lib.to.UserTO;
-import org.apache.syncope.core.persistence.api.entity.user.User;
import org.apache.syncope.core.provisioning.api.sync.ProvisioningResult;
public interface UserProvisioningManager extends ProvisioningManager<UserTO, UserMod> {
@@ -37,7 +36,7 @@ public interface UserProvisioningManager extends ProvisioningManager<UserTO, Use
Pair<Long, List<PropagationStatus>> suspend(StatusMod statusMod);
- void innerSuspend(User user, boolean propagate);
+ void internalSuspend(Long key);
Pair<Long, List<PropagationStatus>> create(UserTO userTO, boolean storePassword);
http://git-wip-us.apache.org/repos/asf/syncope/blob/5cf6aae8/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/UserSuspender.java
----------------------------------------------------------------------
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/UserSuspender.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/UserSuspender.java
deleted file mode 100644
index 610513c..0000000
--- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/UserSuspender.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.core.provisioning.api;
-
-import org.apache.syncope.core.persistence.api.entity.user.User;
-
-public interface UserSuspender {
-
- void suspend(User user, boolean propagateSuspension);
-}
http://git-wip-us.apache.org/repos/asf/syncope/blob/5cf6aae8/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultUserProvisioningManager.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultUserProvisioningManager.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultUserProvisioningManager.java
index 0809607..38264de 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultUserProvisioningManager.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultUserProvisioningManager.java
@@ -288,19 +288,18 @@ public class DefaultUserProvisioningManager implements UserProvisioningManager {
}
@Override
- public void innerSuspend(final User user, final boolean propagate) {
- final WorkflowResult<Long> updated = uwfAdapter.suspend(user);
+ public void internalSuspend(final Long key) {
+ Pair<WorkflowResult<Long>, Boolean> updated = uwfAdapter.internalSuspend(key);
// propagate suspension if and only if it is required by policy
- if (propagate) {
+ if (updated != null && updated.getValue()) {
UserMod userMod = new UserMod();
- userMod.setKey(updated.getResult());
+ userMod.setKey(updated.getKey().getResult());
- final List<PropagationTask> tasks = propagationManager.getUserUpdateTasks(
+ List<PropagationTask> tasks = propagationManager.getUserUpdateTasks(
new WorkflowResult<Pair<UserMod, Boolean>>(
new ImmutablePair<>(userMod, Boolean.FALSE),
- updated.getPropByRes(), updated.getPerformedTasks()));
-
+ updated.getKey().getPropByRes(), updated.getKey().getPerformedTasks()));
taskExecutor.execute(tasks);
}
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/5cf6aae8/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/UserSuspenderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/UserSuspenderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/UserSuspenderImpl.java
deleted file mode 100644
index 7ff9e84..0000000
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/UserSuspenderImpl.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.core.provisioning.java;
-
-import org.apache.syncope.core.persistence.api.entity.user.User;
-import org.apache.syncope.core.provisioning.api.UserSuspender;
-import org.apache.syncope.core.provisioning.api.UserProvisioningManager;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-
-@Component
-public class UserSuspenderImpl implements UserSuspender {
-
- private static final Logger LOG = LoggerFactory.getLogger(UserSuspenderImpl.class);
-
- @Autowired
- private UserProvisioningManager provisioningManager;
-
- @Override
- public void suspend(final User user, final boolean suspend) {
- try {
- LOG.debug("User {}:{} is over to max failed logins", user.getKey(), user.getUsername());
-
- // reduce failed logins number to avoid multiple request
- user.setFailedLogins(user.getFailedLogins() - 1);
-
- // disable user and propagate suspension if and only if it is required by policy
- provisioningManager.innerSuspend(user, suspend);
- } catch (Exception e) {
- LOG.error("Error during user suspension", e);
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/syncope/blob/5cf6aae8/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java
index f52b941..459c052 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java
@@ -88,7 +88,7 @@ public class UserDataBinderImpl extends AbstractAnyDataBinder implements UserDat
public UserTO getAuthenticatedUserTO() {
final UserTO authUserTO;
- final String authUsername = AuthContextUtils.getUsername();
+ String authUsername = AuthContextUtils.getUsername();
if (anonymousUser.equals(authUsername)) {
authUserTO = new UserTO();
authUserTO.setKey(-2);
http://git-wip-us.apache.org/repos/asf/syncope/blob/5cf6aae8/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserServiceImpl.java
----------------------------------------------------------------------
diff --git a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserServiceImpl.java b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserServiceImpl.java
index 391aea8..2447697 100644
--- a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserServiceImpl.java
+++ b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserServiceImpl.java
@@ -62,12 +62,11 @@ public class UserServiceImpl extends AbstractAnyService<UserTO, UserMod> impleme
}
@Override
- public Response status(final Long key, final StatusMod statusMod) {
- UserTO user = logic.read(key);
+ public Response status(final StatusMod statusMod) {
+ UserTO user = logic.read(statusMod.getKey());
checkETag(user.getETagValue());
- statusMod.setKey(key);
UserTO updated = logic.status(statusMod);
return modificationResponse(updated);
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/5cf6aae8/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/ActivitiUserWorkflowAdapter.java
----------------------------------------------------------------------
diff --git a/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/ActivitiUserWorkflowAdapter.java b/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/ActivitiUserWorkflowAdapter.java
index 1ce0d97..7a4ba38 100644
--- a/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/ActivitiUserWorkflowAdapter.java
+++ b/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/ActivitiUserWorkflowAdapter.java
@@ -74,8 +74,6 @@ import org.apache.syncope.core.provisioning.api.data.UserDataBinder;
import org.apache.syncope.core.workflow.api.WorkflowDefinitionFormat;
import org.apache.syncope.core.workflow.api.WorkflowException;
import org.apache.syncope.core.workflow.java.AbstractUserWorkflowAdapter;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
@@ -84,8 +82,6 @@ import org.springframework.transaction.annotation.Transactional;
*/
public class ActivitiUserWorkflowAdapter extends AbstractUserWorkflowAdapter {
- protected static final Logger LOG = LoggerFactory.getLogger(ActivitiUserWorkflowAdapter.class);
-
protected static final String[] PROPERTY_IGNORE_PROPS = { "type" };
public static final String WF_PROCESS_ID = "userWorkflow";
@@ -279,7 +275,7 @@ public class ActivitiUserWorkflowAdapter extends AbstractUserWorkflowAdapter {
protected Set<String> doExecuteTask(final User user, final String task, final Map<String, Object> moreVariables) {
Set<String> preTasks = getPerformedTasks(user);
- final Map<String, Object> variables = new HashMap<>();
+ Map<String, Object> variables = new HashMap<>();
variables.put(WF_EXECUTOR, AuthContextUtils.getUsername());
variables.put(TASK, task);
@@ -345,7 +341,6 @@ public class ActivitiUserWorkflowAdapter extends AbstractUserWorkflowAdapter {
}
@Override
- @Transactional(rollbackFor = { Throwable.class })
protected WorkflowResult<Long> doSuspend(final User user) {
Set<String> performedTasks = doExecuteTask(user, "suspend", null);
updateStatus(user);
@@ -661,7 +656,7 @@ public class ActivitiUserWorkflowAdapter extends AbstractUserWorkflowAdapter {
public List<WorkflowFormTO> getForms() {
List<WorkflowFormTO> forms = new ArrayList<>();
- final String authUser = AuthContextUtils.getUsername();
+ String authUser = AuthContextUtils.getUsername();
if (adminUser.equals(authUser)) {
forms.addAll(getForms(engine.getTaskService().createTaskQuery().
taskVariableValueEquals(TASK_IS_FORM, Boolean.TRUE)));
@@ -772,10 +767,9 @@ public class ActivitiUserWorkflowAdapter extends AbstractUserWorkflowAdapter {
return new ImmutablePair<>(task, formData);
}
- @Transactional
@Override
public WorkflowFormTO claimForm(final String taskId) {
- final String authUser = AuthContextUtils.getUsername();
+ String authUser = AuthContextUtils.getUsername();
Pair<Task, TaskFormData> checked = checkTask(taskId, authUser);
if (!adminUser.equals(authUser)) {
@@ -798,10 +792,9 @@ public class ActivitiUserWorkflowAdapter extends AbstractUserWorkflowAdapter {
return getFormTO(task, checked.getValue());
}
- @Transactional
@Override
public WorkflowResult<UserMod> submitForm(final WorkflowFormTO form) {
- final String authUser = AuthContextUtils.getUsername();
+ String authUser = AuthContextUtils.getUsername();
Pair<Task, TaskFormData> checked = checkTask(form.getTaskId(), authUser);
if (!checked.getKey().getOwner().equals(authUser)) {
http://git-wip-us.apache.org/repos/asf/syncope/blob/5cf6aae8/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/UserWorkflowAdapter.java
----------------------------------------------------------------------
diff --git a/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/UserWorkflowAdapter.java b/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/UserWorkflowAdapter.java
index fbf29c3..7122b84 100644
--- a/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/UserWorkflowAdapter.java
+++ b/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/UserWorkflowAdapter.java
@@ -22,7 +22,6 @@ import org.apache.commons.lang3.tuple.Pair;
import org.apache.syncope.core.provisioning.api.WorkflowResult;
import org.apache.syncope.common.lib.mod.UserMod;
import org.apache.syncope.common.lib.to.UserTO;
-import org.apache.syncope.core.persistence.api.entity.user.User;
/**
* Interface for calling underlying workflow implementations.
@@ -96,12 +95,12 @@ public interface UserWorkflowAdapter extends WorkflowAdapter {
WorkflowResult<Long> suspend(Long key);
/**
- * Suspend an user.
+ * Suspend an user (used by internal authentication process)
*
- * @param user user to be suspended
- * @return user just suspended
+ * @param key to be suspended
+ * @return user just suspended and information whether to propagate suspension
*/
- WorkflowResult<Long> suspend(User user);
+ Pair<WorkflowResult<Long>, Boolean> internalSuspend(Long key);
/**
* Reactivate an user.
http://git-wip-us.apache.org/repos/asf/syncope/blob/5cf6aae8/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/AbstractUserWorkflowAdapter.java
----------------------------------------------------------------------
diff --git a/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/AbstractUserWorkflowAdapter.java b/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/AbstractUserWorkflowAdapter.java
index ecc1c01..b829137 100644
--- a/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/AbstractUserWorkflowAdapter.java
+++ b/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/AbstractUserWorkflowAdapter.java
@@ -18,6 +18,7 @@
*/
package org.apache.syncope.core.workflow.java;
+import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.syncope.common.lib.mod.UserMod;
import org.apache.syncope.core.persistence.api.dao.UserDAO;
@@ -28,6 +29,8 @@ import org.apache.syncope.core.provisioning.api.data.UserDataBinder;
import org.apache.syncope.core.workflow.api.UserWorkflowAdapter;
import org.identityconnectors.common.Base64;
import org.identityconnectors.common.security.EncryptorFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@@ -35,6 +38,8 @@ import org.springframework.transaction.annotation.Transactional;
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = { Throwable.class })
public abstract class AbstractUserWorkflowAdapter implements UserWorkflowAdapter {
+ protected static final Logger LOG = LoggerFactory.getLogger(UserWorkflowAdapter.class);
+
@Autowired
protected UserDataBinder dataBinder;
@@ -62,8 +67,8 @@ public abstract class AbstractUserWorkflowAdapter implements UserWorkflowAdapter
protected abstract WorkflowResult<Long> doActivate(User user, String token);
@Override
- public WorkflowResult<Long> activate(final Long userKey, final String token) {
- return doActivate(userDAO.authFind(userKey), token);
+ public WorkflowResult<Long> activate(final Long key, final String token) {
+ return doActivate(userDAO.authFind(key), token);
}
protected abstract WorkflowResult<Pair<UserMod, Boolean>> doUpdate(User user, UserMod userMod);
@@ -76,23 +81,42 @@ public abstract class AbstractUserWorkflowAdapter implements UserWorkflowAdapter
protected abstract WorkflowResult<Long> doSuspend(User user);
@Override
- public WorkflowResult<Long> suspend(final Long userKey) {
- return suspend(userDAO.authFind(userKey));
- }
+ public WorkflowResult<Long> suspend(final Long key) {
+ User user = userDAO.authFind(key);
- @Override
- public WorkflowResult<Long> suspend(final User user) {
// set suspended flag
user.setSuspended(Boolean.TRUE);
return doSuspend(user);
}
+ @Override
+ public Pair<WorkflowResult<Long>, Boolean> internalSuspend(final Long key) {
+ User user = userDAO.authFind(key);
+
+ Pair<WorkflowResult<Long>, Boolean> result = null;
+
+ Pair<Boolean, Boolean> enforce = userDAO.enforcePolicies(user);
+ if (enforce.getKey()) {
+ LOG.debug("User {} {} is over the max failed logins", user.getKey(), user.getUsername());
+
+ // reduce failed logins number to avoid multiple request
+ user.setFailedLogins(user.getFailedLogins() - 1);
+
+ // set suspended flag
+ user.setSuspended(Boolean.TRUE);
+
+ result = ImmutablePair.of(doSuspend(user), enforce.getValue());
+ }
+
+ return result;
+ }
+
protected abstract WorkflowResult<Long> doReactivate(User user);
@Override
- public WorkflowResult<Long> reactivate(final Long userKey) {
- final User user = userDAO.authFind(userKey);
+ public WorkflowResult<Long> reactivate(final Long key) {
+ User user = userDAO.authFind(key);
// reset failed logins
user.setFailedLogins(0);
@@ -106,21 +130,21 @@ public abstract class AbstractUserWorkflowAdapter implements UserWorkflowAdapter
protected abstract void doRequestPasswordReset(User user);
@Override
- public void requestPasswordReset(final Long userKey) {
- doRequestPasswordReset(userDAO.authFind(userKey));
+ public void requestPasswordReset(final Long key) {
+ doRequestPasswordReset(userDAO.authFind(key));
}
protected abstract void doConfirmPasswordReset(User user, String token, String password);
@Override
- public void confirmPasswordReset(final Long userKey, final String token, final String password) {
- doConfirmPasswordReset(userDAO.authFind(userKey), token, password);
+ public void confirmPasswordReset(final Long key, final String token, final String password) {
+ doConfirmPasswordReset(userDAO.authFind(key), token, password);
}
protected abstract void doDelete(User user);
@Override
- public void delete(final Long userKey) {
- doDelete(userDAO.authFind(userKey));
+ public void delete(final Long key) {
+ doDelete(userDAO.authFind(key));
}
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/5cf6aae8/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/AbstractCamelProvisioningManager.java
----------------------------------------------------------------------
diff --git a/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/AbstractCamelProvisioningManager.java b/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/AbstractCamelProvisioningManager.java
index 516e798..1a6d7df 100644
--- a/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/AbstractCamelProvisioningManager.java
+++ b/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/AbstractCamelProvisioningManager.java
@@ -68,7 +68,7 @@ abstract class AbstractCamelProvisioningManager {
template.send(uri, exchange);
}
- protected void sendMessage(final String uri, final Object obj, final Map<String, Object> properties) {
+ protected void sendMessage(final String uri, final Object body, final Map<String, Object> properties) {
Exchange exchange = new DefaultExchange(getContext());
for (Map.Entry<String, Object> property : properties.entrySet()) {
@@ -77,7 +77,7 @@ abstract class AbstractCamelProvisioningManager {
}
DefaultMessage message = new DefaultMessage();
- message.setBody(obj);
+ message.setBody(body);
exchange.setIn(message);
ProducerTemplate template = getContext().createProducerTemplate();
template.send(uri, exchange);
http://git-wip-us.apache.org/repos/asf/syncope/blob/5cf6aae8/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/CamelUserProvisioningManager.java
----------------------------------------------------------------------
diff --git a/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/CamelUserProvisioningManager.java b/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/CamelUserProvisioningManager.java
index 8b5ad89..fa0b84b 100644
--- a/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/CamelUserProvisioningManager.java
+++ b/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/CamelUserProvisioningManager.java
@@ -34,7 +34,6 @@ import org.apache.syncope.common.lib.mod.UserMod;
import org.apache.syncope.common.lib.to.PropagationStatus;
import org.apache.syncope.common.lib.to.UserTO;
import org.apache.syncope.common.lib.types.PropagationByResource;
-import org.apache.syncope.core.persistence.api.entity.user.User;
import org.apache.syncope.core.provisioning.api.UserProvisioningManager;
import org.apache.syncope.core.provisioning.api.WorkflowResult;
import org.apache.syncope.core.provisioning.api.sync.ProvisioningResult;
@@ -319,13 +318,10 @@ public class CamelUserProvisioningManager extends AbstractCamelProvisioningManag
}
@Override
- public void innerSuspend(final User user, final boolean propagate) {
- PollingConsumer pollingConsumer = getConsumer("direct:innerSuspendUserPort");
+ public void internalSuspend(final Long key) {
+ PollingConsumer pollingConsumer = getConsumer("direct:internalSuspendUserPort");
- Map<String, Object> props = new HashMap<>();
- props.put("propagate", propagate);
-
- sendMessage("direct:innerSuspendUser", user.getKey(), props);
+ sendMessage("direct:internalSuspendUser", key);
Exchange exchange = pollingConsumer.receive();
http://git-wip-us.apache.org/repos/asf/syncope/blob/5cf6aae8/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/UserInnerSuspendProcessor.java
----------------------------------------------------------------------
diff --git a/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/UserInnerSuspendProcessor.java b/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/UserInnerSuspendProcessor.java
deleted file mode 100644
index be3e6ac..0000000
--- a/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/UserInnerSuspendProcessor.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.core.provisioning.camel.processor;
-
-import java.util.List;
-import org.apache.camel.Exchange;
-import org.apache.camel.Processor;
-import org.apache.commons.lang3.tuple.ImmutablePair;
-import org.apache.commons.lang3.tuple.Pair;
-import org.apache.syncope.common.lib.mod.UserMod;
-import org.apache.syncope.core.persistence.api.entity.task.PropagationTask;
-import org.apache.syncope.core.provisioning.api.WorkflowResult;
-import org.apache.syncope.core.provisioning.api.propagation.PropagationManager;
-import org.apache.syncope.core.provisioning.api.propagation.PropagationTaskExecutor;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-
-@Component
-public class UserInnerSuspendProcessor implements Processor {
-
- @Autowired
- protected PropagationManager propagationManager;
-
- @Autowired
- protected PropagationTaskExecutor taskExecutor;
-
- @Override
- public void process(final Exchange exchange) {
- @SuppressWarnings("unchecked")
- WorkflowResult<Long> updated = (WorkflowResult) exchange.getIn().getBody();
- Boolean propagate = exchange.getProperty("propagate", Boolean.class);
-
- if (propagate) {
- UserMod userMod = new UserMod();
- userMod.setKey(updated.getResult());
-
- List<PropagationTask> tasks = propagationManager.getUserUpdateTasks(
- new WorkflowResult<Pair<UserMod, Boolean>>(
- new ImmutablePair<>(userMod, Boolean.FALSE),
- updated.getPropByRes(), updated.getPerformedTasks()));
- taskExecutor.execute(tasks);
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/syncope/blob/5cf6aae8/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/UserInternalSuspendProcessor.java
----------------------------------------------------------------------
diff --git a/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/UserInternalSuspendProcessor.java b/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/UserInternalSuspendProcessor.java
new file mode 100644
index 0000000..73e63ad
--- /dev/null
+++ b/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/UserInternalSuspendProcessor.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.provisioning.camel.processor;
+
+import java.util.List;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.syncope.common.lib.mod.UserMod;
+import org.apache.syncope.core.persistence.api.entity.task.PropagationTask;
+import org.apache.syncope.core.provisioning.api.WorkflowResult;
+import org.apache.syncope.core.provisioning.api.propagation.PropagationManager;
+import org.apache.syncope.core.provisioning.api.propagation.PropagationTaskExecutor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+public class UserInternalSuspendProcessor implements Processor {
+
+ @Autowired
+ protected PropagationManager propagationManager;
+
+ @Autowired
+ protected PropagationTaskExecutor taskExecutor;
+
+ @Override
+ public void process(final Exchange exchange) {
+ @SuppressWarnings("unchecked")
+ Pair<WorkflowResult<Long>, Boolean> updated = (Pair) exchange.getIn().getBody();
+
+ // propagate suspension if and only if it is required by policy
+ if (updated != null && updated.getValue()) {
+ UserMod userMod = new UserMod();
+ userMod.setKey(updated.getKey().getResult());
+
+ List<PropagationTask> tasks = propagationManager.getUserUpdateTasks(
+ new WorkflowResult<Pair<UserMod, Boolean>>(
+ new ImmutablePair<>(userMod, Boolean.FALSE),
+ updated.getKey().getPropByRes(), updated.getKey().getPerformedTasks()));
+ taskExecutor.execute(tasks);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/5cf6aae8/ext/camel/provisioning-camel/src/main/resources/userRoutes.xml
----------------------------------------------------------------------
diff --git a/ext/camel/provisioning-camel/src/main/resources/userRoutes.xml b/ext/camel/provisioning-camel/src/main/resources/userRoutes.xml
index aca6a46..38e48f3 100644
--- a/ext/camel/provisioning-camel/src/main/resources/userRoutes.xml
+++ b/ext/camel/provisioning-camel/src/main/resources/userRoutes.xml
@@ -198,18 +198,18 @@ under the License.
<to uri="direct:deprovisionPort"/>
</route>
- <route id="innerSuspendUser">
- <from uri="direct:innerSuspendUser"/>
+ <route id="internalSuspendUser">
+ <from uri="direct:internalSuspendUser"/>
<doTry>
- <bean ref="uwfAdapter" method="suspend(${body})"/>
- <process ref="userInnerSuspendProcessor"/>
- <to uri="direct:innerSuspendUserPort"/>
+ <bean ref="uwfAdapter" method="internalSuspend(${body})"/>
+ <process ref="userInternalSuspendProcessor"/>
+ <to uri="direct:internalSuspendUserPort"/>
<doCatch>
<exception>java.lang.RuntimeException</exception>
<handled>
<constant>false</constant>
</handled>
- <to uri="direct:innerSuspendUserPort"/>
+ <to uri="direct:internalSuspendUserPort"/>
</doCatch>
</doTry>
</route>
http://git-wip-us.apache.org/repos/asf/syncope/blob/5cf6aae8/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 9d810b6..6378631 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
@@ -258,7 +258,7 @@ public class AuthenticationITCase extends AbstractITCase {
assertEquals(0, getFailedLogins(userService4, userId));
}
- //@Test
+ @Test
public void checkUserSuspension() {
UserTO userTO = UserITCase.getUniqueSampleTO("checkSuspension@syncope.apache.org");
userTO.setRealm("/odd");
@@ -292,8 +292,9 @@ public class AuthenticationITCase extends AbstractITCase {
assertReadFails(goodPwdClient);
StatusMod reactivate = new StatusMod();
+ reactivate.setKey(userTO.getKey());
reactivate.setType(StatusMod.ModType.REACTIVATE);
- userTO = userService.status(userTO.getKey(), reactivate).readEntity(UserTO.class);
+ userTO = userService.status(reactivate).readEntity(UserTO.class);
assertNotNull(userTO);
assertEquals("active", userTO.getStatus());
http://git-wip-us.apache.org/repos/asf/syncope/blob/5cf6aae8/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/UserITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/UserITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/UserITCase.java
index 4cecdf7..048259d 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/UserITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/UserITCase.java
@@ -818,9 +818,10 @@ public class UserITCase extends AbstractITCase {
assertEquals("created", userTO.getStatus());
StatusMod statusMod = new StatusMod();
+ statusMod.setKey(userTO.getKey());
statusMod.setType(StatusMod.ModType.ACTIVATE);
statusMod.setToken(userTO.getToken());
- userTO = userService.status(userTO.getKey(), statusMod).readEntity(UserTO.class);
+ userTO = userService.status(statusMod).readEntity(UserTO.class);
assertNotNull(userTO);
assertNull(userTO.getToken());
@@ -844,14 +845,16 @@ public class UserITCase extends AbstractITCase {
: "created", userTO.getStatus());
StatusMod statusMod = new StatusMod();
+ statusMod.setKey(userTO.getKey());
statusMod.setType(StatusMod.ModType.SUSPEND);
- userTO = userService.status(userTO.getKey(), statusMod).readEntity(UserTO.class);
+ userTO = userService.status(statusMod).readEntity(UserTO.class);
assertNotNull(userTO);
assertEquals("suspended", userTO.getStatus());
statusMod = new StatusMod();
+ statusMod.setKey(userTO.getKey());
statusMod.setType(StatusMod.ModType.REACTIVATE);
- userTO = userService.status(userTO.getKey(), statusMod).readEntity(UserTO.class);
+ userTO = userService.status(statusMod).readEntity(UserTO.class);
assertNotNull(userTO);
assertEquals("active", userTO.getStatus());
}
@@ -875,50 +878,53 @@ public class UserITCase extends AbstractITCase {
assertEquals(ActivitiDetector.isActivitiEnabledForUsers(syncopeService)
? "active"
: "created", userTO.getStatus());
- long userId = userTO.getKey();
+ long userKey = userTO.getKey();
// Suspend with effect on syncope, ldap and db => user should be suspended in syncope and all resources
StatusMod statusMod = new StatusMod();
+ statusMod.setKey(userKey);
statusMod.setType(StatusMod.ModType.SUSPEND);
statusMod.setOnSyncope(true);
statusMod.getResourceNames().add(RESOURCE_NAME_TESTDB);
statusMod.getResourceNames().add(RESOURCE_NAME_LDAP);
- userTO = userService.status(userId, statusMod).readEntity(UserTO.class);
+ userTO = userService.status(statusMod).readEntity(UserTO.class);
assertNotNull(userTO);
assertEquals("suspended", userTO.getStatus());
ConnObjectTO connObjectTO =
- resourceService.readConnObject(RESOURCE_NAME_TESTDB, AnyTypeKind.USER.name(), userId);
+ resourceService.readConnObject(RESOURCE_NAME_TESTDB, AnyTypeKind.USER.name(), userKey);
assertFalse(getBooleanAttribute(connObjectTO, OperationalAttributes.ENABLE_NAME));
- connObjectTO = resourceService.readConnObject(RESOURCE_NAME_LDAP, AnyTypeKind.USER.name(), userId);
+ connObjectTO = resourceService.readConnObject(RESOURCE_NAME_LDAP, AnyTypeKind.USER.name(), userKey);
assertNotNull(connObjectTO);
// Suspend and reactivate only on ldap => db and syncope should still show suspended
statusMod = new StatusMod();
+ statusMod.setKey(userKey);
statusMod.setType(StatusMod.ModType.SUSPEND);
statusMod.setOnSyncope(false);
statusMod.getResourceNames().add(RESOURCE_NAME_LDAP);
- userService.status(userId, statusMod);
+ userService.status(statusMod);
statusMod.setType(StatusMod.ModType.REACTIVATE);
- userTO = userService.status(userId, statusMod).readEntity(UserTO.class);
+ userTO = userService.status(statusMod).readEntity(UserTO.class);
assertNotNull(userTO);
assertEquals("suspended", userTO.getStatus());
- connObjectTO = resourceService.readConnObject(RESOURCE_NAME_TESTDB, AnyTypeKind.USER.name(), userId);
+ connObjectTO = resourceService.readConnObject(RESOURCE_NAME_TESTDB, AnyTypeKind.USER.name(), userKey);
assertFalse(getBooleanAttribute(connObjectTO, OperationalAttributes.ENABLE_NAME));
// Reactivate on syncope and db => syncope and db should show the user as active
statusMod = new StatusMod();
+ statusMod.setKey(userKey);
statusMod.setType(StatusMod.ModType.REACTIVATE);
statusMod.setOnSyncope(true);
statusMod.getResourceNames().add(RESOURCE_NAME_TESTDB);
- userTO = userService.status(userId, statusMod).readEntity(UserTO.class);
+ userTO = userService.status(statusMod).readEntity(UserTO.class);
assertNotNull(userTO);
assertEquals("active", userTO.getStatus());
- connObjectTO = resourceService.readConnObject(RESOURCE_NAME_TESTDB, AnyTypeKind.USER.name(), userId);
+ connObjectTO = resourceService.readConnObject(RESOURCE_NAME_TESTDB, AnyTypeKind.USER.name(), userKey);
assertTrue(getBooleanAttribute(connObjectTO, OperationalAttributes.ENABLE_NAME));
}
@@ -1795,7 +1801,8 @@ public class UserITCase extends AbstractITCase {
final ResourceAssociationMod associationMod = new ResourceAssociationMod();
associationMod.getTargetResources().addAll(CollectionWrapper.wrap(RESOURCE_NAME_CSV, ResourceKey.class));
- assertNotNull(userService.associate(actual.getKey(), ResourceAssociationAction.LINK, associationMod).readEntity(BulkActionResult.class));
+ assertNotNull(userService.associate(actual.getKey(), ResourceAssociationAction.LINK, associationMod).readEntity(
+ BulkActionResult.class));
actual = userService.read(actual.getKey());
assertNotNull(actual);