From defbedc4aa7ba43870839762197df2fc0b49cb53 Mon Sep 17 00:00:00 2001 From: alberto bogi Date: Thu, 14 Aug 2025 10:41:28 +0200 Subject: [PATCH 01/20] [SYNCOPE-1901] Implement PasswordModule for CAS password management in Syncope with JPA persistence --- .../lib/password/PasswordModuleConf.java | 19 +++ .../password/SyncopePasswordModuleConf.java | 100 +++++++++++++++ .../common/lib/to/PasswordModuleTO.java | 91 ++++++++++++++ .../common/lib/types/AMEntitlement.java | 10 ++ .../api/service/PasswordModuleService.java | 104 +++++++++++++++ .../syncope/core/logic/AMLogicContext.java | 10 ++ .../core/logic/PasswordModuleLogic.java | 94 ++++++++++++++ .../core/rest/cxf/AMRESTCXFContext.java | 9 ++ .../service/PasswordModuleServiceImpl.java | 43 +++++++ .../api/dao/PasswordModuleDAO.java | 6 + .../api/entity/am/PasswordModule.java | 23 ++++ .../persistence/jpa/PersistenceContext.java | 18 +++ .../jpa/dao/repo/PasswordModuleRepo.java | 10 ++ .../jpa/dao/repo/PasswordModuleRepoExt.java | 10 ++ .../dao/repo/PasswordModuleRepoExtImpl.java | 24 ++++ .../jpa/entity/AbstractEntityFactory.java | 6 +- .../jpa/entity/am/JPAPasswordModule.java | 114 +++++++++++++++++ .../jpa/inner/PasswordModuleTest.java | 108 ++++++++++++++++ .../test/resources/domains/MasterContent.xml | 5 + .../api/data/PasswordModuleDataBinder.java | 13 ++ .../java/ProvisioningContext.java | 8 ++ .../data/PasswordModuleDataBinderImpl.java | 118 ++++++++++++++++++ 22 files changed, 942 insertions(+), 1 deletion(-) create mode 100644 common/am/lib/src/main/java/org/apache/syncope/common/lib/password/PasswordModuleConf.java create mode 100644 common/am/lib/src/main/java/org/apache/syncope/common/lib/password/SyncopePasswordModuleConf.java create mode 100644 common/am/lib/src/main/java/org/apache/syncope/common/lib/to/PasswordModuleTO.java create mode 100644 common/am/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/PasswordModuleService.java create mode 100644 core/am/logic/src/main/java/org/apache/syncope/core/logic/PasswordModuleLogic.java create mode 100644 core/am/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/PasswordModuleServiceImpl.java create mode 100644 core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PasswordModuleDAO.java create mode 100644 core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/am/PasswordModule.java create mode 100644 core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordModuleRepo.java create mode 100644 core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordModuleRepoExt.java create mode 100644 core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordModuleRepoExtImpl.java create mode 100644 core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/am/JPAPasswordModule.java create mode 100644 core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PasswordModuleTest.java create mode 100644 core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/PasswordModuleDataBinder.java create mode 100644 core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/PasswordModuleDataBinderImpl.java diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/PasswordModuleConf.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/PasswordModuleConf.java new file mode 100644 index 00000000000..b7400b44150 --- /dev/null +++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/PasswordModuleConf.java @@ -0,0 +1,19 @@ +package org.apache.syncope.common.lib.password; + +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import java.util.Map; +import org.apache.syncope.common.lib.BaseBean; +import org.apache.syncope.common.lib.to.PasswordModuleTO; + +@FunctionalInterface +@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "_class") +public interface PasswordModuleConf extends BaseBean { + + interface Mapper { + + Map map(PasswordModuleTO passwordModuleTO, SyncopePasswordModuleConf conf); + + } + + Map map(PasswordModuleTO passwordModuleTO, Mapper mapper); +} diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/SyncopePasswordModuleConf.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/SyncopePasswordModuleConf.java new file mode 100644 index 00000000000..3043d77a729 --- /dev/null +++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/SyncopePasswordModuleConf.java @@ -0,0 +1,100 @@ +package org.apache.syncope.common.lib.password; + +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; +import org.apache.syncope.common.lib.SyncopeConstants; +import org.apache.syncope.common.lib.to.PasswordModuleTO; + +public class SyncopePasswordModuleConf implements PasswordModuleConf{ + + private static final long serialVersionUID = -8203692328056109683L; + + private String domain = SyncopeConstants.MASTER_DOMAIN; + + /** + * User FIQL filter to use for searching. + */ + protected String searchFilter; + + /** + * Specify the username for REST authentication. + */ + private String basicAuthUsername; + + /** + * Specify the password for REST authentication. + */ + private String basicAuthPassword; + + /** + * Headers, defined as a Map, to include in the request when making the REST call. + * Will overwrite any header that CAS is pre-defined to + * send and include in the request. Key in the map should be the header name + * and the value in the map should be the header value. + */ + private Map headers = new HashMap<>(); + + /** + * Map of attributes that optionally may be used to control the names + * of the collected attributes from Syncope. If an attribute is provided by Syncope, + * it can be listed here as the key of the map with a value that should be the name + * of that attribute as collected and recorded by CAS. + * For example, the convention {@code lastLoginDate->lastDate} will process the + * Syncope attribute {@code lastLoginDate} and will internally rename that to {@code lastDate}. + * If no mapping is specified, CAS defaults will be used instead. + */ + private Map attributeMappings = new LinkedHashMap<>(); + + public String getDomain() { + return domain; + } + + public void setDomain(final String domain) { + this.domain = domain; + } + + public String getSearchFilter() { + return searchFilter; + } + + public void setSearchFilter(final String searchFilter) { + this.searchFilter = searchFilter; + } + + public String getBasicAuthUsername() { + return basicAuthUsername; + } + + public void setBasicAuthUsername(final String basicAuthUsername) { + this.basicAuthUsername = basicAuthUsername; + } + + public String getBasicAuthPassword() { + return basicAuthPassword; + } + + public void setBasicAuthPassword(final String basicAuthPassword) { + this.basicAuthPassword = basicAuthPassword; + } + + public Map getHeaders() { + return headers; + } + + public void setHeaders(final Map headers) { + this.headers = headers; + } + + public Map getAttributeMappings() { + return attributeMappings; + } + + public void setAttributeMappings(Map attributeMappings) { + this.attributeMappings = attributeMappings; + } + + @Override public Map map(final PasswordModuleTO passwordModuleTO, final Mapper mapper) { + return mapper.map(passwordModuleTO, this); + } +} diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/to/PasswordModuleTO.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/to/PasswordModuleTO.java new file mode 100644 index 00000000000..b1675e8b48d --- /dev/null +++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/to/PasswordModuleTO.java @@ -0,0 +1,91 @@ +package org.apache.syncope.common.lib.to; + +import jakarta.ws.rs.PathParam; +import java.util.ArrayList; +import java.util.List; +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.apache.syncope.common.lib.password.PasswordModuleConf; + +public class PasswordModuleTO implements EntityTO{ + + private String key; + + private String description; + + private int order = 0; + + private final List items = new ArrayList<>(); + + private PasswordModuleConf conf; + + @Override + public String getKey() { + return key; + } + + @PathParam("key") + @Override + public void setKey(final String key) { + this.key = key; + } + + public String getDescription() { + return description; + } + + public void setDescription(final String description) { + this.description = description; + } + + public int getOrder() { + return order; + } + + public void setOrder(final int order) { + this.order = order; + } + + public List getItems() { + return items; + } + + public PasswordModuleConf getConf() { + return conf; + } + + public void setConf(final PasswordModuleConf conf) { + this.conf = conf; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + PasswordModuleTO other = (PasswordModuleTO) obj; + return new EqualsBuilder(). + append(key, other.key). + append(description, other.description). + append(order, other.order). + append(items, other.items). + append(conf, other.conf). + build(); + } + + @Override + public int hashCode() { + return new HashCodeBuilder(). + append(key). + append(description). + append(items). + append(conf). + build(); + } +} diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/types/AMEntitlement.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/types/AMEntitlement.java index ceae04b368d..cb8a1195e9a 100644 --- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/types/AMEntitlement.java +++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/types/AMEntitlement.java @@ -58,6 +58,16 @@ public final class AMEntitlement { public static final String AUTH_MODULE_DELETE = "AUTH_MODULE_DELETE"; + public static final String PASSWORD_MODULE_LIST = "PASSWORD_MODULE_LIST"; + + public static final String PASSWORD_MODULE_CREATE = "PASSWORD_MODULE_CREATE"; + + public static final String PASSWORD_MODULE_READ = "PASSWORD_MODULE_READ"; + + public static final String PASSWORD_MODULE_UPDATE = "PASSWORD_MODULE_UPDATE"; + + public static final String PASSWORD_MODULE_DELETE = "PASSWORD_MODULE_DELETE"; + public static final String ATTR_REPO_LIST = "ATTR_REPO_LIST"; public static final String ATTR_REPO_CREATE = "ATTR_REPO_CREATE"; diff --git a/common/am/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/PasswordModuleService.java b/common/am/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/PasswordModuleService.java new file mode 100644 index 00000000000..5edc40eac34 --- /dev/null +++ b/common/am/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/PasswordModuleService.java @@ -0,0 +1,104 @@ +package org.apache.syncope.common.rest.api.service; + +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.headers.Header; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.security.SecurityRequirements; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.constraints.NotNull; +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.DELETE; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.PUT; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.HttpHeaders; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; +import java.util.List; +import org.apache.syncope.common.lib.to.PasswordModuleTO; +import org.apache.syncope.common.rest.api.RESTHeaders; + +/** + * REST operations for password management modules. + */ +@Tag(name = "PasswordModules") +@SecurityRequirements({ + @SecurityRequirement(name = "BasicAuthentication"), + @SecurityRequirement(name = "Bearer") }) +@Path("passwordModules") +public interface PasswordModuleService extends JAXRSService { + + /** + * Returns the password management module matching the given key. + * + * @param key key of requested password management module + * @return password management module with matching id + */ + @GET + @Path("{key}") + @Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML }) + PasswordModuleTO read(@NotNull @PathParam("key") String key); + + /** + * Returns a list of password management modules. + * + * @return list of password management modules + */ + @GET + @Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML }) + List list(); + + /** + * Create a new password management module. + * + * @param passwordModuleTO PasswordModule to be created. + * @return Response object featuring Location header of created password management module + */ + @ApiResponses( + @ApiResponse(responseCode = "201", + description = "PasswordModule successfully created", headers = { + @Header(name = RESTHeaders.RESOURCE_KEY, schema = + @Schema(type = "string"), + description = "UUID generated for the entity created"), + @Header(name = HttpHeaders.LOCATION, schema = + @Schema(type = "string"), + description = "URL of the entity created") })) + @POST + @Consumes({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML }) + @Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML }) + Response create(@NotNull PasswordModuleTO passwordModuleTO); + + /** + * Updates password management module matching the given key. + * + * @param passwordModuleTO PasswordModule to replace existing password management module + */ + @Parameter(name = "key", description = "PasswordModule's key", in = ParameterIn.PATH, schema = + @Schema(type = "string")) + @ApiResponses( + @ApiResponse(responseCode = "204", description = "Operation was successful")) + @PUT + @Path("{key}") + @Consumes({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML }) + @Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML }) + void update(@NotNull PasswordModuleTO passwordModuleTO); + + /** + * Delete password management module matching the given key. + * + * @param key key of password management module to be deleted + */ + @ApiResponses( + @ApiResponse(responseCode = "204", description = "Operation was successful")) + @DELETE + @Path("{key}") + @Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML }) + void delete(@NotNull @PathParam("key") String key); +} diff --git a/core/am/logic/src/main/java/org/apache/syncope/core/logic/AMLogicContext.java b/core/am/logic/src/main/java/org/apache/syncope/core/logic/AMLogicContext.java index bdff58a04eb..21ac81f5e2c 100644 --- a/core/am/logic/src/main/java/org/apache/syncope/core/logic/AMLogicContext.java +++ b/core/am/logic/src/main/java/org/apache/syncope/core/logic/AMLogicContext.java @@ -33,6 +33,7 @@ import org.apache.syncope.core.persistence.api.dao.CASSPClientAppDAO; import org.apache.syncope.core.persistence.api.dao.OIDCJWKSDAO; import org.apache.syncope.core.persistence.api.dao.OIDCRPClientAppDAO; +import org.apache.syncope.core.persistence.api.dao.PasswordModuleDAO; import org.apache.syncope.core.persistence.api.dao.SAML2IdPEntityDAO; import org.apache.syncope.core.persistence.api.dao.SAML2SPClientAppDAO; import org.apache.syncope.core.persistence.api.dao.SRARouteDAO; @@ -44,6 +45,7 @@ import org.apache.syncope.core.provisioning.api.data.AuthProfileDataBinder; import org.apache.syncope.core.provisioning.api.data.ClientAppDataBinder; import org.apache.syncope.core.provisioning.api.data.OIDCJWKSDataBinder; +import org.apache.syncope.core.provisioning.api.data.PasswordModuleDataBinder; import org.apache.syncope.core.provisioning.api.data.SAML2IdPEntityDataBinder; import org.apache.syncope.core.provisioning.api.data.SRARouteDataBinder; import org.apache.syncope.core.provisioning.api.data.WAConfigDataBinder; @@ -71,6 +73,14 @@ public AuthModuleLogic authModuleLogic( return new AuthModuleLogic(binder, authModuleDAO); } + @ConditionalOnMissingBean + @Bean + public PasswordModuleLogic passwordModuleLogic( + final PasswordModuleDataBinder passwordModuleDataBinder, + final PasswordModuleDAO passwordModuleDAO) { + return new PasswordModuleLogic(passwordModuleDataBinder, passwordModuleDAO); + } + @ConditionalOnMissingBean @Bean public AttrRepoLogic attrRepoLogic( diff --git a/core/am/logic/src/main/java/org/apache/syncope/core/logic/PasswordModuleLogic.java b/core/am/logic/src/main/java/org/apache/syncope/core/logic/PasswordModuleLogic.java new file mode 100644 index 00000000000..cec47cbe14d --- /dev/null +++ b/core/am/logic/src/main/java/org/apache/syncope/core/logic/PasswordModuleLogic.java @@ -0,0 +1,94 @@ +package org.apache.syncope.core.logic; + +import java.lang.reflect.Method; +import java.util.List; +import org.apache.commons.lang3.ArrayUtils; +import org.apache.syncope.common.lib.to.AuthModuleTO; +import org.apache.syncope.common.lib.to.PasswordModuleTO; +import org.apache.syncope.common.lib.types.AMEntitlement; +import org.apache.syncope.common.lib.types.IdRepoEntitlement; +import org.apache.syncope.core.persistence.api.dao.NotFoundException; +import org.apache.syncope.core.persistence.api.dao.PasswordModuleDAO; +import org.apache.syncope.core.persistence.api.entity.am.PasswordModule; +import org.apache.syncope.core.provisioning.api.data.PasswordModuleDataBinder; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.transaction.annotation.Transactional; + +public class PasswordModuleLogic extends AbstractTransactionalLogic { + + protected final PasswordModuleDataBinder passwordModuleDataBinder; + + protected final PasswordModuleDAO passwordModuleDAO; + + public PasswordModuleLogic(final PasswordModuleDataBinder passwordModuleDataBinder, + final PasswordModuleDAO passwordModuleDAO) { + this.passwordModuleDataBinder = passwordModuleDataBinder; + this.passwordModuleDAO = passwordModuleDAO; + } + + @PreAuthorize("hasRole('" + AMEntitlement.PASSWORD_MODULE_CREATE + "')") + public PasswordModuleTO create(final PasswordModuleTO passwordModuleTO) { + return passwordModuleDataBinder.getPasswordModuleTO( + passwordModuleDAO.save(passwordModuleDataBinder.create(passwordModuleTO))); + } + + @PreAuthorize("hasRole('" + AMEntitlement.PASSWORD_MODULE_UPDATE + "')") + public PasswordModuleTO update(final PasswordModuleTO passwordModuleTO) { + PasswordModule passwordModule = passwordModuleDAO.findById(passwordModuleTO.getKey()). + orElseThrow(() -> new NotFoundException("PasswordModule " + passwordModuleTO.getKey())); + + return passwordModuleDataBinder.getPasswordModuleTO( + passwordModuleDAO.save(passwordModuleDataBinder.update(passwordModule, passwordModuleTO))); + } + + @PreAuthorize("hasRole('" + AMEntitlement.PASSWORD_MODULE_LIST + "') or hasRole('" + IdRepoEntitlement.ANONYMOUS + "')") + @Transactional(readOnly = true) + public List list() { + return passwordModuleDAO.findAll().stream() + .map(passwordModuleDataBinder::getPasswordModuleTO).toList(); + } + + @PreAuthorize("hasRole('" + AMEntitlement.PASSWORD_MODULE_READ + "')") + @Transactional(readOnly = true) + public PasswordModuleTO read(final String key) { + PasswordModule passwordModule = passwordModuleDAO.findById(key). + orElseThrow(() -> new NotFoundException("PasswordModule " + key)); + + return passwordModuleDataBinder.getPasswordModuleTO(passwordModule); + } + + @PreAuthorize("hasRole('" + AMEntitlement.PASSWORD_MODULE_DELETE + "')") + public PasswordModuleTO delete(final String key) { + PasswordModule passwordModule = passwordModuleDAO.findById(key). + orElseThrow(() -> new NotFoundException("PasswordModule " + key)); + + PasswordModuleTO deleted = passwordModuleDataBinder.getPasswordModuleTO(passwordModule); + passwordModuleDAO.delete(passwordModule); + + return deleted; + } + + @Override protected PasswordModuleTO resolveReference(Method method, Object... args) + throws UnresolvedReferenceException { + if (ArrayUtils.isEmpty(args)) { + throw new UnresolvedReferenceException(); + } + + final String key; + + if (args[0] instanceof String string) { + key = string; + } else if (args[0] instanceof AuthModuleTO authModuleTO) { + key = authModuleTO.getKey(); + } else { + throw new UnresolvedReferenceException(); + } + + try { + return passwordModuleDataBinder.getPasswordModuleTO(passwordModuleDAO.findById(key).orElseThrow()); + } catch (Throwable ignore) { + LOG.debug("Unresolved reference", ignore); + throw new UnresolvedReferenceException(ignore); + } + } +} diff --git a/core/am/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/AMRESTCXFContext.java b/core/am/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/AMRESTCXFContext.java index e419126b1ce..c7dabcfb2c0 100644 --- a/core/am/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/AMRESTCXFContext.java +++ b/core/am/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/AMRESTCXFContext.java @@ -24,6 +24,7 @@ import org.apache.syncope.common.rest.api.service.AuthProfileService; import org.apache.syncope.common.rest.api.service.ClientAppService; import org.apache.syncope.common.rest.api.service.OIDCJWKSService; +import org.apache.syncope.common.rest.api.service.PasswordModuleService; import org.apache.syncope.common.rest.api.service.SAML2IdPEntityService; import org.apache.syncope.common.rest.api.service.SRARouteService; import org.apache.syncope.common.rest.api.service.wa.GoogleMfaAuthAccountService; @@ -39,6 +40,7 @@ import org.apache.syncope.core.logic.AuthProfileLogic; import org.apache.syncope.core.logic.ClientAppLogic; import org.apache.syncope.core.logic.OIDCJWKSLogic; +import org.apache.syncope.core.logic.PasswordModuleLogic; import org.apache.syncope.core.logic.SAML2IdPEntityLogic; import org.apache.syncope.core.logic.SRARouteLogic; import org.apache.syncope.core.logic.wa.GoogleMfaAuthAccountLogic; @@ -54,6 +56,7 @@ import org.apache.syncope.core.rest.cxf.service.AuthProfileServiceImpl; import org.apache.syncope.core.rest.cxf.service.ClientAppServiceImpl; import org.apache.syncope.core.rest.cxf.service.OIDCJWKSServiceImpl; +import org.apache.syncope.core.rest.cxf.service.PasswordModuleServiceImpl; import org.apache.syncope.core.rest.cxf.service.SAML2IdPEntityServiceImpl; import org.apache.syncope.core.rest.cxf.service.SRARouteServiceImpl; import org.apache.syncope.core.rest.cxf.service.wa.GoogleMfaAuthAccountServiceImpl; @@ -77,6 +80,12 @@ public AuthModuleService authModuleService(final AuthModuleLogic authModuleLogic return new AuthModuleServiceImpl(authModuleLogic); } + @ConditionalOnMissingBean + @Bean + public PasswordModuleService passwordModuleService(final PasswordModuleLogic passwordModuleLogic) { + return new PasswordModuleServiceImpl(passwordModuleLogic); + } + @ConditionalOnMissingBean @Bean public AttrRepoService attrRepoService(final AttrRepoLogic attrRepoLogic) { diff --git a/core/am/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/PasswordModuleServiceImpl.java b/core/am/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/PasswordModuleServiceImpl.java new file mode 100644 index 00000000000..2a9187f27d4 --- /dev/null +++ b/core/am/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/PasswordModuleServiceImpl.java @@ -0,0 +1,43 @@ +package org.apache.syncope.core.rest.cxf.service; + +import jakarta.ws.rs.core.Response; +import java.net.URI; +import java.util.List; +import org.apache.syncope.common.lib.to.AttrRepoTO; +import org.apache.syncope.common.lib.to.PasswordModuleTO; +import org.apache.syncope.common.rest.api.RESTHeaders; +import org.apache.syncope.common.rest.api.service.PasswordModuleService; +import org.apache.syncope.core.logic.PasswordModuleLogic; + +public class PasswordModuleServiceImpl extends AbstractService implements PasswordModuleService { + + protected final PasswordModuleLogic passwordModuleLogic; + + public PasswordModuleServiceImpl(final PasswordModuleLogic passwordModuleLogic) { + this.passwordModuleLogic = passwordModuleLogic; + } + + @Override public PasswordModuleTO read(String key) { + return passwordModuleLogic.read(key); + } + + @Override public List list() { + return passwordModuleLogic.list(); + } + + @Override public Response create(PasswordModuleTO passwordModuleTO) { + PasswordModuleTO passwordModule = passwordModuleLogic.create(passwordModuleTO); + URI location = uriInfo.getAbsolutePathBuilder().path(passwordModule.getKey()).build(); + return Response.created(location). + header(RESTHeaders.RESOURCE_KEY, passwordModule.getKey()). + build(); + } + + @Override public void update(PasswordModuleTO passwordModuleTO) { + passwordModuleLogic.update(passwordModuleTO); + } + + @Override public void delete(String key) { + passwordModuleLogic.delete(key); + } +} diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PasswordModuleDAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PasswordModuleDAO.java new file mode 100644 index 00000000000..964cf804c9f --- /dev/null +++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PasswordModuleDAO.java @@ -0,0 +1,6 @@ +package org.apache.syncope.core.persistence.api.dao; + +import org.apache.syncope.core.persistence.api.entity.am.PasswordModule; + +public interface PasswordModuleDAO extends DAO{ +} diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/am/PasswordModule.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/am/PasswordModule.java new file mode 100644 index 00000000000..1d3350964b5 --- /dev/null +++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/am/PasswordModule.java @@ -0,0 +1,23 @@ +package org.apache.syncope.core.persistence.api.entity.am; + +import java.util.List; +import org.apache.syncope.common.lib.password.PasswordModuleConf; +import org.apache.syncope.common.lib.to.Item; +import org.apache.syncope.core.persistence.api.entity.ProvidedKeyEntity; + +public interface PasswordModule extends ProvidedKeyEntity { + + String getDescription(); + + void setDescription(String description); + + int getOrder(); + + void setOrder(int order); + + PasswordModuleConf getConf(); + + void setConf(PasswordModuleConf conf); + + List getItems(); +} diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/PersistenceContext.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/PersistenceContext.java index 4d31d9e4f04..1f8fbb81cf3 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/PersistenceContext.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/PersistenceContext.java @@ -57,6 +57,7 @@ import org.apache.syncope.core.persistence.api.dao.NotificationDAO; import org.apache.syncope.core.persistence.api.dao.OIDCJWKSDAO; import org.apache.syncope.core.persistence.api.dao.OIDCRPClientAppDAO; +import org.apache.syncope.core.persistence.api.dao.PasswordModuleDAO; import org.apache.syncope.core.persistence.api.dao.PersistenceInfoDAO; import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO; import org.apache.syncope.core.persistence.api.dao.PolicyDAO; @@ -154,6 +155,9 @@ import org.apache.syncope.core.persistence.jpa.dao.repo.OIDCRPClientAppRepo; import org.apache.syncope.core.persistence.jpa.dao.repo.OIDCRPClientAppRepoExt; import org.apache.syncope.core.persistence.jpa.dao.repo.OIDCRPClientAppRepoExtImpl; +import org.apache.syncope.core.persistence.jpa.dao.repo.PasswordModuleRepo; +import org.apache.syncope.core.persistence.jpa.dao.repo.PasswordModuleRepoExt; +import org.apache.syncope.core.persistence.jpa.dao.repo.PasswordModuleRepoExtImpl; import org.apache.syncope.core.persistence.jpa.dao.repo.PlainSchemaRepo; import org.apache.syncope.core.persistence.jpa.dao.repo.PlainSchemaRepoExt; import org.apache.syncope.core.persistence.jpa.dao.repo.RelationshipTypeRepo; @@ -515,6 +519,20 @@ public AuthModuleDAO authModuleDAO( return jpaRepositoryFactory.getRepository(AuthModuleRepo.class, authModuleRepoExt); } + @ConditionalOnMissingBean + @Bean + public PasswordModuleRepoExt passwordModuleRepoExt(final EntityManager entityManager) { + return new PasswordModuleRepoExtImpl(entityManager); + } + + @ConditionalOnMissingBean + @Bean + public PasswordModuleDAO passwordModuleDAO( + final JpaRepositoryFactory jpaRepositoryFactory, + final PasswordModuleRepoExt passwordModuleRepoExt) { + return jpaRepositoryFactory.getRepository(PasswordModuleRepo.class, passwordModuleRepoExt); + } + @ConditionalOnMissingBean @Bean public AuthProfileDAO authProfileDAO(final JpaRepositoryFactory jpaRepositoryFactory) { diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordModuleRepo.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordModuleRepo.java new file mode 100644 index 00000000000..38cab2f830a --- /dev/null +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordModuleRepo.java @@ -0,0 +1,10 @@ +package org.apache.syncope.core.persistence.jpa.dao.repo; + +import org.apache.syncope.core.persistence.api.dao.PasswordModuleDAO; +import org.apache.syncope.core.persistence.jpa.entity.am.JPAPasswordModule; +import org.springframework.data.repository.ListCrudRepository; + +public interface PasswordModuleRepo + extends ListCrudRepository, PasswordModuleRepoExt, PasswordModuleDAO { + +} diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordModuleRepoExt.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordModuleRepoExt.java new file mode 100644 index 00000000000..466baf1d30f --- /dev/null +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordModuleRepoExt.java @@ -0,0 +1,10 @@ +package org.apache.syncope.core.persistence.jpa.dao.repo; + +import org.apache.syncope.core.persistence.api.entity.am.PasswordModule; + +public interface PasswordModuleRepoExt { + + PasswordModule save(PasswordModule passwordModule); + + void delete(PasswordModule passwordModule); +} diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordModuleRepoExtImpl.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordModuleRepoExtImpl.java new file mode 100644 index 00000000000..39d3fbcccc2 --- /dev/null +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordModuleRepoExtImpl.java @@ -0,0 +1,24 @@ +package org.apache.syncope.core.persistence.jpa.dao.repo; + +import jakarta.persistence.EntityManager; +import org.apache.syncope.core.persistence.api.entity.am.PasswordModule; +import org.apache.syncope.core.persistence.jpa.entity.am.JPAPasswordModule; + +public class PasswordModuleRepoExtImpl implements PasswordModuleRepoExt { + + protected final EntityManager entityManager; + + public PasswordModuleRepoExtImpl(final EntityManager entityManager) { + this.entityManager = entityManager; + } + + + @Override public PasswordModule save(PasswordModule passwordModule) { + ((JPAPasswordModule) passwordModule).list2json(); + return entityManager.merge(passwordModule); + } + + @Override public void delete(PasswordModule passwordModule) { + entityManager.remove(passwordModule); + } +} diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractEntityFactory.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractEntityFactory.java index c1089baa2bd..18af1d92151 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractEntityFactory.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractEntityFactory.java @@ -53,6 +53,7 @@ import org.apache.syncope.core.persistence.api.entity.am.CASSPClientApp; import org.apache.syncope.core.persistence.api.entity.am.OIDCJWKS; import org.apache.syncope.core.persistence.api.entity.am.OIDCRPClientApp; +import org.apache.syncope.core.persistence.api.entity.am.PasswordModule; import org.apache.syncope.core.persistence.api.entity.am.SAML2IdPEntity; import org.apache.syncope.core.persistence.api.entity.am.SAML2SPClientApp; import org.apache.syncope.core.persistence.api.entity.am.WAConfigEntry; @@ -99,6 +100,7 @@ import org.apache.syncope.core.persistence.jpa.entity.am.JPACASSPClientApp; import org.apache.syncope.core.persistence.jpa.entity.am.JPAOIDCJWKS; import org.apache.syncope.core.persistence.jpa.entity.am.JPAOIDCRPClientApp; +import org.apache.syncope.core.persistence.jpa.entity.am.JPAPasswordModule; import org.apache.syncope.core.persistence.jpa.entity.am.JPASAML2IdPEntity; import org.apache.syncope.core.persistence.jpa.entity.am.JPASAML2SPClientApp; import org.apache.syncope.core.persistence.jpa.entity.am.JPAWAConfigEntry; @@ -262,7 +264,9 @@ public E newEntity(final Class reference) { result = (E) new JPASRARoute(); } else if (reference.equals(AuthModule.class)) { result = (E) new JPAAuthModule(); - } else if (reference.equals(AttrRepo.class)) { + } else if (reference.equals(PasswordModule.class)) { + result = (E) new JPAPasswordModule(); + }else if (reference.equals(AttrRepo.class)) { result = (E) new JPAAttrRepo(); } else if (reference.equals(AuthPolicy.class)) { result = (E) new JPAAuthPolicy(); diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/am/JPAPasswordModule.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/am/JPAPasswordModule.java new file mode 100644 index 00000000000..49fe09ab005 --- /dev/null +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/am/JPAPasswordModule.java @@ -0,0 +1,114 @@ +package org.apache.syncope.core.persistence.jpa.entity.am; + +import com.fasterxml.jackson.core.type.TypeReference; +import jakarta.persistence.Entity; +import jakarta.persistence.Lob; +import jakarta.persistence.PostLoad; +import jakarta.persistence.PostPersist; +import jakarta.persistence.PostUpdate; +import jakarta.persistence.PrePersist; +import jakarta.persistence.PreUpdate; +import jakarta.persistence.Table; +import jakarta.persistence.Transient; +import jakarta.validation.constraints.NotNull; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import org.apache.commons.lang3.StringUtils; +import org.apache.syncope.common.lib.password.PasswordModuleConf; +import org.apache.syncope.common.lib.to.Item; +import org.apache.syncope.core.persistence.api.entity.am.PasswordModule; +import org.apache.syncope.core.persistence.jpa.entity.AbstractProvidedKeyEntity; +import org.apache.syncope.core.provisioning.api.serialization.POJOHelper; + +@Entity +@Table(name = JPAPasswordModule.TABLE) +public class JPAPasswordModule extends AbstractProvidedKeyEntity implements PasswordModule { + + private static final long serialVersionUID = 5457779846065079998L; + + public static final String TABLE = "PasswordModule"; + + protected static final TypeReference> TYPEREF = new TypeReference>() { + }; + + private String description; + + @NotNull + private Integer authModuleOrder = 0; + + @Lob + private String items; + + @Transient + private final List itemList = new ArrayList<>(); + + @Lob + private String jsonConf; + + @Override + public String getDescription() { + return description; + } + + @Override + public void setDescription(final String description) { + this.description = description; + } + + @Override + public int getOrder() { + return Optional.ofNullable(authModuleOrder).orElse(0); + } + + @Override + public void setOrder(final int order) { + this.authModuleOrder = order; + } + + @Override + public List getItems() { + return itemList; + } + + @Override + public PasswordModuleConf getConf() { + PasswordModuleConf conf = null; + if (!StringUtils.isBlank(jsonConf)) { + conf = POJOHelper.deserialize(jsonConf, PasswordModuleConf.class); + } + + return conf; + } + + @Override + public void setConf(final PasswordModuleConf conf) { + jsonConf = POJOHelper.serialize(conf); + } + + protected void json2list(final boolean clearFirst) { + if (clearFirst) { + getItems().clear(); + } + if (items != null) { + getItems().addAll(POJOHelper.deserialize(items, TYPEREF)); + } + } + + @PostLoad + public void postLoad() { + json2list(false); + } + + @PostPersist + @PostUpdate + public void postSave() { + json2list(true); + } + + @PrePersist + @PreUpdate + public void list2json() { + items = POJOHelper.serialize(getItems()); + } +} diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PasswordModuleTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PasswordModuleTest.java new file mode 100644 index 00000000000..89b0984e682 --- /dev/null +++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PasswordModuleTest.java @@ -0,0 +1,108 @@ +package org.apache.syncope.core.persistence.jpa.inner; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.List; +import org.apache.commons.lang3.ClassUtils; +import org.apache.syncope.common.lib.password.PasswordModuleConf; +import org.apache.syncope.common.lib.password.SyncopePasswordModuleConf; +import org.apache.syncope.common.lib.to.Item; +import org.apache.syncope.core.persistence.api.dao.PasswordModuleDAO; +import org.apache.syncope.core.persistence.api.entity.am.PasswordModule; +import org.apache.syncope.core.persistence.jpa.AbstractTest; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; + +@Transactional +public class PasswordModuleTest extends AbstractTest { + + private static boolean isSpecificConf(final PasswordModuleConf conf, final Class clazz) { + return ClassUtils.isAssignable(clazz, conf.getClass()); + } + + @Autowired + private PasswordModuleDAO passwordModuleDAO; + + @Test + public void findAll() { + List modules = passwordModuleDAO.findAll(); + assertNotNull(modules); + assertFalse(modules.isEmpty()); + } + + @Test + public void find() { + PasswordModule passwordModule = passwordModuleDAO.findById("DefaultSyncopePasswordModule").orElseThrow(); + assertTrue(passwordModule.getConf() instanceof PasswordModuleConf); + } + + @Test + public void findByType() { + List passwordModules = passwordModuleDAO.findAll(); + assertTrue(passwordModules.stream().anyMatch( + passwordModule -> isSpecificConf(passwordModule.getConf(), + SyncopePasswordModuleConf.class) + && passwordModule.getKey().equals("DefaultSyncopePasswordModule"))); + } + + private void savePasswordModule(final String key, final PasswordModuleConf conf) { + PasswordModule module = entityFactory.newEntity(PasswordModule.class); + module.setKey(key); + module.setDescription("A password management module"); + module.setConf(conf); + + Item keyMapping = new Item(); + keyMapping.setIntAttrName("uid"); + keyMapping.setExtAttrName("username"); + module.getItems().add(keyMapping); + + Item fullnameMapping = new Item(); + fullnameMapping.setIntAttrName("cn"); + fullnameMapping.setExtAttrName("fullname"); + module.getItems().add(fullnameMapping); + + module = passwordModuleDAO.save(module); + entityManager.flush(); + + assertNotNull(module); + assertNotNull(module.getKey()); + assertEquals(module, passwordModuleDAO.findById(module.getKey()).orElseThrow()); + assertEquals(2, module.getItems().size()); + } + + @Test + public void saveWithSyncopeModule() { + SyncopePasswordModuleConf conf = new SyncopePasswordModuleConf(); + conf.setDomain("Master"); + + savePasswordModule("SyncopePasswordModuleTest", conf); + } + + @Test + public void updateWithSyncopeModule() { + PasswordModule module = passwordModuleDAO.findById("DefaultSyncopePasswordModule").orElseThrow(); + + PasswordModuleConf conf = module.getConf(); + SyncopePasswordModuleConf.class.cast(conf).setDomain("Two"); + module.setConf(conf); + + module = passwordModuleDAO.save(module); + assertNotNull(module); + assertNotNull(module.getKey()); + PasswordModule found = passwordModuleDAO.findById(module.getKey()).orElseThrow(); + assertEquals("Two", SyncopePasswordModuleConf.class.cast(found.getConf()).getDomain()); + } + + @Test + public void delete() { + assertTrue(passwordModuleDAO.findById("DefaultSyncopePasswordModule").isPresent()); + + passwordModuleDAO.deleteById("DefaultSyncopePasswordModule"); + + assertTrue(passwordModuleDAO.findById("DefaultSyncopePasswordModule").isEmpty()); + } +} diff --git a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml index 9e02cede0c3..980b54da61e 100644 --- a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml +++ b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml @@ -90,6 +90,11 @@ under the License. + + + + diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/PasswordModuleDataBinder.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/PasswordModuleDataBinder.java new file mode 100644 index 00000000000..59d5e8678c8 --- /dev/null +++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/PasswordModuleDataBinder.java @@ -0,0 +1,13 @@ +package org.apache.syncope.core.provisioning.api.data; + +import org.apache.syncope.common.lib.to.PasswordModuleTO; +import org.apache.syncope.core.persistence.api.entity.am.PasswordModule; + +public interface PasswordModuleDataBinder { + + PasswordModule create(PasswordModuleTO passwordModuleTO); + + PasswordModule update(PasswordModule passwordModule, PasswordModuleTO passwordModuleTO); + + PasswordModuleTO getPasswordModuleTO(PasswordModule passwordModule); +} diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/ProvisioningContext.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/ProvisioningContext.java index 88a3d2fcade..1c95a594875 100644 --- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/ProvisioningContext.java +++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/ProvisioningContext.java @@ -88,6 +88,7 @@ import org.apache.syncope.core.provisioning.api.data.ImplementationDataBinder; import org.apache.syncope.core.provisioning.api.data.NotificationDataBinder; import org.apache.syncope.core.provisioning.api.data.OIDCJWKSDataBinder; +import org.apache.syncope.core.provisioning.api.data.PasswordModuleDataBinder; import org.apache.syncope.core.provisioning.api.data.PolicyDataBinder; import org.apache.syncope.core.provisioning.api.data.RealmDataBinder; import org.apache.syncope.core.provisioning.api.data.RelationshipTypeDataBinder; @@ -125,6 +126,7 @@ import org.apache.syncope.core.provisioning.java.data.ImplementationDataBinderImpl; import org.apache.syncope.core.provisioning.java.data.NotificationDataBinderImpl; import org.apache.syncope.core.provisioning.java.data.OIDCJWKSDataBinderImpl; +import org.apache.syncope.core.provisioning.java.data.PasswordModuleDataBinderImpl; import org.apache.syncope.core.provisioning.java.data.PolicyDataBinderImpl; import org.apache.syncope.core.provisioning.java.data.RealmDataBinderImpl; import org.apache.syncope.core.provisioning.java.data.RelationshipTypeDataBinderImpl; @@ -757,6 +759,12 @@ public AuthModuleDataBinder authModuleDataBinder(final EntityFactory entityFacto return new AuthModuleDataBinderImpl(entityFactory); } + @ConditionalOnMissingBean + @Bean + public PasswordModuleDataBinder passwordModuleDataBinder(final EntityFactory entityFactory) { + return new PasswordModuleDataBinderImpl(entityFactory); + } + @ConditionalOnMissingBean @Bean public AttrRepoDataBinder attrRepoDataBinder(final EntityFactory entityFactory) { diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/PasswordModuleDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/PasswordModuleDataBinderImpl.java new file mode 100644 index 00000000000..e035a08626b --- /dev/null +++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/PasswordModuleDataBinderImpl.java @@ -0,0 +1,118 @@ +package org.apache.syncope.core.provisioning.java.data; + +import org.apache.syncope.common.lib.SyncopeClientCompositeException; +import org.apache.syncope.common.lib.SyncopeClientException; +import org.apache.syncope.common.lib.to.AuthModuleTO; +import org.apache.syncope.common.lib.to.Item; +import org.apache.syncope.common.lib.to.PasswordModuleTO; +import org.apache.syncope.common.lib.types.ClientExceptionType; +import org.apache.syncope.common.lib.types.MappingPurpose; +import org.apache.syncope.core.persistence.api.entity.EntityFactory; +import org.apache.syncope.core.persistence.api.entity.am.AuthModule; +import org.apache.syncope.core.persistence.api.entity.am.PasswordModule; +import org.apache.syncope.core.provisioning.api.data.PasswordModuleDataBinder; +import org.apache.syncope.core.provisioning.api.jexl.JexlUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class PasswordModuleDataBinderImpl implements PasswordModuleDataBinder { + + protected static final Logger LOG = LoggerFactory.getLogger(PasswordModuleDataBinder.class); + + protected final EntityFactory entityFactory; + + public PasswordModuleDataBinderImpl(final EntityFactory entityFactory) { + this.entityFactory = entityFactory; + } + + protected void populateItems(final PasswordModuleTO passwordModuleTO, final PasswordModule passwordModule) { + SyncopeClientCompositeException scce = SyncopeClientException.buildComposite(); + SyncopeClientException invalidMapping = + SyncopeClientException.build(ClientExceptionType.InvalidMapping); + SyncopeClientException requiredValuesMissing = + SyncopeClientException.build(ClientExceptionType.RequiredValuesMissing); + + passwordModuleTO.getItems().forEach(itemTO -> { + if (itemTO == null) { + LOG.error("Null {}", Item.class.getSimpleName()); + invalidMapping.getElements().add("Null " + Item.class.getSimpleName()); + } else if (itemTO.getIntAttrName() == null) { + requiredValuesMissing.getElements().add("intAttrName"); + scce.addException(requiredValuesMissing); + } else { + // no mandatory condition implies mandatory condition false + if (!JexlUtils.isExpressionValid(itemTO.getMandatoryCondition() == null + ? "false" : itemTO.getMandatoryCondition())) { + + SyncopeClientException invalidMandatoryCondition = + SyncopeClientException.build(ClientExceptionType.InvalidValues); + invalidMandatoryCondition.getElements().add(itemTO.getMandatoryCondition()); + scce.addException(invalidMandatoryCondition); + } + + Item item = new Item(); + item.setIntAttrName(itemTO.getIntAttrName()); + item.setExtAttrName(itemTO.getExtAttrName()); + item.setMandatoryCondition(itemTO.getMandatoryCondition()); + item.setConnObjectKey(itemTO.isConnObjectKey()); + item.setPassword(itemTO.isPassword()); + item.setPropagationJEXLTransformer(itemTO.getPropagationJEXLTransformer()); + item.setPullJEXLTransformer(itemTO.getPullJEXLTransformer()); + passwordModule.getItems().add(item); + } + }); + + if (!invalidMapping.getElements().isEmpty()) { + scce.addException(invalidMapping); + } + if (scce.hasExceptions()) { + throw scce; + } + } + + protected void populateItems(final PasswordModule passwordModule, final PasswordModuleTO passwordModuleTO) { + passwordModule.getItems().forEach(item -> { + Item itemTO = new Item(); + itemTO.setIntAttrName(item.getIntAttrName()); + itemTO.setExtAttrName(item.getExtAttrName()); + itemTO.setMandatoryCondition(item.getMandatoryCondition()); + itemTO.setConnObjectKey(item.isConnObjectKey()); + itemTO.setPassword(item.isPassword()); + itemTO.setPropagationJEXLTransformer(item.getPropagationJEXLTransformer()); + itemTO.setPullJEXLTransformer(item.getPullJEXLTransformer()); + itemTO.setPurpose(MappingPurpose.NONE); + + passwordModuleTO.getItems().add(itemTO); + }); + } + + @Override public PasswordModule create(PasswordModuleTO passwordModuleTO) { + PasswordModule passwordModule = entityFactory.newEntity(PasswordModule.class); + passwordModule.setKey(passwordModuleTO.getKey()); + return update(passwordModule, passwordModuleTO); + } + + @Override public PasswordModule update(PasswordModule passwordModule, PasswordModuleTO passwordModuleTO) { + passwordModule.setDescription(passwordModuleTO.getDescription()); + passwordModule.setOrder(passwordModuleTO.getOrder()); + passwordModule.setConf(passwordModuleTO.getConf()); + + passwordModule.getItems().clear(); + populateItems(passwordModuleTO, passwordModule); + + return passwordModule; + } + + @Override public PasswordModuleTO getPasswordModuleTO(PasswordModule passwordModule) { + PasswordModuleTO passwordModuleTO = new PasswordModuleTO(); + + passwordModuleTO.setKey(passwordModule.getKey()); + passwordModuleTO.setDescription(passwordModule.getDescription()); + passwordModuleTO.setOrder(passwordModule.getOrder()); + passwordModuleTO.setConf(passwordModule.getConf()); + + populateItems(passwordModule, passwordModuleTO); + + return passwordModuleTO; + } +} From 9817a35d172353b20fb6da8b0db9c1dc4ee3db8f Mon Sep 17 00:00:00 2001 From: alberto bogi Date: Thu, 14 Aug 2025 10:54:04 +0200 Subject: [PATCH 02/20] [SYNCOPE-1901] Implement Neo4j persistence for PasswordModule in Syncope --- .../persistence/neo4j/PersistenceContext.java | 20 ++++ .../neo4j/dao/repo/PasswordModuleRepo.java | 9 ++ .../neo4j/dao/repo/PasswordModuleRepoExt.java | 10 ++ .../dao/repo/PasswordModuleRepoExtImpl.java | 33 ++++++ .../neo4j/entity/Neo4jEntityFactory.java | 6 +- .../neo4j/entity/am/Neo4jPasswordModule.java | 100 ++++++++++++++++++ 6 files changed, 177 insertions(+), 1 deletion(-) create mode 100644 core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/PasswordModuleRepo.java create mode 100644 core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/PasswordModuleRepoExt.java create mode 100644 core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/PasswordModuleRepoExtImpl.java create mode 100644 core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4jPasswordModule.java diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/PersistenceContext.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/PersistenceContext.java index 9544c68fcd3..d4e3935b440 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/PersistenceContext.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/PersistenceContext.java @@ -59,6 +59,7 @@ import org.apache.syncope.core.persistence.api.dao.NotificationDAO; import org.apache.syncope.core.persistence.api.dao.OIDCJWKSDAO; import org.apache.syncope.core.persistence.api.dao.OIDCRPClientAppDAO; +import org.apache.syncope.core.persistence.api.dao.PasswordModuleDAO; import org.apache.syncope.core.persistence.api.dao.PersistenceInfoDAO; import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO; import org.apache.syncope.core.persistence.api.dao.PolicyDAO; @@ -160,6 +161,9 @@ import org.apache.syncope.core.persistence.neo4j.dao.repo.OIDCRPClientAppRepo; import org.apache.syncope.core.persistence.neo4j.dao.repo.OIDCRPClientAppRepoExt; import org.apache.syncope.core.persistence.neo4j.dao.repo.OIDCRPClientAppRepoExtImpl; +import org.apache.syncope.core.persistence.neo4j.dao.repo.PasswordModuleRepo; +import org.apache.syncope.core.persistence.neo4j.dao.repo.PasswordModuleRepoExt; +import org.apache.syncope.core.persistence.neo4j.dao.repo.PasswordModuleRepoExtImpl; import org.apache.syncope.core.persistence.neo4j.dao.repo.PlainSchemaRepo; import org.apache.syncope.core.persistence.neo4j.dao.repo.PlainSchemaRepoExt; import org.apache.syncope.core.persistence.neo4j.dao.repo.PlainSchemaRepoExtImpl; @@ -673,6 +677,14 @@ public AuthModuleRepoExt authModuleRepoExt( return new AuthModuleRepoExtImpl(policyDAO, neo4jTemplate, nodeValidator); } + @ConditionalOnMissingBean + @Bean + public PasswordModuleRepoExt passwordModuleRepoExt( + final Neo4jTemplate neo4jTemplate, + final NodeValidator nodeValidator) { + return new PasswordModuleRepoExtImpl(neo4jTemplate, nodeValidator); + } + @ConditionalOnMissingBean @Bean public AuthModuleDAO authModuleDAO( @@ -682,6 +694,14 @@ public AuthModuleDAO authModuleDAO( return neo4jRepositoryFactory.getRepository(AuthModuleRepo.class, authModuleRepoExt); } + @ConditionalOnMissingBean + @Bean + public PasswordModuleDAO passwordModuleDAO( + final SyncopeNeo4jRepositoryFactory neo4jRepositoryFactory, + final PasswordModuleRepoExt passwordModuleRepoExt) { + return neo4jRepositoryFactory.getRepository(PasswordModuleRepo.class, passwordModuleRepoExt); + } + @ConditionalOnMissingBean @Bean public AuthProfileDAO authProfileDAO(final SyncopeNeo4jRepositoryFactory neo4jRepositoryFactory) { diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/PasswordModuleRepo.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/PasswordModuleRepo.java new file mode 100644 index 00000000000..0bad60fe210 --- /dev/null +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/PasswordModuleRepo.java @@ -0,0 +1,9 @@ +package org.apache.syncope.core.persistence.neo4j.dao.repo; + +import org.apache.syncope.core.persistence.api.dao.PasswordModuleDAO; +import org.apache.syncope.core.persistence.neo4j.entity.am.Neo4jPasswordModule; +import org.springframework.data.repository.ListCrudRepository; + +public interface PasswordModuleRepo + extends ListCrudRepository, PasswordModuleRepoExt, PasswordModuleDAO { +} diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/PasswordModuleRepoExt.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/PasswordModuleRepoExt.java new file mode 100644 index 00000000000..5c289db4e56 --- /dev/null +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/PasswordModuleRepoExt.java @@ -0,0 +1,10 @@ +package org.apache.syncope.core.persistence.neo4j.dao.repo; + +import org.apache.syncope.core.persistence.api.entity.am.PasswordModule; + +public interface PasswordModuleRepoExt { + + PasswordModule save(PasswordModule passwordModule); + + void delete(PasswordModule passwordModule); +} diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/PasswordModuleRepoExtImpl.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/PasswordModuleRepoExtImpl.java new file mode 100644 index 00000000000..2871433bd42 --- /dev/null +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/PasswordModuleRepoExtImpl.java @@ -0,0 +1,33 @@ +package org.apache.syncope.core.persistence.neo4j.dao.repo; + +import org.apache.syncope.core.persistence.api.entity.am.PasswordModule; +import org.apache.syncope.core.persistence.neo4j.entity.am.Neo4jPasswordModule; +import org.apache.syncope.core.persistence.neo4j.spring.NodeValidator; +import org.springframework.data.neo4j.core.Neo4jTemplate; + +public class PasswordModuleRepoExtImpl implements PasswordModuleRepoExt { + + protected final Neo4jTemplate neo4jTemplate; + + protected final NodeValidator nodeValidator; + + public PasswordModuleRepoExtImpl( + final Neo4jTemplate neo4jTemplate, + final NodeValidator nodeValidator) { + this.neo4jTemplate = neo4jTemplate; + this.nodeValidator = nodeValidator; + } + + @Override + public PasswordModule save(PasswordModule passwordModule) { + ((Neo4jPasswordModule) passwordModule).list2json(); + PasswordModule saved = neo4jTemplate.save(nodeValidator.validate(passwordModule)); + ((Neo4jPasswordModule) saved).postSave(); + return saved; + } + + @Override + public void delete(PasswordModule passwordModule) { + neo4jTemplate.deleteById(passwordModule.getKey(), Neo4jPasswordModule.class); + } +} diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/Neo4jEntityFactory.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/Neo4jEntityFactory.java index b8f71ea9130..c70c36e7c74 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/Neo4jEntityFactory.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/Neo4jEntityFactory.java @@ -54,6 +54,7 @@ import org.apache.syncope.core.persistence.api.entity.am.CASSPClientApp; import org.apache.syncope.core.persistence.api.entity.am.OIDCJWKS; import org.apache.syncope.core.persistence.api.entity.am.OIDCRPClientApp; +import org.apache.syncope.core.persistence.api.entity.am.PasswordModule; import org.apache.syncope.core.persistence.api.entity.am.SAML2IdPEntity; import org.apache.syncope.core.persistence.api.entity.am.SAML2SPClientApp; import org.apache.syncope.core.persistence.api.entity.am.WAConfigEntry; @@ -100,6 +101,7 @@ import org.apache.syncope.core.persistence.neo4j.entity.am.Neo4jCASSPClientApp; import org.apache.syncope.core.persistence.neo4j.entity.am.Neo4jOIDCJWKS; import org.apache.syncope.core.persistence.neo4j.entity.am.Neo4jOIDCRPClientApp; +import org.apache.syncope.core.persistence.neo4j.entity.am.Neo4jPasswordModule; import org.apache.syncope.core.persistence.neo4j.entity.am.Neo4jSAML2IdPEntity; import org.apache.syncope.core.persistence.neo4j.entity.am.Neo4jSAML2SPClientApp; import org.apache.syncope.core.persistence.neo4j.entity.am.Neo4jWAConfigEntry; @@ -263,7 +265,9 @@ public E newEntity(final Class reference) { result = (E) new Neo4jSRARoute(); } else if (reference.equals(AuthModule.class)) { result = (E) new Neo4jAuthModule(); - } else if (reference.equals(AttrRepo.class)) { + } else if (reference.equals(PasswordModule.class)) { + result = (E) new Neo4jPasswordModule(); + }else if (reference.equals(AttrRepo.class)) { result = (E) new Neo4jAttrRepo(); } else if (reference.equals(AuthPolicy.class)) { result = (E) new Neo4jAuthPolicy(); diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4jPasswordModule.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4jPasswordModule.java new file mode 100644 index 00000000000..e5083b20758 --- /dev/null +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4jPasswordModule.java @@ -0,0 +1,100 @@ +package org.apache.syncope.core.persistence.neo4j.entity.am; + +import com.fasterxml.jackson.core.type.TypeReference; +import jakarta.validation.constraints.NotNull; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import org.apache.commons.lang3.StringUtils; +import org.apache.syncope.common.lib.password.PasswordModuleConf; +import org.apache.syncope.common.lib.to.Item; +import org.apache.syncope.core.persistence.api.entity.am.PasswordModule; +import org.apache.syncope.core.persistence.neo4j.entity.AbstractProvidedKeyNode; +import org.apache.syncope.core.provisioning.api.serialization.POJOHelper; +import org.springframework.data.annotation.Transient; +import org.springframework.data.neo4j.core.schema.Node; +import org.springframework.data.neo4j.core.schema.PostLoad; + +@Node(Neo4jPasswordModule.NODE) +public class Neo4jPasswordModule extends AbstractProvidedKeyNode implements PasswordModule { + private static final long serialVersionUID = 5457779846065079998L; + + public static final String NODE = "PasswordModule"; + + protected static final TypeReference> TYPEREF = new TypeReference>() { + }; + + private String description; + + @NotNull + private Integer authModuleOrder = 0; + + private String items; + + @Transient + private final List itemList = new ArrayList<>(); + + private String jsonConf; + + @Override + public String getDescription() { + return description; + } + + @Override + public void setDescription(final String description) { + this.description = description; + } + + @Override + public int getOrder() { + return Optional.ofNullable(authModuleOrder).orElse(0); + } + + @Override + public void setOrder(final int order) { + this.authModuleOrder = order; + } + + @Override + public List getItems() { + return itemList; + } + + @Override + public PasswordModuleConf getConf() { + PasswordModuleConf conf = null; + if (!StringUtils.isBlank(jsonConf)) { + conf = POJOHelper.deserialize(jsonConf, PasswordModuleConf.class); + } + + return conf; + } + + @Override + public void setConf(final PasswordModuleConf conf) { + jsonConf = POJOHelper.serialize(conf); + } + + protected void json2list(final boolean clearFirst) { + if (clearFirst) { + getItems().clear(); + } + if (items != null) { + getItems().addAll(POJOHelper.deserialize(items, TYPEREF)); + } + } + + @PostLoad + public void postLoad() { + json2list(false); + } + + public void postSave() { + json2list(true); + } + + public void list2json() { + items = POJOHelper.serialize(getItems()); + } +} From 24673c576c7e5b998fccb6afe54bc860980d2365 Mon Sep 17 00:00:00 2001 From: alberto bogi Date: Thu, 14 Aug 2025 11:00:42 +0200 Subject: [PATCH 03/20] [SYNCOPE-1901] Unit tests and IT tests for PasswordModule. Only implementation for Syncope is now available --- .../apache/syncope/fit/AbstractITCase.java | 4 + .../fit/core/PasswordModuleITCase.java | 131 ++++++++++++++++++ 2 files changed, 135 insertions(+) create mode 100644 fit/core-reference/src/test/java/org/apache/syncope/fit/core/PasswordModuleITCase.java diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java index 266af6a5576..068daa7b363 100644 --- a/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java +++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java @@ -148,6 +148,7 @@ import org.apache.syncope.common.rest.api.service.OIDCC4UIProviderService; import org.apache.syncope.common.rest.api.service.OIDCC4UIService; import org.apache.syncope.common.rest.api.service.OIDCJWKSService; +import org.apache.syncope.common.rest.api.service.PasswordModuleService; import org.apache.syncope.common.rest.api.service.PolicyService; import org.apache.syncope.common.rest.api.service.RealmService; import org.apache.syncope.common.rest.api.service.ReconciliationService; @@ -354,6 +355,8 @@ public void initialize(final ConfigurableApplicationContext ctx) { protected static AuthModuleService AUTH_MODULE_SERVICE; + protected static PasswordModuleService PASSWORD_MODULE_SERVICE; + protected static AttrRepoService ATTR_REPO_SERVICE; protected static SecurityQuestionService SECURITY_QUESTION_SERVICE; @@ -595,6 +598,7 @@ public static void restSetup() { SCIM_CONF_SERVICE = ADMIN_CLIENT.getService(SCIMConfService.class); CLIENT_APP_SERVICE = ADMIN_CLIENT.getService(ClientAppService.class); AUTH_MODULE_SERVICE = ADMIN_CLIENT.getService(AuthModuleService.class); + PASSWORD_MODULE_SERVICE = ADMIN_CLIENT.getService(PasswordModuleService.class); ATTR_REPO_SERVICE = ADMIN_CLIENT.getService(AttrRepoService.class); SAML2IDP_ENTITY_SERVICE = ADMIN_CLIENT.getService(SAML2IdPEntityService.class); AUTH_PROFILE_SERVICE = ADMIN_CLIENT.getService(AuthProfileService.class); diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PasswordModuleITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PasswordModuleITCase.java new file mode 100644 index 00000000000..1c0389f4c20 --- /dev/null +++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PasswordModuleITCase.java @@ -0,0 +1,131 @@ +package org.apache.syncope.fit.core; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; + +import jakarta.ws.rs.core.Response; +import java.io.IOException; +import java.util.EnumSet; +import java.util.List; +import org.apache.commons.lang3.ClassUtils; +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.password.PasswordModuleConf; +import org.apache.syncope.common.lib.password.SyncopePasswordModuleConf; +import org.apache.syncope.common.lib.to.PasswordModuleTO; +import org.apache.syncope.common.rest.api.service.PasswordModuleService; +import org.apache.syncope.fit.AbstractITCase; +import org.junit.jupiter.api.Test; + +public class PasswordModuleITCase extends AbstractITCase { + + private enum PasswordModuleSupportedType { + SYNCOPE + }; + + private static PasswordModuleTO createAuthModule(final PasswordModuleTO passwordModuleTO) { + Response response = PASSWORD_MODULE_SERVICE.create(passwordModuleTO); + if (response.getStatusInfo().getStatusCode() != Response.Status.CREATED.getStatusCode()) { + Exception ex = CLIENT_FACTORY.getExceptionMapper().fromResponse(response); + if (ex != null) { + throw (RuntimeException) ex; + } + } + return getObject(response.getLocation(), PasswordModuleService.class, passwordModuleTO.getClass()); + } + + private static PasswordModuleTO buildPasswordModuleTO(final PasswordModuleSupportedType type) { + PasswordModuleTO passwordModuleTO = new PasswordModuleTO(); + passwordModuleTO.setKey("Test" + type + "PasswordModule" + getUUIDString()); + passwordModuleTO.setDescription("A test " + type + " Password Module"); + + PasswordModuleConf conf; + switch (type) { + case SYNCOPE: + conf = new SyncopePasswordModuleConf(); + SyncopePasswordModuleConf.class.cast(conf).setDomain(SyncopeConstants.MASTER_DOMAIN); + passwordModuleTO.setConf(conf); + break; + } + + return passwordModuleTO; + } + + private static boolean isSpecificConf(final PasswordModuleConf conf, final Class clazz) { + return ClassUtils.isAssignable(clazz, conf.getClass()); + } + + @Test + public void list() { + List passwordModuleTOS = PASSWORD_MODULE_SERVICE.list(); + assertNotNull(passwordModuleTOS); + assertFalse(passwordModuleTOS.isEmpty()); + + assertTrue(passwordModuleTOS.stream().anyMatch( + authModule -> isSpecificConf(authModule.getConf(), SyncopePasswordModuleConf.class) + && authModule.getKey().equals("DefaultSyncopePasswordModule"))); + } + + @Test + public void getSyncopePasswordModule() { + PasswordModuleTO passwordModuleTO = PASSWORD_MODULE_SERVICE.read("DefaultSyncopePasswordModule"); + + assertNotNull(passwordModuleTO); + assertTrue(StringUtils.isNotBlank(passwordModuleTO.getDescription())); + assertTrue(isSpecificConf(passwordModuleTO.getConf(), SyncopePasswordModuleConf.class)); + } + + @Test + public void create() { + EnumSet.allOf(PasswordModuleSupportedType.class).forEach(type -> { + PasswordModuleTO passwordModuleTO = createAuthModule(buildPasswordModuleTO(type)); + assertNotNull(passwordModuleTO); + assertTrue(passwordModuleTO.getDescription().contains("A test " + type + " Password Module")); + assertTrue(passwordModuleTO.getItems().isEmpty()); + }); + } + + @Test + public void updateSyncopePasswordModule() { + PasswordModuleTO syncopePasswordModuleTO = PASSWORD_MODULE_SERVICE.read("DefaultSyncopePasswordModule"); + assertNotNull(syncopePasswordModuleTO); + + PasswordModuleTO newSyncopePasswordModuleTO = buildPasswordModuleTO(PasswordModuleSupportedType.SYNCOPE); + newSyncopePasswordModuleTO = createAuthModule(newSyncopePasswordModuleTO); + assertNotNull(newSyncopePasswordModuleTO); + + PasswordModuleConf conf = syncopePasswordModuleTO.getConf(); + assertNotNull(conf); + SyncopePasswordModuleConf.class.cast(conf).setDomain("Two"); + newSyncopePasswordModuleTO.setConf(conf); + + // update new password module + PASSWORD_MODULE_SERVICE.update(newSyncopePasswordModuleTO); + newSyncopePasswordModuleTO = PASSWORD_MODULE_SERVICE.read(newSyncopePasswordModuleTO.getKey()); + assertNotNull(newSyncopePasswordModuleTO); + + conf = newSyncopePasswordModuleTO.getConf(); + assertEquals("Two", SyncopePasswordModuleConf.class.cast(conf).getDomain()); + } + + @Test + public void delete() throws IOException { + EnumSet.allOf(PasswordModuleSupportedType.class).forEach(type -> { + PasswordModuleTO read = createAuthModule(buildPasswordModuleTO(type)); + assertNotNull(read); + + PASSWORD_MODULE_SERVICE.delete(read.getKey()); + + try { + PASSWORD_MODULE_SERVICE.read(read.getKey()); + fail("This should not happen"); + } catch (SyncopeClientException e) { + assertNotNull(e); + } + }); + } +} From 4bd557a98d19e5615297d06d9341348bb9df2145 Mon Sep 17 00:00:00 2001 From: alberto bogi Date: Mon, 18 Aug 2025 10:54:02 +0200 Subject: [PATCH 04/20] [SYNCOPE-1901] Implemented the UI for configuring password management in CAS through Syncope --- .../client/console/AMConsoleContext.java | 7 + ...lassPathScanImplementationContributor.java | 5 + .../syncope/client/console/pages/WA.java | 17 ++ .../panels/PasswordModuleDirectoryPanel.java | 223 ++++++++++++++++++ .../rest/PasswordModuleRestClient.java | 30 +++ .../wizards/PasswordModuleWizardBuilder.java | 143 +++++++++++ .../client/console/pages/WA.properties | 1 + .../client/console/pages/WA_fr_CA.properties | 1 + .../client/console/pages/WA_it.properties | 1 + .../client/console/pages/WA_ja.properties | 1 + .../client/console/pages/WA_pt_BR.properties | 1 + .../client/console/pages/WA_ru.properties | 1 + .../PasswordModuleDirectoryPanel.properties | 8 + ...PasswordModuleDirectoryPanel_fr.properties | 8 + ...swordModuleDirectoryPanel_fr_CA.properties | 8 + ...PasswordModuleDirectoryPanel_it.properties | 8 + ...PasswordModuleDirectoryPanel_ja.properties | 8 + ...swordModuleDirectoryPanel_pt_BR.properties | 8 + ...PasswordModuleDirectoryPanel_ru.properties | 8 + ...wordModuleWizardBuilder$Configuration.html | 5 + ...duleWizardBuilder$Configuration.properties | 7 + ...eWizardBuilder$Configuration_fr.properties | 7 + ...zardBuilder$Configuration_fr_CA.properties | 7 + ...eWizardBuilder$Configuration_it.properties | 7 + ...eWizardBuilder$Configuration_ja.properties | 7 + ...zardBuilder$Configuration_pt_BR.properties | 7 + ...eWizardBuilder$Configuration_ru.properties | 7 + .../PasswordModuleWizardBuilder$Profile.html | 9 + ...wordModuleWizardBuilder$Profile.properties | 4 + ...dModuleWizardBuilder$Profile_fr.properties | 4 + ...duleWizardBuilder$Profile_fr_CA.properties | 4 + ...dModuleWizardBuilder$Profile_it.properties | 4 + ...dModuleWizardBuilder$Profile_ja.properties | 4 + ...duleWizardBuilder$Profile_pt_BR.properties | 4 + ...dModuleWizardBuilder$Profile_ru.properties | 4 + .../password/SyncopePasswordModuleConf.java | 20 -- .../test/resources/domains/MasterContent.xml | 2 +- .../data/PasswordModuleDataBinderImpl.java | 2 - .../src/main/resources/wa-embedded.properties | 3 - .../bootstrap/WABootstrapConfiguration.java | 9 + .../wa/bootstrap/WAPropertySourceLocator.java | 14 +- .../PasswordModulePropertySourceMapper.java | 37 +++ 42 files changed, 637 insertions(+), 28 deletions(-) create mode 100644 client/am/console/src/main/java/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel.java create mode 100644 client/am/console/src/main/java/org/apache/syncope/client/console/rest/PasswordModuleRestClient.java create mode 100644 client/am/console/src/main/java/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder.java create mode 100644 client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel.properties create mode 100644 client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_fr.properties create mode 100644 client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_fr_CA.properties create mode 100644 client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_it.properties create mode 100644 client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_ja.properties create mode 100644 client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_pt_BR.properties create mode 100644 client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_ru.properties create mode 100644 client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration.html create mode 100644 client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration.properties create mode 100644 client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_fr.properties create mode 100644 client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_fr_CA.properties create mode 100644 client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_it.properties create mode 100644 client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_ja.properties create mode 100644 client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_pt_BR.properties create mode 100644 client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_ru.properties create mode 100644 client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile.html create mode 100644 client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile.properties create mode 100644 client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_fr.properties create mode 100644 client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_fr_CA.properties create mode 100644 client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_it.properties create mode 100644 client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_ja.properties create mode 100644 client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_pt_BR.properties create mode 100644 client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_ru.properties create mode 100644 wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/PasswordModulePropertySourceMapper.java diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/AMConsoleContext.java b/client/am/console/src/main/java/org/apache/syncope/client/console/AMConsoleContext.java index 8d8b53f3bc3..a7cc623ac4a 100644 --- a/client/am/console/src/main/java/org/apache/syncope/client/console/AMConsoleContext.java +++ b/client/am/console/src/main/java/org/apache/syncope/client/console/AMConsoleContext.java @@ -31,6 +31,7 @@ import org.apache.syncope.client.console.rest.AuthProfileRestClient; import org.apache.syncope.client.console.rest.ClientAppRestClient; import org.apache.syncope.client.console.rest.OIDCJWKSRestClient; +import org.apache.syncope.client.console.rest.PasswordModuleRestClient; import org.apache.syncope.client.console.rest.PolicyRestClient; import org.apache.syncope.client.console.rest.SAML2IdPEntityRestClient; import org.apache.syncope.client.console.rest.SRARouteRestClient; @@ -75,6 +76,12 @@ public AuthModuleRestClient authModuleRestClient() { return new AuthModuleRestClient(); } + @ConditionalOnMissingBean + @Bean + public PasswordModuleRestClient passwordModuleRestClient() { + return new PasswordModuleRestClient(); + } + @ConditionalOnMissingBean @Bean public AuthProfileRestClient authProfileRestClient() { diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/init/AMClassPathScanImplementationContributor.java b/client/am/console/src/main/java/org/apache/syncope/client/console/init/AMClassPathScanImplementationContributor.java index f995e5de2ad..2b0a59a919c 100644 --- a/client/am/console/src/main/java/org/apache/syncope/client/console/init/AMClassPathScanImplementationContributor.java +++ b/client/am/console/src/main/java/org/apache/syncope/client/console/init/AMClassPathScanImplementationContributor.java @@ -22,6 +22,7 @@ import org.apache.syncope.common.lib.attr.AttrRepoConf; import org.apache.syncope.common.lib.auth.AuthModuleConf; import org.apache.syncope.common.lib.clientapps.UsernameAttributeProviderConf; +import org.apache.syncope.common.lib.password.PasswordModuleConf; import org.apache.syncope.common.lib.policy.AccessPolicyConf; import org.apache.syncope.common.lib.policy.AttrReleasePolicyConf; import org.apache.syncope.common.lib.policy.AuthPolicyConf; @@ -35,6 +36,7 @@ public class AMClassPathScanImplementationContributor implements ClassPathScanIm @Override public void extend(final ClassPathScanningCandidateComponentProvider scanner) { scanner.addIncludeFilter(new AssignableTypeFilter(AuthModuleConf.class)); + scanner.addIncludeFilter(new AssignableTypeFilter(PasswordModuleConf.class)); scanner.addIncludeFilter(new AssignableTypeFilter(AttrRepoConf.class)); scanner.addIncludeFilter(new AssignableTypeFilter(AccessPolicyConf.class)); scanner.addIncludeFilter(new AssignableTypeFilter(AttrReleasePolicyConf.class)); @@ -47,6 +49,9 @@ public Optional getLabel(final Class clazz) { if (AuthModuleConf.class.isAssignableFrom(clazz)) { return Optional.of(AuthModuleConf.class.getName()); } + if (PasswordModuleConf.class.isAssignableFrom(clazz)) { + return Optional.of(PasswordModuleConf.class.getName()); + } if (AttrRepoConf.class.isAssignableFrom(clazz)) { return Optional.of(AttrRepoConf.class.getName()); } diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/pages/WA.java b/client/am/console/src/main/java/org/apache/syncope/client/console/pages/WA.java index 58dda5ea16e..8101ee3c9b6 100644 --- a/client/am/console/src/main/java/org/apache/syncope/client/console/pages/WA.java +++ b/client/am/console/src/main/java/org/apache/syncope/client/console/pages/WA.java @@ -39,12 +39,14 @@ import org.apache.syncope.client.console.panels.AttrRepoDirectoryPanel; import org.apache.syncope.client.console.panels.AuthModuleDirectoryPanel; import org.apache.syncope.client.console.panels.OIDC; +import org.apache.syncope.client.console.panels.PasswordModuleDirectoryPanel; import org.apache.syncope.client.console.panels.SAML2IdPEntityDirectoryPanel; import org.apache.syncope.client.console.panels.WAConfigDirectoryPanel; import org.apache.syncope.client.console.panels.WAPushModalPanel; import org.apache.syncope.client.console.rest.AttrRepoRestClient; import org.apache.syncope.client.console.rest.AuthModuleRestClient; import org.apache.syncope.client.console.rest.AuthProfileRestClient; +import org.apache.syncope.client.console.rest.PasswordModuleRestClient; import org.apache.syncope.client.console.rest.SAML2IdPEntityRestClient; import org.apache.syncope.client.console.rest.WAConfigRestClient; import org.apache.syncope.client.console.rest.WASessionRestClient; @@ -81,6 +83,9 @@ public class WA extends BasePage { @SpringBean protected AuthModuleRestClient authModuleRestClient; + @SpringBean + protected PasswordModuleRestClient passwordModuleRestClient; + @SpringBean protected AttrRepoRestClient attrRepoRestClient; @@ -179,6 +184,18 @@ public Panel getPanel(final String panelId) { }); } + if (SyncopeConsoleSession.get().owns(AMEntitlement.PASSWORD_MODULE_LIST)) { + tabs.add(new AbstractTab(new ResourceModel("passwordModules")) { + + private static final long serialVersionUID = 5211692813425391144L; + + @Override + public Panel getPanel(final String panelId) { + return new PasswordModuleDirectoryPanel(panelId, passwordModuleRestClient, getPageReference()); + } + }); + } + if (SyncopeConsoleSession.get().owns(AMEntitlement.ATTR_REPO_LIST)) { tabs.add(new AbstractTab(new ResourceModel("attrRepos")) { diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel.java b/client/am/console/src/main/java/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel.java new file mode 100644 index 00000000000..3e378082692 --- /dev/null +++ b/client/am/console/src/main/java/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel.java @@ -0,0 +1,223 @@ +package org.apache.syncope.client.console.panels; + +import de.agilecoders.wicket.core.markup.html.bootstrap.dialog.Modal; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import org.apache.commons.lang3.StringUtils; +import org.apache.syncope.client.console.SyncopeConsoleSession; +import org.apache.syncope.client.console.audit.AuditHistoryModal; +import org.apache.syncope.client.console.commons.AMConstants; +import org.apache.syncope.client.console.commons.DirectoryDataProvider; +import org.apache.syncope.client.console.commons.SortableDataProviderComparator; +import org.apache.syncope.client.console.pages.BasePage; +import org.apache.syncope.client.console.rest.AuditRestClient; +import org.apache.syncope.client.console.rest.PasswordModuleRestClient; +import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal; +import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink; +import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel; +import org.apache.syncope.client.console.wizards.PasswordModuleWizardBuilder; +import org.apache.syncope.client.ui.commons.Constants; +import org.apache.syncope.client.ui.commons.pages.BaseWebPage; +import org.apache.syncope.client.ui.commons.wizards.AjaxWizard; +import org.apache.syncope.common.lib.to.PasswordModuleTO; +import org.apache.syncope.common.lib.types.AMEntitlement; +import org.apache.syncope.common.lib.types.IdRepoEntitlement; +import org.apache.syncope.common.lib.types.OpEvent; +import org.apache.wicket.PageReference; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy; +import org.apache.wicket.event.Broadcast; +import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator; +import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn; +import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn; +import org.apache.wicket.markup.html.basic.Label; +import org.apache.wicket.markup.repeater.Item; +import org.apache.wicket.model.CompoundPropertyModel; +import org.apache.wicket.model.IModel; +import org.apache.wicket.model.Model; +import org.apache.wicket.model.ResourceModel; +import org.apache.wicket.model.StringResourceModel; +import org.apache.wicket.spring.injection.annot.SpringBean; + +public class PasswordModuleDirectoryPanel + extends DirectoryPanel { + private static final long serialVersionUID = 1005345990563741296L; + + @SpringBean + protected AuditRestClient auditRestClient; + + protected final BaseModal historyModal; + + public PasswordModuleDirectoryPanel( + final String id, + final PasswordModuleRestClient restClient, + final PageReference pageRef) { + + super(id, restClient, pageRef); + + disableCheckBoxes(); + + addNewItemPanelBuilder(new PasswordModuleWizardBuilder(new PasswordModuleTO(), restClient, pageRef), true); + + MetaDataRoleAuthorizationStrategy.authorize(addAjaxLink, RENDER, AMEntitlement.AUTH_MODULE_CREATE); + + modal.size(Modal.Size.Extra_large); + initResultTable(); + + historyModal = new BaseModal<>(Constants.OUTER); + historyModal.size(Modal.Size.Large); + addOuterObject(historyModal); + } + + @Override + protected PasswordModuleProvider dataProvider() { + return new PasswordModuleProvider(rows); + } + + @Override + protected String paginatorRowsKey() { + return AMConstants.PREF_AUTHMODULE_PAGINATOR_ROWS; + } + + @Override + protected Collection getBatches() { + return List.of(); + } + + @Override + protected List> getColumns() { + List> columns = new ArrayList<>(); + columns.add(new PropertyColumn<>( + new StringResourceModel(Constants.KEY_FIELD_NAME, this), + Constants.KEY_FIELD_NAME, Constants.KEY_FIELD_NAME)); + columns.add(new PropertyColumn<>(new ResourceModel(Constants.DESCRIPTION_FIELD_NAME), + Constants.DESCRIPTION_FIELD_NAME, Constants.DESCRIPTION_FIELD_NAME)); + columns.add(new PropertyColumn<>(new ResourceModel("type"), "conf") { + + private static final long serialVersionUID = -1822504503325964706L; + + @Override + public void populateItem( + final Item> item, + final String componentId, + final IModel rowModel) { + + item.add(new Label(componentId, rowModel.getObject().getConf() == null + ? StringUtils.EMPTY + : StringUtils.substringBefore( + rowModel.getObject().getConf().getClass().getSimpleName(), "PasswordModuleConf"))); + } + }); + //columns.add(new PropertyColumn<>(new ResourceModel("state"), "state", "state")); + columns.add(new PropertyColumn<>(new ResourceModel("order"), "order", "order")); + return columns; + } + + @Override + public ActionsPanel getActions(final IModel model) { + ActionsPanel panel = super.getActions(model); + + panel.add(new ActionLink<>() { + + private static final long serialVersionUID = -3722207913631435501L; + + @Override + public void onClick(final AjaxRequestTarget target, final PasswordModuleTO ignore) { + send(PasswordModuleDirectoryPanel.this, Broadcast.EXACT, new AjaxWizard.EditItemActionEvent<>( + restClient.read(model.getObject().getKey()), target)); + } + }, ActionLink.ActionType.EDIT, AMEntitlement.PASSWORD_MODULE_UPDATE); + + panel.add(new ActionLink<>() { + + private static final long serialVersionUID = -5432034353017728756L; + + @Override + public void onClick(final AjaxRequestTarget target, final PasswordModuleTO ignore) { + model.setObject(restClient.read(model.getObject().getKey())); + + target.add(historyModal.setContent(new AuditHistoryModal<>( + OpEvent.CategoryType.LOGIC, + "PasswordModuleLogic", + model.getObject(), + AMEntitlement.PASSWORD_MODULE_UPDATE, + auditRestClient) { + + private static final long serialVersionUID = -3712506022627033822L; + + @Override + protected void restore(final String json, final AjaxRequestTarget target) { + try { + PasswordModuleTO updated = MAPPER.readValue(json, PasswordModuleTO.class); + restClient.update(updated); + + SyncopeConsoleSession.get().success(getString(Constants.OPERATION_SUCCEEDED)); + } catch (Exception e) { + LOG.error("While restoring AuthModule {}", model.getObject().getKey(), e); + SyncopeConsoleSession.get().onException(e); + } + ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(target); + } + })); + + historyModal.header(new Model<>(getString("auditHistory.title", new Model<>(model.getObject())))); + + historyModal.show(true); + } + }, ActionLink.ActionType.VIEW_AUDIT_HISTORY, String.format("%s,%s", AMEntitlement.PASSWORD_MODULE_READ, + IdRepoEntitlement.AUDIT_LIST)); + + panel.add(new ActionLink<>() { + + private static final long serialVersionUID = -3722207913631435501L; + + @Override + public void onClick(final AjaxRequestTarget target, final PasswordModuleTO ignore) { + try { + restClient.delete(model.getObject().getKey()); + + SyncopeConsoleSession.get().success(getString(Constants.OPERATION_SUCCEEDED)); + target.add(container); + } catch (Exception e) { + LOG.error("While deleting {}", model.getObject().getKey(), e); + SyncopeConsoleSession.get().onException(e); + } + ((BaseWebPage) pageRef.getPage()).getNotificationPanel().refresh(target); + } + }, ActionLink.ActionType.DELETE, AMEntitlement.PASSWORD_MODULE_DELETE, true); + + return panel; + } + + protected final class PasswordModuleProvider extends DirectoryDataProvider { + + private static final long serialVersionUID = -185944053385660794L; + + private final SortableDataProviderComparator comparator; + + private PasswordModuleProvider(final int paginatorRows) { + super(paginatorRows); + comparator = new SortableDataProviderComparator<>(this); + } + + @Override + public Iterator iterator(final long first, final long count) { + List passwordModules = restClient.list(); + passwordModules.sort(comparator); + return passwordModules.subList((int) first, (int) first + (int) count).iterator(); + } + + @Override + public long size() { + return restClient.list().size(); + } + + @Override + public IModel model(final PasswordModuleTO object) { + return new CompoundPropertyModel<>(object); + } + } +} diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/rest/PasswordModuleRestClient.java b/client/am/console/src/main/java/org/apache/syncope/client/console/rest/PasswordModuleRestClient.java new file mode 100644 index 00000000000..fe3e240f998 --- /dev/null +++ b/client/am/console/src/main/java/org/apache/syncope/client/console/rest/PasswordModuleRestClient.java @@ -0,0 +1,30 @@ +package org.apache.syncope.client.console.rest; + +import java.util.List; +import org.apache.syncope.common.lib.to.PasswordModuleTO; +import org.apache.syncope.common.rest.api.service.PasswordModuleService; + +public class PasswordModuleRestClient extends BaseRestClient { + + private static final long serialVersionUID = -3961377654788868099L; + + public List list() { + return getService(PasswordModuleService.class).list(); + } + + public void create(final PasswordModuleTO passwordModuleTO) { + getService(PasswordModuleService.class).create(passwordModuleTO); + } + + public PasswordModuleTO read(final String key) { + return getService(PasswordModuleService.class).read(key); + } + + public void update(final PasswordModuleTO passwordModuleTO) { + getService(PasswordModuleService.class).update(passwordModuleTO); + } + + public void delete(final String key) { + getService(PasswordModuleService.class).delete(key); + } +} diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder.java b/client/am/console/src/main/java/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder.java new file mode 100644 index 00000000000..3c27115af0d --- /dev/null +++ b/client/am/console/src/main/java/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder.java @@ -0,0 +1,143 @@ +package org.apache.syncope.client.console.wizards; + +import java.io.Serializable; +import java.util.List; +import java.util.stream.Collectors; +import org.apache.syncope.client.console.SyncopeWebApplication; +import org.apache.syncope.client.console.panels.BeanPanel; +import org.apache.syncope.client.console.rest.PasswordModuleRestClient; +import org.apache.syncope.client.ui.commons.Constants; +import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel; +import org.apache.syncope.client.ui.commons.markup.html.form.AjaxNumberFieldPanel; +import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel; +import org.apache.syncope.client.ui.commons.wizards.AjaxWizard; +import org.apache.syncope.common.lib.password.PasswordModuleConf; +import org.apache.syncope.common.lib.to.PasswordModuleTO; +import org.apache.wicket.PageReference; +import org.apache.wicket.ajax.AjaxEventBehavior; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.extensions.wizard.WizardModel; +import org.apache.wicket.extensions.wizard.WizardStep; +import org.apache.wicket.model.LoadableDetachableModel; +import org.apache.wicket.model.Model; +import org.apache.wicket.model.PropertyModel; +import org.springframework.util.ClassUtils; + +public class PasswordModuleWizardBuilder extends BaseAjaxWizardBuilder { + + private static final long serialVersionUID = -6355254150868269721L; + + protected final LoadableDetachableModel> passwordModuleConfs = new LoadableDetachableModel<>() { + + private static final long serialVersionUID = 5275935387613157437L; + + @Override + protected List load() { + return SyncopeWebApplication.get().getLookup().getClasses(PasswordModuleConf.class).stream(). + map(Class::getName).sorted().collect(Collectors.toList()); + } + }; + + protected final PasswordModuleRestClient passwordModuleRestClient; + + protected final Model> passwordModuleConfClass = Model.of(); + + public PasswordModuleWizardBuilder( + final PasswordModuleTO defaultItem, + final PasswordModuleRestClient passwordModuleRestClient, + final PageReference pageRef) { + + super(defaultItem, pageRef); + this.passwordModuleRestClient = passwordModuleRestClient; + } + + @Override + protected Serializable onApplyInternal(final PasswordModuleTO modelObject) { + if (mode == AjaxWizard.Mode.CREATE) { + passwordModuleRestClient.create(modelObject); + } else { + passwordModuleRestClient.update(modelObject); + } + return modelObject; + } + + @Override + protected WizardModel buildModelSteps(final PasswordModuleTO modelObject, final WizardModel wizardModel) { + wizardModel.add(new Profile(modelObject, passwordModuleConfs, passwordModuleConfClass)); + wizardModel.add(new Configuration(modelObject)); + //wizardModel.add(new AuthModuleWizardBuilder.Mapping(modelObject)); + return wizardModel; + } + + protected static class Profile extends WizardStep { + + private static final long serialVersionUID = -3043839139187792810L; + + Profile( + final PasswordModuleTO passwordModule, + final LoadableDetachableModel> passwordModuleConfs, + final Model> passwordModuleConfClass) { + + boolean isNew = passwordModule.getConf() == null; + if (!isNew) { + passwordModuleConfClass.setObject(passwordModule.getConf().getClass()); + } + + AjaxTextFieldPanel key = new AjaxTextFieldPanel( + Constants.KEY_FIELD_NAME, Constants.KEY_FIELD_NAME, + new PropertyModel<>(passwordModule, Constants.KEY_FIELD_NAME)); + key.addRequiredLabel(); + key.setEnabled(isNew); + add(key); + + AjaxTextFieldPanel description = new AjaxTextFieldPanel( + Constants.DESCRIPTION_FIELD_NAME, getString(Constants.DESCRIPTION_FIELD_NAME), + new PropertyModel<>(passwordModule, Constants.DESCRIPTION_FIELD_NAME)); + add(description); + + add(new AjaxNumberFieldPanel.Builder().build( + "order", + "order", + Integer.class, + new PropertyModel<>(passwordModule, "order")).addRequiredLabel()); + + AjaxDropDownChoicePanel conf = new AjaxDropDownChoicePanel<>("conf", getString("type"), isNew + ? Model.of() + : Model.of(passwordModule.getConf().getClass().getName())); + conf.setChoices(passwordModuleConfs.getObject()); + conf.addRequiredLabel(); + conf.setNullValid(false); + conf.setEnabled(isNew); + conf.add(new AjaxEventBehavior(Constants.ON_CHANGE) { + + private static final long serialVersionUID = -7133385027739964990L; + + @SuppressWarnings("unchecked") + @Override + protected void onEvent(final AjaxRequestTarget target) { + try { + Class clazz = + (Class) ClassUtils.resolveClassName( + conf.getModelObject(), ClassUtils.getDefaultClassLoader()); + + passwordModule.setConf(clazz.getConstructor().newInstance()); + passwordModuleConfClass.setObject(clazz); + } catch (Exception e) { + LOG.error("Cannot instantiate {}", conf.getModelObject(), e); + } + } + }); + add(conf); + } + } + + protected class Configuration extends WizardStep { + + private static final long serialVersionUID = -785981096328637758L; + + Configuration(final PasswordModuleTO passwordModule) { + add(new BeanPanel<>("bean", new PropertyModel<>(passwordModule, "conf"), pageRef, + "ldap", "keystore", "serviceProviderMetadata").setRenderBodyOnly(true)); + } + } +} diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA.properties index cdd3184c2bf..4155ee093b3 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA.properties @@ -16,6 +16,7 @@ # under the License. wa=WA authModules=Authentication Modules +passwordModules=Password Management clientApps=Client Applications config=Parameters sessions=Sessions diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_fr_CA.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_fr_CA.properties index cdd3184c2bf..4155ee093b3 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_fr_CA.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_fr_CA.properties @@ -16,6 +16,7 @@ # under the License. wa=WA authModules=Authentication Modules +passwordModules=Password Management clientApps=Client Applications config=Parameters sessions=Sessions diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_it.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_it.properties index 672aa66750e..fe9a0530804 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_it.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_it.properties @@ -16,6 +16,7 @@ # under the License. wa=WA authModules=Moduli di Autenticazione +passwordModules=Password Management clientApps=Applicazioni Client config=Parametri sessions=Sessioni diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_ja.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_ja.properties index cdd3184c2bf..4155ee093b3 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_ja.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_ja.properties @@ -16,6 +16,7 @@ # under the License. wa=WA authModules=Authentication Modules +passwordModules=Password Management clientApps=Client Applications config=Parameters sessions=Sessions diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_pt_BR.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_pt_BR.properties index cdd3184c2bf..4155ee093b3 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_pt_BR.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_pt_BR.properties @@ -16,6 +16,7 @@ # under the License. wa=WA authModules=Authentication Modules +passwordModules=Password Management clientApps=Client Applications config=Parameters sessions=Sessions diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_ru.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_ru.properties index cdd3184c2bf..4155ee093b3 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_ru.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_ru.properties @@ -16,6 +16,7 @@ # under the License. wa=WA authModules=Authentication Modules +passwordModules=Password Management clientApps=Client Applications config=Parameters sessions=Sessions diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel.properties new file mode 100644 index 00000000000..59952970b0a --- /dev/null +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel.properties @@ -0,0 +1,8 @@ +any.edit=Edit Parameter ${key} +any.new=New Password Module +any.edit=Edit Auth Password Module +description=Description +type=Type +state=State +order=Order +menu.history=Configuration history \ No newline at end of file diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_fr.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_fr.properties new file mode 100644 index 00000000000..59952970b0a --- /dev/null +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_fr.properties @@ -0,0 +1,8 @@ +any.edit=Edit Parameter ${key} +any.new=New Password Module +any.edit=Edit Auth Password Module +description=Description +type=Type +state=State +order=Order +menu.history=Configuration history \ No newline at end of file diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_fr_CA.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_fr_CA.properties new file mode 100644 index 00000000000..59952970b0a --- /dev/null +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_fr_CA.properties @@ -0,0 +1,8 @@ +any.edit=Edit Parameter ${key} +any.new=New Password Module +any.edit=Edit Auth Password Module +description=Description +type=Type +state=State +order=Order +menu.history=Configuration history \ No newline at end of file diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_it.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_it.properties new file mode 100644 index 00000000000..64ebb25442b --- /dev/null +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_it.properties @@ -0,0 +1,8 @@ +any.edit=Modifica parametro ${key} +any.new=Nuovo Modulo di Gestione Password +any.edit=Aggiorna Modulo di Gestione Password +description=Descrizione +type=Tipo +state=Stato +order=Ordinamento +auditHistory.title=Storico delle configurazioni \ No newline at end of file diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_ja.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_ja.properties new file mode 100644 index 00000000000..59952970b0a --- /dev/null +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_ja.properties @@ -0,0 +1,8 @@ +any.edit=Edit Parameter ${key} +any.new=New Password Module +any.edit=Edit Auth Password Module +description=Description +type=Type +state=State +order=Order +menu.history=Configuration history \ No newline at end of file diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_pt_BR.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_pt_BR.properties new file mode 100644 index 00000000000..59952970b0a --- /dev/null +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_pt_BR.properties @@ -0,0 +1,8 @@ +any.edit=Edit Parameter ${key} +any.new=New Password Module +any.edit=Edit Auth Password Module +description=Description +type=Type +state=State +order=Order +menu.history=Configuration history \ No newline at end of file diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_ru.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_ru.properties new file mode 100644 index 00000000000..59952970b0a --- /dev/null +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_ru.properties @@ -0,0 +1,8 @@ +any.edit=Edit Parameter ${key} +any.new=New Password Module +any.edit=Edit Auth Password Module +description=Description +type=Type +state=State +order=Order +menu.history=Configuration history \ No newline at end of file diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration.html b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration.html new file mode 100644 index 00000000000..b7ba12c53ed --- /dev/null +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration.html @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration.properties new file mode 100644 index 00000000000..59526fc3cfb --- /dev/null +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration.properties @@ -0,0 +1,7 @@ +plainAttrs=Plain Attributes +derAttrs=Derived Attributes +features=Features +matchingCond=Matching Condition +userMatchingCond=User Matching Condition +groupMatchingCond=Group Matching Condition +anyObjectMatchingCond=AnyObject Matching Condition \ No newline at end of file diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_fr.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_fr.properties new file mode 100644 index 00000000000..59526fc3cfb --- /dev/null +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_fr.properties @@ -0,0 +1,7 @@ +plainAttrs=Plain Attributes +derAttrs=Derived Attributes +features=Features +matchingCond=Matching Condition +userMatchingCond=User Matching Condition +groupMatchingCond=Group Matching Condition +anyObjectMatchingCond=AnyObject Matching Condition \ No newline at end of file diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_fr_CA.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_fr_CA.properties new file mode 100644 index 00000000000..59526fc3cfb --- /dev/null +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_fr_CA.properties @@ -0,0 +1,7 @@ +plainAttrs=Plain Attributes +derAttrs=Derived Attributes +features=Features +matchingCond=Matching Condition +userMatchingCond=User Matching Condition +groupMatchingCond=Group Matching Condition +anyObjectMatchingCond=AnyObject Matching Condition \ No newline at end of file diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_it.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_it.properties new file mode 100644 index 00000000000..1c997143677 --- /dev/null +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_it.properties @@ -0,0 +1,7 @@ +plainAttrs=Attributi +derAttrs=Attributi Derivati +features=Features +matchingCond=Condizione di matching +userMatchingCond=Condizione di matching utente +groupMatchingCond=Condizione di matching gruppo +anyObjectMatchingCond=Condizione di matching any \ No newline at end of file diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_ja.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_ja.properties new file mode 100644 index 00000000000..59526fc3cfb --- /dev/null +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_ja.properties @@ -0,0 +1,7 @@ +plainAttrs=Plain Attributes +derAttrs=Derived Attributes +features=Features +matchingCond=Matching Condition +userMatchingCond=User Matching Condition +groupMatchingCond=Group Matching Condition +anyObjectMatchingCond=AnyObject Matching Condition \ No newline at end of file diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_pt_BR.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_pt_BR.properties new file mode 100644 index 00000000000..59526fc3cfb --- /dev/null +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_pt_BR.properties @@ -0,0 +1,7 @@ +plainAttrs=Plain Attributes +derAttrs=Derived Attributes +features=Features +matchingCond=Matching Condition +userMatchingCond=User Matching Condition +groupMatchingCond=Group Matching Condition +anyObjectMatchingCond=AnyObject Matching Condition \ No newline at end of file diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_ru.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_ru.properties new file mode 100644 index 00000000000..59526fc3cfb --- /dev/null +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_ru.properties @@ -0,0 +1,7 @@ +plainAttrs=Plain Attributes +derAttrs=Derived Attributes +features=Features +matchingCond=Matching Condition +userMatchingCond=User Matching Condition +groupMatchingCond=Group Matching Condition +anyObjectMatchingCond=AnyObject Matching Condition \ No newline at end of file diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile.html b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile.html new file mode 100644 index 00000000000..f24b821dcbf --- /dev/null +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile.html @@ -0,0 +1,9 @@ + + +
[key]
+
[description]
+ +
[order]
+
[conf]
+
+ \ No newline at end of file diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile.properties new file mode 100644 index 00000000000..a350401cf15 --- /dev/null +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile.properties @@ -0,0 +1,4 @@ +description=Description +configuration=Configuration +type=Type +state=State \ No newline at end of file diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_fr.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_fr.properties new file mode 100644 index 00000000000..a350401cf15 --- /dev/null +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_fr.properties @@ -0,0 +1,4 @@ +description=Description +configuration=Configuration +type=Type +state=State \ No newline at end of file diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_fr_CA.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_fr_CA.properties new file mode 100644 index 00000000000..a350401cf15 --- /dev/null +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_fr_CA.properties @@ -0,0 +1,4 @@ +description=Description +configuration=Configuration +type=Type +state=State \ No newline at end of file diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_it.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_it.properties new file mode 100644 index 00000000000..c0c3d523024 --- /dev/null +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_it.properties @@ -0,0 +1,4 @@ +description=Descrizione +configuration=Configurazione +type=Tipo +state=Stato \ No newline at end of file diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_ja.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_ja.properties new file mode 100644 index 00000000000..a350401cf15 --- /dev/null +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_ja.properties @@ -0,0 +1,4 @@ +description=Description +configuration=Configuration +type=Type +state=State \ No newline at end of file diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_pt_BR.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_pt_BR.properties new file mode 100644 index 00000000000..a350401cf15 --- /dev/null +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_pt_BR.properties @@ -0,0 +1,4 @@ +description=Description +configuration=Configuration +type=Type +state=State \ No newline at end of file diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_ru.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_ru.properties new file mode 100644 index 00000000000..a350401cf15 --- /dev/null +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_ru.properties @@ -0,0 +1,4 @@ +description=Description +configuration=Configuration +type=Type +state=State \ No newline at end of file diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/SyncopePasswordModuleConf.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/SyncopePasswordModuleConf.java index 3043d77a729..ff036da7af8 100644 --- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/SyncopePasswordModuleConf.java +++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/SyncopePasswordModuleConf.java @@ -1,7 +1,6 @@ package org.apache.syncope.common.lib.password; import java.util.HashMap; -import java.util.LinkedHashMap; import java.util.Map; import org.apache.syncope.common.lib.SyncopeConstants; import org.apache.syncope.common.lib.to.PasswordModuleTO; @@ -35,17 +34,6 @@ public class SyncopePasswordModuleConf implements PasswordModuleConf{ */ private Map headers = new HashMap<>(); - /** - * Map of attributes that optionally may be used to control the names - * of the collected attributes from Syncope. If an attribute is provided by Syncope, - * it can be listed here as the key of the map with a value that should be the name - * of that attribute as collected and recorded by CAS. - * For example, the convention {@code lastLoginDate->lastDate} will process the - * Syncope attribute {@code lastLoginDate} and will internally rename that to {@code lastDate}. - * If no mapping is specified, CAS defaults will be used instead. - */ - private Map attributeMappings = new LinkedHashMap<>(); - public String getDomain() { return domain; } @@ -86,14 +74,6 @@ public void setHeaders(final Map headers) { this.headers = headers; } - public Map getAttributeMappings() { - return attributeMappings; - } - - public void setAttributeMappings(Map attributeMappings) { - this.attributeMappings = attributeMappings; - } - @Override public Map map(final PasswordModuleTO passwordModuleTO, final Mapper mapper) { return mapper.map(passwordModuleTO, this); } diff --git a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml index 980b54da61e..1118a342073 100644 --- a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml +++ b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml @@ -92,7 +92,7 @@ under the License. + jsonConf='{"_class":"org.apache.syncope.common.lib.password.SyncopePasswordModuleConf","domain":"Master","searchFilter":"username={user}","basicAuthUsername":"admin","basicAuthPassword":"password", "headers":{}}'/> diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/PasswordModuleDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/PasswordModuleDataBinderImpl.java index e035a08626b..1827da930ad 100644 --- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/PasswordModuleDataBinderImpl.java +++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/PasswordModuleDataBinderImpl.java @@ -2,13 +2,11 @@ import org.apache.syncope.common.lib.SyncopeClientCompositeException; import org.apache.syncope.common.lib.SyncopeClientException; -import org.apache.syncope.common.lib.to.AuthModuleTO; import org.apache.syncope.common.lib.to.Item; import org.apache.syncope.common.lib.to.PasswordModuleTO; import org.apache.syncope.common.lib.types.ClientExceptionType; import org.apache.syncope.common.lib.types.MappingPurpose; import org.apache.syncope.core.persistence.api.entity.EntityFactory; -import org.apache.syncope.core.persistence.api.entity.am.AuthModule; import org.apache.syncope.core.persistence.api.entity.am.PasswordModule; import org.apache.syncope.core.provisioning.api.data.PasswordModuleDataBinder; import org.apache.syncope.core.provisioning.api.jexl.JexlUtils; diff --git a/fit/wa-reference/src/main/resources/wa-embedded.properties b/fit/wa-reference/src/main/resources/wa-embedded.properties index 35d6c68bb99..d8118ebf77e 100644 --- a/fit/wa-reference/src/main/resources/wa-embedded.properties +++ b/fit/wa-reference/src/main/resources/wa-embedded.properties @@ -30,9 +30,6 @@ cas.authn.syncope.url=${cas.server.name}/syncope cas.authn.syncope.name=DefaultSyncopeAuthModule cas.authn.pm.core.enabled=true -# TMP until SYNCOPE-1901 -cas.authn.pm.syncope.basic-auth-username=placeholder -cas.authn.pm.syncope.basic-auth-password=placeholder service.discovery.address=https://localhost:9443/syncope-wa/ diff --git a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WABootstrapConfiguration.java b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WABootstrapConfiguration.java index dcd0fb7a213..79038c20352 100644 --- a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WABootstrapConfiguration.java +++ b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WABootstrapConfiguration.java @@ -22,6 +22,7 @@ import org.apache.syncope.wa.bootstrap.mapping.AttrRepoPropertySourceMapper; import org.apache.syncope.wa.bootstrap.mapping.AuthModulePropertySourceMapper; import org.apache.syncope.wa.bootstrap.mapping.DefaultAttrReleaseMapper; +import org.apache.syncope.wa.bootstrap.mapping.PasswordModulePropertySourceMapper; import org.apereo.cas.configuration.support.CasConfigurationJasyptCipherExecutor; import org.apereo.cas.util.crypto.CipherExecutor; import org.springframework.beans.factory.annotation.Qualifier; @@ -74,6 +75,12 @@ public AuthModulePropertySourceMapper authModulePropertySourceMapper(final WARes return new AuthModulePropertySourceMapper(waRestClient); } + @ConditionalOnMissingBean + @Bean + public PasswordModulePropertySourceMapper passwordModulePropertySourceMapper(final WARestClient waRestClient) { + return new PasswordModulePropertySourceMapper(waRestClient); + } + @ConditionalOnMissingBean @Bean public AttrRepoPropertySourceMapper attrRepoPropertySourceMapper(final WARestClient waRestClient) { @@ -93,12 +100,14 @@ public PropertySourceLocator configPropertySourceLocator( final WARestClient waRestClient, final AuthModulePropertySourceMapper authModulePropertySourceMapper, final AttrRepoPropertySourceMapper attrRepoPropertySourceMapper, + final PasswordModulePropertySourceMapper passwordModulePropertySourceMapper, final AttrReleaseMapper attrReleaseMapper) { return new WAPropertySourceLocator( waRestClient, authModulePropertySourceMapper, attrRepoPropertySourceMapper, + passwordModulePropertySourceMapper, attrReleaseMapper, waConfigurationCipher); } diff --git a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WAPropertySourceLocator.java b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WAPropertySourceLocator.java index 120652772a8..541b2d49880 100644 --- a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WAPropertySourceLocator.java +++ b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WAPropertySourceLocator.java @@ -31,11 +31,13 @@ import org.apache.syncope.common.lib.to.OIDCRPClientAppTO; import org.apache.syncope.common.rest.api.service.AttrRepoService; import org.apache.syncope.common.rest.api.service.AuthModuleService; +import org.apache.syncope.common.rest.api.service.PasswordModuleService; import org.apache.syncope.common.rest.api.service.wa.WAClientAppService; import org.apache.syncope.common.rest.api.service.wa.WAConfigService; import org.apache.syncope.wa.bootstrap.mapping.AttrReleaseMapper; import org.apache.syncope.wa.bootstrap.mapping.AttrRepoPropertySourceMapper; import org.apache.syncope.wa.bootstrap.mapping.AuthModulePropertySourceMapper; +import org.apache.syncope.wa.bootstrap.mapping.PasswordModulePropertySourceMapper; import org.apereo.cas.configuration.model.support.oidc.OidcDiscoveryProperties; import org.apereo.cas.oidc.claims.OidcCustomScopeAttributeReleasePolicy; import org.apereo.cas.services.ChainingAttributeReleasePolicy; @@ -60,6 +62,8 @@ public class WAPropertySourceLocator implements PropertySourceLocator { protected final AttrRepoPropertySourceMapper attrRepoPropertySourceMapper; + protected final PasswordModulePropertySourceMapper passwordModulePropertySourceMapper; + protected final AttrReleaseMapper attrReleaseMapper; protected final CipherExecutor configurationCipher; @@ -68,12 +72,14 @@ public WAPropertySourceLocator( final WARestClient waRestClient, final AuthModulePropertySourceMapper authModulePropertySourceMapper, final AttrRepoPropertySourceMapper attrRepoPropertySourceMapper, + final PasswordModulePropertySourceMapper passwordModulePropertySourceMapper, final AttrReleaseMapper attrReleaseMapper, final CipherExecutor configurationCipher) { this.waRestClient = waRestClient; this.authModulePropertySourceMapper = authModulePropertySourceMapper; this.attrRepoPropertySourceMapper = attrRepoPropertySourceMapper; + this.passwordModulePropertySourceMapper = passwordModulePropertySourceMapper; this.attrReleaseMapper = attrReleaseMapper; this.configurationCipher = configurationCipher; } @@ -124,8 +130,12 @@ public PropertySource locate(final Environment environment) { properties.putAll(index(map, prefixes)); }); - properties.put("cas.authn.pm.syncope.url", - StringUtils.substringBefore(syncopeClient.getAddress(), "/rest")); + syncopeClient.getService(PasswordModuleService.class).list().forEach(passwordModuleTO -> { + LOG.debug("Mapping password module {} ", passwordModuleTO.getKey()); + + Map map = passwordModuleTO.getConf().map(passwordModuleTO, passwordModulePropertySourceMapper); + properties.putAll(index(map, prefixes)); + }); Set customClaims = syncopeClient.getService(WAClientAppService.class).list().stream(). filter(app -> app.getClientAppTO() instanceof OIDCRPClientAppTO && app.getAttrReleasePolicy() != null). diff --git a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/PasswordModulePropertySourceMapper.java b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/PasswordModulePropertySourceMapper.java new file mode 100644 index 00000000000..669b093755a --- /dev/null +++ b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/PasswordModulePropertySourceMapper.java @@ -0,0 +1,37 @@ +package org.apache.syncope.wa.bootstrap.mapping; + +import java.util.Map; +import org.apache.commons.lang3.StringUtils; +import org.apache.syncope.client.lib.SyncopeClient; +import org.apache.syncope.common.lib.password.PasswordModuleConf; +import org.apache.syncope.common.lib.password.SyncopePasswordModuleConf; +import org.apache.syncope.common.lib.to.PasswordModuleTO; +import org.apache.syncope.wa.bootstrap.WARestClient; +import org.apereo.cas.configuration.model.support.pm.SyncopePasswordManagementProperties; + +public class PasswordModulePropertySourceMapper extends PropertySourceMapper implements PasswordModuleConf.Mapper { + + protected final WARestClient waRestClient; + + public PasswordModulePropertySourceMapper(final WARestClient waRestClient) { + this.waRestClient = waRestClient; + } + + @Override public Map map(PasswordModuleTO passwordModuleTO, SyncopePasswordModuleConf conf) { + SyncopeClient syncopeClient = waRestClient.getSyncopeClient(); + if (syncopeClient == null) { + LOG.warn("Application context is not ready to bootstrap WA configuration"); + return Map.of(); + } + + SyncopePasswordManagementProperties props = new SyncopePasswordManagementProperties(); + props.setDomain(conf.getDomain()); + props.setUrl(StringUtils.substringBefore(syncopeClient.getAddress(), "/rest")); + props.setBasicAuthUsername(conf.getBasicAuthUsername()); + props.setBasicAuthPassword(conf.getBasicAuthPassword()); + props.setSearchFilter(conf.getSearchFilter()); + props.setHeaders(conf.getHeaders()); + + return prefix("cas.authn.pm.syncope.", WAConfUtils.asMap(props)); + } +} From 78cdd062449cf9c38953e9dbbf2236172c826559 Mon Sep 17 00:00:00 2001 From: alberto bogi Date: Mon, 18 Aug 2025 16:24:31 +0200 Subject: [PATCH 05/20] [SYNCOPE-1901] Adding LDAPPasswordModuleConf to configure CAS password management with LDAP --- .../lib/password/LDAPPasswordModuleConf.java | 25 +++ .../lib/password/PasswordModuleConf.java | 2 + .../jpa/inner/PasswordModuleTest.java | 43 ++++- .../test/resources/domains/MasterContent.xml | 162 +++++++++--------- .../fit/core/PasswordModuleITCase.java | 49 +++++- .../PasswordModulePropertySourceMapper.java | 18 +- 6 files changed, 215 insertions(+), 84 deletions(-) create mode 100644 common/am/lib/src/main/java/org/apache/syncope/common/lib/password/LDAPPasswordModuleConf.java diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/LDAPPasswordModuleConf.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/LDAPPasswordModuleConf.java new file mode 100644 index 00000000000..b00173edd9d --- /dev/null +++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/LDAPPasswordModuleConf.java @@ -0,0 +1,25 @@ +package org.apache.syncope.common.lib.password; + +import java.util.Map; +import org.apache.syncope.common.lib.AbstractLDAPConf; +import org.apache.syncope.common.lib.to.PasswordModuleTO; + +public class LDAPPasswordModuleConf extends AbstractLDAPConf implements PasswordModuleConf { + + /** + * Username attribute required by LDAP. + */ + private String usernameAttribute = "uid"; + + public String getUsernameAttribute() { + return usernameAttribute; + } + + public void setUsernameAttribute(String usernameAttribute) { + this.usernameAttribute = usernameAttribute; + } + + @Override public Map map(PasswordModuleTO passwordModuleTO, Mapper mapper) { + return mapper.map(passwordModuleTO, this); + } +} diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/PasswordModuleConf.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/PasswordModuleConf.java index b7400b44150..3457df68eed 100644 --- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/PasswordModuleConf.java +++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/PasswordModuleConf.java @@ -13,6 +13,8 @@ interface Mapper { Map map(PasswordModuleTO passwordModuleTO, SyncopePasswordModuleConf conf); + Map map(PasswordModuleTO passwordModuleTO, LDAPPasswordModuleConf conf); + } Map map(PasswordModuleTO passwordModuleTO, Mapper mapper); diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PasswordModuleTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PasswordModuleTest.java index 89b0984e682..064be888c92 100644 --- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PasswordModuleTest.java +++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PasswordModuleTest.java @@ -7,6 +7,7 @@ import java.util.List; import org.apache.commons.lang3.ClassUtils; +import org.apache.syncope.common.lib.password.LDAPPasswordModuleConf; import org.apache.syncope.common.lib.password.PasswordModuleConf; import org.apache.syncope.common.lib.password.SyncopePasswordModuleConf; import org.apache.syncope.common.lib.to.Item; @@ -32,12 +33,16 @@ public void findAll() { List modules = passwordModuleDAO.findAll(); assertNotNull(modules); assertFalse(modules.isEmpty()); + assertEquals(2, modules.size()); } @Test public void find() { PasswordModule passwordModule = passwordModuleDAO.findById("DefaultSyncopePasswordModule").orElseThrow(); - assertTrue(passwordModule.getConf() instanceof PasswordModuleConf); + assertTrue(passwordModule.getConf() instanceof SyncopePasswordModuleConf); + + passwordModule = passwordModuleDAO.findById("DefaultLDAPPasswordModule").orElseThrow(); + assertTrue(passwordModule.getConf() instanceof LDAPPasswordModuleConf); } @Test @@ -47,6 +52,10 @@ public void findByType() { passwordModule -> isSpecificConf(passwordModule.getConf(), SyncopePasswordModuleConf.class) && passwordModule.getKey().equals("DefaultSyncopePasswordModule"))); + assertTrue(passwordModules.stream().anyMatch( + passwordModule -> isSpecificConf(passwordModule.getConf(), + LDAPPasswordModuleConf.class) + && passwordModule.getKey().equals("DefaultLDAPPasswordModule"))); } private void savePasswordModule(final String key, final PasswordModuleConf conf) { @@ -82,6 +91,19 @@ public void saveWithSyncopeModule() { savePasswordModule("SyncopePasswordModuleTest", conf); } + @Test + public void saveWithLdapModule() { + LDAPPasswordModuleConf conf = new LDAPPasswordModuleConf(); + conf.setBaseDn("dc=example,dc=org"); + conf.setSearchFilter("cn={user}"); + conf.setSubtreeSearch(true); + conf.setLdapUrl("ldap://localhost:1389"); + conf.setUsernameAttribute("uid"); + conf.setBindCredential("Password"); + + savePasswordModule("LDAPPasswordModuleTest", conf); + } + @Test public void updateWithSyncopeModule() { PasswordModule module = passwordModuleDAO.findById("DefaultSyncopePasswordModule").orElseThrow(); @@ -93,10 +115,29 @@ public void updateWithSyncopeModule() { module = passwordModuleDAO.save(module); assertNotNull(module); assertNotNull(module.getKey()); + PasswordModule found = passwordModuleDAO.findById(module.getKey()).orElseThrow(); assertEquals("Two", SyncopePasswordModuleConf.class.cast(found.getConf()).getDomain()); } + @Test + public void updateWithLdapModule() { + PasswordModule module = passwordModuleDAO.findById("DefaultLDAPPasswordModule").orElseThrow(); + + PasswordModuleConf conf = module.getConf(); + LDAPPasswordModuleConf.class.cast(conf).setBaseDn("dc=example2,dc=org"); + LDAPPasswordModuleConf.class.cast(conf).setSearchFilter("cn={user2}"); + module.setConf(conf); + + module = passwordModuleDAO.save(module); + assertNotNull(module); + assertNotNull(module.getKey()); + + PasswordModule found = passwordModuleDAO.findById(module.getKey()).orElseThrow(); + assertEquals("dc=example2,dc=org", LDAPPasswordModuleConf.class.cast(found.getConf()).getBaseDn()); + assertEquals("cn={user2}", LDAPPasswordModuleConf.class.cast(found.getConf()).getSearchFilter()); + } + @Test public void delete() { assertTrue(passwordModuleDAO.findById("DefaultSyncopePasswordModule").isPresent()); diff --git a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml index 1118a342073..e008077f73d 100644 --- a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml +++ b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml @@ -93,8 +93,8 @@ under the License. - - + @@ -117,7 +117,7 @@ under the License. - + @@ -163,7 +163,7 @@ under the License. - - + @@ -204,7 +204,7 @@ under the License. + mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/> @@ -213,7 +213,7 @@ under the License. mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/> + mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/> @@ -243,7 +243,7 @@ under the License. mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/> + mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/> @@ -251,9 +251,9 @@ under the License. - - + @@ -263,29 +263,29 @@ under the License. - - - + @@ -296,13 +296,13 @@ under the License. - + - + @@ -341,83 +341,83 @@ under the License. - + - + - + + creator="admin" lastModifier="admin" + creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/> @@ -425,9 +425,9 @@ under the License. - + @@ -446,13 +446,13 @@ under the License. user_id="74cd8ece-715a-44a4-a736-e17b46c4e7e6" group_id="29f96485-729e-4d31-88a1-6fc60e4677f3"/> - + - @@ -461,7 +461,7 @@ under the License. - - + - + - - - - - + - + - - - - - + - + @@ -688,7 +688,7 @@ under the License. - + - + - - - + + diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PasswordModuleITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PasswordModuleITCase.java index 1c0389f4c20..0a280edd078 100644 --- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PasswordModuleITCase.java +++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PasswordModuleITCase.java @@ -14,6 +14,7 @@ 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.password.LDAPPasswordModuleConf; import org.apache.syncope.common.lib.password.PasswordModuleConf; import org.apache.syncope.common.lib.password.SyncopePasswordModuleConf; import org.apache.syncope.common.lib.to.PasswordModuleTO; @@ -24,7 +25,8 @@ public class PasswordModuleITCase extends AbstractITCase { private enum PasswordModuleSupportedType { - SYNCOPE + SYNCOPE, + LDAP }; private static PasswordModuleTO createAuthModule(final PasswordModuleTO passwordModuleTO) { @@ -50,6 +52,16 @@ private static PasswordModuleTO buildPasswordModuleTO(final PasswordModuleSuppor SyncopePasswordModuleConf.class.cast(conf).setDomain(SyncopeConstants.MASTER_DOMAIN); passwordModuleTO.setConf(conf); break; + case LDAP: + conf = new LDAPPasswordModuleConf(); + LDAPPasswordModuleConf.class.cast(conf).setBaseDn("dc=example,dc=org"); + LDAPPasswordModuleConf.class.cast(conf).setSearchFilter("cn={user}"); + LDAPPasswordModuleConf.class.cast(conf).setSubtreeSearch(true); + LDAPPasswordModuleConf.class.cast(conf).setLdapUrl("ldap://localhost:1389"); + LDAPPasswordModuleConf.class.cast(conf).setUsernameAttribute("uid"); + LDAPPasswordModuleConf.class.cast(conf).setBaseDn("cn=Directory Manager,dc=example,dc=org"); + LDAPPasswordModuleConf.class.cast(conf).setBindCredential("Password"); + break; } return passwordModuleTO; @@ -68,6 +80,9 @@ public void list() { assertTrue(passwordModuleTOS.stream().anyMatch( authModule -> isSpecificConf(authModule.getConf(), SyncopePasswordModuleConf.class) && authModule.getKey().equals("DefaultSyncopePasswordModule"))); + assertTrue(passwordModuleTOS.stream().anyMatch( + authModule -> isSpecificConf(authModule.getConf(), LDAPPasswordModuleConf.class) + && authModule.getKey().equals("DefaultLDAPPasswordModule"))); } @Test @@ -79,6 +94,15 @@ public void getSyncopePasswordModule() { assertTrue(isSpecificConf(passwordModuleTO.getConf(), SyncopePasswordModuleConf.class)); } + @Test + public void getLdapPasswordModule() { + PasswordModuleTO passwordModuleTO = PASSWORD_MODULE_SERVICE.read("DefaultLDAPPasswordModule"); + + assertNotNull(passwordModuleTO); + assertTrue(StringUtils.isNotBlank(passwordModuleTO.getDescription())); + assertTrue(isSpecificConf(passwordModuleTO.getConf(), LDAPPasswordModuleConf.class)); + } + @Test public void create() { EnumSet.allOf(PasswordModuleSupportedType.class).forEach(type -> { @@ -112,6 +136,29 @@ public void updateSyncopePasswordModule() { assertEquals("Two", SyncopePasswordModuleConf.class.cast(conf).getDomain()); } + @Test + public void updateLdapPasswordModule() { + PasswordModuleTO ldapPasswordModuleTO = PASSWORD_MODULE_SERVICE.read("DefaultLDAPPasswordModule"); + assertNotNull(ldapPasswordModuleTO); + + PasswordModuleTO newLdapPasswordModuleTO = buildPasswordModuleTO(PasswordModuleSupportedType.LDAP); + newLdapPasswordModuleTO = createAuthModule(newLdapPasswordModuleTO); + assertNotNull(newLdapPasswordModuleTO); + + PasswordModuleConf conf = ldapPasswordModuleTO.getConf(); + assertNotNull(conf); + LDAPPasswordModuleConf.class.cast(conf).setSubtreeSearch(false); + newLdapPasswordModuleTO.setConf(conf); + + // update new password module + PASSWORD_MODULE_SERVICE.update(newLdapPasswordModuleTO); + newLdapPasswordModuleTO = PASSWORD_MODULE_SERVICE.read(newLdapPasswordModuleTO.getKey()); + assertNotNull(newLdapPasswordModuleTO); + + conf = newLdapPasswordModuleTO.getConf(); + assertFalse(LDAPPasswordModuleConf.class.cast(conf).isSubtreeSearch()); + } + @Test public void delete() throws IOException { EnumSet.allOf(PasswordModuleSupportedType.class).forEach(type -> { diff --git a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/PasswordModulePropertySourceMapper.java b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/PasswordModulePropertySourceMapper.java index 669b093755a..3db0f4e2818 100644 --- a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/PasswordModulePropertySourceMapper.java +++ b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/PasswordModulePropertySourceMapper.java @@ -3,10 +3,13 @@ import java.util.Map; import org.apache.commons.lang3.StringUtils; import org.apache.syncope.client.lib.SyncopeClient; +import org.apache.syncope.common.lib.password.LDAPPasswordModuleConf; import org.apache.syncope.common.lib.password.PasswordModuleConf; import org.apache.syncope.common.lib.password.SyncopePasswordModuleConf; import org.apache.syncope.common.lib.to.PasswordModuleTO; import org.apache.syncope.wa.bootstrap.WARestClient; +import org.apereo.cas.configuration.model.support.ldap.AbstractLdapProperties; +import org.apereo.cas.configuration.model.support.pm.LdapPasswordManagementProperties; import org.apereo.cas.configuration.model.support.pm.SyncopePasswordManagementProperties; public class PasswordModulePropertySourceMapper extends PropertySourceMapper implements PasswordModuleConf.Mapper { @@ -17,7 +20,8 @@ public PasswordModulePropertySourceMapper(final WARestClient waRestClient) { this.waRestClient = waRestClient; } - @Override public Map map(PasswordModuleTO passwordModuleTO, SyncopePasswordModuleConf conf) { + @Override + public Map map(PasswordModuleTO passwordModuleTO, SyncopePasswordModuleConf conf) { SyncopeClient syncopeClient = waRestClient.getSyncopeClient(); if (syncopeClient == null) { LOG.warn("Application context is not ready to bootstrap WA configuration"); @@ -34,4 +38,16 @@ public PasswordModulePropertySourceMapper(final WARestClient waRestClient) { return prefix("cas.authn.pm.syncope.", WAConfUtils.asMap(props)); } + + @Override + public Map map(PasswordModuleTO passwordModuleTO, LDAPPasswordModuleConf conf) { + LdapPasswordManagementProperties props = new LdapPasswordManagementProperties(); + props.setName(passwordModuleTO.getKey()); + props.setType(AbstractLdapProperties.LdapType.valueOf(conf.getLdapType().name())); + props.setUsernameAttribute(conf.getUsernameAttribute()); + + fill(props, conf); + + return prefix("cas.authn.pm.ldap[].", WAConfUtils.asMap(props)); + } } From ec3c4cafa6991a854b087a1fafb61504958619b9 Mon Sep 17 00:00:00 2001 From: alberto bogi Date: Mon, 18 Aug 2025 17:28:33 +0200 Subject: [PATCH 06/20] [SYNCOPE-1901] Checkstyle --- .../panels/PasswordModuleDirectoryPanel.java | 7 +++++-- .../PasswordModuleDirectoryPanel.properties | 2 +- .../PasswordModuleDirectoryPanel_fr.properties | 2 +- ...PasswordModuleDirectoryPanel_fr_CA.properties | 2 +- .../PasswordModuleDirectoryPanel_it.properties | 2 +- .../PasswordModuleDirectoryPanel_ja.properties | 2 +- ...PasswordModuleDirectoryPanel_pt_BR.properties | 2 +- .../PasswordModuleDirectoryPanel_ru.properties | 2 +- ...dModuleWizardBuilder$Configuration.properties | 2 +- ...duleWizardBuilder$Configuration_fr.properties | 2 +- ...eWizardBuilder$Configuration_fr_CA.properties | 2 +- ...duleWizardBuilder$Configuration_it.properties | 2 +- ...duleWizardBuilder$Configuration_ja.properties | 2 +- ...eWizardBuilder$Configuration_pt_BR.properties | 2 +- ...duleWizardBuilder$Configuration_ru.properties | 2 +- ...asswordModuleWizardBuilder$Profile.properties | 2 +- ...wordModuleWizardBuilder$Profile_fr.properties | 2 +- ...dModuleWizardBuilder$Profile_fr_CA.properties | 2 +- ...wordModuleWizardBuilder$Profile_it.properties | 2 +- ...wordModuleWizardBuilder$Profile_ja.properties | 2 +- ...dModuleWizardBuilder$Profile_pt_BR.properties | 2 +- ...wordModuleWizardBuilder$Profile_ru.properties | 2 +- .../lib/password/LDAPPasswordModuleConf.java | 4 ++-- .../lib/password/SyncopePasswordModuleConf.java | 2 +- .../syncope/common/lib/to/PasswordModuleTO.java | 2 +- .../syncope/core/logic/PasswordModuleLogic.java | 6 ++++-- .../cxf/service/PasswordModuleServiceImpl.java | 16 ++++++++++------ .../persistence/api/dao/PasswordModuleDAO.java | 2 +- .../jpa/dao/repo/PasswordModuleRepoExtImpl.java | 4 ++-- .../jpa/entity/AbstractEntityFactory.java | 2 +- .../jpa/inner/PasswordModuleTest.java | 4 +++- .../dao/repo/PasswordModuleRepoExtImpl.java | 4 ++-- .../neo4j/entity/Neo4jEntityFactory.java | 2 +- .../java/data/PasswordModuleDataBinderImpl.java | 9 ++++++--- .../syncope/fit/core/PasswordModuleITCase.java | 6 +++++- .../wa/bootstrap/WAPropertySourceLocator.java | 3 ++- .../PasswordModulePropertySourceMapper.java | 4 ++-- 37 files changed, 69 insertions(+), 50 deletions(-) diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel.java b/client/am/console/src/main/java/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel.java index 3e378082692..76ae7fff6e8 100644 --- a/client/am/console/src/main/java/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel.java +++ b/client/am/console/src/main/java/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel.java @@ -42,8 +42,11 @@ import org.apache.wicket.model.StringResourceModel; import org.apache.wicket.spring.injection.annot.SpringBean; -public class PasswordModuleDirectoryPanel - extends DirectoryPanel { +public class PasswordModuleDirectoryPanel extends DirectoryPanel< + PasswordModuleTO, + PasswordModuleTO, + PasswordModuleDirectoryPanel.PasswordModuleProvider, + PasswordModuleRestClient> { private static final long serialVersionUID = 1005345990563741296L; @SpringBean diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel.properties index 59952970b0a..ee38222f198 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel.properties @@ -5,4 +5,4 @@ description=Description type=Type state=State order=Order -menu.history=Configuration history \ No newline at end of file +menu.history=Configuration history diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_fr.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_fr.properties index 59952970b0a..ee38222f198 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_fr.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_fr.properties @@ -5,4 +5,4 @@ description=Description type=Type state=State order=Order -menu.history=Configuration history \ No newline at end of file +menu.history=Configuration history diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_fr_CA.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_fr_CA.properties index 59952970b0a..ee38222f198 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_fr_CA.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_fr_CA.properties @@ -5,4 +5,4 @@ description=Description type=Type state=State order=Order -menu.history=Configuration history \ No newline at end of file +menu.history=Configuration history diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_it.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_it.properties index 64ebb25442b..4d1fa8a0826 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_it.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_it.properties @@ -5,4 +5,4 @@ description=Descrizione type=Tipo state=Stato order=Ordinamento -auditHistory.title=Storico delle configurazioni \ No newline at end of file +auditHistory.title=Storico delle configurazioni diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_ja.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_ja.properties index 59952970b0a..ee38222f198 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_ja.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_ja.properties @@ -5,4 +5,4 @@ description=Description type=Type state=State order=Order -menu.history=Configuration history \ No newline at end of file +menu.history=Configuration history diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_pt_BR.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_pt_BR.properties index 59952970b0a..ee38222f198 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_pt_BR.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_pt_BR.properties @@ -5,4 +5,4 @@ description=Description type=Type state=State order=Order -menu.history=Configuration history \ No newline at end of file +menu.history=Configuration history diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_ru.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_ru.properties index 59952970b0a..ee38222f198 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_ru.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_ru.properties @@ -5,4 +5,4 @@ description=Description type=Type state=State order=Order -menu.history=Configuration history \ No newline at end of file +menu.history=Configuration history diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration.properties index 59526fc3cfb..d58df7d7a4f 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration.properties @@ -4,4 +4,4 @@ features=Features matchingCond=Matching Condition userMatchingCond=User Matching Condition groupMatchingCond=Group Matching Condition -anyObjectMatchingCond=AnyObject Matching Condition \ No newline at end of file +anyObjectMatchingCond=AnyObject Matching Condition diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_fr.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_fr.properties index 59526fc3cfb..d58df7d7a4f 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_fr.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_fr.properties @@ -4,4 +4,4 @@ features=Features matchingCond=Matching Condition userMatchingCond=User Matching Condition groupMatchingCond=Group Matching Condition -anyObjectMatchingCond=AnyObject Matching Condition \ No newline at end of file +anyObjectMatchingCond=AnyObject Matching Condition diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_fr_CA.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_fr_CA.properties index 59526fc3cfb..d58df7d7a4f 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_fr_CA.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_fr_CA.properties @@ -4,4 +4,4 @@ features=Features matchingCond=Matching Condition userMatchingCond=User Matching Condition groupMatchingCond=Group Matching Condition -anyObjectMatchingCond=AnyObject Matching Condition \ No newline at end of file +anyObjectMatchingCond=AnyObject Matching Condition diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_it.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_it.properties index 1c997143677..c318f44bfcc 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_it.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_it.properties @@ -4,4 +4,4 @@ features=Features matchingCond=Condizione di matching userMatchingCond=Condizione di matching utente groupMatchingCond=Condizione di matching gruppo -anyObjectMatchingCond=Condizione di matching any \ No newline at end of file +anyObjectMatchingCond=Condizione di matching any diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_ja.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_ja.properties index 59526fc3cfb..d58df7d7a4f 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_ja.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_ja.properties @@ -4,4 +4,4 @@ features=Features matchingCond=Matching Condition userMatchingCond=User Matching Condition groupMatchingCond=Group Matching Condition -anyObjectMatchingCond=AnyObject Matching Condition \ No newline at end of file +anyObjectMatchingCond=AnyObject Matching Condition diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_pt_BR.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_pt_BR.properties index 59526fc3cfb..d58df7d7a4f 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_pt_BR.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_pt_BR.properties @@ -4,4 +4,4 @@ features=Features matchingCond=Matching Condition userMatchingCond=User Matching Condition groupMatchingCond=Group Matching Condition -anyObjectMatchingCond=AnyObject Matching Condition \ No newline at end of file +anyObjectMatchingCond=AnyObject Matching Condition diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_ru.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_ru.properties index 59526fc3cfb..d58df7d7a4f 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_ru.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_ru.properties @@ -4,4 +4,4 @@ features=Features matchingCond=Matching Condition userMatchingCond=User Matching Condition groupMatchingCond=Group Matching Condition -anyObjectMatchingCond=AnyObject Matching Condition \ No newline at end of file +anyObjectMatchingCond=AnyObject Matching Condition diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile.properties index a350401cf15..2e0c01a7f9e 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile.properties @@ -1,4 +1,4 @@ description=Description configuration=Configuration type=Type -state=State \ No newline at end of file +state=State diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_fr.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_fr.properties index a350401cf15..2e0c01a7f9e 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_fr.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_fr.properties @@ -1,4 +1,4 @@ description=Description configuration=Configuration type=Type -state=State \ No newline at end of file +state=State diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_fr_CA.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_fr_CA.properties index a350401cf15..2e0c01a7f9e 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_fr_CA.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_fr_CA.properties @@ -1,4 +1,4 @@ description=Description configuration=Configuration type=Type -state=State \ No newline at end of file +state=State diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_it.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_it.properties index c0c3d523024..427644db502 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_it.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_it.properties @@ -1,4 +1,4 @@ description=Descrizione configuration=Configurazione type=Tipo -state=Stato \ No newline at end of file +state=Stato diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_ja.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_ja.properties index a350401cf15..2e0c01a7f9e 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_ja.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_ja.properties @@ -1,4 +1,4 @@ description=Description configuration=Configuration type=Type -state=State \ No newline at end of file +state=State diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_pt_BR.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_pt_BR.properties index a350401cf15..2e0c01a7f9e 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_pt_BR.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_pt_BR.properties @@ -1,4 +1,4 @@ description=Description configuration=Configuration type=Type -state=State \ No newline at end of file +state=State diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_ru.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_ru.properties index a350401cf15..2e0c01a7f9e 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_ru.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_ru.properties @@ -1,4 +1,4 @@ description=Description configuration=Configuration type=Type -state=State \ No newline at end of file +state=State diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/LDAPPasswordModuleConf.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/LDAPPasswordModuleConf.java index b00173edd9d..6aad347a622 100644 --- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/LDAPPasswordModuleConf.java +++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/LDAPPasswordModuleConf.java @@ -15,11 +15,11 @@ public String getUsernameAttribute() { return usernameAttribute; } - public void setUsernameAttribute(String usernameAttribute) { + public void setUsernameAttribute(final String usernameAttribute) { this.usernameAttribute = usernameAttribute; } - @Override public Map map(PasswordModuleTO passwordModuleTO, Mapper mapper) { + @Override public Map map(final PasswordModuleTO passwordModuleTO, final Mapper mapper) { return mapper.map(passwordModuleTO, this); } } diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/SyncopePasswordModuleConf.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/SyncopePasswordModuleConf.java index ff036da7af8..c63b279d6b7 100644 --- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/SyncopePasswordModuleConf.java +++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/SyncopePasswordModuleConf.java @@ -5,7 +5,7 @@ import org.apache.syncope.common.lib.SyncopeConstants; import org.apache.syncope.common.lib.to.PasswordModuleTO; -public class SyncopePasswordModuleConf implements PasswordModuleConf{ +public class SyncopePasswordModuleConf implements PasswordModuleConf { private static final long serialVersionUID = -8203692328056109683L; diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/to/PasswordModuleTO.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/to/PasswordModuleTO.java index b1675e8b48d..c059a8ff8c5 100644 --- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/to/PasswordModuleTO.java +++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/to/PasswordModuleTO.java @@ -7,7 +7,7 @@ import org.apache.commons.lang3.builder.HashCodeBuilder; import org.apache.syncope.common.lib.password.PasswordModuleConf; -public class PasswordModuleTO implements EntityTO{ +public class PasswordModuleTO implements EntityTO { private String key; diff --git a/core/am/logic/src/main/java/org/apache/syncope/core/logic/PasswordModuleLogic.java b/core/am/logic/src/main/java/org/apache/syncope/core/logic/PasswordModuleLogic.java index cec47cbe14d..c4ec342c488 100644 --- a/core/am/logic/src/main/java/org/apache/syncope/core/logic/PasswordModuleLogic.java +++ b/core/am/logic/src/main/java/org/apache/syncope/core/logic/PasswordModuleLogic.java @@ -41,7 +41,8 @@ public PasswordModuleTO update(final PasswordModuleTO passwordModuleTO) { passwordModuleDAO.save(passwordModuleDataBinder.update(passwordModule, passwordModuleTO))); } - @PreAuthorize("hasRole('" + AMEntitlement.PASSWORD_MODULE_LIST + "') or hasRole('" + IdRepoEntitlement.ANONYMOUS + "')") + @PreAuthorize("hasRole('" + AMEntitlement.PASSWORD_MODULE_LIST + "') or hasRole('" + + IdRepoEntitlement.ANONYMOUS + "')") @Transactional(readOnly = true) public List list() { return passwordModuleDAO.findAll().stream() @@ -68,7 +69,8 @@ public PasswordModuleTO delete(final String key) { return deleted; } - @Override protected PasswordModuleTO resolveReference(Method method, Object... args) + @Override + protected PasswordModuleTO resolveReference(final Method method, final Object... args) throws UnresolvedReferenceException { if (ArrayUtils.isEmpty(args)) { throw new UnresolvedReferenceException(); diff --git a/core/am/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/PasswordModuleServiceImpl.java b/core/am/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/PasswordModuleServiceImpl.java index 2a9187f27d4..570ce4a068e 100644 --- a/core/am/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/PasswordModuleServiceImpl.java +++ b/core/am/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/PasswordModuleServiceImpl.java @@ -3,7 +3,6 @@ import jakarta.ws.rs.core.Response; import java.net.URI; import java.util.List; -import org.apache.syncope.common.lib.to.AttrRepoTO; import org.apache.syncope.common.lib.to.PasswordModuleTO; import org.apache.syncope.common.rest.api.RESTHeaders; import org.apache.syncope.common.rest.api.service.PasswordModuleService; @@ -17,15 +16,18 @@ public PasswordModuleServiceImpl(final PasswordModuleLogic passwordModuleLogic) this.passwordModuleLogic = passwordModuleLogic; } - @Override public PasswordModuleTO read(String key) { + @Override + public PasswordModuleTO read(final String key) { return passwordModuleLogic.read(key); } - @Override public List list() { + @Override + public List list() { return passwordModuleLogic.list(); } - @Override public Response create(PasswordModuleTO passwordModuleTO) { + @Override + public Response create(final PasswordModuleTO passwordModuleTO) { PasswordModuleTO passwordModule = passwordModuleLogic.create(passwordModuleTO); URI location = uriInfo.getAbsolutePathBuilder().path(passwordModule.getKey()).build(); return Response.created(location). @@ -33,11 +35,13 @@ public PasswordModuleServiceImpl(final PasswordModuleLogic passwordModuleLogic) build(); } - @Override public void update(PasswordModuleTO passwordModuleTO) { + @Override + public void update(final PasswordModuleTO passwordModuleTO) { passwordModuleLogic.update(passwordModuleTO); } - @Override public void delete(String key) { + @Override + public void delete(final String key) { passwordModuleLogic.delete(key); } } diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PasswordModuleDAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PasswordModuleDAO.java index 964cf804c9f..07ab8352498 100644 --- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PasswordModuleDAO.java +++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PasswordModuleDAO.java @@ -2,5 +2,5 @@ import org.apache.syncope.core.persistence.api.entity.am.PasswordModule; -public interface PasswordModuleDAO extends DAO{ +public interface PasswordModuleDAO extends DAO { } diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordModuleRepoExtImpl.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordModuleRepoExtImpl.java index 39d3fbcccc2..9d9ef269c56 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordModuleRepoExtImpl.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordModuleRepoExtImpl.java @@ -13,12 +13,12 @@ public PasswordModuleRepoExtImpl(final EntityManager entityManager) { } - @Override public PasswordModule save(PasswordModule passwordModule) { + @Override public PasswordModule save(final PasswordModule passwordModule) { ((JPAPasswordModule) passwordModule).list2json(); return entityManager.merge(passwordModule); } - @Override public void delete(PasswordModule passwordModule) { + @Override public void delete(final PasswordModule passwordModule) { entityManager.remove(passwordModule); } } diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractEntityFactory.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractEntityFactory.java index 18af1d92151..bf9cb0bf495 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractEntityFactory.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractEntityFactory.java @@ -266,7 +266,7 @@ public E newEntity(final Class reference) { result = (E) new JPAAuthModule(); } else if (reference.equals(PasswordModule.class)) { result = (E) new JPAPasswordModule(); - }else if (reference.equals(AttrRepo.class)) { + } else if (reference.equals(AttrRepo.class)) { result = (E) new JPAAttrRepo(); } else if (reference.equals(AuthPolicy.class)) { result = (E) new JPAAuthPolicy(); diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PasswordModuleTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PasswordModuleTest.java index 064be888c92..4cf39f172ac 100644 --- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PasswordModuleTest.java +++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PasswordModuleTest.java @@ -21,7 +21,9 @@ @Transactional public class PasswordModuleTest extends AbstractTest { - private static boolean isSpecificConf(final PasswordModuleConf conf, final Class clazz) { + private static boolean isSpecificConf( + final PasswordModuleConf conf, + final Class clazz) { return ClassUtils.isAssignable(clazz, conf.getClass()); } diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/PasswordModuleRepoExtImpl.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/PasswordModuleRepoExtImpl.java index 2871433bd42..73e20da2f64 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/PasswordModuleRepoExtImpl.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/PasswordModuleRepoExtImpl.java @@ -19,7 +19,7 @@ public PasswordModuleRepoExtImpl( } @Override - public PasswordModule save(PasswordModule passwordModule) { + public PasswordModule save(final PasswordModule passwordModule) { ((Neo4jPasswordModule) passwordModule).list2json(); PasswordModule saved = neo4jTemplate.save(nodeValidator.validate(passwordModule)); ((Neo4jPasswordModule) saved).postSave(); @@ -27,7 +27,7 @@ public PasswordModule save(PasswordModule passwordModule) { } @Override - public void delete(PasswordModule passwordModule) { + public void delete(final PasswordModule passwordModule) { neo4jTemplate.deleteById(passwordModule.getKey(), Neo4jPasswordModule.class); } } diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/Neo4jEntityFactory.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/Neo4jEntityFactory.java index c70c36e7c74..3b3a980eddc 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/Neo4jEntityFactory.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/Neo4jEntityFactory.java @@ -267,7 +267,7 @@ public E newEntity(final Class reference) { result = (E) new Neo4jAuthModule(); } else if (reference.equals(PasswordModule.class)) { result = (E) new Neo4jPasswordModule(); - }else if (reference.equals(AttrRepo.class)) { + } else if (reference.equals(AttrRepo.class)) { result = (E) new Neo4jAttrRepo(); } else if (reference.equals(AuthPolicy.class)) { result = (E) new Neo4jAuthPolicy(); diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/PasswordModuleDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/PasswordModuleDataBinderImpl.java index 1827da930ad..a7494b84dc3 100644 --- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/PasswordModuleDataBinderImpl.java +++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/PasswordModuleDataBinderImpl.java @@ -84,13 +84,15 @@ protected void populateItems(final PasswordModule passwordModule, final Password }); } - @Override public PasswordModule create(PasswordModuleTO passwordModuleTO) { + @Override + public PasswordModule create(final PasswordModuleTO passwordModuleTO) { PasswordModule passwordModule = entityFactory.newEntity(PasswordModule.class); passwordModule.setKey(passwordModuleTO.getKey()); return update(passwordModule, passwordModuleTO); } - @Override public PasswordModule update(PasswordModule passwordModule, PasswordModuleTO passwordModuleTO) { + @Override + public PasswordModule update(final PasswordModule passwordModule, final PasswordModuleTO passwordModuleTO) { passwordModule.setDescription(passwordModuleTO.getDescription()); passwordModule.setOrder(passwordModuleTO.getOrder()); passwordModule.setConf(passwordModuleTO.getConf()); @@ -101,7 +103,8 @@ protected void populateItems(final PasswordModule passwordModule, final Password return passwordModule; } - @Override public PasswordModuleTO getPasswordModuleTO(PasswordModule passwordModule) { + @Override + public PasswordModuleTO getPasswordModuleTO(final PasswordModule passwordModule) { PasswordModuleTO passwordModuleTO = new PasswordModuleTO(); passwordModuleTO.setKey(passwordModule.getKey()); diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PasswordModuleITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PasswordModuleITCase.java index 0a280edd078..753c76bff4f 100644 --- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PasswordModuleITCase.java +++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PasswordModuleITCase.java @@ -62,12 +62,16 @@ private static PasswordModuleTO buildPasswordModuleTO(final PasswordModuleSuppor LDAPPasswordModuleConf.class.cast(conf).setBaseDn("cn=Directory Manager,dc=example,dc=org"); LDAPPasswordModuleConf.class.cast(conf).setBindCredential("Password"); break; + default: + break; } return passwordModuleTO; } - private static boolean isSpecificConf(final PasswordModuleConf conf, final Class clazz) { + private static boolean isSpecificConf( + final PasswordModuleConf conf, + final Class clazz) { return ClassUtils.isAssignable(clazz, conf.getClass()); } diff --git a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WAPropertySourceLocator.java b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WAPropertySourceLocator.java index 541b2d49880..ebd6c43e0ea 100644 --- a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WAPropertySourceLocator.java +++ b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WAPropertySourceLocator.java @@ -133,7 +133,8 @@ public PropertySource locate(final Environment environment) { syncopeClient.getService(PasswordModuleService.class).list().forEach(passwordModuleTO -> { LOG.debug("Mapping password module {} ", passwordModuleTO.getKey()); - Map map = passwordModuleTO.getConf().map(passwordModuleTO, passwordModulePropertySourceMapper); + Map map = passwordModuleTO.getConf() + .map(passwordModuleTO, passwordModulePropertySourceMapper); properties.putAll(index(map, prefixes)); }); diff --git a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/PasswordModulePropertySourceMapper.java b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/PasswordModulePropertySourceMapper.java index 3db0f4e2818..6942db13795 100644 --- a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/PasswordModulePropertySourceMapper.java +++ b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/PasswordModulePropertySourceMapper.java @@ -21,7 +21,7 @@ public PasswordModulePropertySourceMapper(final WARestClient waRestClient) { } @Override - public Map map(PasswordModuleTO passwordModuleTO, SyncopePasswordModuleConf conf) { + public Map map(final PasswordModuleTO passwordModuleTO, final SyncopePasswordModuleConf conf) { SyncopeClient syncopeClient = waRestClient.getSyncopeClient(); if (syncopeClient == null) { LOG.warn("Application context is not ready to bootstrap WA configuration"); @@ -40,7 +40,7 @@ public Map map(PasswordModuleTO passwordModuleTO, SyncopePasswor } @Override - public Map map(PasswordModuleTO passwordModuleTO, LDAPPasswordModuleConf conf) { + public Map map(final PasswordModuleTO passwordModuleTO, final LDAPPasswordModuleConf conf) { LdapPasswordManagementProperties props = new LdapPasswordManagementProperties(); props.setName(passwordModuleTO.getKey()); props.setType(AbstractLdapProperties.LdapType.valueOf(conf.getLdapType().name())); From 8c1a0de12ed9132192ae4d38384b91fb7c8865ca Mon Sep 17 00:00:00 2001 From: alberto bogi Date: Thu, 21 Aug 2025 12:17:44 +0200 Subject: [PATCH 07/20] [SYNCOPE-1901] Adding JDBCPasswordModuleConf to configure CAS password management with JDBC --- .../lib/password/JDBCPasswordModuleConf.java | 119 ++++++++++++++++++ .../lib/password/PasswordModuleConf.java | 2 + .../jpa/entity/am/JPAPasswordModule.java | 6 +- .../jpa/inner/PasswordModuleTest.java | 38 +++++- .../test/resources/domains/MasterContent.xml | 10 +- .../neo4j/entity/am/Neo4jPasswordModule.java | 6 +- .../fit/core/PasswordModuleITCase.java | 51 +++++++- .../PasswordModulePropertySourceMapper.java | 18 +++ wa/starter/pom.xml | 8 ++ wa/starter/src/main/resources/wa.properties | 2 +- 10 files changed, 249 insertions(+), 11 deletions(-) create mode 100644 common/am/lib/src/main/java/org/apache/syncope/common/lib/password/JDBCPasswordModuleConf.java diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/JDBCPasswordModuleConf.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/JDBCPasswordModuleConf.java new file mode 100644 index 00000000000..feca3a764c6 --- /dev/null +++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/JDBCPasswordModuleConf.java @@ -0,0 +1,119 @@ +package org.apache.syncope.common.lib.password; + +import java.util.Map; +import org.apache.syncope.common.lib.AbstractJDBCConf; +import org.apache.syncope.common.lib.to.PasswordModuleTO; + +public class JDBCPasswordModuleConf extends AbstractJDBCConf implements PasswordModuleConf { + + private static final long serialVersionUID = 1335379501740158360L; + + /** + * SQL query to change the password and update. + */ + private String sqlChangePassword; + + /** + * SQL query to locate the user email address. + */ + private String sqlFindEmail; + + /** + * SQL query to locate the user phone number. + */ + private String sqlFindPhone; + + /** + * SQL query to locate the user via email. + */ + private String sqlFindUser; + + /** + * SQL query to locate security questions for the account, if any. + */ + private String sqlGetSecurityQuestions; + + /** + * SQL query to update security questions for the account, if any. + */ + private String sqlUpdateSecurityQuestions; + + /** + * SQL query to unlock accounts. + */ + private String sqlUnlockAccount; + + /** + * SQL query to delete security questions for the account, if any. + */ + private String sqlDeleteSecurityQuestions; + + public String getSqlChangePassword() { + return sqlChangePassword; + } + + public void setSqlChangePassword(final String sqlChangePassword) { + this.sqlChangePassword = sqlChangePassword; + } + + public String getSqlFindEmail() { + return sqlFindEmail; + } + + public void setSqlFindEmail(final String sqlFindEmail) { + this.sqlFindEmail = sqlFindEmail; + } + + public String getSqlFindPhone() { + return sqlFindPhone; + } + + public void setSqlFindPhone(final String sqlFindPhone) { + this.sqlFindPhone = sqlFindPhone; + } + + public String getSqlFindUser() { + return sqlFindUser; + } + + public void setSqlFindUser(final String sqlFindUser) { + this.sqlFindUser = sqlFindUser; + } + + public String getSqlGetSecurityQuestions() { + return sqlGetSecurityQuestions; + } + + public void setSqlGetSecurityQuestions(final String sqlGetSecurityQuestions) { + this.sqlGetSecurityQuestions = sqlGetSecurityQuestions; + } + + public String getSqlUpdateSecurityQuestions() { + return sqlUpdateSecurityQuestions; + } + + public void setSqlUpdateSecurityQuestions(final String sqlUpdateSecurityQuestions) { + this.sqlUpdateSecurityQuestions = sqlUpdateSecurityQuestions; + } + + public String getSqlUnlockAccount() { + return sqlUnlockAccount; + } + + public void setSqlUnlockAccount(final String sqlUnlockAccount) { + this.sqlUnlockAccount = sqlUnlockAccount; + } + + public String getSqlDeleteSecurityQuestions() { + return sqlDeleteSecurityQuestions; + } + + public void setSqlDeleteSecurityQuestions(final String sqlDeleteSecurityQuestions) { + this.sqlDeleteSecurityQuestions = sqlDeleteSecurityQuestions; + } + + @Override + public Map map(final PasswordModuleTO passwordModuleTO, final Mapper mapper) { + return mapper.map(passwordModuleTO, this); + } +} diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/PasswordModuleConf.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/PasswordModuleConf.java index 3457df68eed..384c4417f44 100644 --- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/PasswordModuleConf.java +++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/PasswordModuleConf.java @@ -15,6 +15,8 @@ interface Mapper { Map map(PasswordModuleTO passwordModuleTO, LDAPPasswordModuleConf conf); + Map map(PasswordModuleTO passwordModuleTO, JDBCPasswordModuleConf conf); + } Map map(PasswordModuleTO passwordModuleTO, Mapper mapper); diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/am/JPAPasswordModule.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/am/JPAPasswordModule.java index 49fe09ab005..ab7cd976177 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/am/JPAPasswordModule.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/am/JPAPasswordModule.java @@ -35,7 +35,7 @@ public class JPAPasswordModule extends AbstractProvidedKeyEntity implements Pass private String description; @NotNull - private Integer authModuleOrder = 0; + private Integer passwordModuleOrder = 0; @Lob private String items; @@ -58,12 +58,12 @@ public void setDescription(final String description) { @Override public int getOrder() { - return Optional.ofNullable(authModuleOrder).orElse(0); + return Optional.ofNullable(passwordModuleOrder).orElse(0); } @Override public void setOrder(final int order) { - this.authModuleOrder = order; + this.passwordModuleOrder = order; } @Override diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PasswordModuleTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PasswordModuleTest.java index 4cf39f172ac..a587ba61df6 100644 --- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PasswordModuleTest.java +++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PasswordModuleTest.java @@ -7,6 +7,7 @@ import java.util.List; import org.apache.commons.lang3.ClassUtils; +import org.apache.syncope.common.lib.password.JDBCPasswordModuleConf; import org.apache.syncope.common.lib.password.LDAPPasswordModuleConf; import org.apache.syncope.common.lib.password.PasswordModuleConf; import org.apache.syncope.common.lib.password.SyncopePasswordModuleConf; @@ -35,7 +36,7 @@ public void findAll() { List modules = passwordModuleDAO.findAll(); assertNotNull(modules); assertFalse(modules.isEmpty()); - assertEquals(2, modules.size()); + assertEquals(3, modules.size()); } @Test @@ -45,6 +46,9 @@ public void find() { passwordModule = passwordModuleDAO.findById("DefaultLDAPPasswordModule").orElseThrow(); assertTrue(passwordModule.getConf() instanceof LDAPPasswordModuleConf); + + passwordModule = passwordModuleDAO.findById("DefaultJDBCPasswordModule").orElseThrow(); + assertTrue(passwordModule.getConf() instanceof JDBCPasswordModuleConf); } @Test @@ -58,6 +62,10 @@ public void findByType() { passwordModule -> isSpecificConf(passwordModule.getConf(), LDAPPasswordModuleConf.class) && passwordModule.getKey().equals("DefaultLDAPPasswordModule"))); + assertTrue(passwordModules.stream().anyMatch( + passwordModule -> isSpecificConf(passwordModule.getConf(), + JDBCPasswordModuleConf.class) + && passwordModule.getKey().equals("DefaultJDBCPasswordModule"))); } private void savePasswordModule(final String key, final PasswordModuleConf conf) { @@ -106,6 +114,17 @@ public void saveWithLdapModule() { savePasswordModule("LDAPPasswordModuleTest", conf); } + @Test + public void saveWithJdbcModule() { + JDBCPasswordModuleConf conf = new JDBCPasswordModuleConf(); + conf.setSqlFindEmail("SELECT email from users_table where name=?"); + conf.setSqlFindPhone("SELECT phoneNumber from users_table where name=?"); + conf.setSqlFindUser("SELECT * from users_table where name=?"); + conf.setSqlChangePassword("UPDATE users_table SET password=? WHERE name=?"); + + savePasswordModule("JDBCPasswordModuleTest", conf); + } + @Test public void updateWithSyncopeModule() { PasswordModule module = passwordModuleDAO.findById("DefaultSyncopePasswordModule").orElseThrow(); @@ -140,6 +159,23 @@ public void updateWithLdapModule() { assertEquals("cn={user2}", LDAPPasswordModuleConf.class.cast(found.getConf()).getSearchFilter()); } + @Test + public void updateWithJDBCModule() { + PasswordModule module = passwordModuleDAO.findById("DefaultJDBCPasswordModule").orElseThrow(); + + PasswordModuleConf conf = module.getConf(); + JDBCPasswordModuleConf.class.cast(conf).setSqlFindUser("SELECT * from other_table where name=?"); + module.setConf(conf); + + module = passwordModuleDAO.save(module); + assertNotNull(module); + assertNotNull(module.getKey()); + + PasswordModule found = passwordModuleDAO.findById(module.getKey()).orElseThrow(); + assertEquals("SELECT * from other_table where name=?", + JDBCPasswordModuleConf.class.cast(found.getConf()).getSqlFindUser()); + } + @Test public void delete() { assertTrue(passwordModuleDAO.findById("DefaultSyncopePasswordModule").isPresent()); diff --git a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml index e008077f73d..cafb1e3a382 100644 --- a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml +++ b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml @@ -92,9 +92,15 @@ under the License. + jsonConf='{"_class":"org.apache.syncope.common.lib.password.SyncopePasswordModuleConf","domain":"Master","searchFilter":"username={user}","basicAuthUsername":"admin","basicAuthPassword":"password", "headers":{}}' + passwordModuleOrder="0"/> + jsonConf='{"_class":"org.apache.syncope.common.lib.password.LDAPPasswordModuleConf","searchFilter":"cn={user}","subtreeSearch":true,"pageSize":0,"baseDn":"ou=People,${testds.rootDn}","ldapUrl":"ldap://localhost:${testds.port}","ldapType":"GENERIC","bindDn":"${testds.bindDn}","bindCredential":"${testds.password}","disablePooling":false,"minPoolSize":3,"maxPoolSize":10,"poolPassivator":"BIND","hostnameVerifier":"DEFAULT","trustManager":null,"validateOnCheckout":true,"validatePeriodically":true,"validateTimeout":5.000000000,"validatePeriod":300.000000000,"failFast":true,"idleTime":600.000000000,"prunePeriod":7200.000000000,"blockWaitTime":3.000000000,"connectionStrategy":null,"useStartTls":false,"connectTimeout":5.000000000,"responseTimeout":5.000000000,"allowMultipleDns":false,"allowMultipleEntries":false,"followReferrals":true,"binaryAttributes":["objectGUID","objectSid"],"usernameAttribute":"uid"}' + passwordModuleOrder="0"/> + + diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4jPasswordModule.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4jPasswordModule.java index e5083b20758..0fa889db63c 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4jPasswordModule.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4jPasswordModule.java @@ -27,7 +27,7 @@ public class Neo4jPasswordModule extends AbstractProvidedKeyNode implements Pass private String description; @NotNull - private Integer authModuleOrder = 0; + private Integer passwordModuleOrder = 0; private String items; @@ -48,12 +48,12 @@ public void setDescription(final String description) { @Override public int getOrder() { - return Optional.ofNullable(authModuleOrder).orElse(0); + return Optional.ofNullable(passwordModuleOrder).orElse(0); } @Override public void setOrder(final int order) { - this.authModuleOrder = order; + this.passwordModuleOrder = order; } @Override diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PasswordModuleITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PasswordModuleITCase.java index 753c76bff4f..ce6cdb7945b 100644 --- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PasswordModuleITCase.java +++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PasswordModuleITCase.java @@ -14,6 +14,7 @@ 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.password.JDBCPasswordModuleConf; import org.apache.syncope.common.lib.password.LDAPPasswordModuleConf; import org.apache.syncope.common.lib.password.PasswordModuleConf; import org.apache.syncope.common.lib.password.SyncopePasswordModuleConf; @@ -26,7 +27,8 @@ public class PasswordModuleITCase extends AbstractITCase { private enum PasswordModuleSupportedType { SYNCOPE, - LDAP + LDAP, + JDBC }; private static PasswordModuleTO createAuthModule(final PasswordModuleTO passwordModuleTO) { @@ -62,6 +64,17 @@ private static PasswordModuleTO buildPasswordModuleTO(final PasswordModuleSuppor LDAPPasswordModuleConf.class.cast(conf).setBaseDn("cn=Directory Manager,dc=example,dc=org"); LDAPPasswordModuleConf.class.cast(conf).setBindCredential("Password"); break; + case JDBC: + conf = new JDBCPasswordModuleConf(); + JDBCPasswordModuleConf.class.cast(conf) + .setSqlFindEmail("SELECT email from users_table where name=?"); + JDBCPasswordModuleConf.class.cast(conf) + .setSqlFindPhone("SELECT phoneNumber from users_table where name=?"); + JDBCPasswordModuleConf.class.cast(conf) + .setSqlFindUser("SELECT * from users_table where name=?"); + JDBCPasswordModuleConf.class.cast(conf) + .setSqlChangePassword("UPDATE users_table SET password=? WHERE name=?"); + break; default: break; } @@ -87,6 +100,9 @@ public void list() { assertTrue(passwordModuleTOS.stream().anyMatch( authModule -> isSpecificConf(authModule.getConf(), LDAPPasswordModuleConf.class) && authModule.getKey().equals("DefaultLDAPPasswordModule"))); + assertTrue(passwordModuleTOS.stream().anyMatch( + authModule -> isSpecificConf(authModule.getConf(), JDBCPasswordModuleConf.class) + && authModule.getKey().equals("DefaultJDBCPasswordModule"))); } @Test @@ -107,6 +123,15 @@ public void getLdapPasswordModule() { assertTrue(isSpecificConf(passwordModuleTO.getConf(), LDAPPasswordModuleConf.class)); } + @Test + public void getJdbcPasswordModule() { + PasswordModuleTO passwordModuleTO = PASSWORD_MODULE_SERVICE.read("DefaultJDBCPasswordModule"); + + assertNotNull(passwordModuleTO); + assertTrue(StringUtils.isNotBlank(passwordModuleTO.getDescription())); + assertTrue(isSpecificConf(passwordModuleTO.getConf(), JDBCPasswordModuleConf.class)); + } + @Test public void create() { EnumSet.allOf(PasswordModuleSupportedType.class).forEach(type -> { @@ -163,6 +188,30 @@ public void updateLdapPasswordModule() { assertFalse(LDAPPasswordModuleConf.class.cast(conf).isSubtreeSearch()); } + @Test + public void updateJdbcPasswordModule() { + PasswordModuleTO jdbcPasswordModuleTO = PASSWORD_MODULE_SERVICE.read("DefaultJDBCPasswordModule"); + assertNotNull(jdbcPasswordModuleTO); + + PasswordModuleTO newJdbcPasswordModuleTO = buildPasswordModuleTO(PasswordModuleSupportedType.JDBC); + newJdbcPasswordModuleTO = createAuthModule(newJdbcPasswordModuleTO); + assertNotNull(newJdbcPasswordModuleTO); + + PasswordModuleConf conf = jdbcPasswordModuleTO.getConf(); + assertNotNull(conf); + JDBCPasswordModuleConf.class.cast(conf).setSqlFindUser("SELECT * from other_table where name=?"); + newJdbcPasswordModuleTO.setConf(conf); + + // update new password module + PASSWORD_MODULE_SERVICE.update(newJdbcPasswordModuleTO); + newJdbcPasswordModuleTO = PASSWORD_MODULE_SERVICE.read(newJdbcPasswordModuleTO.getKey()); + assertNotNull(newJdbcPasswordModuleTO); + + conf = newJdbcPasswordModuleTO.getConf(); + assertEquals("SELECT * from other_table where name=?", + JDBCPasswordModuleConf.class.cast(conf).getSqlFindUser()); + } + @Test public void delete() throws IOException { EnumSet.allOf(PasswordModuleSupportedType.class).forEach(type -> { diff --git a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/PasswordModulePropertySourceMapper.java b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/PasswordModulePropertySourceMapper.java index 6942db13795..9ccab749707 100644 --- a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/PasswordModulePropertySourceMapper.java +++ b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/PasswordModulePropertySourceMapper.java @@ -3,12 +3,14 @@ import java.util.Map; import org.apache.commons.lang3.StringUtils; import org.apache.syncope.client.lib.SyncopeClient; +import org.apache.syncope.common.lib.password.JDBCPasswordModuleConf; import org.apache.syncope.common.lib.password.LDAPPasswordModuleConf; import org.apache.syncope.common.lib.password.PasswordModuleConf; import org.apache.syncope.common.lib.password.SyncopePasswordModuleConf; import org.apache.syncope.common.lib.to.PasswordModuleTO; import org.apache.syncope.wa.bootstrap.WARestClient; import org.apereo.cas.configuration.model.support.ldap.AbstractLdapProperties; +import org.apereo.cas.configuration.model.support.pm.JdbcPasswordManagementProperties; import org.apereo.cas.configuration.model.support.pm.LdapPasswordManagementProperties; import org.apereo.cas.configuration.model.support.pm.SyncopePasswordManagementProperties; @@ -50,4 +52,20 @@ public Map map(final PasswordModuleTO passwordModuleTO, final LD return prefix("cas.authn.pm.ldap[].", WAConfUtils.asMap(props)); } + + @Override + public Map map(final PasswordModuleTO passwordModuleTO, final JDBCPasswordModuleConf conf) { + JdbcPasswordManagementProperties props = new JdbcPasswordManagementProperties(); + props.setSqlChangePassword(conf.getSqlChangePassword()); + props.setSqlFindEmail(conf.getSqlFindEmail()); + props.setSqlFindPhone(conf.getSqlFindPhone()); + props.setSqlFindUser(conf.getSqlFindUser()); + props.setSqlGetSecurityQuestions(conf.getSqlGetSecurityQuestions()); + props.setSqlUpdateSecurityQuestions(conf.getSqlUpdateSecurityQuestions()); + props.setSqlDeleteSecurityQuestions(conf.getSqlDeleteSecurityQuestions()); + props.setSqlUnlockAccount(conf.getSqlUnlockAccount()); + fill(props, conf); + + return prefix("cas.authn.pm.jdbc.", WAConfUtils.asMap(props)); + } } diff --git a/wa/starter/pom.xml b/wa/starter/pom.xml index 3806e684d31..4af2d473b83 100644 --- a/wa/starter/pom.xml +++ b/wa/starter/pom.xml @@ -161,6 +161,14 @@ under the License. org.apereo.cas cas-server-support-ldap + + org.apereo.cas + cas-server-support-jdbc + + + org.apereo.cas + cas-server-support-pm-ldap + org.apereo.cas cas-server-support-reports diff --git a/wa/starter/src/main/resources/wa.properties b/wa/starter/src/main/resources/wa.properties index da54a7d4267..2d68caa19b7 100644 --- a/wa/starter/src/main/resources/wa.properties +++ b/wa/starter/src/main/resources/wa.properties @@ -37,7 +37,7 @@ spring.web.resources.static-locations=classpath:/thymeleaf/static,classpath:/syn cas.monitor.endpoints.endpoint.defaults.access=AUTHENTICATED management.endpoints.access.default=UNRESTRICTED -management.endpoints.web.exposure.include=info,health,env,loggers,ssoSessions,registeredServices,refresh,authenticationHandlers,authenticationPolicies,resolveAttributes +management.endpoints.web.exposure.include=info,health,env,beans,loggers,ssoSessions,registeredServices,refresh,authenticationHandlers,authenticationPolicies,resolveAttributes management.endpoint.health.show-details=ALWAYS management.endpoint.env.show-values=WHEN_AUTHORIZED spring.cloud.discovery.client.health-indicator.enabled=false From 13d817d38c05cfac974b66bb68d6d657a0ba71e1 Mon Sep 17 00:00:00 2001 From: alberto bogi Date: Thu, 21 Aug 2025 14:29:14 +0200 Subject: [PATCH 08/20] [SYNCOPE-1901] Add PasswordModule implementations and unit/IT tests for Neo4j --- .../neo4j/inner/PasswordModuleTest.java | 186 ++++++++++++++++++ .../test/resources/domains/MasterContent.xml | 11 ++ 2 files changed, 197 insertions(+) create mode 100644 core/persistence-neo4j/src/test/java/org/apache/syncope/core/persistence/neo4j/inner/PasswordModuleTest.java diff --git a/core/persistence-neo4j/src/test/java/org/apache/syncope/core/persistence/neo4j/inner/PasswordModuleTest.java b/core/persistence-neo4j/src/test/java/org/apache/syncope/core/persistence/neo4j/inner/PasswordModuleTest.java new file mode 100644 index 00000000000..66b307d659c --- /dev/null +++ b/core/persistence-neo4j/src/test/java/org/apache/syncope/core/persistence/neo4j/inner/PasswordModuleTest.java @@ -0,0 +1,186 @@ +package org.apache.syncope.core.persistence.neo4j.inner; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.List; +import org.apache.commons.lang3.ClassUtils; +import org.apache.syncope.common.lib.password.JDBCPasswordModuleConf; +import org.apache.syncope.common.lib.password.LDAPPasswordModuleConf; +import org.apache.syncope.common.lib.password.PasswordModuleConf; +import org.apache.syncope.common.lib.password.SyncopePasswordModuleConf; +import org.apache.syncope.common.lib.to.Item; +import org.apache.syncope.core.persistence.api.dao.PasswordModuleDAO; +import org.apache.syncope.core.persistence.api.entity.am.PasswordModule; +import org.apache.syncope.core.persistence.neo4j.AbstractTest; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; + +@Transactional +public class PasswordModuleTest extends AbstractTest { + + private static boolean isSpecificConf( + final PasswordModuleConf conf, + final Class clazz) { + return ClassUtils.isAssignable(clazz, conf.getClass()); + } + + @Autowired + private PasswordModuleDAO passwordModuleDAO; + + @Test + public void findAll() { + List modules = passwordModuleDAO.findAll(); + assertNotNull(modules); + assertFalse(modules.isEmpty()); + assertEquals(3, modules.size()); + } + + @Test + public void find() { + PasswordModule passwordModule = passwordModuleDAO.findById("DefaultSyncopePasswordModule").orElseThrow(); + assertTrue(passwordModule.getConf() instanceof SyncopePasswordModuleConf); + + passwordModule = passwordModuleDAO.findById("DefaultLDAPPasswordModule").orElseThrow(); + assertTrue(passwordModule.getConf() instanceof LDAPPasswordModuleConf); + + passwordModule = passwordModuleDAO.findById("DefaultJDBCPasswordModule").orElseThrow(); + assertTrue(passwordModule.getConf() instanceof JDBCPasswordModuleConf); + } + + @Test + public void findByType() { + List passwordModules = passwordModuleDAO.findAll(); + assertTrue(passwordModules.stream().anyMatch( + passwordModule -> isSpecificConf(passwordModule.getConf(), + SyncopePasswordModuleConf.class) + && passwordModule.getKey().equals("DefaultSyncopePasswordModule"))); + assertTrue(passwordModules.stream().anyMatch( + passwordModule -> isSpecificConf(passwordModule.getConf(), + LDAPPasswordModuleConf.class) + && passwordModule.getKey().equals("DefaultLDAPPasswordModule"))); + assertTrue(passwordModules.stream().anyMatch( + passwordModule -> isSpecificConf(passwordModule.getConf(), + JDBCPasswordModuleConf.class) + && passwordModule.getKey().equals("DefaultJDBCPasswordModule"))); + } + + private void savePasswordModule(final String key, final PasswordModuleConf conf) { + PasswordModule module = entityFactory.newEntity(PasswordModule.class); + module.setKey(key); + module.setDescription("A password management module"); + module.setConf(conf); + + Item keyMapping = new Item(); + keyMapping.setIntAttrName("uid"); + keyMapping.setExtAttrName("username"); + module.getItems().add(keyMapping); + + Item fullnameMapping = new Item(); + fullnameMapping.setIntAttrName("cn"); + fullnameMapping.setExtAttrName("fullname"); + module.getItems().add(fullnameMapping); + + module = passwordModuleDAO.save(module); + + assertNotNull(module); + assertNotNull(module.getKey()); + assertEquals(module, passwordModuleDAO.findById(module.getKey()).orElseThrow()); + assertEquals(2, module.getItems().size()); + } + + @Test + public void saveWithSyncopeModule() { + SyncopePasswordModuleConf conf = new SyncopePasswordModuleConf(); + conf.setDomain("Master"); + + savePasswordModule("SyncopePasswordModuleTest", conf); + } + + @Test + public void saveWithLdapModule() { + LDAPPasswordModuleConf conf = new LDAPPasswordModuleConf(); + conf.setBaseDn("dc=example,dc=org"); + conf.setSearchFilter("cn={user}"); + conf.setSubtreeSearch(true); + conf.setLdapUrl("ldap://localhost:1389"); + conf.setUsernameAttribute("uid"); + conf.setBindCredential("Password"); + + savePasswordModule("LDAPPasswordModuleTest", conf); + } + + @Test + public void saveWithJdbcModule() { + JDBCPasswordModuleConf conf = new JDBCPasswordModuleConf(); + conf.setSqlFindEmail("SELECT email from users_table where name=?"); + conf.setSqlFindPhone("SELECT phoneNumber from users_table where name=?"); + conf.setSqlFindUser("SELECT * from users_table where name=?"); + conf.setSqlChangePassword("UPDATE users_table SET password=? WHERE name=?"); + + savePasswordModule("JDBCPasswordModuleTest", conf); + } + + @Test + public void updateWithSyncopeModule() { + PasswordModule module = passwordModuleDAO.findById("DefaultSyncopePasswordModule").orElseThrow(); + + PasswordModuleConf conf = module.getConf(); + SyncopePasswordModuleConf.class.cast(conf).setDomain("Two"); + module.setConf(conf); + + module = passwordModuleDAO.save(module); + assertNotNull(module); + assertNotNull(module.getKey()); + + PasswordModule found = passwordModuleDAO.findById(module.getKey()).orElseThrow(); + assertEquals("Two", SyncopePasswordModuleConf.class.cast(found.getConf()).getDomain()); + } + + @Test + public void updateWithLdapModule() { + PasswordModule module = passwordModuleDAO.findById("DefaultLDAPPasswordModule").orElseThrow(); + + PasswordModuleConf conf = module.getConf(); + LDAPPasswordModuleConf.class.cast(conf).setBaseDn("dc=example2,dc=org"); + LDAPPasswordModuleConf.class.cast(conf).setSearchFilter("cn={user2}"); + module.setConf(conf); + + module = passwordModuleDAO.save(module); + assertNotNull(module); + assertNotNull(module.getKey()); + + PasswordModule found = passwordModuleDAO.findById(module.getKey()).orElseThrow(); + assertEquals("dc=example2,dc=org", LDAPPasswordModuleConf.class.cast(found.getConf()).getBaseDn()); + assertEquals("cn={user2}", LDAPPasswordModuleConf.class.cast(found.getConf()).getSearchFilter()); + } + + @Test + public void updateWithJDBCModule() { + PasswordModule module = passwordModuleDAO.findById("DefaultJDBCPasswordModule").orElseThrow(); + + PasswordModuleConf conf = module.getConf(); + JDBCPasswordModuleConf.class.cast(conf).setSqlFindUser("SELECT * from other_table where name=?"); + module.setConf(conf); + + module = passwordModuleDAO.save(module); + assertNotNull(module); + assertNotNull(module.getKey()); + + PasswordModule found = passwordModuleDAO.findById(module.getKey()).orElseThrow(); + assertEquals("SELECT * from other_table where name=?", + JDBCPasswordModuleConf.class.cast(found.getConf()).getSqlFindUser()); + } + + @Test + public void delete() { + assertTrue(passwordModuleDAO.findById("DefaultSyncopePasswordModule").isPresent()); + + passwordModuleDAO.deleteById("DefaultSyncopePasswordModule"); + + assertTrue(passwordModuleDAO.findById("DefaultSyncopePasswordModule").isEmpty()); + } +} diff --git a/core/persistence-neo4j/src/test/resources/domains/MasterContent.xml b/core/persistence-neo4j/src/test/resources/domains/MasterContent.xml index c271719ecf6..13ae8916c5a 100644 --- a/core/persistence-neo4j/src/test/resources/domains/MasterContent.xml +++ b/core/persistence-neo4j/src/test/resources/domains/MasterContent.xml @@ -90,6 +90,17 @@ under the License. + + + + + From 55d131e2af1df619db239975821b5797798312cf Mon Sep 17 00:00:00 2001 From: alberto bogi Date: Wed, 27 Aug 2025 17:15:07 +0200 Subject: [PATCH 09/20] [SYNCOPE-1901] allow defining a single instance of passwordChangeService based on the PasswordManagement configuration enabled via syncope-wa UI --- .../panels/PasswordModuleDirectoryPanel.java | 3 +- .../wizards/PasswordModuleWizardBuilder.java | 25 ++-- .../PasswordModuleWizardBuilder$Profile.html | 3 +- .../common/lib/to/PasswordModuleTO.java | 13 +- .../common/lib/types/PasswordModuleState.java | 14 +++ .../api/entity/am/PasswordModule.java | 5 +- .../jpa/entity/am/JPAPasswordModule.java | 15 ++- .../test/resources/domains/MasterContent.xml | 6 +- .../neo4j/entity/am/Neo4jPasswordModule.java | 14 +-- .../data/PasswordModuleDataBinderImpl.java | 4 +- .../src/main/resources/wa-embedded.properties | 1 + .../wa/bootstrap/WAPropertySourceLocator.java | 15 ++- .../PasswordModulePropertySourceMapper.java | 13 +- wa/starter/pom.xml | 16 ++- .../syncope/wa/starter/config/WAContext.java | 111 ++++++++++++++++++ wa/starter/src/main/resources/wa.properties | 8 +- 16 files changed, 215 insertions(+), 51 deletions(-) create mode 100644 common/am/lib/src/main/java/org/apache/syncope/common/lib/types/PasswordModuleState.java diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel.java b/client/am/console/src/main/java/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel.java index 76ae7fff6e8..036d93d527b 100644 --- a/client/am/console/src/main/java/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel.java +++ b/client/am/console/src/main/java/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel.java @@ -114,8 +114,7 @@ public void populateItem( rowModel.getObject().getConf().getClass().getSimpleName(), "PasswordModuleConf"))); } }); - //columns.add(new PropertyColumn<>(new ResourceModel("state"), "state", "state")); - columns.add(new PropertyColumn<>(new ResourceModel("order"), "order", "order")); + columns.add(new PropertyColumn<>(new ResourceModel("state"), "state", "state")); return columns; } diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder.java b/client/am/console/src/main/java/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder.java index 3c27115af0d..adc8a071321 100644 --- a/client/am/console/src/main/java/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder.java +++ b/client/am/console/src/main/java/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder.java @@ -8,11 +8,11 @@ import org.apache.syncope.client.console.rest.PasswordModuleRestClient; import org.apache.syncope.client.ui.commons.Constants; import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel; -import org.apache.syncope.client.ui.commons.markup.html.form.AjaxNumberFieldPanel; import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel; import org.apache.syncope.client.ui.commons.wizards.AjaxWizard; import org.apache.syncope.common.lib.password.PasswordModuleConf; import org.apache.syncope.common.lib.to.PasswordModuleTO; +import org.apache.syncope.common.lib.types.PasswordModuleState; import org.apache.wicket.PageReference; import org.apache.wicket.ajax.AjaxEventBehavior; import org.apache.wicket.ajax.AjaxRequestTarget; @@ -58,6 +58,17 @@ protected Serializable onApplyInternal(final PasswordModuleTO modelObject) { } else { passwordModuleRestClient.update(modelObject); } + + // PasswordManagement works on single source. + if (PasswordModuleState.ACTIVE.equals(modelObject.getState())) { + passwordModuleRestClient.list().stream().filter(passwordModuleTO -> + !passwordModuleTO.getKey().equals(modelObject.getKey())).toList() + .forEach(passwordModuleTO -> { + passwordModuleTO.setState(PasswordModuleState.DISABLED); + passwordModuleRestClient.update(passwordModuleTO); + }); + } + return modelObject; } @@ -65,7 +76,6 @@ protected Serializable onApplyInternal(final PasswordModuleTO modelObject) { protected WizardModel buildModelSteps(final PasswordModuleTO modelObject, final WizardModel wizardModel) { wizardModel.add(new Profile(modelObject, passwordModuleConfs, passwordModuleConfClass)); wizardModel.add(new Configuration(modelObject)); - //wizardModel.add(new AuthModuleWizardBuilder.Mapping(modelObject)); return wizardModel; } @@ -95,11 +105,12 @@ Constants.DESCRIPTION_FIELD_NAME, getString(Constants.DESCRIPTION_FIELD_NAME), new PropertyModel<>(passwordModule, Constants.DESCRIPTION_FIELD_NAME)); add(description); - add(new AjaxNumberFieldPanel.Builder().build( - "order", - "order", - Integer.class, - new PropertyModel<>(passwordModule, "order")).addRequiredLabel()); + AjaxDropDownChoicePanel state = new AjaxDropDownChoicePanel<>( + "state", getString("state"), new PropertyModel<>(passwordModule, "state")); + state.setChoices(List.of(PasswordModuleState.values())); + state.addRequiredLabel(); + state.setNullValid(false); + add(state); AjaxDropDownChoicePanel conf = new AjaxDropDownChoicePanel<>("conf", getString("type"), isNew ? Model.of() diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile.html b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile.html index f24b821dcbf..8367068f1a4 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile.html +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile.html @@ -2,8 +2,7 @@
[key]
[description]
- -
[order]
+
[state]
[conf]
\ No newline at end of file diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/to/PasswordModuleTO.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/to/PasswordModuleTO.java index c059a8ff8c5..d9004e985da 100644 --- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/to/PasswordModuleTO.java +++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/to/PasswordModuleTO.java @@ -6,6 +6,7 @@ import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; import org.apache.syncope.common.lib.password.PasswordModuleConf; +import org.apache.syncope.common.lib.types.PasswordModuleState; public class PasswordModuleTO implements EntityTO { @@ -13,7 +14,7 @@ public class PasswordModuleTO implements EntityTO { private String description; - private int order = 0; + private PasswordModuleState state = PasswordModuleState.DISABLED; private final List items = new ArrayList<>(); @@ -38,12 +39,12 @@ public void setDescription(final String description) { this.description = description; } - public int getOrder() { - return order; + public PasswordModuleState getState() { + return state; } - public void setOrder(final int order) { - this.order = order; + public void setState(final PasswordModuleState state) { + this.state = state; } public List getItems() { @@ -73,7 +74,7 @@ public boolean equals(final Object obj) { return new EqualsBuilder(). append(key, other.key). append(description, other.description). - append(order, other.order). + append(state, other.state). append(items, other.items). append(conf, other.conf). build(); diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/types/PasswordModuleState.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/types/PasswordModuleState.java new file mode 100644 index 00000000000..673cac79ccd --- /dev/null +++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/types/PasswordModuleState.java @@ -0,0 +1,14 @@ +package org.apache.syncope.common.lib.types; + +public enum PasswordModuleState { + /** + * Active password management configuration, + * This password management is used for CAS reset password flow. + */ + ACTIVE, + /** + * Disabled password management configuration, + * and is invoked by default automatically. + */ + DISABLED +} diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/am/PasswordModule.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/am/PasswordModule.java index 1d3350964b5..d26b66141d8 100644 --- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/am/PasswordModule.java +++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/am/PasswordModule.java @@ -3,6 +3,7 @@ import java.util.List; import org.apache.syncope.common.lib.password.PasswordModuleConf; import org.apache.syncope.common.lib.to.Item; +import org.apache.syncope.common.lib.types.PasswordModuleState; import org.apache.syncope.core.persistence.api.entity.ProvidedKeyEntity; public interface PasswordModule extends ProvidedKeyEntity { @@ -11,9 +12,9 @@ public interface PasswordModule extends ProvidedKeyEntity { void setDescription(String description); - int getOrder(); + PasswordModuleState getState(); - void setOrder(int order); + void setState(PasswordModuleState state); PasswordModuleConf getConf(); diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/am/JPAPasswordModule.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/am/JPAPasswordModule.java index ab7cd976177..49065e4ffc4 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/am/JPAPasswordModule.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/am/JPAPasswordModule.java @@ -2,6 +2,8 @@ import com.fasterxml.jackson.core.type.TypeReference; import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; import jakarta.persistence.Lob; import jakarta.persistence.PostLoad; import jakarta.persistence.PostPersist; @@ -13,10 +15,10 @@ import jakarta.validation.constraints.NotNull; import java.util.ArrayList; import java.util.List; -import java.util.Optional; import org.apache.commons.lang3.StringUtils; import org.apache.syncope.common.lib.password.PasswordModuleConf; import org.apache.syncope.common.lib.to.Item; +import org.apache.syncope.common.lib.types.PasswordModuleState; import org.apache.syncope.core.persistence.api.entity.am.PasswordModule; import org.apache.syncope.core.persistence.jpa.entity.AbstractProvidedKeyEntity; import org.apache.syncope.core.provisioning.api.serialization.POJOHelper; @@ -34,8 +36,9 @@ public class JPAPasswordModule extends AbstractProvidedKeyEntity implements Pass private String description; + @Enumerated(EnumType.STRING) @NotNull - private Integer passwordModuleOrder = 0; + private PasswordModuleState passwordModuleState; @Lob private String items; @@ -57,13 +60,13 @@ public void setDescription(final String description) { } @Override - public int getOrder() { - return Optional.ofNullable(passwordModuleOrder).orElse(0); + public PasswordModuleState getState() { + return passwordModuleState; } @Override - public void setOrder(final int order) { - this.passwordModuleOrder = order; + public void setState(final PasswordModuleState passwordModuleState) { + this.passwordModuleState = passwordModuleState; } @Override diff --git a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml index cafb1e3a382..74f35af051b 100644 --- a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml +++ b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml @@ -93,13 +93,13 @@ under the License. + passwordModuleState="DISABLED"/> + passwordModuleState="DISABLED"/> + passwordModuleState="DISABLED"/> locate(final Environment environment) { properties.putAll(index(map, prefixes)); }); - syncopeClient.getService(PasswordModuleService.class).list().forEach(passwordModuleTO -> { - LOG.debug("Mapping password module {} ", passwordModuleTO.getKey()); + syncopeClient.getService(PasswordModuleService.class).list().stream().filter( + passwordModuleTO -> PasswordModuleState.ACTIVE.equals(passwordModuleTO.getState())) + .findFirst().ifPresent(passwordModuleTO -> { + LOG.debug("Mapping password module {} ", passwordModuleTO.getKey()); - Map map = passwordModuleTO.getConf() - .map(passwordModuleTO, passwordModulePropertySourceMapper); - properties.putAll(index(map, prefixes)); - }); + Map map = passwordModuleTO.getConf() + .map(passwordModuleTO, passwordModulePropertySourceMapper); + properties.putAll(index(map, prefixes)); + }); Set customClaims = syncopeClient.getService(WAClientAppService.class).list().stream(). filter(app -> app.getClientAppTO() instanceof OIDCRPClientAppTO && app.getAttrReleasePolicy() != null). diff --git a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/PasswordModulePropertySourceMapper.java b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/PasswordModulePropertySourceMapper.java index 9ccab749707..884f748856b 100644 --- a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/PasswordModulePropertySourceMapper.java +++ b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/PasswordModulePropertySourceMapper.java @@ -8,6 +8,7 @@ import org.apache.syncope.common.lib.password.PasswordModuleConf; import org.apache.syncope.common.lib.password.SyncopePasswordModuleConf; import org.apache.syncope.common.lib.to.PasswordModuleTO; +import org.apache.syncope.common.lib.types.PasswordModuleState; import org.apache.syncope.wa.bootstrap.WARestClient; import org.apereo.cas.configuration.model.support.ldap.AbstractLdapProperties; import org.apereo.cas.configuration.model.support.pm.JdbcPasswordManagementProperties; @@ -38,7 +39,9 @@ public Map map(final PasswordModuleTO passwordModuleTO, final Sy props.setSearchFilter(conf.getSearchFilter()); props.setHeaders(conf.getHeaders()); - return prefix("cas.authn.pm.syncope.", WAConfUtils.asMap(props)); + Map mappedProps = prefix("cas.authn.pm.syncope.", WAConfUtils.asMap(props)); + mappedProps.put("cas.authn.pm.syncope.enabled", PasswordModuleState.ACTIVE.equals(passwordModuleTO.getState())); + return mappedProps; } @Override @@ -50,7 +53,9 @@ public Map map(final PasswordModuleTO passwordModuleTO, final LD fill(props, conf); - return prefix("cas.authn.pm.ldap[].", WAConfUtils.asMap(props)); + Map mappedProps = prefix("cas.authn.pm.ldap[].", WAConfUtils.asMap(props)); + mappedProps.put("cas.authn.pm.ldap.enabled", PasswordModuleState.ACTIVE.equals(passwordModuleTO.getState())); + return mappedProps; } @Override @@ -66,6 +71,8 @@ public Map map(final PasswordModuleTO passwordModuleTO, final JD props.setSqlUnlockAccount(conf.getSqlUnlockAccount()); fill(props, conf); - return prefix("cas.authn.pm.jdbc.", WAConfUtils.asMap(props)); + Map mappedProps = prefix("cas.authn.pm.jdbc.", WAConfUtils.asMap(props)); + mappedProps.put("cas.authn.pm.jdbc.enabled", PasswordModuleState.ACTIVE.equals(passwordModuleTO.getState())); + return mappedProps; } } diff --git a/wa/starter/pom.xml b/wa/starter/pom.xml index 4af2d473b83..0cfe588d52b 100644 --- a/wa/starter/pom.xml +++ b/wa/starter/pom.xml @@ -169,6 +169,10 @@ under the License. org.apereo.cas cas-server-support-pm-ldap
+ + org.apereo.cas + cas-server-support-pm-jdbc + org.apereo.cas cas-server-support-reports @@ -413,6 +417,12 @@ under the License. + + + org.apereo.cas + cas-server-support-pm-core + + org.pac4j pac4j-oidc @@ -424,15 +434,15 @@ under the License. org.springframework.boot - spring-boot-starter-actuator + spring-boot-starter-security org.springframework.boot - spring-boot-starter-security + spring-boot-starter-validation org.springframework.boot - spring-boot-starter-validation + spring-boot-starter-actuator diff --git a/wa/starter/src/main/java/org/apache/syncope/wa/starter/config/WAContext.java b/wa/starter/src/main/java/org/apache/syncope/wa/starter/config/WAContext.java index 60a58e1c4ba..aef845491a7 100644 --- a/wa/starter/src/main/java/org/apache/syncope/wa/starter/config/WAContext.java +++ b/wa/starter/src/main/java/org/apache/syncope/wa/starter/config/WAContext.java @@ -27,6 +27,8 @@ import java.util.ArrayList; import java.util.List; import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; +import javax.sql.DataSource; import org.apache.commons.lang3.StringUtils; import org.apache.syncope.common.keymaster.client.api.model.NetworkService; import org.apache.syncope.common.keymaster.client.api.startstop.KeymasterStart; @@ -67,13 +69,22 @@ import org.apereo.cas.audit.AuditTrailExecutionPlanConfigurer; import org.apereo.cas.authentication.AuthenticationEventExecutionPlan; import org.apereo.cas.authentication.MultifactorAuthenticationProvider; +import org.apereo.cas.authentication.support.password.PasswordEncoderUtils; import org.apereo.cas.authentication.surrogate.SurrogateAuthenticationService; import org.apereo.cas.configuration.CasConfigurationProperties; import org.apereo.cas.configuration.model.support.mfa.gauth.LdapGoogleAuthenticatorMultifactorProperties; +import org.apereo.cas.configuration.model.support.pm.JdbcPasswordManagementProperties; +import org.apereo.cas.configuration.model.support.pm.LdapPasswordManagementProperties; +import org.apereo.cas.configuration.model.support.pm.PasswordManagementProperties; import org.apereo.cas.gauth.CasGoogleAuthenticator; import org.apereo.cas.gauth.credential.LdapGoogleAuthenticatorTokenCredentialRepository; import org.apereo.cas.oidc.jwks.generator.OidcJsonWebKeystoreGeneratorService; import org.apereo.cas.otp.repository.credentials.OneTimeTokenCredentialRepository; +import org.apereo.cas.pm.LdapPasswordManagementService; +import org.apereo.cas.pm.PasswordHistoryService; +import org.apereo.cas.pm.PasswordManagementService; +import org.apereo.cas.pm.impl.NoOpPasswordManagementService; +import org.apereo.cas.pm.jdbc.JdbcPasswordManagementService; import org.apereo.cas.services.ServiceRegistryExecutionPlanConfigurer; import org.apereo.cas.services.ServiceRegistryListener; import org.apereo.cas.support.events.CasEventRepository; @@ -84,6 +95,7 @@ import org.apereo.cas.support.saml.idp.metadata.generator.SamlIdPMetadataGeneratorConfigurationContext; import org.apereo.cas.support.saml.idp.metadata.locator.SamlIdPMetadataLocator; import org.apereo.cas.support.saml.services.idp.metadata.SamlIdPMetadataDocument; +import org.apereo.cas.syncope.pm.SyncopePasswordManagementService; import org.apereo.cas.trusted.authentication.api.MultifactorAuthenticationTrustRecordKeyGenerator; import org.apereo.cas.trusted.authentication.api.MultifactorAuthenticationTrustStorage; import org.apereo.cas.util.LdapUtils; @@ -105,7 +117,9 @@ 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.crypto.password.PasswordEncoder; import org.springframework.security.provisioning.InMemoryUserDetailsManager; +import org.springframework.transaction.support.TransactionOperations; @Configuration(proxyBeanMethods = false) public class WAContext { @@ -337,6 +351,103 @@ public OneTimeTokenCredentialRepository googleAuthenticatorAccountRegistry( return new WAGoogleMfaAuthCredentialRepository(waRestClient, googleAuthenticatorInstance); } + @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) + @Bean + public PasswordManagementService syncopePasswordChangeService( + final CasConfigurationProperties casProperties, + @Qualifier("passwordManagementCipherExecutor") + final CipherExecutor passwordManagementCipherExecutor, + @Qualifier(PasswordHistoryService.BEAN_NAME) + final PasswordHistoryService passwordHistoryService) { + PasswordManagementProperties pm = casProperties.getAuthn().getPm(); + if (pm.getCore().isEnabled() && pm.getSyncope().isDefined()) { + return new SyncopePasswordManagementService( + passwordManagementCipherExecutor, + casProperties, + passwordHistoryService); + } + return new NoOpPasswordManagementService(passwordManagementCipherExecutor, casProperties); + } + + @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) + @Bean + public PasswordManagementService ldapPasswordChangeService( + final CasConfigurationProperties casProperties, + @Qualifier("passwordManagementCipherExecutor") + final CipherExecutor passwordManagementCipherExecutor, + @Qualifier(PasswordHistoryService.BEAN_NAME) + final PasswordHistoryService passwordHistoryService) { + List ldaps = casProperties.getAuthn().getPm().getLdap(); + if (!ldaps.isEmpty() && StringUtils.isNotBlank(ldaps.get(0).getLdapUrl())) { + ConcurrentHashMap connectionFactoryMap = + new ConcurrentHashMap(); + ldaps.forEach(ldap -> connectionFactoryMap.put( + ldap.getLdapUrl(), + LdapUtils.newLdaptiveConnectionFactory(ldap))); + return new LdapPasswordManagementService(passwordManagementCipherExecutor, casProperties, + passwordHistoryService, connectionFactoryMap); + } + return new NoOpPasswordManagementService(passwordManagementCipherExecutor, casProperties); + } + + @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) + @Bean + public PasswordManagementService jdbcPasswordChangeService( + final CasConfigurationProperties casProperties, + final ConfigurableApplicationContext applicationContext, + @Qualifier("jdbcPasswordManagementDataSource") + final DataSource jdbcPasswordManagementDataSource, + @Qualifier("jdbcPasswordManagementTransactionTemplate") + final TransactionOperations jdbcPasswordManagementTransactionTemplate, + @Qualifier("passwordManagementCipherExecutor") + final CipherExecutor passwordManagementCipherExecutor, + @Qualifier(PasswordHistoryService.BEAN_NAME) + final PasswordHistoryService passwordHistoryService) { + JdbcPasswordManagementProperties jdbc = casProperties.getAuthn().getPm().getJdbc(); + if (StringUtils.isNotBlank(jdbc.getUrl())) { + PasswordEncoder encoder = PasswordEncoderUtils.newPasswordEncoder( + casProperties.getAuthn().getPm().getJdbc().getPasswordEncoder(), applicationContext); + return new JdbcPasswordManagementService(passwordManagementCipherExecutor, + casProperties, jdbcPasswordManagementDataSource, + jdbcPasswordManagementTransactionTemplate, passwordHistoryService, encoder); + } + return new NoOpPasswordManagementService(passwordManagementCipherExecutor, casProperties); + } + + @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) + @Bean + public PasswordManagementService passwordChangeService( + final ConfigurableApplicationContext applicationContext, + final CasConfigurationProperties casProperties, + @Qualifier("passwordManagementCipherExecutor") + final CipherExecutor passwordManagementCipherExecutor, + @Qualifier(PasswordHistoryService.BEAN_NAME) + final PasswordHistoryService passwordHistoryService, + @Qualifier("syncopePasswordChangeService") + final PasswordManagementService syncopePasswordManagementService, + @Qualifier("ldapPasswordChangeService") + final PasswordManagementService ldapPasswordManagementService, + @Qualifier("jdbcPasswordChangeService") + final PasswordManagementService jdbcPasswordManagementService) { + + if (applicationContext.getEnvironment() + .getProperty("cas.authn.pm.syncope.enabled", Boolean.class, Boolean.FALSE)) { + return syncopePasswordManagementService; + } + + if (applicationContext.getEnvironment() + .getProperty("cas.authn.pm.ldap.enabled", Boolean.class, Boolean.FALSE)) { + return ldapPasswordManagementService; + } + + if (applicationContext.getEnvironment() + .getProperty("cas.authn.pm.jdbc.enabled", Boolean.class, Boolean.FALSE)) { + return jdbcPasswordManagementService; + } + + return new NoOpPasswordManagementService(passwordManagementCipherExecutor, casProperties); + } + @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) @Bean(name = MultifactorAuthenticationTrustStorage.BEAN_NAME) public MultifactorAuthenticationTrustStorage mfaTrustStorage( diff --git a/wa/starter/src/main/resources/wa.properties b/wa/starter/src/main/resources/wa.properties index 2d68caa19b7..666db9b8f1b 100644 --- a/wa/starter/src/main/resources/wa.properties +++ b/wa/starter/src/main/resources/wa.properties @@ -37,7 +37,7 @@ spring.web.resources.static-locations=classpath:/thymeleaf/static,classpath:/syn cas.monitor.endpoints.endpoint.defaults.access=AUTHENTICATED management.endpoints.access.default=UNRESTRICTED -management.endpoints.web.exposure.include=info,health,env,beans,loggers,ssoSessions,registeredServices,refresh,authenticationHandlers,authenticationPolicies,resolveAttributes +management.endpoints.web.exposure.include=info,health,env,loggers,ssoSessions,registeredServices,refresh,authenticationHandlers,authenticationPolicies,resolveAttributes management.endpoint.health.show-details=ALWAYS management.endpoint.env.show-values=WHEN_AUTHORIZED spring.cloud.discovery.client.health-indicator.enabled=false @@ -139,3 +139,9 @@ management.metrics.enable.system.cpu=true management.metrics.enable.process.cpu=true management.metrics.enable.process.uptime=true management.metrics.enable.process.start.time=true + +## +# Spring Boot Actuator Database Health Check Configuration +management.health.db.enabled=false + + From e7ef873ac8ea46cef08a68215191be916a0ee674 Mon Sep 17 00:00:00 2001 From: alberto bogi Date: Fri, 29 Aug 2025 15:02:12 +0200 Subject: [PATCH 10/20] [SYNCOPE-1901] Fix PasswordModuleState for Neo4j persistence --- .../syncope/common/lib/to/PasswordModuleTO.java | 2 ++ .../jpa/dao/repo/PasswordModuleRepoExtImpl.java | 6 ++++-- .../src/test/resources/domains/MasterContent.xml | 2 +- .../neo4j/entity/am/Neo4jPasswordModule.java | 11 +++++++---- .../src/test/resources/domains/MasterContent.xml | 6 +++--- .../syncope/fit/core/PasswordModuleITCase.java | 12 ++++++------ 6 files changed, 23 insertions(+), 16 deletions(-) diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/to/PasswordModuleTO.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/to/PasswordModuleTO.java index d9004e985da..ee5ac3f9f85 100644 --- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/to/PasswordModuleTO.java +++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/to/PasswordModuleTO.java @@ -10,6 +10,8 @@ public class PasswordModuleTO implements EntityTO { + private static final long serialVersionUID = -7203295929825782174L; + private String key; private String description; diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordModuleRepoExtImpl.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordModuleRepoExtImpl.java index 9d9ef269c56..40ba8dcd722 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordModuleRepoExtImpl.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordModuleRepoExtImpl.java @@ -13,12 +13,14 @@ public PasswordModuleRepoExtImpl(final EntityManager entityManager) { } - @Override public PasswordModule save(final PasswordModule passwordModule) { + @Override + public PasswordModule save(final PasswordModule passwordModule) { ((JPAPasswordModule) passwordModule).list2json(); return entityManager.merge(passwordModule); } - @Override public void delete(final PasswordModule passwordModule) { + @Override + public void delete(final PasswordModule passwordModule) { entityManager.remove(passwordModule); } } diff --git a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml index 74f35af051b..79001acd749 100644 --- a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml +++ b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml @@ -93,7 +93,7 @@ under the License. + passwordModuleState="ACTIVE"/> diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4jPasswordModule.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4jPasswordModule.java index c6675be8bef..d2769b0ce1e 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4jPasswordModule.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4jPasswordModule.java @@ -17,6 +17,7 @@ @Node(Neo4jPasswordModule.NODE) public class Neo4jPasswordModule extends AbstractProvidedKeyNode implements PasswordModule { + private static final long serialVersionUID = 5457779846065079998L; public static final String NODE = "PasswordModule"; @@ -26,7 +27,7 @@ public class Neo4jPasswordModule extends AbstractProvidedKeyNode implements Pass private String description; - @NotNull + @NotNull(message = "passwordModuleState must not be empty") private PasswordModuleState passwordModuleState; private String items; @@ -46,12 +47,14 @@ public void setDescription(final String description) { this.description = description; } - @Override public PasswordModuleState getState() { + @Override + public PasswordModuleState getState() { return passwordModuleState; } - @Override public void setState(final PasswordModuleState state) { - this.passwordModuleState = passwordModuleState; + @Override + public void setState(final PasswordModuleState state) { + this.passwordModuleState = state; } @Override diff --git a/core/persistence-neo4j/src/test/resources/domains/MasterContent.xml b/core/persistence-neo4j/src/test/resources/domains/MasterContent.xml index 13ae8916c5a..7579bf9cb9f 100644 --- a/core/persistence-neo4j/src/test/resources/domains/MasterContent.xml +++ b/core/persistence-neo4j/src/test/resources/domains/MasterContent.xml @@ -93,13 +93,13 @@ under the License. + passwordModuleState="ACTIVE"/> + passwordModuleState="DISABLED"/> + passwordModuleState="DISABLED"/> { - PasswordModuleTO passwordModuleTO = createAuthModule(buildPasswordModuleTO(type)); + PasswordModuleTO passwordModuleTO = createPasswordModule(buildPasswordModuleTO(type)); assertNotNull(passwordModuleTO); assertTrue(passwordModuleTO.getDescription().contains("A test " + type + " Password Module")); assertTrue(passwordModuleTO.getItems().isEmpty()); @@ -148,7 +148,7 @@ public void updateSyncopePasswordModule() { assertNotNull(syncopePasswordModuleTO); PasswordModuleTO newSyncopePasswordModuleTO = buildPasswordModuleTO(PasswordModuleSupportedType.SYNCOPE); - newSyncopePasswordModuleTO = createAuthModule(newSyncopePasswordModuleTO); + newSyncopePasswordModuleTO = createPasswordModule(newSyncopePasswordModuleTO); assertNotNull(newSyncopePasswordModuleTO); PasswordModuleConf conf = syncopePasswordModuleTO.getConf(); @@ -171,7 +171,7 @@ public void updateLdapPasswordModule() { assertNotNull(ldapPasswordModuleTO); PasswordModuleTO newLdapPasswordModuleTO = buildPasswordModuleTO(PasswordModuleSupportedType.LDAP); - newLdapPasswordModuleTO = createAuthModule(newLdapPasswordModuleTO); + newLdapPasswordModuleTO = createPasswordModule(newLdapPasswordModuleTO); assertNotNull(newLdapPasswordModuleTO); PasswordModuleConf conf = ldapPasswordModuleTO.getConf(); @@ -194,7 +194,7 @@ public void updateJdbcPasswordModule() { assertNotNull(jdbcPasswordModuleTO); PasswordModuleTO newJdbcPasswordModuleTO = buildPasswordModuleTO(PasswordModuleSupportedType.JDBC); - newJdbcPasswordModuleTO = createAuthModule(newJdbcPasswordModuleTO); + newJdbcPasswordModuleTO = createPasswordModule(newJdbcPasswordModuleTO); assertNotNull(newJdbcPasswordModuleTO); PasswordModuleConf conf = jdbcPasswordModuleTO.getConf(); @@ -215,7 +215,7 @@ public void updateJdbcPasswordModule() { @Test public void delete() throws IOException { EnumSet.allOf(PasswordModuleSupportedType.class).forEach(type -> { - PasswordModuleTO read = createAuthModule(buildPasswordModuleTO(type)); + PasswordModuleTO read = createPasswordModule(buildPasswordModuleTO(type)); assertNotNull(read); PASSWORD_MODULE_SERVICE.delete(read.getKey()); From d634cc7f2b4deebd4b7aee4623b5cc6ebc727556 Mon Sep 17 00:00:00 2001 From: alberto bogi Date: Tue, 2 Sep 2025 12:14:05 +0200 Subject: [PATCH 11/20] [SYNCOPE-1901] Refactoring PasswordModule to PasswordManagement --- .../client/console/AMConsoleContext.java | 6 +- ...lassPathScanImplementationContributor.java | 8 +- .../syncope/client/console/pages/WA.java | 12 +- ... => PasswordManagementDirectoryPanel.java} | 80 +++--- .../rest/PasswordManagementRestClient.java | 30 +++ .../rest/PasswordModuleRestClient.java | 30 --- ...a => PasswordManagementWizardBuilder.java} | 87 +++---- .../client/console/pages/WA.properties | 2 +- .../client/console/pages/WA_fr_CA.properties | 2 +- .../client/console/pages/WA_it.properties | 2 +- .../client/console/pages/WA_ja.properties | 2 +- .../client/console/pages/WA_pt_BR.properties | 2 +- .../client/console/pages/WA_ru.properties | 2 +- ...sswordManagementDirectoryPanel.properties} | 2 +- ...ordManagementDirectoryPanel_fr.properties} | 2 +- ...ManagementDirectoryPanel_fr_CA.properties} | 2 +- ...ordManagementDirectoryPanel_it.properties} | 2 +- ...ordManagementDirectoryPanel_ja.properties} | 2 +- ...dManagementDirectoryPanel_pt_BR.properties | 8 + ...wordManagementDirectoryPanel_ru.properties | 8 + ...swordModuleDirectoryPanel_pt_BR.properties | 8 - ...PasswordModuleDirectoryPanel_ru.properties | 8 - .../AuthModuleWizardBuilder$Profile.html | 2 +- ...anagementWizardBuilder$Configuration.html} | 0 ...entWizardBuilder$Configuration.properties} | 0 ...WizardBuilder$Configuration_fr.properties} | 0 ...ardBuilder$Configuration_fr_CA.properties} | 0 ...WizardBuilder$Configuration_it.properties} | 0 ...WizardBuilder$Configuration_ja.properties} | 0 ...ardBuilder$Configuration_pt_BR.properties} | 0 ...WizardBuilder$Configuration_ru.properties} | 0 ...swordManagementWizardBuilder$Profile.html} | 2 +- ...anagementWizardBuilder$Profile.properties} | 0 ...gementWizardBuilder$Profile_fr.properties} | 0 ...entWizardBuilder$Profile_fr_CA.properties} | 0 ...gementWizardBuilder$Profile_it.properties} | 0 ...gementWizardBuilder$Profile_ja.properties} | 0 ...entWizardBuilder$Profile_pt_BR.properties} | 0 ...gementWizardBuilder$Profile_ru.properties} | 0 ...f.java => JDBCPasswordManagementConf.java} | 8 +- ...f.java => LDAPPasswordManagementConf.java} | 8 +- .../lib/password/PasswordManagementConf.java | 23 ++ .../lib/password/PasswordModuleConf.java | 23 -- ...ava => SyncopePasswordManagementConf.java} | 8 +- ...oduleTO.java => PasswordManagementTO.java} | 38 +-- .../common/lib/types/AMEntitlement.java | 10 +- ...tate.java => PasswordManagementState.java} | 2 +- ...ce.java => PasswordManagementService.java} | 24 +- .../syncope/core/logic/AMLogicContext.java | 12 +- .../core/logic/PasswordManagementLogic.java | 96 ++++++++ .../core/logic/PasswordModuleLogic.java | 96 -------- .../core/rest/cxf/AMRESTCXFContext.java | 10 +- .../PasswordManagementServiceImpl.java | 47 ++++ .../service/PasswordModuleServiceImpl.java | 47 ---- ...uleDAO.java => PasswordManagementDAO.java} | 4 +- .../api/entity/am/PasswordModule.java | 24 -- .../persistence/jpa/PersistenceContext.java | 18 +- .../jpa/dao/repo/PasswordManagementRepo.java | 10 + .../dao/repo/PasswordManagementRepoExt.java | 10 + .../repo/PasswordManagementRepoExtImpl.java | 26 ++ .../jpa/dao/repo/PasswordModuleRepo.java | 10 - .../jpa/dao/repo/PasswordModuleRepoExt.java | 10 - .../dao/repo/PasswordModuleRepoExtImpl.java | 26 -- .../jpa/entity/AbstractEntityFactory.java | 8 +- ...Module.java => JPAPasswordManagement.java} | 33 ++- .../jpa/inner/PasswordManagementTest.java | 187 ++++++++++++++ .../jpa/inner/PasswordModuleTest.java | 187 -------------- .../test/resources/domains/MasterContent.xml | 18 +- .../persistence/neo4j/PersistenceContext.java | 18 +- .../dao/repo/PasswordManagementRepo.java | 9 + .../dao/repo/PasswordManagementRepoExt.java | 10 + .../repo/PasswordManagementRepoExtImpl.java | 33 +++ .../neo4j/dao/repo/PasswordModuleRepo.java | 9 - .../neo4j/dao/repo/PasswordModuleRepoExt.java | 10 - .../dao/repo/PasswordModuleRepoExtImpl.java | 33 --- .../neo4j/entity/Neo4jEntityFactory.java | 8 +- ...dule.java => Neo4JPasswordManagement.java} | 31 ++- .../neo4j/inner/PasswordManagementTest.java | 187 ++++++++++++++ .../neo4j/inner/PasswordModuleTest.java | 186 -------------- .../test/resources/domains/MasterContent.xml | 18 +- .../data/PasswordManagementDataBinder.java | 13 + .../api/data/PasswordModuleDataBinder.java | 13 - .../java/ProvisioningContext.java | 8 +- .../PasswordManagementDataBinderImpl.java | 119 +++++++++ .../data/PasswordModuleDataBinderImpl.java | 119 --------- .../apache/syncope/fit/AbstractITCase.java | 6 +- .../fit/core/PasswordManagementITCase.java | 233 ++++++++++++++++++ .../fit/core/PasswordModuleITCase.java | 231 ----------------- .../bootstrap/WABootstrapConfiguration.java | 12 +- .../wa/bootstrap/WAPropertySourceLocator.java | 25 +- ...sswordManagementPropertySourceMapper.java} | 30 +-- 91 files changed, 1331 insertions(+), 1364 deletions(-) rename client/am/console/src/main/java/org/apache/syncope/client/console/panels/{PasswordModuleDirectoryPanel.java => PasswordManagementDirectoryPanel.java} (71%) create mode 100644 client/am/console/src/main/java/org/apache/syncope/client/console/rest/PasswordManagementRestClient.java delete mode 100644 client/am/console/src/main/java/org/apache/syncope/client/console/rest/PasswordModuleRestClient.java rename client/am/console/src/main/java/org/apache/syncope/client/console/wizards/{PasswordModuleWizardBuilder.java => PasswordManagementWizardBuilder.java} (53%) rename client/am/console/src/main/resources/org/apache/syncope/client/console/panels/{PasswordModuleDirectoryPanel_fr.properties => PasswordManagementDirectoryPanel.properties} (84%) rename client/am/console/src/main/resources/org/apache/syncope/client/console/panels/{PasswordModuleDirectoryPanel_fr_CA.properties => PasswordManagementDirectoryPanel_fr.properties} (84%) rename client/am/console/src/main/resources/org/apache/syncope/client/console/panels/{PasswordModuleDirectoryPanel_ja.properties => PasswordManagementDirectoryPanel_fr_CA.properties} (84%) rename client/am/console/src/main/resources/org/apache/syncope/client/console/panels/{PasswordModuleDirectoryPanel_it.properties => PasswordManagementDirectoryPanel_it.properties} (83%) rename client/am/console/src/main/resources/org/apache/syncope/client/console/panels/{PasswordModuleDirectoryPanel.properties => PasswordManagementDirectoryPanel_ja.properties} (84%) create mode 100644 client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_pt_BR.properties create mode 100644 client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_ru.properties delete mode 100644 client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_pt_BR.properties delete mode 100644 client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_ru.properties rename client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/{PasswordModuleWizardBuilder$Configuration.html => PasswordManagementWizardBuilder$Configuration.html} (100%) rename client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/{PasswordModuleWizardBuilder$Configuration.properties => PasswordManagementWizardBuilder$Configuration.properties} (100%) rename client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/{PasswordModuleWizardBuilder$Configuration_fr.properties => PasswordManagementWizardBuilder$Configuration_fr.properties} (100%) rename client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/{PasswordModuleWizardBuilder$Configuration_fr_CA.properties => PasswordManagementWizardBuilder$Configuration_fr_CA.properties} (100%) rename client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/{PasswordModuleWizardBuilder$Configuration_it.properties => PasswordManagementWizardBuilder$Configuration_it.properties} (100%) rename client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/{PasswordModuleWizardBuilder$Configuration_ja.properties => PasswordManagementWizardBuilder$Configuration_ja.properties} (100%) rename client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/{PasswordModuleWizardBuilder$Configuration_pt_BR.properties => PasswordManagementWizardBuilder$Configuration_pt_BR.properties} (100%) rename client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/{PasswordModuleWizardBuilder$Configuration_ru.properties => PasswordManagementWizardBuilder$Configuration_ru.properties} (100%) rename client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/{PasswordModuleWizardBuilder$Profile.html => PasswordManagementWizardBuilder$Profile.html} (81%) rename client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/{PasswordModuleWizardBuilder$Profile.properties => PasswordManagementWizardBuilder$Profile.properties} (100%) rename client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/{PasswordModuleWizardBuilder$Profile_fr.properties => PasswordManagementWizardBuilder$Profile_fr.properties} (100%) rename client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/{PasswordModuleWizardBuilder$Profile_fr_CA.properties => PasswordManagementWizardBuilder$Profile_fr_CA.properties} (100%) rename client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/{PasswordModuleWizardBuilder$Profile_it.properties => PasswordManagementWizardBuilder$Profile_it.properties} (100%) rename client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/{PasswordModuleWizardBuilder$Profile_ja.properties => PasswordManagementWizardBuilder$Profile_ja.properties} (100%) rename client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/{PasswordModuleWizardBuilder$Profile_pt_BR.properties => PasswordManagementWizardBuilder$Profile_pt_BR.properties} (100%) rename client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/{PasswordModuleWizardBuilder$Profile_ru.properties => PasswordManagementWizardBuilder$Profile_ru.properties} (100%) rename common/am/lib/src/main/java/org/apache/syncope/common/lib/password/{JDBCPasswordModuleConf.java => JDBCPasswordManagementConf.java} (89%) rename common/am/lib/src/main/java/org/apache/syncope/common/lib/password/{LDAPPasswordModuleConf.java => LDAPPasswordManagementConf.java} (57%) create mode 100644 common/am/lib/src/main/java/org/apache/syncope/common/lib/password/PasswordManagementConf.java delete mode 100644 common/am/lib/src/main/java/org/apache/syncope/common/lib/password/PasswordModuleConf.java rename common/am/lib/src/main/java/org/apache/syncope/common/lib/password/{SyncopePasswordModuleConf.java => SyncopePasswordManagementConf.java} (85%) rename common/am/lib/src/main/java/org/apache/syncope/common/lib/to/{PasswordModuleTO.java => PasswordManagementTO.java} (64%) rename common/am/lib/src/main/java/org/apache/syncope/common/lib/types/{PasswordModuleState.java => PasswordManagementState.java} (89%) rename common/am/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/{PasswordModuleService.java => PasswordManagementService.java} (81%) create mode 100644 core/am/logic/src/main/java/org/apache/syncope/core/logic/PasswordManagementLogic.java delete mode 100644 core/am/logic/src/main/java/org/apache/syncope/core/logic/PasswordModuleLogic.java create mode 100644 core/am/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/PasswordManagementServiceImpl.java delete mode 100644 core/am/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/PasswordModuleServiceImpl.java rename core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/{PasswordModuleDAO.java => PasswordManagementDAO.java} (58%) delete mode 100644 core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/am/PasswordModule.java create mode 100644 core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordManagementRepo.java create mode 100644 core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordManagementRepoExt.java create mode 100644 core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordManagementRepoExtImpl.java delete mode 100644 core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordModuleRepo.java delete mode 100644 core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordModuleRepoExt.java delete mode 100644 core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordModuleRepoExtImpl.java rename core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/am/{JPAPasswordModule.java => JPAPasswordManagement.java} (73%) create mode 100644 core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PasswordManagementTest.java delete mode 100644 core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PasswordModuleTest.java create mode 100644 core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/PasswordManagementRepo.java create mode 100644 core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/PasswordManagementRepoExt.java create mode 100644 core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/PasswordManagementRepoExtImpl.java delete mode 100644 core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/PasswordModuleRepo.java delete mode 100644 core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/PasswordModuleRepoExt.java delete mode 100644 core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/PasswordModuleRepoExtImpl.java rename core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/{Neo4jPasswordModule.java => Neo4JPasswordManagement.java} (70%) create mode 100644 core/persistence-neo4j/src/test/java/org/apache/syncope/core/persistence/neo4j/inner/PasswordManagementTest.java delete mode 100644 core/persistence-neo4j/src/test/java/org/apache/syncope/core/persistence/neo4j/inner/PasswordModuleTest.java create mode 100644 core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/PasswordManagementDataBinder.java delete mode 100644 core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/PasswordModuleDataBinder.java create mode 100644 core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/PasswordManagementDataBinderImpl.java delete mode 100644 core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/PasswordModuleDataBinderImpl.java create mode 100644 fit/core-reference/src/test/java/org/apache/syncope/fit/core/PasswordManagementITCase.java delete mode 100644 fit/core-reference/src/test/java/org/apache/syncope/fit/core/PasswordModuleITCase.java rename wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/{PasswordModulePropertySourceMapper.java => PasswordManagementPropertySourceMapper.java} (67%) diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/AMConsoleContext.java b/client/am/console/src/main/java/org/apache/syncope/client/console/AMConsoleContext.java index a7cc623ac4a..2766573414d 100644 --- a/client/am/console/src/main/java/org/apache/syncope/client/console/AMConsoleContext.java +++ b/client/am/console/src/main/java/org/apache/syncope/client/console/AMConsoleContext.java @@ -31,7 +31,7 @@ import org.apache.syncope.client.console.rest.AuthProfileRestClient; import org.apache.syncope.client.console.rest.ClientAppRestClient; import org.apache.syncope.client.console.rest.OIDCJWKSRestClient; -import org.apache.syncope.client.console.rest.PasswordModuleRestClient; +import org.apache.syncope.client.console.rest.PasswordManagementRestClient; import org.apache.syncope.client.console.rest.PolicyRestClient; import org.apache.syncope.client.console.rest.SAML2IdPEntityRestClient; import org.apache.syncope.client.console.rest.SRARouteRestClient; @@ -78,8 +78,8 @@ public AuthModuleRestClient authModuleRestClient() { @ConditionalOnMissingBean @Bean - public PasswordModuleRestClient passwordModuleRestClient() { - return new PasswordModuleRestClient(); + public PasswordManagementRestClient passwordManagementRestClient() { + return new PasswordManagementRestClient(); } @ConditionalOnMissingBean diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/init/AMClassPathScanImplementationContributor.java b/client/am/console/src/main/java/org/apache/syncope/client/console/init/AMClassPathScanImplementationContributor.java index 2b0a59a919c..d945603db84 100644 --- a/client/am/console/src/main/java/org/apache/syncope/client/console/init/AMClassPathScanImplementationContributor.java +++ b/client/am/console/src/main/java/org/apache/syncope/client/console/init/AMClassPathScanImplementationContributor.java @@ -22,7 +22,7 @@ import org.apache.syncope.common.lib.attr.AttrRepoConf; import org.apache.syncope.common.lib.auth.AuthModuleConf; import org.apache.syncope.common.lib.clientapps.UsernameAttributeProviderConf; -import org.apache.syncope.common.lib.password.PasswordModuleConf; +import org.apache.syncope.common.lib.password.PasswordManagementConf; import org.apache.syncope.common.lib.policy.AccessPolicyConf; import org.apache.syncope.common.lib.policy.AttrReleasePolicyConf; import org.apache.syncope.common.lib.policy.AuthPolicyConf; @@ -36,7 +36,7 @@ public class AMClassPathScanImplementationContributor implements ClassPathScanIm @Override public void extend(final ClassPathScanningCandidateComponentProvider scanner) { scanner.addIncludeFilter(new AssignableTypeFilter(AuthModuleConf.class)); - scanner.addIncludeFilter(new AssignableTypeFilter(PasswordModuleConf.class)); + scanner.addIncludeFilter(new AssignableTypeFilter(PasswordManagementConf.class)); scanner.addIncludeFilter(new AssignableTypeFilter(AttrRepoConf.class)); scanner.addIncludeFilter(new AssignableTypeFilter(AccessPolicyConf.class)); scanner.addIncludeFilter(new AssignableTypeFilter(AttrReleasePolicyConf.class)); @@ -49,8 +49,8 @@ public Optional getLabel(final Class clazz) { if (AuthModuleConf.class.isAssignableFrom(clazz)) { return Optional.of(AuthModuleConf.class.getName()); } - if (PasswordModuleConf.class.isAssignableFrom(clazz)) { - return Optional.of(PasswordModuleConf.class.getName()); + if (PasswordManagementConf.class.isAssignableFrom(clazz)) { + return Optional.of(PasswordManagementConf.class.getName()); } if (AttrRepoConf.class.isAssignableFrom(clazz)) { return Optional.of(AttrRepoConf.class.getName()); diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/pages/WA.java b/client/am/console/src/main/java/org/apache/syncope/client/console/pages/WA.java index 8101ee3c9b6..949321f0988 100644 --- a/client/am/console/src/main/java/org/apache/syncope/client/console/pages/WA.java +++ b/client/am/console/src/main/java/org/apache/syncope/client/console/pages/WA.java @@ -39,14 +39,14 @@ import org.apache.syncope.client.console.panels.AttrRepoDirectoryPanel; import org.apache.syncope.client.console.panels.AuthModuleDirectoryPanel; import org.apache.syncope.client.console.panels.OIDC; -import org.apache.syncope.client.console.panels.PasswordModuleDirectoryPanel; +import org.apache.syncope.client.console.panels.PasswordManagementDirectoryPanel; import org.apache.syncope.client.console.panels.SAML2IdPEntityDirectoryPanel; import org.apache.syncope.client.console.panels.WAConfigDirectoryPanel; import org.apache.syncope.client.console.panels.WAPushModalPanel; import org.apache.syncope.client.console.rest.AttrRepoRestClient; import org.apache.syncope.client.console.rest.AuthModuleRestClient; import org.apache.syncope.client.console.rest.AuthProfileRestClient; -import org.apache.syncope.client.console.rest.PasswordModuleRestClient; +import org.apache.syncope.client.console.rest.PasswordManagementRestClient; import org.apache.syncope.client.console.rest.SAML2IdPEntityRestClient; import org.apache.syncope.client.console.rest.WAConfigRestClient; import org.apache.syncope.client.console.rest.WASessionRestClient; @@ -84,7 +84,7 @@ public class WA extends BasePage { protected AuthModuleRestClient authModuleRestClient; @SpringBean - protected PasswordModuleRestClient passwordModuleRestClient; + protected PasswordManagementRestClient passwordManagementRestClient; @SpringBean protected AttrRepoRestClient attrRepoRestClient; @@ -184,14 +184,14 @@ public Panel getPanel(final String panelId) { }); } - if (SyncopeConsoleSession.get().owns(AMEntitlement.PASSWORD_MODULE_LIST)) { - tabs.add(new AbstractTab(new ResourceModel("passwordModules")) { + if (SyncopeConsoleSession.get().owns(AMEntitlement.PASSWORD_MANAGEMENT_LIST)) { + tabs.add(new AbstractTab(new ResourceModel("passwordManagements")) { private static final long serialVersionUID = 5211692813425391144L; @Override public Panel getPanel(final String panelId) { - return new PasswordModuleDirectoryPanel(panelId, passwordModuleRestClient, getPageReference()); + return new PasswordManagementDirectoryPanel(panelId, passwordManagementRestClient, getPageReference()); } }); } diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel.java b/client/am/console/src/main/java/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel.java similarity index 71% rename from client/am/console/src/main/java/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel.java rename to client/am/console/src/main/java/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel.java index 036d93d527b..ec686811846 100644 --- a/client/am/console/src/main/java/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel.java +++ b/client/am/console/src/main/java/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel.java @@ -14,15 +14,16 @@ import org.apache.syncope.client.console.commons.SortableDataProviderComparator; import org.apache.syncope.client.console.pages.BasePage; import org.apache.syncope.client.console.rest.AuditRestClient; -import org.apache.syncope.client.console.rest.PasswordModuleRestClient; +import org.apache.syncope.client.console.rest.PasswordManagementRestClient; +import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.BooleanPropertyColumn; import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal; import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink; import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel; -import org.apache.syncope.client.console.wizards.PasswordModuleWizardBuilder; +import org.apache.syncope.client.console.wizards.PasswordManagementWizardBuilder; import org.apache.syncope.client.ui.commons.Constants; import org.apache.syncope.client.ui.commons.pages.BaseWebPage; import org.apache.syncope.client.ui.commons.wizards.AjaxWizard; -import org.apache.syncope.common.lib.to.PasswordModuleTO; +import org.apache.syncope.common.lib.to.PasswordManagementTO; import org.apache.syncope.common.lib.types.AMEntitlement; import org.apache.syncope.common.lib.types.IdRepoEntitlement; import org.apache.syncope.common.lib.types.OpEvent; @@ -42,11 +43,7 @@ import org.apache.wicket.model.StringResourceModel; import org.apache.wicket.spring.injection.annot.SpringBean; -public class PasswordModuleDirectoryPanel extends DirectoryPanel< - PasswordModuleTO, - PasswordModuleTO, - PasswordModuleDirectoryPanel.PasswordModuleProvider, - PasswordModuleRestClient> { +public class PasswordManagementDirectoryPanel extends DirectoryPanel { private static final long serialVersionUID = 1005345990563741296L; @SpringBean @@ -54,16 +51,16 @@ public class PasswordModuleDirectoryPanel extends DirectoryPanel< protected final BaseModal historyModal; - public PasswordModuleDirectoryPanel( + public PasswordManagementDirectoryPanel( final String id, - final PasswordModuleRestClient restClient, + final PasswordManagementRestClient restClient, final PageReference pageRef) { super(id, restClient, pageRef); disableCheckBoxes(); - addNewItemPanelBuilder(new PasswordModuleWizardBuilder(new PasswordModuleTO(), restClient, pageRef), true); + addNewItemPanelBuilder(new PasswordManagementWizardBuilder(new PasswordManagementTO(), restClient, pageRef), true); MetaDataRoleAuthorizationStrategy.authorize(addAjaxLink, RENDER, AMEntitlement.AUTH_MODULE_CREATE); @@ -76,8 +73,8 @@ public PasswordModuleDirectoryPanel( } @Override - protected PasswordModuleProvider dataProvider() { - return new PasswordModuleProvider(rows); + protected PasswordManagementProvider dataProvider() { + return new PasswordManagementProvider(rows); } @Override @@ -91,8 +88,8 @@ protected Collection getBatches() { } @Override - protected List> getColumns() { - List> columns = new ArrayList<>(); + protected List> getColumns() { + List> columns = new ArrayList<>(); columns.add(new PropertyColumn<>( new StringResourceModel(Constants.KEY_FIELD_NAME, this), Constants.KEY_FIELD_NAME, Constants.KEY_FIELD_NAME)); @@ -104,48 +101,51 @@ protected List> getColumns() { @Override public void populateItem( - final Item> item, + final Item> item, final String componentId, - final IModel rowModel) { + final IModel rowModel) { item.add(new Label(componentId, rowModel.getObject().getConf() == null ? StringUtils.EMPTY : StringUtils.substringBefore( - rowModel.getObject().getConf().getClass().getSimpleName(), "PasswordModuleConf"))); + rowModel.getObject().getConf().getClass().getSimpleName(), "PasswordManagementConf"))); } }); - columns.add(new PropertyColumn<>(new ResourceModel("state"), "state", "state")); + columns.add(new BooleanPropertyColumn<>( + new StringResourceModel("enabled", this), + "enabled", + "enabled")); return columns; } @Override - public ActionsPanel getActions(final IModel model) { - ActionsPanel panel = super.getActions(model); + public ActionsPanel getActions(final IModel model) { + ActionsPanel panel = super.getActions(model); panel.add(new ActionLink<>() { private static final long serialVersionUID = -3722207913631435501L; @Override - public void onClick(final AjaxRequestTarget target, final PasswordModuleTO ignore) { - send(PasswordModuleDirectoryPanel.this, Broadcast.EXACT, new AjaxWizard.EditItemActionEvent<>( + public void onClick(final AjaxRequestTarget target, final PasswordManagementTO ignore) { + send(PasswordManagementDirectoryPanel.this, Broadcast.EXACT, new AjaxWizard.EditItemActionEvent<>( restClient.read(model.getObject().getKey()), target)); } - }, ActionLink.ActionType.EDIT, AMEntitlement.PASSWORD_MODULE_UPDATE); + }, ActionLink.ActionType.EDIT, AMEntitlement.PASSWORD_MANAGEMENT_UPDATE); panel.add(new ActionLink<>() { private static final long serialVersionUID = -5432034353017728756L; @Override - public void onClick(final AjaxRequestTarget target, final PasswordModuleTO ignore) { + public void onClick(final AjaxRequestTarget target, final PasswordManagementTO ignore) { model.setObject(restClient.read(model.getObject().getKey())); target.add(historyModal.setContent(new AuditHistoryModal<>( OpEvent.CategoryType.LOGIC, - "PasswordModuleLogic", + "PasswordManagementLogic", model.getObject(), - AMEntitlement.PASSWORD_MODULE_UPDATE, + AMEntitlement.PASSWORD_MANAGEMENT_UPDATE, auditRestClient) { private static final long serialVersionUID = -3712506022627033822L; @@ -153,7 +153,7 @@ public void onClick(final AjaxRequestTarget target, final PasswordModuleTO ignor @Override protected void restore(final String json, final AjaxRequestTarget target) { try { - PasswordModuleTO updated = MAPPER.readValue(json, PasswordModuleTO.class); + PasswordManagementTO updated = MAPPER.readValue(json, PasswordManagementTO.class); restClient.update(updated); SyncopeConsoleSession.get().success(getString(Constants.OPERATION_SUCCEEDED)); @@ -169,7 +169,7 @@ protected void restore(final String json, final AjaxRequestTarget target) { historyModal.show(true); } - }, ActionLink.ActionType.VIEW_AUDIT_HISTORY, String.format("%s,%s", AMEntitlement.PASSWORD_MODULE_READ, + }, ActionLink.ActionType.VIEW_AUDIT_HISTORY, String.format("%s,%s", AMEntitlement.PASSWORD_MANAGEMENT_READ, IdRepoEntitlement.AUDIT_LIST)); panel.add(new ActionLink<>() { @@ -177,7 +177,7 @@ protected void restore(final String json, final AjaxRequestTarget target) { private static final long serialVersionUID = -3722207913631435501L; @Override - public void onClick(final AjaxRequestTarget target, final PasswordModuleTO ignore) { + public void onClick(final AjaxRequestTarget target, final PasswordManagementTO ignore) { try { restClient.delete(model.getObject().getKey()); @@ -189,27 +189,27 @@ public void onClick(final AjaxRequestTarget target, final PasswordModuleTO ignor } ((BaseWebPage) pageRef.getPage()).getNotificationPanel().refresh(target); } - }, ActionLink.ActionType.DELETE, AMEntitlement.PASSWORD_MODULE_DELETE, true); + }, ActionLink.ActionType.DELETE, AMEntitlement.PASSWORD_MANAGEMENT_DELETE, true); return panel; } - protected final class PasswordModuleProvider extends DirectoryDataProvider { + protected final class PasswordManagementProvider extends DirectoryDataProvider { - private static final long serialVersionUID = -185944053385660794L; + private static final long serialVersionUID = 4972693840864025955L; - private final SortableDataProviderComparator comparator; + private final SortableDataProviderComparator comparator; - private PasswordModuleProvider(final int paginatorRows) { + private PasswordManagementProvider(final int paginatorRows) { super(paginatorRows); comparator = new SortableDataProviderComparator<>(this); } @Override - public Iterator iterator(final long first, final long count) { - List passwordModules = restClient.list(); - passwordModules.sort(comparator); - return passwordModules.subList((int) first, (int) first + (int) count).iterator(); + public Iterator iterator(final long first, final long count) { + List passwordManagements = restClient.list(); + passwordManagements.sort(comparator); + return passwordManagements.subList((int) first, (int) first + (int) count).iterator(); } @Override @@ -218,7 +218,7 @@ public long size() { } @Override - public IModel model(final PasswordModuleTO object) { + public IModel model(final PasswordManagementTO object) { return new CompoundPropertyModel<>(object); } } diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/rest/PasswordManagementRestClient.java b/client/am/console/src/main/java/org/apache/syncope/client/console/rest/PasswordManagementRestClient.java new file mode 100644 index 00000000000..bb8945b764a --- /dev/null +++ b/client/am/console/src/main/java/org/apache/syncope/client/console/rest/PasswordManagementRestClient.java @@ -0,0 +1,30 @@ +package org.apache.syncope.client.console.rest; + +import java.util.List; +import org.apache.syncope.common.lib.to.PasswordManagementTO; +import org.apache.syncope.common.rest.api.service.PasswordManagementService; + +public class PasswordManagementRestClient extends BaseRestClient { + + private static final long serialVersionUID = -3961377654788868099L; + + public List list() { + return getService(PasswordManagementService.class).list(); + } + + public void create(final PasswordManagementTO passwordManagementTO) { + getService(PasswordManagementService.class).create(passwordManagementTO); + } + + public PasswordManagementTO read(final String key) { + return getService(PasswordManagementService.class).read(key); + } + + public void update(final PasswordManagementTO passwordManagementTO) { + getService(PasswordManagementService.class).update(passwordManagementTO); + } + + public void delete(final String key) { + getService(PasswordManagementService.class).delete(key); + } +} diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/rest/PasswordModuleRestClient.java b/client/am/console/src/main/java/org/apache/syncope/client/console/rest/PasswordModuleRestClient.java deleted file mode 100644 index fe3e240f998..00000000000 --- a/client/am/console/src/main/java/org/apache/syncope/client/console/rest/PasswordModuleRestClient.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.apache.syncope.client.console.rest; - -import java.util.List; -import org.apache.syncope.common.lib.to.PasswordModuleTO; -import org.apache.syncope.common.rest.api.service.PasswordModuleService; - -public class PasswordModuleRestClient extends BaseRestClient { - - private static final long serialVersionUID = -3961377654788868099L; - - public List list() { - return getService(PasswordModuleService.class).list(); - } - - public void create(final PasswordModuleTO passwordModuleTO) { - getService(PasswordModuleService.class).create(passwordModuleTO); - } - - public PasswordModuleTO read(final String key) { - return getService(PasswordModuleService.class).read(key); - } - - public void update(final PasswordModuleTO passwordModuleTO) { - getService(PasswordModuleService.class).update(passwordModuleTO); - } - - public void delete(final String key) { - getService(PasswordModuleService.class).delete(key); - } -} diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder.java b/client/am/console/src/main/java/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder.java similarity index 53% rename from client/am/console/src/main/java/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder.java rename to client/am/console/src/main/java/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder.java index adc8a071321..8d1045f535d 100644 --- a/client/am/console/src/main/java/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder.java +++ b/client/am/console/src/main/java/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder.java @@ -5,14 +5,15 @@ import java.util.stream.Collectors; import org.apache.syncope.client.console.SyncopeWebApplication; import org.apache.syncope.client.console.panels.BeanPanel; -import org.apache.syncope.client.console.rest.PasswordModuleRestClient; +import org.apache.syncope.client.console.rest.PasswordManagementRestClient; import org.apache.syncope.client.ui.commons.Constants; +import org.apache.syncope.client.ui.commons.markup.html.form.AjaxCheckBoxPanel; import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel; import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel; import org.apache.syncope.client.ui.commons.wizards.AjaxWizard; -import org.apache.syncope.common.lib.password.PasswordModuleConf; -import org.apache.syncope.common.lib.to.PasswordModuleTO; -import org.apache.syncope.common.lib.types.PasswordModuleState; +import org.apache.syncope.common.lib.password.PasswordManagementConf; +import org.apache.syncope.common.lib.to.PasswordManagementTO; +import org.apache.syncope.common.lib.types.PasswordManagementState; import org.apache.wicket.PageReference; import org.apache.wicket.ajax.AjaxEventBehavior; import org.apache.wicket.ajax.AjaxRequestTarget; @@ -23,58 +24,48 @@ import org.apache.wicket.model.PropertyModel; import org.springframework.util.ClassUtils; -public class PasswordModuleWizardBuilder extends BaseAjaxWizardBuilder { +public class PasswordManagementWizardBuilder extends BaseAjaxWizardBuilder { private static final long serialVersionUID = -6355254150868269721L; - protected final LoadableDetachableModel> passwordModuleConfs = new LoadableDetachableModel<>() { + protected final LoadableDetachableModel> passwordManagementConfs = new LoadableDetachableModel<>() { private static final long serialVersionUID = 5275935387613157437L; @Override protected List load() { - return SyncopeWebApplication.get().getLookup().getClasses(PasswordModuleConf.class).stream(). + return SyncopeWebApplication.get().getLookup().getClasses(PasswordManagementConf.class).stream(). map(Class::getName).sorted().collect(Collectors.toList()); } }; - protected final PasswordModuleRestClient passwordModuleRestClient; + protected final PasswordManagementRestClient passwordManagementRestClient; - protected final Model> passwordModuleConfClass = Model.of(); + protected final Model> passwordManagementConfClass = Model.of(); - public PasswordModuleWizardBuilder( - final PasswordModuleTO defaultItem, - final PasswordModuleRestClient passwordModuleRestClient, + public PasswordManagementWizardBuilder( + final PasswordManagementTO defaultItem, + final PasswordManagementRestClient passwordManagementRestClient, final PageReference pageRef) { super(defaultItem, pageRef); - this.passwordModuleRestClient = passwordModuleRestClient; + this.passwordManagementRestClient = passwordManagementRestClient; } @Override - protected Serializable onApplyInternal(final PasswordModuleTO modelObject) { + protected Serializable onApplyInternal(final PasswordManagementTO modelObject) { if (mode == AjaxWizard.Mode.CREATE) { - passwordModuleRestClient.create(modelObject); + passwordManagementRestClient.create(modelObject); } else { - passwordModuleRestClient.update(modelObject); - } - - // PasswordManagement works on single source. - if (PasswordModuleState.ACTIVE.equals(modelObject.getState())) { - passwordModuleRestClient.list().stream().filter(passwordModuleTO -> - !passwordModuleTO.getKey().equals(modelObject.getKey())).toList() - .forEach(passwordModuleTO -> { - passwordModuleTO.setState(PasswordModuleState.DISABLED); - passwordModuleRestClient.update(passwordModuleTO); - }); + passwordManagementRestClient.update(modelObject); } return modelObject; } @Override - protected WizardModel buildModelSteps(final PasswordModuleTO modelObject, final WizardModel wizardModel) { - wizardModel.add(new Profile(modelObject, passwordModuleConfs, passwordModuleConfClass)); + protected WizardModel buildModelSteps(final PasswordManagementTO modelObject, final WizardModel wizardModel) { + wizardModel.add(new Profile(modelObject, passwordManagementConfs, passwordManagementConfClass)); wizardModel.add(new Configuration(modelObject)); return wizardModel; } @@ -84,38 +75,36 @@ protected static class Profile extends WizardStep { private static final long serialVersionUID = -3043839139187792810L; Profile( - final PasswordModuleTO passwordModule, - final LoadableDetachableModel> passwordModuleConfs, - final Model> passwordModuleConfClass) { + final PasswordManagementTO passwordManagement, + final LoadableDetachableModel> passwordManagementConfs, + final Model> passwordManagementConfClass) { - boolean isNew = passwordModule.getConf() == null; + boolean isNew = passwordManagement.getConf() == null; if (!isNew) { - passwordModuleConfClass.setObject(passwordModule.getConf().getClass()); + passwordManagementConfClass.setObject(passwordManagement.getConf().getClass()); } AjaxTextFieldPanel key = new AjaxTextFieldPanel( Constants.KEY_FIELD_NAME, Constants.KEY_FIELD_NAME, - new PropertyModel<>(passwordModule, Constants.KEY_FIELD_NAME)); + new PropertyModel<>(passwordManagement, Constants.KEY_FIELD_NAME)); key.addRequiredLabel(); key.setEnabled(isNew); add(key); AjaxTextFieldPanel description = new AjaxTextFieldPanel( Constants.DESCRIPTION_FIELD_NAME, getString(Constants.DESCRIPTION_FIELD_NAME), - new PropertyModel<>(passwordModule, Constants.DESCRIPTION_FIELD_NAME)); + new PropertyModel<>(passwordManagement, Constants.DESCRIPTION_FIELD_NAME)); add(description); - AjaxDropDownChoicePanel state = new AjaxDropDownChoicePanel<>( - "state", getString("state"), new PropertyModel<>(passwordModule, "state")); - state.setChoices(List.of(PasswordModuleState.values())); - state.addRequiredLabel(); - state.setNullValid(false); - add(state); + AjaxCheckBoxPanel isEnabled = new AjaxCheckBoxPanel( + "enabled", getString("enabled"), new PropertyModel<>(passwordManagement, "enabled")); + isEnabled.addRequiredLabel(); + add(isEnabled); AjaxDropDownChoicePanel conf = new AjaxDropDownChoicePanel<>("conf", getString("type"), isNew ? Model.of() - : Model.of(passwordModule.getConf().getClass().getName())); - conf.setChoices(passwordModuleConfs.getObject()); + : Model.of(passwordManagement.getConf().getClass().getName())); + conf.setChoices(passwordManagementConfs.getObject()); conf.addRequiredLabel(); conf.setNullValid(false); conf.setEnabled(isNew); @@ -127,12 +116,12 @@ Constants.DESCRIPTION_FIELD_NAME, getString(Constants.DESCRIPTION_FIELD_NAME), @Override protected void onEvent(final AjaxRequestTarget target) { try { - Class clazz = - (Class) ClassUtils.resolveClassName( + Class clazz = + (Class) ClassUtils.resolveClassName( conf.getModelObject(), ClassUtils.getDefaultClassLoader()); - passwordModule.setConf(clazz.getConstructor().newInstance()); - passwordModuleConfClass.setObject(clazz); + passwordManagement.setConf(clazz.getConstructor().newInstance()); + passwordManagementConfClass.setObject(clazz); } catch (Exception e) { LOG.error("Cannot instantiate {}", conf.getModelObject(), e); } @@ -146,8 +135,8 @@ protected class Configuration extends WizardStep { private static final long serialVersionUID = -785981096328637758L; - Configuration(final PasswordModuleTO passwordModule) { - add(new BeanPanel<>("bean", new PropertyModel<>(passwordModule, "conf"), pageRef, + Configuration(final PasswordManagementTO passwordManagement) { + add(new BeanPanel<>("bean", new PropertyModel<>(passwordManagement, "conf"), pageRef, "ldap", "keystore", "serviceProviderMetadata").setRenderBodyOnly(true)); } } diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA.properties index 4155ee093b3..fe17d6fa4fd 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA.properties @@ -16,7 +16,7 @@ # under the License. wa=WA authModules=Authentication Modules -passwordModules=Password Management +passwordManagements=Password Management clientApps=Client Applications config=Parameters sessions=Sessions diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_fr_CA.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_fr_CA.properties index 4155ee093b3..fe17d6fa4fd 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_fr_CA.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_fr_CA.properties @@ -16,7 +16,7 @@ # under the License. wa=WA authModules=Authentication Modules -passwordModules=Password Management +passwordManagements=Password Management clientApps=Client Applications config=Parameters sessions=Sessions diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_it.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_it.properties index fe9a0530804..e497a18a676 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_it.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_it.properties @@ -16,7 +16,7 @@ # under the License. wa=WA authModules=Moduli di Autenticazione -passwordModules=Password Management +passwordManagements=Password Management clientApps=Applicazioni Client config=Parametri sessions=Sessioni diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_ja.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_ja.properties index 4155ee093b3..fe17d6fa4fd 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_ja.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_ja.properties @@ -16,7 +16,7 @@ # under the License. wa=WA authModules=Authentication Modules -passwordModules=Password Management +passwordManagements=Password Management clientApps=Client Applications config=Parameters sessions=Sessions diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_pt_BR.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_pt_BR.properties index 4155ee093b3..fe17d6fa4fd 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_pt_BR.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_pt_BR.properties @@ -16,7 +16,7 @@ # under the License. wa=WA authModules=Authentication Modules -passwordModules=Password Management +passwordManagements=Password Management clientApps=Client Applications config=Parameters sessions=Sessions diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_ru.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_ru.properties index 4155ee093b3..fe17d6fa4fd 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_ru.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_ru.properties @@ -16,7 +16,7 @@ # under the License. wa=WA authModules=Authentication Modules -passwordModules=Password Management +passwordManagements=Password Management clientApps=Client Applications config=Parameters sessions=Sessions diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_fr.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel.properties similarity index 84% rename from client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_fr.properties rename to client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel.properties index ee38222f198..e6fbb66201d 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_fr.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel.properties @@ -3,6 +3,6 @@ any.new=New Password Module any.edit=Edit Auth Password Module description=Description type=Type -state=State +enabled=Configuration is enabled order=Order menu.history=Configuration history diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_fr_CA.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_fr.properties similarity index 84% rename from client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_fr_CA.properties rename to client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_fr.properties index ee38222f198..e6fbb66201d 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_fr_CA.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_fr.properties @@ -3,6 +3,6 @@ any.new=New Password Module any.edit=Edit Auth Password Module description=Description type=Type -state=State +enabled=Configuration is enabled order=Order menu.history=Configuration history diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_ja.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_fr_CA.properties similarity index 84% rename from client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_ja.properties rename to client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_fr_CA.properties index ee38222f198..e6fbb66201d 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_ja.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_fr_CA.properties @@ -3,6 +3,6 @@ any.new=New Password Module any.edit=Edit Auth Password Module description=Description type=Type -state=State +enabled=Configuration is enabled order=Order menu.history=Configuration history diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_it.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_it.properties similarity index 83% rename from client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_it.properties rename to client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_it.properties index 4d1fa8a0826..9bae4433771 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_it.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_it.properties @@ -3,6 +3,6 @@ any.new=Nuovo Modulo di Gestione Password any.edit=Aggiorna Modulo di Gestione Password description=Descrizione type=Tipo -state=Stato +enabled=Questa configurazione \u00e8 attiva order=Ordinamento auditHistory.title=Storico delle configurazioni diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_ja.properties similarity index 84% rename from client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel.properties rename to client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_ja.properties index ee38222f198..e6fbb66201d 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_ja.properties @@ -3,6 +3,6 @@ any.new=New Password Module any.edit=Edit Auth Password Module description=Description type=Type -state=State +enabled=Configuration is enabled order=Order menu.history=Configuration history diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_pt_BR.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_pt_BR.properties new file mode 100644 index 00000000000..e6fbb66201d --- /dev/null +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_pt_BR.properties @@ -0,0 +1,8 @@ +any.edit=Edit Parameter ${key} +any.new=New Password Module +any.edit=Edit Auth Password Module +description=Description +type=Type +enabled=Configuration is enabled +order=Order +menu.history=Configuration history diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_ru.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_ru.properties new file mode 100644 index 00000000000..e6fbb66201d --- /dev/null +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_ru.properties @@ -0,0 +1,8 @@ +any.edit=Edit Parameter ${key} +any.new=New Password Module +any.edit=Edit Auth Password Module +description=Description +type=Type +enabled=Configuration is enabled +order=Order +menu.history=Configuration history diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_pt_BR.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_pt_BR.properties deleted file mode 100644 index ee38222f198..00000000000 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_pt_BR.properties +++ /dev/null @@ -1,8 +0,0 @@ -any.edit=Edit Parameter ${key} -any.new=New Password Module -any.edit=Edit Auth Password Module -description=Description -type=Type -state=State -order=Order -menu.history=Configuration history diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_ru.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_ru.properties deleted file mode 100644 index ee38222f198..00000000000 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordModuleDirectoryPanel_ru.properties +++ /dev/null @@ -1,8 +0,0 @@ -any.edit=Edit Parameter ${key} -any.new=New Password Module -any.edit=Edit Auth Password Module -description=Description -type=Type -state=State -order=Order -menu.history=Configuration history diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Profile.html b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Profile.html index ec6f0108f63..6ed776f5e9e 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Profile.html +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Profile.html @@ -20,7 +20,7 @@
[key]
[description]
-
[state]
+
[enabled]
[order]
[conf]
diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration.html b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Configuration.html similarity index 100% rename from client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration.html rename to client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Configuration.html diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Configuration.properties similarity index 100% rename from client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration.properties rename to client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Configuration.properties diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_fr.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Configuration_fr.properties similarity index 100% rename from client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_fr.properties rename to client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Configuration_fr.properties diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_fr_CA.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Configuration_fr_CA.properties similarity index 100% rename from client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_fr_CA.properties rename to client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Configuration_fr_CA.properties diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_it.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Configuration_it.properties similarity index 100% rename from client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_it.properties rename to client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Configuration_it.properties diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_ja.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Configuration_ja.properties similarity index 100% rename from client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_ja.properties rename to client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Configuration_ja.properties diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_pt_BR.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Configuration_pt_BR.properties similarity index 100% rename from client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_pt_BR.properties rename to client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Configuration_pt_BR.properties diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_ru.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Configuration_ru.properties similarity index 100% rename from client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Configuration_ru.properties rename to client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Configuration_ru.properties diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile.html b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile.html similarity index 81% rename from client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile.html rename to client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile.html index 8367068f1a4..2746f1142a8 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile.html +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile.html @@ -2,7 +2,7 @@
[key]
[description]
-
[state]
+
[enabled]
[conf]
\ No newline at end of file diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile.properties similarity index 100% rename from client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile.properties rename to client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile.properties diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_fr.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_fr.properties similarity index 100% rename from client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_fr.properties rename to client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_fr.properties diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_fr_CA.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_fr_CA.properties similarity index 100% rename from client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_fr_CA.properties rename to client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_fr_CA.properties diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_it.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_it.properties similarity index 100% rename from client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_it.properties rename to client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_it.properties diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_ja.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_ja.properties similarity index 100% rename from client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_ja.properties rename to client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_ja.properties diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_pt_BR.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_pt_BR.properties similarity index 100% rename from client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_pt_BR.properties rename to client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_pt_BR.properties diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_ru.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_ru.properties similarity index 100% rename from client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordModuleWizardBuilder$Profile_ru.properties rename to client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_ru.properties diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/JDBCPasswordModuleConf.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/JDBCPasswordManagementConf.java similarity index 89% rename from common/am/lib/src/main/java/org/apache/syncope/common/lib/password/JDBCPasswordModuleConf.java rename to common/am/lib/src/main/java/org/apache/syncope/common/lib/password/JDBCPasswordManagementConf.java index feca3a764c6..441f9aafe80 100644 --- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/JDBCPasswordModuleConf.java +++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/JDBCPasswordManagementConf.java @@ -2,9 +2,9 @@ import java.util.Map; import org.apache.syncope.common.lib.AbstractJDBCConf; -import org.apache.syncope.common.lib.to.PasswordModuleTO; +import org.apache.syncope.common.lib.to.PasswordManagementTO; -public class JDBCPasswordModuleConf extends AbstractJDBCConf implements PasswordModuleConf { +public class JDBCPasswordManagementConf extends AbstractJDBCConf implements PasswordManagementConf { private static final long serialVersionUID = 1335379501740158360L; @@ -113,7 +113,7 @@ public void setSqlDeleteSecurityQuestions(final String sqlDeleteSecurityQuestion } @Override - public Map map(final PasswordModuleTO passwordModuleTO, final Mapper mapper) { - return mapper.map(passwordModuleTO, this); + public Map map(final PasswordManagementTO passwordManagementTO, final Mapper mapper) { + return mapper.map(passwordManagementTO, this); } } diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/LDAPPasswordModuleConf.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/LDAPPasswordManagementConf.java similarity index 57% rename from common/am/lib/src/main/java/org/apache/syncope/common/lib/password/LDAPPasswordModuleConf.java rename to common/am/lib/src/main/java/org/apache/syncope/common/lib/password/LDAPPasswordManagementConf.java index 6aad347a622..22a513fb5b4 100644 --- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/LDAPPasswordModuleConf.java +++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/LDAPPasswordManagementConf.java @@ -2,9 +2,9 @@ import java.util.Map; import org.apache.syncope.common.lib.AbstractLDAPConf; -import org.apache.syncope.common.lib.to.PasswordModuleTO; +import org.apache.syncope.common.lib.to.PasswordManagementTO; -public class LDAPPasswordModuleConf extends AbstractLDAPConf implements PasswordModuleConf { +public class LDAPPasswordManagementConf extends AbstractLDAPConf implements PasswordManagementConf { /** * Username attribute required by LDAP. @@ -19,7 +19,7 @@ public void setUsernameAttribute(final String usernameAttribute) { this.usernameAttribute = usernameAttribute; } - @Override public Map map(final PasswordModuleTO passwordModuleTO, final Mapper mapper) { - return mapper.map(passwordModuleTO, this); + @Override public Map map(final PasswordManagementTO passwordManagementTO, final Mapper mapper) { + return mapper.map(passwordManagementTO, this); } } diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/PasswordManagementConf.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/PasswordManagementConf.java new file mode 100644 index 00000000000..9d0a29c79fb --- /dev/null +++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/PasswordManagementConf.java @@ -0,0 +1,23 @@ +package org.apache.syncope.common.lib.password; + +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import java.util.Map; +import org.apache.syncope.common.lib.BaseBean; +import org.apache.syncope.common.lib.to.PasswordManagementTO; + +@FunctionalInterface +@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "_class") +public interface PasswordManagementConf extends BaseBean { + + interface Mapper { + + Map map(PasswordManagementTO passwordManagementTO, SyncopePasswordManagementConf conf); + + Map map(PasswordManagementTO passwordManagementTO, LDAPPasswordManagementConf conf); + + Map map(PasswordManagementTO passwordManagementTO, JDBCPasswordManagementConf conf); + + } + + Map map(PasswordManagementTO passwordManagementTO, Mapper mapper); +} diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/PasswordModuleConf.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/PasswordModuleConf.java deleted file mode 100644 index 384c4417f44..00000000000 --- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/PasswordModuleConf.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.apache.syncope.common.lib.password; - -import com.fasterxml.jackson.annotation.JsonTypeInfo; -import java.util.Map; -import org.apache.syncope.common.lib.BaseBean; -import org.apache.syncope.common.lib.to.PasswordModuleTO; - -@FunctionalInterface -@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "_class") -public interface PasswordModuleConf extends BaseBean { - - interface Mapper { - - Map map(PasswordModuleTO passwordModuleTO, SyncopePasswordModuleConf conf); - - Map map(PasswordModuleTO passwordModuleTO, LDAPPasswordModuleConf conf); - - Map map(PasswordModuleTO passwordModuleTO, JDBCPasswordModuleConf conf); - - } - - Map map(PasswordModuleTO passwordModuleTO, Mapper mapper); -} diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/SyncopePasswordModuleConf.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/SyncopePasswordManagementConf.java similarity index 85% rename from common/am/lib/src/main/java/org/apache/syncope/common/lib/password/SyncopePasswordModuleConf.java rename to common/am/lib/src/main/java/org/apache/syncope/common/lib/password/SyncopePasswordManagementConf.java index c63b279d6b7..f7fee820b11 100644 --- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/SyncopePasswordModuleConf.java +++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/SyncopePasswordManagementConf.java @@ -3,9 +3,9 @@ import java.util.HashMap; import java.util.Map; import org.apache.syncope.common.lib.SyncopeConstants; -import org.apache.syncope.common.lib.to.PasswordModuleTO; +import org.apache.syncope.common.lib.to.PasswordManagementTO; -public class SyncopePasswordModuleConf implements PasswordModuleConf { +public class SyncopePasswordManagementConf implements PasswordManagementConf { private static final long serialVersionUID = -8203692328056109683L; @@ -74,7 +74,7 @@ public void setHeaders(final Map headers) { this.headers = headers; } - @Override public Map map(final PasswordModuleTO passwordModuleTO, final Mapper mapper) { - return mapper.map(passwordModuleTO, this); + @Override public Map map(final PasswordManagementTO passwordManagementTO, final Mapper mapper) { + return mapper.map(passwordManagementTO, this); } } diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/to/PasswordModuleTO.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/to/PasswordManagementTO.java similarity index 64% rename from common/am/lib/src/main/java/org/apache/syncope/common/lib/to/PasswordModuleTO.java rename to common/am/lib/src/main/java/org/apache/syncope/common/lib/to/PasswordManagementTO.java index ee5ac3f9f85..49f338cea8a 100644 --- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/to/PasswordModuleTO.java +++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/to/PasswordManagementTO.java @@ -5,10 +5,10 @@ import java.util.List; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; -import org.apache.syncope.common.lib.password.PasswordModuleConf; -import org.apache.syncope.common.lib.types.PasswordModuleState; +import org.apache.syncope.common.lib.password.PasswordManagementConf; +import org.apache.syncope.common.lib.types.PasswordManagementState; -public class PasswordModuleTO implements EntityTO { +public class PasswordManagementTO implements EntityTO { private static final long serialVersionUID = -7203295929825782174L; @@ -16,11 +16,11 @@ public class PasswordModuleTO implements EntityTO { private String description; - private PasswordModuleState state = PasswordModuleState.DISABLED; + private boolean enabled = false; - private final List items = new ArrayList<>(); +// private final List items = new ArrayList<>(); - private PasswordModuleConf conf; + private PasswordManagementConf conf; @Override public String getKey() { @@ -41,23 +41,23 @@ public void setDescription(final String description) { this.description = description; } - public PasswordModuleState getState() { - return state; + public boolean isEnabled() { + return enabled; } - public void setState(final PasswordModuleState state) { - this.state = state; + public void setEnabled(boolean enabled) { + this.enabled = enabled; } - public List getItems() { - return items; - } +// public List getItems() { +// return items; +// } - public PasswordModuleConf getConf() { + public PasswordManagementConf getConf() { return conf; } - public void setConf(final PasswordModuleConf conf) { + public void setConf(final PasswordManagementConf conf) { this.conf = conf; } @@ -72,12 +72,12 @@ public boolean equals(final Object obj) { if (getClass() != obj.getClass()) { return false; } - PasswordModuleTO other = (PasswordModuleTO) obj; + PasswordManagementTO other = (PasswordManagementTO) obj; return new EqualsBuilder(). append(key, other.key). append(description, other.description). - append(state, other.state). - append(items, other.items). + append(enabled, other.enabled). +// append(items, other.items). append(conf, other.conf). build(); } @@ -87,7 +87,7 @@ public int hashCode() { return new HashCodeBuilder(). append(key). append(description). - append(items). +// append(items). append(conf). build(); } diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/types/AMEntitlement.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/types/AMEntitlement.java index cb8a1195e9a..fb4103d12fd 100644 --- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/types/AMEntitlement.java +++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/types/AMEntitlement.java @@ -58,15 +58,15 @@ public final class AMEntitlement { public static final String AUTH_MODULE_DELETE = "AUTH_MODULE_DELETE"; - public static final String PASSWORD_MODULE_LIST = "PASSWORD_MODULE_LIST"; + public static final String PASSWORD_MANAGEMENT_LIST = "PASSWORD_MANAGEMENT_LIST"; - public static final String PASSWORD_MODULE_CREATE = "PASSWORD_MODULE_CREATE"; + public static final String PASSWORD_MANAGEMENT_CREATE = "PASSWORD_MANAGEMENT_CREATE"; - public static final String PASSWORD_MODULE_READ = "PASSWORD_MODULE_READ"; + public static final String PASSWORD_MANAGEMENT_READ = "PASSWORD_MANAGEMENT_READ"; - public static final String PASSWORD_MODULE_UPDATE = "PASSWORD_MODULE_UPDATE"; + public static final String PASSWORD_MANAGEMENT_UPDATE = "PASSWORD_MANAGEMENT_UPDATE"; - public static final String PASSWORD_MODULE_DELETE = "PASSWORD_MODULE_DELETE"; + public static final String PASSWORD_MANAGEMENT_DELETE = "PASSWORD_MANAGEMENT_DELETE"; public static final String ATTR_REPO_LIST = "ATTR_REPO_LIST"; diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/types/PasswordModuleState.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/types/PasswordManagementState.java similarity index 89% rename from common/am/lib/src/main/java/org/apache/syncope/common/lib/types/PasswordModuleState.java rename to common/am/lib/src/main/java/org/apache/syncope/common/lib/types/PasswordManagementState.java index 673cac79ccd..b9343593ea0 100644 --- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/types/PasswordModuleState.java +++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/types/PasswordManagementState.java @@ -1,6 +1,6 @@ package org.apache.syncope.common.lib.types; -public enum PasswordModuleState { +public enum PasswordManagementState { /** * Active password management configuration, * This password management is used for CAS reset password flow. diff --git a/common/am/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/PasswordModuleService.java b/common/am/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/PasswordManagementService.java similarity index 81% rename from common/am/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/PasswordModuleService.java rename to common/am/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/PasswordManagementService.java index 5edc40eac34..7dd54e2fc7a 100644 --- a/common/am/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/PasswordModuleService.java +++ b/common/am/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/PasswordManagementService.java @@ -22,18 +22,18 @@ import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; import java.util.List; -import org.apache.syncope.common.lib.to.PasswordModuleTO; +import org.apache.syncope.common.lib.to.PasswordManagementTO; import org.apache.syncope.common.rest.api.RESTHeaders; /** * REST operations for password management modules. */ -@Tag(name = "PasswordModules") +@Tag(name = "PasswordManagement") @SecurityRequirements({ @SecurityRequirement(name = "BasicAuthentication"), @SecurityRequirement(name = "Bearer") }) -@Path("passwordModules") -public interface PasswordModuleService extends JAXRSService { +@Path("passwordManagement") +public interface PasswordManagementService extends JAXRSService { /** * Returns the password management module matching the given key. @@ -44,7 +44,7 @@ public interface PasswordModuleService extends JAXRSService { @GET @Path("{key}") @Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML }) - PasswordModuleTO read(@NotNull @PathParam("key") String key); + PasswordManagementTO read(@NotNull @PathParam("key") String key); /** * Returns a list of password management modules. @@ -53,17 +53,17 @@ public interface PasswordModuleService extends JAXRSService { */ @GET @Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML }) - List list(); + List list(); /** * Create a new password management module. * - * @param passwordModuleTO PasswordModule to be created. + * @param passwordManagementTO PasswordManagement to be created. * @return Response object featuring Location header of created password management module */ @ApiResponses( @ApiResponse(responseCode = "201", - description = "PasswordModule successfully created", headers = { + description = "PasswordManagement successfully created", headers = { @Header(name = RESTHeaders.RESOURCE_KEY, schema = @Schema(type = "string"), description = "UUID generated for the entity created"), @@ -73,14 +73,14 @@ public interface PasswordModuleService extends JAXRSService { @POST @Consumes({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML }) @Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML }) - Response create(@NotNull PasswordModuleTO passwordModuleTO); + Response create(@NotNull PasswordManagementTO passwordManagementTO); /** * Updates password management module matching the given key. * - * @param passwordModuleTO PasswordModule to replace existing password management module + * @param passwordManagementTO PasswordManagement to replace existing password management module */ - @Parameter(name = "key", description = "PasswordModule's key", in = ParameterIn.PATH, schema = + @Parameter(name = "key", description = "PasswordManagement's key", in = ParameterIn.PATH, schema = @Schema(type = "string")) @ApiResponses( @ApiResponse(responseCode = "204", description = "Operation was successful")) @@ -88,7 +88,7 @@ public interface PasswordModuleService extends JAXRSService { @Path("{key}") @Consumes({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML }) @Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML }) - void update(@NotNull PasswordModuleTO passwordModuleTO); + void update(@NotNull PasswordManagementTO passwordManagementTO); /** * Delete password management module matching the given key. diff --git a/core/am/logic/src/main/java/org/apache/syncope/core/logic/AMLogicContext.java b/core/am/logic/src/main/java/org/apache/syncope/core/logic/AMLogicContext.java index 21ac81f5e2c..eeb57b75803 100644 --- a/core/am/logic/src/main/java/org/apache/syncope/core/logic/AMLogicContext.java +++ b/core/am/logic/src/main/java/org/apache/syncope/core/logic/AMLogicContext.java @@ -33,7 +33,7 @@ import org.apache.syncope.core.persistence.api.dao.CASSPClientAppDAO; import org.apache.syncope.core.persistence.api.dao.OIDCJWKSDAO; import org.apache.syncope.core.persistence.api.dao.OIDCRPClientAppDAO; -import org.apache.syncope.core.persistence.api.dao.PasswordModuleDAO; +import org.apache.syncope.core.persistence.api.dao.PasswordManagementDAO; import org.apache.syncope.core.persistence.api.dao.SAML2IdPEntityDAO; import org.apache.syncope.core.persistence.api.dao.SAML2SPClientAppDAO; import org.apache.syncope.core.persistence.api.dao.SRARouteDAO; @@ -45,7 +45,7 @@ import org.apache.syncope.core.provisioning.api.data.AuthProfileDataBinder; import org.apache.syncope.core.provisioning.api.data.ClientAppDataBinder; import org.apache.syncope.core.provisioning.api.data.OIDCJWKSDataBinder; -import org.apache.syncope.core.provisioning.api.data.PasswordModuleDataBinder; +import org.apache.syncope.core.provisioning.api.data.PasswordManagementDataBinder; import org.apache.syncope.core.provisioning.api.data.SAML2IdPEntityDataBinder; import org.apache.syncope.core.provisioning.api.data.SRARouteDataBinder; import org.apache.syncope.core.provisioning.api.data.WAConfigDataBinder; @@ -75,10 +75,10 @@ public AuthModuleLogic authModuleLogic( @ConditionalOnMissingBean @Bean - public PasswordModuleLogic passwordModuleLogic( - final PasswordModuleDataBinder passwordModuleDataBinder, - final PasswordModuleDAO passwordModuleDAO) { - return new PasswordModuleLogic(passwordModuleDataBinder, passwordModuleDAO); + public PasswordManagementLogic passwordManagementLogic( + final PasswordManagementDataBinder passwordManagementDataBinder, + final PasswordManagementDAO passwordManagementDAO) { + return new PasswordManagementLogic(passwordManagementDataBinder, passwordManagementDAO); } @ConditionalOnMissingBean diff --git a/core/am/logic/src/main/java/org/apache/syncope/core/logic/PasswordManagementLogic.java b/core/am/logic/src/main/java/org/apache/syncope/core/logic/PasswordManagementLogic.java new file mode 100644 index 00000000000..9436e1557e0 --- /dev/null +++ b/core/am/logic/src/main/java/org/apache/syncope/core/logic/PasswordManagementLogic.java @@ -0,0 +1,96 @@ +package org.apache.syncope.core.logic; + +import java.lang.reflect.Method; +import java.util.List; +import org.apache.commons.lang3.ArrayUtils; +import org.apache.syncope.common.lib.to.AuthModuleTO; +import org.apache.syncope.common.lib.to.PasswordManagementTO; +import org.apache.syncope.common.lib.types.AMEntitlement; +import org.apache.syncope.common.lib.types.IdRepoEntitlement; +import org.apache.syncope.core.persistence.api.dao.NotFoundException; +import org.apache.syncope.core.persistence.api.dao.PasswordManagementDAO; +import org.apache.syncope.core.persistence.api.entity.am.PasswordManagement; +import org.apache.syncope.core.provisioning.api.data.PasswordManagementDataBinder; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.transaction.annotation.Transactional; + +public class PasswordManagementLogic extends AbstractTransactionalLogic { + + protected final PasswordManagementDataBinder passwordManagementDataBinder; + + protected final PasswordManagementDAO passwordManagementDAO; + + public PasswordManagementLogic(final PasswordManagementDataBinder passwordManagementDataBinder, + final PasswordManagementDAO passwordManagementDAO) { + this.passwordManagementDataBinder = passwordManagementDataBinder; + this.passwordManagementDAO = passwordManagementDAO; + } + + @PreAuthorize("hasRole('" + AMEntitlement.PASSWORD_MANAGEMENT_CREATE + "')") + public PasswordManagementTO create(final PasswordManagementTO passwordManagementTO) { + return passwordManagementDataBinder.getPasswordManagementTO( + passwordManagementDAO.save(passwordManagementDataBinder.create(passwordManagementTO))); + } + + @PreAuthorize("hasRole('" + AMEntitlement.PASSWORD_MANAGEMENT_UPDATE + "')") + public PasswordManagementTO update(final PasswordManagementTO passwordManagementTO) { + PasswordManagement passwordManagement = passwordManagementDAO.findById(passwordManagementTO.getKey()). + orElseThrow(() -> new NotFoundException("PasswordManagement " + passwordManagementTO.getKey())); + + return passwordManagementDataBinder.getPasswordManagementTO( + passwordManagementDAO.save(passwordManagementDataBinder.update(passwordManagement, passwordManagementTO))); + } + + @PreAuthorize("hasRole('" + AMEntitlement.PASSWORD_MANAGEMENT_LIST + "') or hasRole('" + + IdRepoEntitlement.ANONYMOUS + "')") + @Transactional(readOnly = true) + public List list() { + return passwordManagementDAO.findAll().stream() + .map(passwordManagementDataBinder::getPasswordManagementTO).toList(); + } + + @PreAuthorize("hasRole('" + AMEntitlement.PASSWORD_MANAGEMENT_READ + "')") + @Transactional(readOnly = true) + public PasswordManagementTO read(final String key) { + PasswordManagement passwordManagement = passwordManagementDAO.findById(key). + orElseThrow(() -> new NotFoundException("PasswordManagement " + key)); + + return passwordManagementDataBinder.getPasswordManagementTO(passwordManagement); + } + + @PreAuthorize("hasRole('" + AMEntitlement.PASSWORD_MANAGEMENT_DELETE + "')") + public PasswordManagementTO delete(final String key) { + PasswordManagement passwordManagement = passwordManagementDAO.findById(key). + orElseThrow(() -> new NotFoundException("PasswordManagement " + key)); + + PasswordManagementTO deleted = passwordManagementDataBinder.getPasswordManagementTO(passwordManagement); + passwordManagementDAO.delete(passwordManagement); + + return deleted; + } + + @Override + protected PasswordManagementTO resolveReference(final Method method, final Object... args) + throws UnresolvedReferenceException { + if (ArrayUtils.isEmpty(args)) { + throw new UnresolvedReferenceException(); + } + + final String key; + + if (args[0] instanceof String string) { + key = string; + } else if (args[0] instanceof AuthModuleTO authModuleTO) { + key = authModuleTO.getKey(); + } else { + throw new UnresolvedReferenceException(); + } + + try { + return passwordManagementDataBinder.getPasswordManagementTO(passwordManagementDAO.findById(key).orElseThrow()); + } catch (Throwable ignore) { + LOG.debug("Unresolved reference", ignore); + throw new UnresolvedReferenceException(ignore); + } + } +} diff --git a/core/am/logic/src/main/java/org/apache/syncope/core/logic/PasswordModuleLogic.java b/core/am/logic/src/main/java/org/apache/syncope/core/logic/PasswordModuleLogic.java deleted file mode 100644 index c4ec342c488..00000000000 --- a/core/am/logic/src/main/java/org/apache/syncope/core/logic/PasswordModuleLogic.java +++ /dev/null @@ -1,96 +0,0 @@ -package org.apache.syncope.core.logic; - -import java.lang.reflect.Method; -import java.util.List; -import org.apache.commons.lang3.ArrayUtils; -import org.apache.syncope.common.lib.to.AuthModuleTO; -import org.apache.syncope.common.lib.to.PasswordModuleTO; -import org.apache.syncope.common.lib.types.AMEntitlement; -import org.apache.syncope.common.lib.types.IdRepoEntitlement; -import org.apache.syncope.core.persistence.api.dao.NotFoundException; -import org.apache.syncope.core.persistence.api.dao.PasswordModuleDAO; -import org.apache.syncope.core.persistence.api.entity.am.PasswordModule; -import org.apache.syncope.core.provisioning.api.data.PasswordModuleDataBinder; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.transaction.annotation.Transactional; - -public class PasswordModuleLogic extends AbstractTransactionalLogic { - - protected final PasswordModuleDataBinder passwordModuleDataBinder; - - protected final PasswordModuleDAO passwordModuleDAO; - - public PasswordModuleLogic(final PasswordModuleDataBinder passwordModuleDataBinder, - final PasswordModuleDAO passwordModuleDAO) { - this.passwordModuleDataBinder = passwordModuleDataBinder; - this.passwordModuleDAO = passwordModuleDAO; - } - - @PreAuthorize("hasRole('" + AMEntitlement.PASSWORD_MODULE_CREATE + "')") - public PasswordModuleTO create(final PasswordModuleTO passwordModuleTO) { - return passwordModuleDataBinder.getPasswordModuleTO( - passwordModuleDAO.save(passwordModuleDataBinder.create(passwordModuleTO))); - } - - @PreAuthorize("hasRole('" + AMEntitlement.PASSWORD_MODULE_UPDATE + "')") - public PasswordModuleTO update(final PasswordModuleTO passwordModuleTO) { - PasswordModule passwordModule = passwordModuleDAO.findById(passwordModuleTO.getKey()). - orElseThrow(() -> new NotFoundException("PasswordModule " + passwordModuleTO.getKey())); - - return passwordModuleDataBinder.getPasswordModuleTO( - passwordModuleDAO.save(passwordModuleDataBinder.update(passwordModule, passwordModuleTO))); - } - - @PreAuthorize("hasRole('" + AMEntitlement.PASSWORD_MODULE_LIST + "') or hasRole('" - + IdRepoEntitlement.ANONYMOUS + "')") - @Transactional(readOnly = true) - public List list() { - return passwordModuleDAO.findAll().stream() - .map(passwordModuleDataBinder::getPasswordModuleTO).toList(); - } - - @PreAuthorize("hasRole('" + AMEntitlement.PASSWORD_MODULE_READ + "')") - @Transactional(readOnly = true) - public PasswordModuleTO read(final String key) { - PasswordModule passwordModule = passwordModuleDAO.findById(key). - orElseThrow(() -> new NotFoundException("PasswordModule " + key)); - - return passwordModuleDataBinder.getPasswordModuleTO(passwordModule); - } - - @PreAuthorize("hasRole('" + AMEntitlement.PASSWORD_MODULE_DELETE + "')") - public PasswordModuleTO delete(final String key) { - PasswordModule passwordModule = passwordModuleDAO.findById(key). - orElseThrow(() -> new NotFoundException("PasswordModule " + key)); - - PasswordModuleTO deleted = passwordModuleDataBinder.getPasswordModuleTO(passwordModule); - passwordModuleDAO.delete(passwordModule); - - return deleted; - } - - @Override - protected PasswordModuleTO resolveReference(final Method method, final Object... args) - throws UnresolvedReferenceException { - if (ArrayUtils.isEmpty(args)) { - throw new UnresolvedReferenceException(); - } - - final String key; - - if (args[0] instanceof String string) { - key = string; - } else if (args[0] instanceof AuthModuleTO authModuleTO) { - key = authModuleTO.getKey(); - } else { - throw new UnresolvedReferenceException(); - } - - try { - return passwordModuleDataBinder.getPasswordModuleTO(passwordModuleDAO.findById(key).orElseThrow()); - } catch (Throwable ignore) { - LOG.debug("Unresolved reference", ignore); - throw new UnresolvedReferenceException(ignore); - } - } -} diff --git a/core/am/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/AMRESTCXFContext.java b/core/am/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/AMRESTCXFContext.java index c7dabcfb2c0..76de34ecaaa 100644 --- a/core/am/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/AMRESTCXFContext.java +++ b/core/am/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/AMRESTCXFContext.java @@ -24,7 +24,7 @@ import org.apache.syncope.common.rest.api.service.AuthProfileService; import org.apache.syncope.common.rest.api.service.ClientAppService; import org.apache.syncope.common.rest.api.service.OIDCJWKSService; -import org.apache.syncope.common.rest.api.service.PasswordModuleService; +import org.apache.syncope.common.rest.api.service.PasswordManagementService; import org.apache.syncope.common.rest.api.service.SAML2IdPEntityService; import org.apache.syncope.common.rest.api.service.SRARouteService; import org.apache.syncope.common.rest.api.service.wa.GoogleMfaAuthAccountService; @@ -40,7 +40,7 @@ import org.apache.syncope.core.logic.AuthProfileLogic; import org.apache.syncope.core.logic.ClientAppLogic; import org.apache.syncope.core.logic.OIDCJWKSLogic; -import org.apache.syncope.core.logic.PasswordModuleLogic; +import org.apache.syncope.core.logic.PasswordManagementLogic; import org.apache.syncope.core.logic.SAML2IdPEntityLogic; import org.apache.syncope.core.logic.SRARouteLogic; import org.apache.syncope.core.logic.wa.GoogleMfaAuthAccountLogic; @@ -56,7 +56,7 @@ import org.apache.syncope.core.rest.cxf.service.AuthProfileServiceImpl; import org.apache.syncope.core.rest.cxf.service.ClientAppServiceImpl; import org.apache.syncope.core.rest.cxf.service.OIDCJWKSServiceImpl; -import org.apache.syncope.core.rest.cxf.service.PasswordModuleServiceImpl; +import org.apache.syncope.core.rest.cxf.service.PasswordManagementServiceImpl; import org.apache.syncope.core.rest.cxf.service.SAML2IdPEntityServiceImpl; import org.apache.syncope.core.rest.cxf.service.SRARouteServiceImpl; import org.apache.syncope.core.rest.cxf.service.wa.GoogleMfaAuthAccountServiceImpl; @@ -82,8 +82,8 @@ public AuthModuleService authModuleService(final AuthModuleLogic authModuleLogic @ConditionalOnMissingBean @Bean - public PasswordModuleService passwordModuleService(final PasswordModuleLogic passwordModuleLogic) { - return new PasswordModuleServiceImpl(passwordModuleLogic); + public PasswordManagementService passwordManagementService(final PasswordManagementLogic passwordManagementLogic) { + return new PasswordManagementServiceImpl(passwordManagementLogic); } @ConditionalOnMissingBean diff --git a/core/am/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/PasswordManagementServiceImpl.java b/core/am/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/PasswordManagementServiceImpl.java new file mode 100644 index 00000000000..346ba7237d0 --- /dev/null +++ b/core/am/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/PasswordManagementServiceImpl.java @@ -0,0 +1,47 @@ +package org.apache.syncope.core.rest.cxf.service; + +import jakarta.ws.rs.core.Response; +import java.net.URI; +import java.util.List; +import org.apache.syncope.common.lib.to.PasswordManagementTO; +import org.apache.syncope.common.rest.api.RESTHeaders; +import org.apache.syncope.common.rest.api.service.PasswordManagementService; +import org.apache.syncope.core.logic.PasswordManagementLogic; + +public class PasswordManagementServiceImpl extends AbstractService implements PasswordManagementService { + + protected final PasswordManagementLogic passwordManagementLogic; + + public PasswordManagementServiceImpl(final PasswordManagementLogic passwordManagementLogic) { + this.passwordManagementLogic = passwordManagementLogic; + } + + @Override + public PasswordManagementTO read(final String key) { + return passwordManagementLogic.read(key); + } + + @Override + public List list() { + return passwordManagementLogic.list(); + } + + @Override + public Response create(final PasswordManagementTO passwordManagementTO) { + PasswordManagementTO passwordManagement = passwordManagementLogic.create(passwordManagementTO); + URI location = uriInfo.getAbsolutePathBuilder().path(passwordManagement.getKey()).build(); + return Response.created(location). + header(RESTHeaders.RESOURCE_KEY, passwordManagement.getKey()). + build(); + } + + @Override + public void update(final PasswordManagementTO passwordManagementTO) { + passwordManagementLogic.update(passwordManagementTO); + } + + @Override + public void delete(final String key) { + passwordManagementLogic.delete(key); + } +} diff --git a/core/am/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/PasswordModuleServiceImpl.java b/core/am/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/PasswordModuleServiceImpl.java deleted file mode 100644 index 570ce4a068e..00000000000 --- a/core/am/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/PasswordModuleServiceImpl.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.apache.syncope.core.rest.cxf.service; - -import jakarta.ws.rs.core.Response; -import java.net.URI; -import java.util.List; -import org.apache.syncope.common.lib.to.PasswordModuleTO; -import org.apache.syncope.common.rest.api.RESTHeaders; -import org.apache.syncope.common.rest.api.service.PasswordModuleService; -import org.apache.syncope.core.logic.PasswordModuleLogic; - -public class PasswordModuleServiceImpl extends AbstractService implements PasswordModuleService { - - protected final PasswordModuleLogic passwordModuleLogic; - - public PasswordModuleServiceImpl(final PasswordModuleLogic passwordModuleLogic) { - this.passwordModuleLogic = passwordModuleLogic; - } - - @Override - public PasswordModuleTO read(final String key) { - return passwordModuleLogic.read(key); - } - - @Override - public List list() { - return passwordModuleLogic.list(); - } - - @Override - public Response create(final PasswordModuleTO passwordModuleTO) { - PasswordModuleTO passwordModule = passwordModuleLogic.create(passwordModuleTO); - URI location = uriInfo.getAbsolutePathBuilder().path(passwordModule.getKey()).build(); - return Response.created(location). - header(RESTHeaders.RESOURCE_KEY, passwordModule.getKey()). - build(); - } - - @Override - public void update(final PasswordModuleTO passwordModuleTO) { - passwordModuleLogic.update(passwordModuleTO); - } - - @Override - public void delete(final String key) { - passwordModuleLogic.delete(key); - } -} diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PasswordModuleDAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PasswordManagementDAO.java similarity index 58% rename from core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PasswordModuleDAO.java rename to core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PasswordManagementDAO.java index 07ab8352498..914c17d1d98 100644 --- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PasswordModuleDAO.java +++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PasswordManagementDAO.java @@ -1,6 +1,6 @@ package org.apache.syncope.core.persistence.api.dao; -import org.apache.syncope.core.persistence.api.entity.am.PasswordModule; +import org.apache.syncope.core.persistence.api.entity.am.PasswordManagement; -public interface PasswordModuleDAO extends DAO { +public interface PasswordManagementDAO extends DAO { } diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/am/PasswordModule.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/am/PasswordModule.java deleted file mode 100644 index d26b66141d8..00000000000 --- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/am/PasswordModule.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.apache.syncope.core.persistence.api.entity.am; - -import java.util.List; -import org.apache.syncope.common.lib.password.PasswordModuleConf; -import org.apache.syncope.common.lib.to.Item; -import org.apache.syncope.common.lib.types.PasswordModuleState; -import org.apache.syncope.core.persistence.api.entity.ProvidedKeyEntity; - -public interface PasswordModule extends ProvidedKeyEntity { - - String getDescription(); - - void setDescription(String description); - - PasswordModuleState getState(); - - void setState(PasswordModuleState state); - - PasswordModuleConf getConf(); - - void setConf(PasswordModuleConf conf); - - List getItems(); -} diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/PersistenceContext.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/PersistenceContext.java index 1f8fbb81cf3..03ffa1805a0 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/PersistenceContext.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/PersistenceContext.java @@ -57,7 +57,7 @@ import org.apache.syncope.core.persistence.api.dao.NotificationDAO; import org.apache.syncope.core.persistence.api.dao.OIDCJWKSDAO; import org.apache.syncope.core.persistence.api.dao.OIDCRPClientAppDAO; -import org.apache.syncope.core.persistence.api.dao.PasswordModuleDAO; +import org.apache.syncope.core.persistence.api.dao.PasswordManagementDAO; import org.apache.syncope.core.persistence.api.dao.PersistenceInfoDAO; import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO; import org.apache.syncope.core.persistence.api.dao.PolicyDAO; @@ -155,9 +155,9 @@ import org.apache.syncope.core.persistence.jpa.dao.repo.OIDCRPClientAppRepo; import org.apache.syncope.core.persistence.jpa.dao.repo.OIDCRPClientAppRepoExt; import org.apache.syncope.core.persistence.jpa.dao.repo.OIDCRPClientAppRepoExtImpl; -import org.apache.syncope.core.persistence.jpa.dao.repo.PasswordModuleRepo; -import org.apache.syncope.core.persistence.jpa.dao.repo.PasswordModuleRepoExt; -import org.apache.syncope.core.persistence.jpa.dao.repo.PasswordModuleRepoExtImpl; +import org.apache.syncope.core.persistence.jpa.dao.repo.PasswordManagementRepo; +import org.apache.syncope.core.persistence.jpa.dao.repo.PasswordManagementRepoExt; +import org.apache.syncope.core.persistence.jpa.dao.repo.PasswordManagementRepoExtImpl; import org.apache.syncope.core.persistence.jpa.dao.repo.PlainSchemaRepo; import org.apache.syncope.core.persistence.jpa.dao.repo.PlainSchemaRepoExt; import org.apache.syncope.core.persistence.jpa.dao.repo.RelationshipTypeRepo; @@ -521,16 +521,16 @@ public AuthModuleDAO authModuleDAO( @ConditionalOnMissingBean @Bean - public PasswordModuleRepoExt passwordModuleRepoExt(final EntityManager entityManager) { - return new PasswordModuleRepoExtImpl(entityManager); + public PasswordManagementRepoExt passwordManagementRepoExt(final EntityManager entityManager) { + return new PasswordManagementRepoExtImpl(entityManager); } @ConditionalOnMissingBean @Bean - public PasswordModuleDAO passwordModuleDAO( + public PasswordManagementDAO passwordManagementDAO( final JpaRepositoryFactory jpaRepositoryFactory, - final PasswordModuleRepoExt passwordModuleRepoExt) { - return jpaRepositoryFactory.getRepository(PasswordModuleRepo.class, passwordModuleRepoExt); + final PasswordManagementRepoExt passwordManagementRepoExt) { + return jpaRepositoryFactory.getRepository(PasswordManagementRepo.class, passwordManagementRepoExt); } @ConditionalOnMissingBean diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordManagementRepo.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordManagementRepo.java new file mode 100644 index 00000000000..4351e45ac32 --- /dev/null +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordManagementRepo.java @@ -0,0 +1,10 @@ +package org.apache.syncope.core.persistence.jpa.dao.repo; + +import org.apache.syncope.core.persistence.api.dao.PasswordManagementDAO; +import org.apache.syncope.core.persistence.jpa.entity.am.JPAPasswordManagement; +import org.springframework.data.repository.ListCrudRepository; + +public interface PasswordManagementRepo + extends ListCrudRepository, PasswordManagementRepoExt, PasswordManagementDAO { + +} diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordManagementRepoExt.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordManagementRepoExt.java new file mode 100644 index 00000000000..e0f6ec8023d --- /dev/null +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordManagementRepoExt.java @@ -0,0 +1,10 @@ +package org.apache.syncope.core.persistence.jpa.dao.repo; + +import org.apache.syncope.core.persistence.api.entity.am.PasswordManagement; + +public interface PasswordManagementRepoExt { + + PasswordManagement save(PasswordManagement passwordManagement); + + void delete(PasswordManagement passwordManagement); +} diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordManagementRepoExtImpl.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordManagementRepoExtImpl.java new file mode 100644 index 00000000000..b9e0b116a7b --- /dev/null +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordManagementRepoExtImpl.java @@ -0,0 +1,26 @@ +package org.apache.syncope.core.persistence.jpa.dao.repo; + +import jakarta.persistence.EntityManager; +import org.apache.syncope.core.persistence.api.entity.am.PasswordManagement; +import org.apache.syncope.core.persistence.jpa.entity.am.JPAPasswordManagement; + +public class PasswordManagementRepoExtImpl implements PasswordManagementRepoExt { + + protected final EntityManager entityManager; + + public PasswordManagementRepoExtImpl(final EntityManager entityManager) { + this.entityManager = entityManager; + } + + + @Override + public PasswordManagement save(final PasswordManagement passwordManagement) { + ((JPAPasswordManagement) passwordManagement).list2json(); + return entityManager.merge(passwordManagement); + } + + @Override + public void delete(final PasswordManagement passwordManagement) { + entityManager.remove(passwordManagement); + } +} diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordModuleRepo.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordModuleRepo.java deleted file mode 100644 index 38cab2f830a..00000000000 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordModuleRepo.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.apache.syncope.core.persistence.jpa.dao.repo; - -import org.apache.syncope.core.persistence.api.dao.PasswordModuleDAO; -import org.apache.syncope.core.persistence.jpa.entity.am.JPAPasswordModule; -import org.springframework.data.repository.ListCrudRepository; - -public interface PasswordModuleRepo - extends ListCrudRepository, PasswordModuleRepoExt, PasswordModuleDAO { - -} diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordModuleRepoExt.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordModuleRepoExt.java deleted file mode 100644 index 466baf1d30f..00000000000 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordModuleRepoExt.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.apache.syncope.core.persistence.jpa.dao.repo; - -import org.apache.syncope.core.persistence.api.entity.am.PasswordModule; - -public interface PasswordModuleRepoExt { - - PasswordModule save(PasswordModule passwordModule); - - void delete(PasswordModule passwordModule); -} diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordModuleRepoExtImpl.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordModuleRepoExtImpl.java deleted file mode 100644 index 40ba8dcd722..00000000000 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordModuleRepoExtImpl.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.apache.syncope.core.persistence.jpa.dao.repo; - -import jakarta.persistence.EntityManager; -import org.apache.syncope.core.persistence.api.entity.am.PasswordModule; -import org.apache.syncope.core.persistence.jpa.entity.am.JPAPasswordModule; - -public class PasswordModuleRepoExtImpl implements PasswordModuleRepoExt { - - protected final EntityManager entityManager; - - public PasswordModuleRepoExtImpl(final EntityManager entityManager) { - this.entityManager = entityManager; - } - - - @Override - public PasswordModule save(final PasswordModule passwordModule) { - ((JPAPasswordModule) passwordModule).list2json(); - return entityManager.merge(passwordModule); - } - - @Override - public void delete(final PasswordModule passwordModule) { - entityManager.remove(passwordModule); - } -} diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractEntityFactory.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractEntityFactory.java index bf9cb0bf495..1002f9c764d 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractEntityFactory.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractEntityFactory.java @@ -53,7 +53,7 @@ import org.apache.syncope.core.persistence.api.entity.am.CASSPClientApp; import org.apache.syncope.core.persistence.api.entity.am.OIDCJWKS; import org.apache.syncope.core.persistence.api.entity.am.OIDCRPClientApp; -import org.apache.syncope.core.persistence.api.entity.am.PasswordModule; +import org.apache.syncope.core.persistence.api.entity.am.PasswordManagement; import org.apache.syncope.core.persistence.api.entity.am.SAML2IdPEntity; import org.apache.syncope.core.persistence.api.entity.am.SAML2SPClientApp; import org.apache.syncope.core.persistence.api.entity.am.WAConfigEntry; @@ -100,7 +100,7 @@ import org.apache.syncope.core.persistence.jpa.entity.am.JPACASSPClientApp; import org.apache.syncope.core.persistence.jpa.entity.am.JPAOIDCJWKS; import org.apache.syncope.core.persistence.jpa.entity.am.JPAOIDCRPClientApp; -import org.apache.syncope.core.persistence.jpa.entity.am.JPAPasswordModule; +import org.apache.syncope.core.persistence.jpa.entity.am.JPAPasswordManagement; import org.apache.syncope.core.persistence.jpa.entity.am.JPASAML2IdPEntity; import org.apache.syncope.core.persistence.jpa.entity.am.JPASAML2SPClientApp; import org.apache.syncope.core.persistence.jpa.entity.am.JPAWAConfigEntry; @@ -264,8 +264,8 @@ public E newEntity(final Class reference) { result = (E) new JPASRARoute(); } else if (reference.equals(AuthModule.class)) { result = (E) new JPAAuthModule(); - } else if (reference.equals(PasswordModule.class)) { - result = (E) new JPAPasswordModule(); + } else if (reference.equals(PasswordManagement.class)) { + result = (E) new JPAPasswordManagement(); } else if (reference.equals(AttrRepo.class)) { result = (E) new JPAAttrRepo(); } else if (reference.equals(AuthPolicy.class)) { diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/am/JPAPasswordModule.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/am/JPAPasswordManagement.java similarity index 73% rename from core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/am/JPAPasswordModule.java rename to core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/am/JPAPasswordManagement.java index 49065e4ffc4..f75cfc1eec6 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/am/JPAPasswordModule.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/am/JPAPasswordManagement.java @@ -16,29 +16,27 @@ import java.util.ArrayList; import java.util.List; import org.apache.commons.lang3.StringUtils; -import org.apache.syncope.common.lib.password.PasswordModuleConf; +import org.apache.syncope.common.lib.password.PasswordManagementConf; import org.apache.syncope.common.lib.to.Item; -import org.apache.syncope.common.lib.types.PasswordModuleState; -import org.apache.syncope.core.persistence.api.entity.am.PasswordModule; +import org.apache.syncope.common.lib.types.PasswordManagementState; +import org.apache.syncope.core.persistence.api.entity.am.PasswordManagement; import org.apache.syncope.core.persistence.jpa.entity.AbstractProvidedKeyEntity; import org.apache.syncope.core.provisioning.api.serialization.POJOHelper; @Entity -@Table(name = JPAPasswordModule.TABLE) -public class JPAPasswordModule extends AbstractProvidedKeyEntity implements PasswordModule { +@Table(name = JPAPasswordManagement.TABLE) +public class JPAPasswordManagement extends AbstractProvidedKeyEntity implements PasswordManagement { private static final long serialVersionUID = 5457779846065079998L; - public static final String TABLE = "PasswordModule"; + public static final String TABLE = "PasswordManagement"; protected static final TypeReference> TYPEREF = new TypeReference>() { }; private String description; - @Enumerated(EnumType.STRING) - @NotNull - private PasswordModuleState passwordModuleState; + private boolean enabled; @Lob private String items; @@ -60,13 +58,14 @@ public void setDescription(final String description) { } @Override - public PasswordModuleState getState() { - return passwordModuleState; + public boolean isEnabled() { + return enabled; } @Override - public void setState(final PasswordModuleState passwordModuleState) { - this.passwordModuleState = passwordModuleState; + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } @Override @@ -75,17 +74,17 @@ public List getItems() { } @Override - public PasswordModuleConf getConf() { - PasswordModuleConf conf = null; + public PasswordManagementConf getConf() { + PasswordManagementConf conf = null; if (!StringUtils.isBlank(jsonConf)) { - conf = POJOHelper.deserialize(jsonConf, PasswordModuleConf.class); + conf = POJOHelper.deserialize(jsonConf, PasswordManagementConf.class); } return conf; } @Override - public void setConf(final PasswordModuleConf conf) { + public void setConf(final PasswordManagementConf conf) { jsonConf = POJOHelper.serialize(conf); } diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PasswordManagementTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PasswordManagementTest.java new file mode 100644 index 00000000000..20f000b2cf9 --- /dev/null +++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PasswordManagementTest.java @@ -0,0 +1,187 @@ +package org.apache.syncope.core.persistence.jpa.inner; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.List; +import org.apache.commons.lang3.ClassUtils; +import org.apache.syncope.common.lib.password.JDBCPasswordManagementConf; +import org.apache.syncope.common.lib.password.LDAPPasswordManagementConf; +import org.apache.syncope.common.lib.password.PasswordManagementConf; +import org.apache.syncope.common.lib.password.SyncopePasswordManagementConf; +import org.apache.syncope.common.lib.to.Item; +import org.apache.syncope.core.persistence.api.dao.PasswordManagementDAO; +import org.apache.syncope.core.persistence.api.entity.am.PasswordManagement; +import org.apache.syncope.core.persistence.jpa.AbstractTest; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; + +@Transactional +public class PasswordManagementTest extends AbstractTest { + + private static boolean isSpecificConf( + final PasswordManagementConf conf, + final Class clazz) { + return ClassUtils.isAssignable(clazz, conf.getClass()); + } + + @Autowired + private PasswordManagementDAO passwordManagementDAO; + + @Test + public void findAll() { + List modules = passwordManagementDAO.findAll(); + assertNotNull(modules); + assertFalse(modules.isEmpty()); + assertEquals(3, modules.size()); + } + + @Test + public void find() { + PasswordManagement passwordManagement = passwordManagementDAO.findById("DefaultSyncopePasswordManagement").orElseThrow(); + assertTrue(passwordManagement.getConf() instanceof SyncopePasswordManagementConf); + + passwordManagement = passwordManagementDAO.findById("DefaultLDAPPasswordManagement").orElseThrow(); + assertTrue(passwordManagement.getConf() instanceof LDAPPasswordManagementConf); + + passwordManagement = passwordManagementDAO.findById("DefaultJDBCPasswordManagement").orElseThrow(); + assertTrue(passwordManagement.getConf() instanceof JDBCPasswordManagementConf); + } + + @Test + public void findByType() { + List passwordManagements = passwordManagementDAO.findAll(); + assertTrue(passwordManagements.stream().anyMatch( + passwordManagement -> isSpecificConf(passwordManagement.getConf(), + SyncopePasswordManagementConf.class) + && passwordManagement.getKey().equals("DefaultSyncopePasswordManagement"))); + assertTrue(passwordManagements.stream().anyMatch( + passwordManagement -> isSpecificConf(passwordManagement.getConf(), + LDAPPasswordManagementConf.class) + && passwordManagement.getKey().equals("DefaultLDAPPasswordManagement"))); + assertTrue(passwordManagements.stream().anyMatch( + passwordManagement -> isSpecificConf(passwordManagement.getConf(), + JDBCPasswordManagementConf.class) + && passwordManagement.getKey().equals("DefaultJDBCPasswordManagement"))); + } + + private void savePasswordManagement(final String key, final PasswordManagementConf conf) { + PasswordManagement module = entityFactory.newEntity(PasswordManagement.class); + module.setKey(key); + module.setDescription("A password management module"); + module.setConf(conf); + + Item keyMapping = new Item(); + keyMapping.setIntAttrName("uid"); + keyMapping.setExtAttrName("username"); + module.getItems().add(keyMapping); + + Item fullnameMapping = new Item(); + fullnameMapping.setIntAttrName("cn"); + fullnameMapping.setExtAttrName("fullname"); + module.getItems().add(fullnameMapping); + + module = passwordManagementDAO.save(module); + entityManager.flush(); + + assertNotNull(module); + assertNotNull(module.getKey()); + assertEquals(module, passwordManagementDAO.findById(module.getKey()).orElseThrow()); + assertEquals(2, module.getItems().size()); + } + + @Test + public void saveWithSyncopeModule() { + SyncopePasswordManagementConf conf = new SyncopePasswordManagementConf(); + conf.setDomain("Master"); + + savePasswordManagement("SyncopePasswordManagementTest", conf); + } + + @Test + public void saveWithLdapModule() { + LDAPPasswordManagementConf conf = new LDAPPasswordManagementConf(); + conf.setBaseDn("dc=example,dc=org"); + conf.setSearchFilter("cn={user}"); + conf.setSubtreeSearch(true); + conf.setLdapUrl("ldap://localhost:1389"); + conf.setUsernameAttribute("uid"); + conf.setBindCredential("Password"); + + savePasswordManagement("LDAPPasswordManagementTest", conf); + } + + @Test + public void saveWithJdbcModule() { + JDBCPasswordManagementConf conf = new JDBCPasswordManagementConf(); + conf.setSqlFindEmail("SELECT email from users_table where name=?"); + conf.setSqlFindPhone("SELECT phoneNumber from users_table where name=?"); + conf.setSqlFindUser("SELECT * from users_table where name=?"); + conf.setSqlChangePassword("UPDATE users_table SET password=? WHERE name=?"); + + savePasswordManagement("JDBCPasswordManagementTest", conf); + } + + @Test + public void updateWithSyncopeModule() { + PasswordManagement module = passwordManagementDAO.findById("DefaultSyncopePasswordManagement").orElseThrow(); + + PasswordManagementConf conf = module.getConf(); + SyncopePasswordManagementConf.class.cast(conf).setDomain("Two"); + module.setConf(conf); + + module = passwordManagementDAO.save(module); + assertNotNull(module); + assertNotNull(module.getKey()); + + PasswordManagement found = passwordManagementDAO.findById(module.getKey()).orElseThrow(); + assertEquals("Two", SyncopePasswordManagementConf.class.cast(found.getConf()).getDomain()); + } + + @Test + public void updateWithLdapModule() { + PasswordManagement module = passwordManagementDAO.findById("DefaultLDAPPasswordManagement").orElseThrow(); + + PasswordManagementConf conf = module.getConf(); + LDAPPasswordManagementConf.class.cast(conf).setBaseDn("dc=example2,dc=org"); + LDAPPasswordManagementConf.class.cast(conf).setSearchFilter("cn={user2}"); + module.setConf(conf); + + module = passwordManagementDAO.save(module); + assertNotNull(module); + assertNotNull(module.getKey()); + + PasswordManagement found = passwordManagementDAO.findById(module.getKey()).orElseThrow(); + assertEquals("dc=example2,dc=org", LDAPPasswordManagementConf.class.cast(found.getConf()).getBaseDn()); + assertEquals("cn={user2}", LDAPPasswordManagementConf.class.cast(found.getConf()).getSearchFilter()); + } + + @Test + public void updateWithJDBCModule() { + PasswordManagement module = passwordManagementDAO.findById("DefaultJDBCPasswordManagement").orElseThrow(); + + PasswordManagementConf conf = module.getConf(); + JDBCPasswordManagementConf.class.cast(conf).setSqlFindUser("SELECT * from other_table where name=?"); + module.setConf(conf); + + module = passwordManagementDAO.save(module); + assertNotNull(module); + assertNotNull(module.getKey()); + + PasswordManagement found = passwordManagementDAO.findById(module.getKey()).orElseThrow(); + assertEquals("SELECT * from other_table where name=?", + JDBCPasswordManagementConf.class.cast(found.getConf()).getSqlFindUser()); + } + + @Test + public void delete() { + assertTrue(passwordManagementDAO.findById("DefaultSyncopePasswordManagement").isPresent()); + + passwordManagementDAO.deleteById("DefaultSyncopePasswordManagement"); + + assertTrue(passwordManagementDAO.findById("DefaultSyncopePasswordManagement").isEmpty()); + } +} diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PasswordModuleTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PasswordModuleTest.java deleted file mode 100644 index a587ba61df6..00000000000 --- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PasswordModuleTest.java +++ /dev/null @@ -1,187 +0,0 @@ -package org.apache.syncope.core.persistence.jpa.inner; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.util.List; -import org.apache.commons.lang3.ClassUtils; -import org.apache.syncope.common.lib.password.JDBCPasswordModuleConf; -import org.apache.syncope.common.lib.password.LDAPPasswordModuleConf; -import org.apache.syncope.common.lib.password.PasswordModuleConf; -import org.apache.syncope.common.lib.password.SyncopePasswordModuleConf; -import org.apache.syncope.common.lib.to.Item; -import org.apache.syncope.core.persistence.api.dao.PasswordModuleDAO; -import org.apache.syncope.core.persistence.api.entity.am.PasswordModule; -import org.apache.syncope.core.persistence.jpa.AbstractTest; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.transaction.annotation.Transactional; - -@Transactional -public class PasswordModuleTest extends AbstractTest { - - private static boolean isSpecificConf( - final PasswordModuleConf conf, - final Class clazz) { - return ClassUtils.isAssignable(clazz, conf.getClass()); - } - - @Autowired - private PasswordModuleDAO passwordModuleDAO; - - @Test - public void findAll() { - List modules = passwordModuleDAO.findAll(); - assertNotNull(modules); - assertFalse(modules.isEmpty()); - assertEquals(3, modules.size()); - } - - @Test - public void find() { - PasswordModule passwordModule = passwordModuleDAO.findById("DefaultSyncopePasswordModule").orElseThrow(); - assertTrue(passwordModule.getConf() instanceof SyncopePasswordModuleConf); - - passwordModule = passwordModuleDAO.findById("DefaultLDAPPasswordModule").orElseThrow(); - assertTrue(passwordModule.getConf() instanceof LDAPPasswordModuleConf); - - passwordModule = passwordModuleDAO.findById("DefaultJDBCPasswordModule").orElseThrow(); - assertTrue(passwordModule.getConf() instanceof JDBCPasswordModuleConf); - } - - @Test - public void findByType() { - List passwordModules = passwordModuleDAO.findAll(); - assertTrue(passwordModules.stream().anyMatch( - passwordModule -> isSpecificConf(passwordModule.getConf(), - SyncopePasswordModuleConf.class) - && passwordModule.getKey().equals("DefaultSyncopePasswordModule"))); - assertTrue(passwordModules.stream().anyMatch( - passwordModule -> isSpecificConf(passwordModule.getConf(), - LDAPPasswordModuleConf.class) - && passwordModule.getKey().equals("DefaultLDAPPasswordModule"))); - assertTrue(passwordModules.stream().anyMatch( - passwordModule -> isSpecificConf(passwordModule.getConf(), - JDBCPasswordModuleConf.class) - && passwordModule.getKey().equals("DefaultJDBCPasswordModule"))); - } - - private void savePasswordModule(final String key, final PasswordModuleConf conf) { - PasswordModule module = entityFactory.newEntity(PasswordModule.class); - module.setKey(key); - module.setDescription("A password management module"); - module.setConf(conf); - - Item keyMapping = new Item(); - keyMapping.setIntAttrName("uid"); - keyMapping.setExtAttrName("username"); - module.getItems().add(keyMapping); - - Item fullnameMapping = new Item(); - fullnameMapping.setIntAttrName("cn"); - fullnameMapping.setExtAttrName("fullname"); - module.getItems().add(fullnameMapping); - - module = passwordModuleDAO.save(module); - entityManager.flush(); - - assertNotNull(module); - assertNotNull(module.getKey()); - assertEquals(module, passwordModuleDAO.findById(module.getKey()).orElseThrow()); - assertEquals(2, module.getItems().size()); - } - - @Test - public void saveWithSyncopeModule() { - SyncopePasswordModuleConf conf = new SyncopePasswordModuleConf(); - conf.setDomain("Master"); - - savePasswordModule("SyncopePasswordModuleTest", conf); - } - - @Test - public void saveWithLdapModule() { - LDAPPasswordModuleConf conf = new LDAPPasswordModuleConf(); - conf.setBaseDn("dc=example,dc=org"); - conf.setSearchFilter("cn={user}"); - conf.setSubtreeSearch(true); - conf.setLdapUrl("ldap://localhost:1389"); - conf.setUsernameAttribute("uid"); - conf.setBindCredential("Password"); - - savePasswordModule("LDAPPasswordModuleTest", conf); - } - - @Test - public void saveWithJdbcModule() { - JDBCPasswordModuleConf conf = new JDBCPasswordModuleConf(); - conf.setSqlFindEmail("SELECT email from users_table where name=?"); - conf.setSqlFindPhone("SELECT phoneNumber from users_table where name=?"); - conf.setSqlFindUser("SELECT * from users_table where name=?"); - conf.setSqlChangePassword("UPDATE users_table SET password=? WHERE name=?"); - - savePasswordModule("JDBCPasswordModuleTest", conf); - } - - @Test - public void updateWithSyncopeModule() { - PasswordModule module = passwordModuleDAO.findById("DefaultSyncopePasswordModule").orElseThrow(); - - PasswordModuleConf conf = module.getConf(); - SyncopePasswordModuleConf.class.cast(conf).setDomain("Two"); - module.setConf(conf); - - module = passwordModuleDAO.save(module); - assertNotNull(module); - assertNotNull(module.getKey()); - - PasswordModule found = passwordModuleDAO.findById(module.getKey()).orElseThrow(); - assertEquals("Two", SyncopePasswordModuleConf.class.cast(found.getConf()).getDomain()); - } - - @Test - public void updateWithLdapModule() { - PasswordModule module = passwordModuleDAO.findById("DefaultLDAPPasswordModule").orElseThrow(); - - PasswordModuleConf conf = module.getConf(); - LDAPPasswordModuleConf.class.cast(conf).setBaseDn("dc=example2,dc=org"); - LDAPPasswordModuleConf.class.cast(conf).setSearchFilter("cn={user2}"); - module.setConf(conf); - - module = passwordModuleDAO.save(module); - assertNotNull(module); - assertNotNull(module.getKey()); - - PasswordModule found = passwordModuleDAO.findById(module.getKey()).orElseThrow(); - assertEquals("dc=example2,dc=org", LDAPPasswordModuleConf.class.cast(found.getConf()).getBaseDn()); - assertEquals("cn={user2}", LDAPPasswordModuleConf.class.cast(found.getConf()).getSearchFilter()); - } - - @Test - public void updateWithJDBCModule() { - PasswordModule module = passwordModuleDAO.findById("DefaultJDBCPasswordModule").orElseThrow(); - - PasswordModuleConf conf = module.getConf(); - JDBCPasswordModuleConf.class.cast(conf).setSqlFindUser("SELECT * from other_table where name=?"); - module.setConf(conf); - - module = passwordModuleDAO.save(module); - assertNotNull(module); - assertNotNull(module.getKey()); - - PasswordModule found = passwordModuleDAO.findById(module.getKey()).orElseThrow(); - assertEquals("SELECT * from other_table where name=?", - JDBCPasswordModuleConf.class.cast(found.getConf()).getSqlFindUser()); - } - - @Test - public void delete() { - assertTrue(passwordModuleDAO.findById("DefaultSyncopePasswordModule").isPresent()); - - passwordModuleDAO.deleteById("DefaultSyncopePasswordModule"); - - assertTrue(passwordModuleDAO.findById("DefaultSyncopePasswordModule").isEmpty()); - } -} diff --git a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml index 271051a2a23..a69024507d7 100644 --- a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml +++ b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml @@ -91,15 +91,15 @@ under the License. jsonConf='{"_class":"org.apache.syncope.common.lib.auth.OAuth20AuthModuleConf","clientName":"oauth20","clientId":"OAUTH20","clientSecret":"secret","enabled":true,"customParams":{},"tokenUrl":"https://localhost/oauth2/token","responseType":"code","scope":"oauth test","userIdAttribute":"username","authUrl":"https://localhost/oauth2/auth","profileUrl":"https://localhost/oauth2/profile","withState":false,"profileVerb":"POST"}' authModuleState="ACTIVE"/> - - - + + + , PasswordManagementRepoExt, PasswordManagementDAO { +} diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/PasswordManagementRepoExt.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/PasswordManagementRepoExt.java new file mode 100644 index 00000000000..cbd2c71d445 --- /dev/null +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/PasswordManagementRepoExt.java @@ -0,0 +1,10 @@ +package org.apache.syncope.core.persistence.neo4j.dao.repo; + +import org.apache.syncope.core.persistence.api.entity.am.PasswordManagement; + +public interface PasswordManagementRepoExt { + + PasswordManagement save(PasswordManagement passwordManagement); + + void delete(PasswordManagement passwordManagement); +} diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/PasswordManagementRepoExtImpl.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/PasswordManagementRepoExtImpl.java new file mode 100644 index 00000000000..683104f1fc9 --- /dev/null +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/PasswordManagementRepoExtImpl.java @@ -0,0 +1,33 @@ +package org.apache.syncope.core.persistence.neo4j.dao.repo; + +import org.apache.syncope.core.persistence.api.entity.am.PasswordManagement; +import org.apache.syncope.core.persistence.neo4j.entity.am.Neo4JPasswordManagement; +import org.apache.syncope.core.persistence.neo4j.spring.NodeValidator; +import org.springframework.data.neo4j.core.Neo4jTemplate; + +public class PasswordManagementRepoExtImpl implements PasswordManagementRepoExt { + + protected final Neo4jTemplate neo4jTemplate; + + protected final NodeValidator nodeValidator; + + public PasswordManagementRepoExtImpl( + final Neo4jTemplate neo4jTemplate, + final NodeValidator nodeValidator) { + this.neo4jTemplate = neo4jTemplate; + this.nodeValidator = nodeValidator; + } + + @Override + public PasswordManagement save(final PasswordManagement passwordManagement) { + ((Neo4JPasswordManagement) passwordManagement).list2json(); + PasswordManagement saved = neo4jTemplate.save(nodeValidator.validate(passwordManagement)); + ((Neo4JPasswordManagement) saved).postSave(); + return saved; + } + + @Override + public void delete(final PasswordManagement passwordManagement) { + neo4jTemplate.deleteById(passwordManagement.getKey(), Neo4JPasswordManagement.class); + } +} diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/PasswordModuleRepo.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/PasswordModuleRepo.java deleted file mode 100644 index 0bad60fe210..00000000000 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/PasswordModuleRepo.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.apache.syncope.core.persistence.neo4j.dao.repo; - -import org.apache.syncope.core.persistence.api.dao.PasswordModuleDAO; -import org.apache.syncope.core.persistence.neo4j.entity.am.Neo4jPasswordModule; -import org.springframework.data.repository.ListCrudRepository; - -public interface PasswordModuleRepo - extends ListCrudRepository, PasswordModuleRepoExt, PasswordModuleDAO { -} diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/PasswordModuleRepoExt.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/PasswordModuleRepoExt.java deleted file mode 100644 index 5c289db4e56..00000000000 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/PasswordModuleRepoExt.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.apache.syncope.core.persistence.neo4j.dao.repo; - -import org.apache.syncope.core.persistence.api.entity.am.PasswordModule; - -public interface PasswordModuleRepoExt { - - PasswordModule save(PasswordModule passwordModule); - - void delete(PasswordModule passwordModule); -} diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/PasswordModuleRepoExtImpl.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/PasswordModuleRepoExtImpl.java deleted file mode 100644 index 73e20da2f64..00000000000 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/PasswordModuleRepoExtImpl.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.apache.syncope.core.persistence.neo4j.dao.repo; - -import org.apache.syncope.core.persistence.api.entity.am.PasswordModule; -import org.apache.syncope.core.persistence.neo4j.entity.am.Neo4jPasswordModule; -import org.apache.syncope.core.persistence.neo4j.spring.NodeValidator; -import org.springframework.data.neo4j.core.Neo4jTemplate; - -public class PasswordModuleRepoExtImpl implements PasswordModuleRepoExt { - - protected final Neo4jTemplate neo4jTemplate; - - protected final NodeValidator nodeValidator; - - public PasswordModuleRepoExtImpl( - final Neo4jTemplate neo4jTemplate, - final NodeValidator nodeValidator) { - this.neo4jTemplate = neo4jTemplate; - this.nodeValidator = nodeValidator; - } - - @Override - public PasswordModule save(final PasswordModule passwordModule) { - ((Neo4jPasswordModule) passwordModule).list2json(); - PasswordModule saved = neo4jTemplate.save(nodeValidator.validate(passwordModule)); - ((Neo4jPasswordModule) saved).postSave(); - return saved; - } - - @Override - public void delete(final PasswordModule passwordModule) { - neo4jTemplate.deleteById(passwordModule.getKey(), Neo4jPasswordModule.class); - } -} diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/Neo4jEntityFactory.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/Neo4jEntityFactory.java index 3b3a980eddc..bbbb25c6c23 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/Neo4jEntityFactory.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/Neo4jEntityFactory.java @@ -54,7 +54,7 @@ import org.apache.syncope.core.persistence.api.entity.am.CASSPClientApp; import org.apache.syncope.core.persistence.api.entity.am.OIDCJWKS; import org.apache.syncope.core.persistence.api.entity.am.OIDCRPClientApp; -import org.apache.syncope.core.persistence.api.entity.am.PasswordModule; +import org.apache.syncope.core.persistence.api.entity.am.PasswordManagement; import org.apache.syncope.core.persistence.api.entity.am.SAML2IdPEntity; import org.apache.syncope.core.persistence.api.entity.am.SAML2SPClientApp; import org.apache.syncope.core.persistence.api.entity.am.WAConfigEntry; @@ -101,7 +101,7 @@ import org.apache.syncope.core.persistence.neo4j.entity.am.Neo4jCASSPClientApp; import org.apache.syncope.core.persistence.neo4j.entity.am.Neo4jOIDCJWKS; import org.apache.syncope.core.persistence.neo4j.entity.am.Neo4jOIDCRPClientApp; -import org.apache.syncope.core.persistence.neo4j.entity.am.Neo4jPasswordModule; +import org.apache.syncope.core.persistence.neo4j.entity.am.Neo4JPasswordManagement; import org.apache.syncope.core.persistence.neo4j.entity.am.Neo4jSAML2IdPEntity; import org.apache.syncope.core.persistence.neo4j.entity.am.Neo4jSAML2SPClientApp; import org.apache.syncope.core.persistence.neo4j.entity.am.Neo4jWAConfigEntry; @@ -265,8 +265,8 @@ public E newEntity(final Class reference) { result = (E) new Neo4jSRARoute(); } else if (reference.equals(AuthModule.class)) { result = (E) new Neo4jAuthModule(); - } else if (reference.equals(PasswordModule.class)) { - result = (E) new Neo4jPasswordModule(); + } else if (reference.equals(PasswordManagement.class)) { + result = (E) new Neo4JPasswordManagement(); } else if (reference.equals(AttrRepo.class)) { result = (E) new Neo4jAttrRepo(); } else if (reference.equals(AuthPolicy.class)) { diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4jPasswordModule.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4JPasswordManagement.java similarity index 70% rename from core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4jPasswordModule.java rename to core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4JPasswordManagement.java index d2769b0ce1e..c04baa3d815 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4jPasswordModule.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4JPasswordManagement.java @@ -5,30 +5,29 @@ import java.util.ArrayList; import java.util.List; import org.apache.commons.lang3.StringUtils; -import org.apache.syncope.common.lib.password.PasswordModuleConf; +import org.apache.syncope.common.lib.password.PasswordManagementConf; import org.apache.syncope.common.lib.to.Item; -import org.apache.syncope.common.lib.types.PasswordModuleState; -import org.apache.syncope.core.persistence.api.entity.am.PasswordModule; +import org.apache.syncope.common.lib.types.PasswordManagementState; +import org.apache.syncope.core.persistence.api.entity.am.PasswordManagement; import org.apache.syncope.core.persistence.neo4j.entity.AbstractProvidedKeyNode; import org.apache.syncope.core.provisioning.api.serialization.POJOHelper; import org.springframework.data.annotation.Transient; import org.springframework.data.neo4j.core.schema.Node; import org.springframework.data.neo4j.core.schema.PostLoad; -@Node(Neo4jPasswordModule.NODE) -public class Neo4jPasswordModule extends AbstractProvidedKeyNode implements PasswordModule { +@Node(Neo4JPasswordManagement.NODE) +public class Neo4JPasswordManagement extends AbstractProvidedKeyNode implements PasswordManagement { private static final long serialVersionUID = 5457779846065079998L; - public static final String NODE = "PasswordModule"; + public static final String NODE = "PasswordManagement"; protected static final TypeReference> TYPEREF = new TypeReference>() { }; private String description; - @NotNull(message = "passwordModuleState must not be empty") - private PasswordModuleState passwordModuleState; + private boolean enabled; private String items; @@ -48,13 +47,13 @@ public void setDescription(final String description) { } @Override - public PasswordModuleState getState() { - return passwordModuleState; + public boolean isEnabled() { + return enabled; } @Override - public void setState(final PasswordModuleState state) { - this.passwordModuleState = state; + public void setEnabled(final boolean enabled) { + this.enabled = enabled; } @Override @@ -63,17 +62,17 @@ public List getItems() { } @Override - public PasswordModuleConf getConf() { - PasswordModuleConf conf = null; + public PasswordManagementConf getConf() { + PasswordManagementConf conf = null; if (!StringUtils.isBlank(jsonConf)) { - conf = POJOHelper.deserialize(jsonConf, PasswordModuleConf.class); + conf = POJOHelper.deserialize(jsonConf, PasswordManagementConf.class); } return conf; } @Override - public void setConf(final PasswordModuleConf conf) { + public void setConf(final PasswordManagementConf conf) { jsonConf = POJOHelper.serialize(conf); } diff --git a/core/persistence-neo4j/src/test/java/org/apache/syncope/core/persistence/neo4j/inner/PasswordManagementTest.java b/core/persistence-neo4j/src/test/java/org/apache/syncope/core/persistence/neo4j/inner/PasswordManagementTest.java new file mode 100644 index 00000000000..cbce67dcd16 --- /dev/null +++ b/core/persistence-neo4j/src/test/java/org/apache/syncope/core/persistence/neo4j/inner/PasswordManagementTest.java @@ -0,0 +1,187 @@ +package org.apache.syncope.core.persistence.neo4j.inner; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.List; +import org.apache.commons.lang3.ClassUtils; +import org.apache.syncope.common.lib.password.JDBCPasswordManagementConf; +import org.apache.syncope.common.lib.password.LDAPPasswordManagementConf; +import org.apache.syncope.common.lib.password.PasswordManagementConf; +import org.apache.syncope.common.lib.password.SyncopePasswordManagementConf; +import org.apache.syncope.common.lib.to.Item; +import org.apache.syncope.core.persistence.api.dao.PasswordManagementDAO; +import org.apache.syncope.core.persistence.api.entity.am.PasswordManagement; +import org.apache.syncope.core.persistence.neo4j.AbstractTest; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; + +@Transactional +public class PasswordManagementTest extends AbstractTest { + + private static boolean isSpecificConf( + final PasswordManagementConf conf, + final Class clazz) { + return ClassUtils.isAssignable(clazz, conf.getClass()); + } + + @Autowired + private PasswordManagementDAO passwordManagementDAO; + + @Test + public void findAll() { + List modules = passwordManagementDAO.findAll(); + assertNotNull(modules); + assertFalse(modules.isEmpty()); + assertEquals(3, modules.size()); + } + + @Test + public void find() { + PasswordManagement passwordManagement = passwordManagementDAO.findById("DefaultSyncopePasswordManagement") + .orElseThrow(); + assertTrue(passwordManagement.getConf() instanceof SyncopePasswordManagementConf); + + passwordManagement = passwordManagementDAO.findById("DefaultLDAPPasswordManagement").orElseThrow(); + assertTrue(passwordManagement.getConf() instanceof LDAPPasswordManagementConf); + + passwordManagement = passwordManagementDAO.findById("DefaultJDBCPasswordManagement").orElseThrow(); + assertTrue(passwordManagement.getConf() instanceof JDBCPasswordManagementConf); + } + + @Test + public void findByType() { + List passwordManagements = passwordManagementDAO.findAll(); + assertTrue(passwordManagements.stream().anyMatch( + passwordManagement -> isSpecificConf(passwordManagement.getConf(), + SyncopePasswordManagementConf.class) + && passwordManagement.getKey().equals("DefaultSyncopePasswordManagement"))); + assertTrue(passwordManagements.stream().anyMatch( + passwordManagement -> isSpecificConf(passwordManagement.getConf(), + LDAPPasswordManagementConf.class) + && passwordManagement.getKey().equals("DefaultLDAPPasswordManagement"))); + assertTrue(passwordManagements.stream().anyMatch( + passwordManagement -> isSpecificConf(passwordManagement.getConf(), + JDBCPasswordManagementConf.class) + && passwordManagement.getKey().equals("DefaultJDBCPasswordManagement"))); + } + + private void savePasswordManagement(final String key, final PasswordManagementConf conf) { + PasswordManagement module = entityFactory.newEntity(PasswordManagement.class); + module.setKey(key); + module.setDescription("A password management module"); + module.setConf(conf); + + Item keyMapping = new Item(); + keyMapping.setIntAttrName("uid"); + keyMapping.setExtAttrName("username"); + module.getItems().add(keyMapping); + + Item fullnameMapping = new Item(); + fullnameMapping.setIntAttrName("cn"); + fullnameMapping.setExtAttrName("fullname"); + module.getItems().add(fullnameMapping); + + module = passwordManagementDAO.save(module); + + assertNotNull(module); + assertNotNull(module.getKey()); + assertEquals(module, passwordManagementDAO.findById(module.getKey()).orElseThrow()); + assertEquals(2, module.getItems().size()); + } + + @Test + public void saveWithSyncopeModule() { + SyncopePasswordManagementConf conf = new SyncopePasswordManagementConf(); + conf.setDomain("Master"); + + savePasswordManagement("SyncopePasswordManagementTest", conf); + } + + @Test + public void saveWithLdapModule() { + LDAPPasswordManagementConf conf = new LDAPPasswordManagementConf(); + conf.setBaseDn("dc=example,dc=org"); + conf.setSearchFilter("cn={user}"); + conf.setSubtreeSearch(true); + conf.setLdapUrl("ldap://localhost:1389"); + conf.setUsernameAttribute("uid"); + conf.setBindCredential("Password"); + + savePasswordManagement("LDAPPasswordManagementTest", conf); + } + + @Test + public void saveWithJdbcModule() { + JDBCPasswordManagementConf conf = new JDBCPasswordManagementConf(); + conf.setSqlFindEmail("SELECT email from users_table where name=?"); + conf.setSqlFindPhone("SELECT phoneNumber from users_table where name=?"); + conf.setSqlFindUser("SELECT * from users_table where name=?"); + conf.setSqlChangePassword("UPDATE users_table SET password=? WHERE name=?"); + + savePasswordManagement("JDBCPasswordManagementTest", conf); + } + + @Test + public void updateWithSyncopeModule() { + PasswordManagement module = passwordManagementDAO.findById("DefaultSyncopePasswordManagement").orElseThrow(); + + PasswordManagementConf conf = module.getConf(); + SyncopePasswordManagementConf.class.cast(conf).setDomain("Two"); + module.setConf(conf); + + module = passwordManagementDAO.save(module); + assertNotNull(module); + assertNotNull(module.getKey()); + + PasswordManagement found = passwordManagementDAO.findById(module.getKey()).orElseThrow(); + assertEquals("Two", SyncopePasswordManagementConf.class.cast(found.getConf()).getDomain()); + } + + @Test + public void updateWithLdapModule() { + PasswordManagement module = passwordManagementDAO.findById("DefaultLDAPPasswordManagement").orElseThrow(); + + PasswordManagementConf conf = module.getConf(); + LDAPPasswordManagementConf.class.cast(conf).setBaseDn("dc=example2,dc=org"); + LDAPPasswordManagementConf.class.cast(conf).setSearchFilter("cn={user2}"); + module.setConf(conf); + + module = passwordManagementDAO.save(module); + assertNotNull(module); + assertNotNull(module.getKey()); + + PasswordManagement found = passwordManagementDAO.findById(module.getKey()).orElseThrow(); + assertEquals("dc=example2,dc=org", LDAPPasswordManagementConf.class.cast(found.getConf()).getBaseDn()); + assertEquals("cn={user2}", LDAPPasswordManagementConf.class.cast(found.getConf()).getSearchFilter()); + } + + @Test + public void updateWithJDBCModule() { + PasswordManagement module = passwordManagementDAO.findById("DefaultJDBCPasswordManagement").orElseThrow(); + + PasswordManagementConf conf = module.getConf(); + JDBCPasswordManagementConf.class.cast(conf).setSqlFindUser("SELECT * from other_table where name=?"); + module.setConf(conf); + + module = passwordManagementDAO.save(module); + assertNotNull(module); + assertNotNull(module.getKey()); + + PasswordManagement found = passwordManagementDAO.findById(module.getKey()).orElseThrow(); + assertEquals("SELECT * from other_table where name=?", + JDBCPasswordManagementConf.class.cast(found.getConf()).getSqlFindUser()); + } + + @Test + public void delete() { + assertTrue(passwordManagementDAO.findById("DefaultSyncopePasswordManagement").isPresent()); + + passwordManagementDAO.deleteById("DefaultSyncopePasswordManagement"); + + assertTrue(passwordManagementDAO.findById("DefaultSyncopePasswordManagement").isEmpty()); + } +} diff --git a/core/persistence-neo4j/src/test/java/org/apache/syncope/core/persistence/neo4j/inner/PasswordModuleTest.java b/core/persistence-neo4j/src/test/java/org/apache/syncope/core/persistence/neo4j/inner/PasswordModuleTest.java deleted file mode 100644 index 66b307d659c..00000000000 --- a/core/persistence-neo4j/src/test/java/org/apache/syncope/core/persistence/neo4j/inner/PasswordModuleTest.java +++ /dev/null @@ -1,186 +0,0 @@ -package org.apache.syncope.core.persistence.neo4j.inner; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.util.List; -import org.apache.commons.lang3.ClassUtils; -import org.apache.syncope.common.lib.password.JDBCPasswordModuleConf; -import org.apache.syncope.common.lib.password.LDAPPasswordModuleConf; -import org.apache.syncope.common.lib.password.PasswordModuleConf; -import org.apache.syncope.common.lib.password.SyncopePasswordModuleConf; -import org.apache.syncope.common.lib.to.Item; -import org.apache.syncope.core.persistence.api.dao.PasswordModuleDAO; -import org.apache.syncope.core.persistence.api.entity.am.PasswordModule; -import org.apache.syncope.core.persistence.neo4j.AbstractTest; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.transaction.annotation.Transactional; - -@Transactional -public class PasswordModuleTest extends AbstractTest { - - private static boolean isSpecificConf( - final PasswordModuleConf conf, - final Class clazz) { - return ClassUtils.isAssignable(clazz, conf.getClass()); - } - - @Autowired - private PasswordModuleDAO passwordModuleDAO; - - @Test - public void findAll() { - List modules = passwordModuleDAO.findAll(); - assertNotNull(modules); - assertFalse(modules.isEmpty()); - assertEquals(3, modules.size()); - } - - @Test - public void find() { - PasswordModule passwordModule = passwordModuleDAO.findById("DefaultSyncopePasswordModule").orElseThrow(); - assertTrue(passwordModule.getConf() instanceof SyncopePasswordModuleConf); - - passwordModule = passwordModuleDAO.findById("DefaultLDAPPasswordModule").orElseThrow(); - assertTrue(passwordModule.getConf() instanceof LDAPPasswordModuleConf); - - passwordModule = passwordModuleDAO.findById("DefaultJDBCPasswordModule").orElseThrow(); - assertTrue(passwordModule.getConf() instanceof JDBCPasswordModuleConf); - } - - @Test - public void findByType() { - List passwordModules = passwordModuleDAO.findAll(); - assertTrue(passwordModules.stream().anyMatch( - passwordModule -> isSpecificConf(passwordModule.getConf(), - SyncopePasswordModuleConf.class) - && passwordModule.getKey().equals("DefaultSyncopePasswordModule"))); - assertTrue(passwordModules.stream().anyMatch( - passwordModule -> isSpecificConf(passwordModule.getConf(), - LDAPPasswordModuleConf.class) - && passwordModule.getKey().equals("DefaultLDAPPasswordModule"))); - assertTrue(passwordModules.stream().anyMatch( - passwordModule -> isSpecificConf(passwordModule.getConf(), - JDBCPasswordModuleConf.class) - && passwordModule.getKey().equals("DefaultJDBCPasswordModule"))); - } - - private void savePasswordModule(final String key, final PasswordModuleConf conf) { - PasswordModule module = entityFactory.newEntity(PasswordModule.class); - module.setKey(key); - module.setDescription("A password management module"); - module.setConf(conf); - - Item keyMapping = new Item(); - keyMapping.setIntAttrName("uid"); - keyMapping.setExtAttrName("username"); - module.getItems().add(keyMapping); - - Item fullnameMapping = new Item(); - fullnameMapping.setIntAttrName("cn"); - fullnameMapping.setExtAttrName("fullname"); - module.getItems().add(fullnameMapping); - - module = passwordModuleDAO.save(module); - - assertNotNull(module); - assertNotNull(module.getKey()); - assertEquals(module, passwordModuleDAO.findById(module.getKey()).orElseThrow()); - assertEquals(2, module.getItems().size()); - } - - @Test - public void saveWithSyncopeModule() { - SyncopePasswordModuleConf conf = new SyncopePasswordModuleConf(); - conf.setDomain("Master"); - - savePasswordModule("SyncopePasswordModuleTest", conf); - } - - @Test - public void saveWithLdapModule() { - LDAPPasswordModuleConf conf = new LDAPPasswordModuleConf(); - conf.setBaseDn("dc=example,dc=org"); - conf.setSearchFilter("cn={user}"); - conf.setSubtreeSearch(true); - conf.setLdapUrl("ldap://localhost:1389"); - conf.setUsernameAttribute("uid"); - conf.setBindCredential("Password"); - - savePasswordModule("LDAPPasswordModuleTest", conf); - } - - @Test - public void saveWithJdbcModule() { - JDBCPasswordModuleConf conf = new JDBCPasswordModuleConf(); - conf.setSqlFindEmail("SELECT email from users_table where name=?"); - conf.setSqlFindPhone("SELECT phoneNumber from users_table where name=?"); - conf.setSqlFindUser("SELECT * from users_table where name=?"); - conf.setSqlChangePassword("UPDATE users_table SET password=? WHERE name=?"); - - savePasswordModule("JDBCPasswordModuleTest", conf); - } - - @Test - public void updateWithSyncopeModule() { - PasswordModule module = passwordModuleDAO.findById("DefaultSyncopePasswordModule").orElseThrow(); - - PasswordModuleConf conf = module.getConf(); - SyncopePasswordModuleConf.class.cast(conf).setDomain("Two"); - module.setConf(conf); - - module = passwordModuleDAO.save(module); - assertNotNull(module); - assertNotNull(module.getKey()); - - PasswordModule found = passwordModuleDAO.findById(module.getKey()).orElseThrow(); - assertEquals("Two", SyncopePasswordModuleConf.class.cast(found.getConf()).getDomain()); - } - - @Test - public void updateWithLdapModule() { - PasswordModule module = passwordModuleDAO.findById("DefaultLDAPPasswordModule").orElseThrow(); - - PasswordModuleConf conf = module.getConf(); - LDAPPasswordModuleConf.class.cast(conf).setBaseDn("dc=example2,dc=org"); - LDAPPasswordModuleConf.class.cast(conf).setSearchFilter("cn={user2}"); - module.setConf(conf); - - module = passwordModuleDAO.save(module); - assertNotNull(module); - assertNotNull(module.getKey()); - - PasswordModule found = passwordModuleDAO.findById(module.getKey()).orElseThrow(); - assertEquals("dc=example2,dc=org", LDAPPasswordModuleConf.class.cast(found.getConf()).getBaseDn()); - assertEquals("cn={user2}", LDAPPasswordModuleConf.class.cast(found.getConf()).getSearchFilter()); - } - - @Test - public void updateWithJDBCModule() { - PasswordModule module = passwordModuleDAO.findById("DefaultJDBCPasswordModule").orElseThrow(); - - PasswordModuleConf conf = module.getConf(); - JDBCPasswordModuleConf.class.cast(conf).setSqlFindUser("SELECT * from other_table where name=?"); - module.setConf(conf); - - module = passwordModuleDAO.save(module); - assertNotNull(module); - assertNotNull(module.getKey()); - - PasswordModule found = passwordModuleDAO.findById(module.getKey()).orElseThrow(); - assertEquals("SELECT * from other_table where name=?", - JDBCPasswordModuleConf.class.cast(found.getConf()).getSqlFindUser()); - } - - @Test - public void delete() { - assertTrue(passwordModuleDAO.findById("DefaultSyncopePasswordModule").isPresent()); - - passwordModuleDAO.deleteById("DefaultSyncopePasswordModule"); - - assertTrue(passwordModuleDAO.findById("DefaultSyncopePasswordModule").isEmpty()); - } -} diff --git a/core/persistence-neo4j/src/test/resources/domains/MasterContent.xml b/core/persistence-neo4j/src/test/resources/domains/MasterContent.xml index 1bae159ff28..2fc95ad7bb8 100644 --- a/core/persistence-neo4j/src/test/resources/domains/MasterContent.xml +++ b/core/persistence-neo4j/src/test/resources/domains/MasterContent.xml @@ -91,15 +91,15 @@ under the License. jsonConf='{"_class":"org.apache.syncope.common.lib.auth.OAuth20AuthModuleConf","clientName":"oauth20","clientId":"OAUTH20","clientSecret":"secret","enabled":true,"customParams":{},"tokenUrl":"https://localhost/oauth2/token","responseType":"code","scope":"oauth test","userIdAttribute":"username","authUrl":"https://localhost/oauth2/auth","profileUrl":"https://localhost/oauth2/profile","withState":false,"profileVerb":"POST"}' authModuleState="ACTIVE"/> - - - + + + { +// if (itemTO == null) { +// LOG.error("Null {}", Item.class.getSimpleName()); +// invalidMapping.getElements().add("Null " + Item.class.getSimpleName()); +// } else if (itemTO.getIntAttrName() == null) { +// requiredValuesMissing.getElements().add("intAttrName"); +// scce.addException(requiredValuesMissing); +// } else { +// // no mandatory condition implies mandatory condition false +// if (!JexlUtils.isExpressionValid(itemTO.getMandatoryCondition() == null +// ? "false" : itemTO.getMandatoryCondition())) { +// +// SyncopeClientException invalidMandatoryCondition = +// SyncopeClientException.build(ClientExceptionType.InvalidValues); +// invalidMandatoryCondition.getElements().add(itemTO.getMandatoryCondition()); +// scce.addException(invalidMandatoryCondition); +// } +// +// Item item = new Item(); +// item.setIntAttrName(itemTO.getIntAttrName()); +// item.setExtAttrName(itemTO.getExtAttrName()); +// item.setMandatoryCondition(itemTO.getMandatoryCondition()); +// item.setConnObjectKey(itemTO.isConnObjectKey()); +// item.setPassword(itemTO.isPassword()); +// item.setPropagationJEXLTransformer(itemTO.getPropagationJEXLTransformer()); +// item.setPullJEXLTransformer(itemTO.getPullJEXLTransformer()); +// passwordManagement.getItems().add(item); +// } +// }); +// +// if (!invalidMapping.getElements().isEmpty()) { +// scce.addException(invalidMapping); +// } +// if (scce.hasExceptions()) { +// throw scce; +// } +// } + +// protected void populateItems(final PasswordManagement passwordManagement, final PasswordManagementTO passwordManagementTO) { +// passwordManagement.getItems().forEach(item -> { +// Item itemTO = new Item(); +// itemTO.setIntAttrName(item.getIntAttrName()); +// itemTO.setExtAttrName(item.getExtAttrName()); +// itemTO.setMandatoryCondition(item.getMandatoryCondition()); +// itemTO.setConnObjectKey(item.isConnObjectKey()); +// itemTO.setPassword(item.isPassword()); +// itemTO.setPropagationJEXLTransformer(item.getPropagationJEXLTransformer()); +// itemTO.setPullJEXLTransformer(item.getPullJEXLTransformer()); +// itemTO.setPurpose(MappingPurpose.NONE); +// +// passwordManagementTO.getItems().add(itemTO); +// }); +// } + + @Override + public PasswordManagement create(final PasswordManagementTO passwordManagementTO) { + PasswordManagement passwordManagement = entityFactory.newEntity(PasswordManagement.class); + passwordManagement.setKey(passwordManagementTO.getKey()); + return update(passwordManagement, passwordManagementTO); + } + + @Override + public PasswordManagement update(final PasswordManagement passwordManagement, final PasswordManagementTO passwordManagementTO) { + passwordManagement.setDescription(passwordManagementTO.getDescription()); + passwordManagement.setEnabled(passwordManagementTO.isEnabled()); + passwordManagement.setConf(passwordManagementTO.getConf()); + + passwordManagement.getItems().clear(); +// populateItems(passwordManagementTO, passwordManagement); + + return passwordManagement; + } + + @Override + public PasswordManagementTO getPasswordManagementTO(final PasswordManagement passwordManagement) { + PasswordManagementTO passwordManagementTO = new PasswordManagementTO(); + + passwordManagementTO.setKey(passwordManagement.getKey()); + passwordManagementTO.setDescription(passwordManagement.getDescription()); + passwordManagementTO.setEnabled(passwordManagement.isEnabled()); + passwordManagementTO.setConf(passwordManagement.getConf()); + +// populateItems(passwordManagement, passwordManagementTO); + + return passwordManagementTO; + } +} diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/PasswordModuleDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/PasswordModuleDataBinderImpl.java deleted file mode 100644 index 2f1ec178778..00000000000 --- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/PasswordModuleDataBinderImpl.java +++ /dev/null @@ -1,119 +0,0 @@ -package org.apache.syncope.core.provisioning.java.data; - -import org.apache.syncope.common.lib.SyncopeClientCompositeException; -import org.apache.syncope.common.lib.SyncopeClientException; -import org.apache.syncope.common.lib.to.Item; -import org.apache.syncope.common.lib.to.PasswordModuleTO; -import org.apache.syncope.common.lib.types.ClientExceptionType; -import org.apache.syncope.common.lib.types.MappingPurpose; -import org.apache.syncope.core.persistence.api.entity.EntityFactory; -import org.apache.syncope.core.persistence.api.entity.am.PasswordModule; -import org.apache.syncope.core.provisioning.api.data.PasswordModuleDataBinder; -import org.apache.syncope.core.provisioning.api.jexl.JexlUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class PasswordModuleDataBinderImpl implements PasswordModuleDataBinder { - - protected static final Logger LOG = LoggerFactory.getLogger(PasswordModuleDataBinder.class); - - protected final EntityFactory entityFactory; - - public PasswordModuleDataBinderImpl(final EntityFactory entityFactory) { - this.entityFactory = entityFactory; - } - - protected void populateItems(final PasswordModuleTO passwordModuleTO, final PasswordModule passwordModule) { - SyncopeClientCompositeException scce = SyncopeClientException.buildComposite(); - SyncopeClientException invalidMapping = - SyncopeClientException.build(ClientExceptionType.InvalidMapping); - SyncopeClientException requiredValuesMissing = - SyncopeClientException.build(ClientExceptionType.RequiredValuesMissing); - - passwordModuleTO.getItems().forEach(itemTO -> { - if (itemTO == null) { - LOG.error("Null {}", Item.class.getSimpleName()); - invalidMapping.getElements().add("Null " + Item.class.getSimpleName()); - } else if (itemTO.getIntAttrName() == null) { - requiredValuesMissing.getElements().add("intAttrName"); - scce.addException(requiredValuesMissing); - } else { - // no mandatory condition implies mandatory condition false - if (!JexlUtils.isExpressionValid(itemTO.getMandatoryCondition() == null - ? "false" : itemTO.getMandatoryCondition())) { - - SyncopeClientException invalidMandatoryCondition = - SyncopeClientException.build(ClientExceptionType.InvalidValues); - invalidMandatoryCondition.getElements().add(itemTO.getMandatoryCondition()); - scce.addException(invalidMandatoryCondition); - } - - Item item = new Item(); - item.setIntAttrName(itemTO.getIntAttrName()); - item.setExtAttrName(itemTO.getExtAttrName()); - item.setMandatoryCondition(itemTO.getMandatoryCondition()); - item.setConnObjectKey(itemTO.isConnObjectKey()); - item.setPassword(itemTO.isPassword()); - item.setPropagationJEXLTransformer(itemTO.getPropagationJEXLTransformer()); - item.setPullJEXLTransformer(itemTO.getPullJEXLTransformer()); - passwordModule.getItems().add(item); - } - }); - - if (!invalidMapping.getElements().isEmpty()) { - scce.addException(invalidMapping); - } - if (scce.hasExceptions()) { - throw scce; - } - } - - protected void populateItems(final PasswordModule passwordModule, final PasswordModuleTO passwordModuleTO) { - passwordModule.getItems().forEach(item -> { - Item itemTO = new Item(); - itemTO.setIntAttrName(item.getIntAttrName()); - itemTO.setExtAttrName(item.getExtAttrName()); - itemTO.setMandatoryCondition(item.getMandatoryCondition()); - itemTO.setConnObjectKey(item.isConnObjectKey()); - itemTO.setPassword(item.isPassword()); - itemTO.setPropagationJEXLTransformer(item.getPropagationJEXLTransformer()); - itemTO.setPullJEXLTransformer(item.getPullJEXLTransformer()); - itemTO.setPurpose(MappingPurpose.NONE); - - passwordModuleTO.getItems().add(itemTO); - }); - } - - @Override - public PasswordModule create(final PasswordModuleTO passwordModuleTO) { - PasswordModule passwordModule = entityFactory.newEntity(PasswordModule.class); - passwordModule.setKey(passwordModuleTO.getKey()); - return update(passwordModule, passwordModuleTO); - } - - @Override - public PasswordModule update(final PasswordModule passwordModule, final PasswordModuleTO passwordModuleTO) { - passwordModule.setDescription(passwordModuleTO.getDescription()); - passwordModule.setState(passwordModuleTO.getState()); - passwordModule.setConf(passwordModuleTO.getConf()); - - passwordModule.getItems().clear(); - populateItems(passwordModuleTO, passwordModule); - - return passwordModule; - } - - @Override - public PasswordModuleTO getPasswordModuleTO(final PasswordModule passwordModule) { - PasswordModuleTO passwordModuleTO = new PasswordModuleTO(); - - passwordModuleTO.setKey(passwordModule.getKey()); - passwordModuleTO.setDescription(passwordModule.getDescription()); - passwordModuleTO.setState(passwordModule.getState()); - passwordModuleTO.setConf(passwordModule.getConf()); - - populateItems(passwordModule, passwordModuleTO); - - return passwordModuleTO; - } -} diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java index 068daa7b363..4285ad6e40f 100644 --- a/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java +++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java @@ -148,7 +148,7 @@ import org.apache.syncope.common.rest.api.service.OIDCC4UIProviderService; import org.apache.syncope.common.rest.api.service.OIDCC4UIService; import org.apache.syncope.common.rest.api.service.OIDCJWKSService; -import org.apache.syncope.common.rest.api.service.PasswordModuleService; +import org.apache.syncope.common.rest.api.service.PasswordManagementService; import org.apache.syncope.common.rest.api.service.PolicyService; import org.apache.syncope.common.rest.api.service.RealmService; import org.apache.syncope.common.rest.api.service.ReconciliationService; @@ -355,7 +355,7 @@ public void initialize(final ConfigurableApplicationContext ctx) { protected static AuthModuleService AUTH_MODULE_SERVICE; - protected static PasswordModuleService PASSWORD_MODULE_SERVICE; + protected static PasswordManagementService PASSWORD_MANAGEMENT_SERVICE; protected static AttrRepoService ATTR_REPO_SERVICE; @@ -598,7 +598,7 @@ public static void restSetup() { SCIM_CONF_SERVICE = ADMIN_CLIENT.getService(SCIMConfService.class); CLIENT_APP_SERVICE = ADMIN_CLIENT.getService(ClientAppService.class); AUTH_MODULE_SERVICE = ADMIN_CLIENT.getService(AuthModuleService.class); - PASSWORD_MODULE_SERVICE = ADMIN_CLIENT.getService(PasswordModuleService.class); + PASSWORD_MANAGEMENT_SERVICE = ADMIN_CLIENT.getService(PasswordManagementService.class); ATTR_REPO_SERVICE = ADMIN_CLIENT.getService(AttrRepoService.class); SAML2IDP_ENTITY_SERVICE = ADMIN_CLIENT.getService(SAML2IdPEntityService.class); AUTH_PROFILE_SERVICE = ADMIN_CLIENT.getService(AuthProfileService.class); diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PasswordManagementITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PasswordManagementITCase.java new file mode 100644 index 00000000000..b505b3d66ac --- /dev/null +++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PasswordManagementITCase.java @@ -0,0 +1,233 @@ +package org.apache.syncope.fit.core; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; + +import jakarta.ws.rs.core.Response; +import java.io.IOException; +import java.util.EnumSet; +import java.util.List; +import org.apache.commons.lang3.ClassUtils; +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.password.JDBCPasswordManagementConf; +import org.apache.syncope.common.lib.password.LDAPPasswordManagementConf; +import org.apache.syncope.common.lib.password.PasswordManagementConf; +import org.apache.syncope.common.lib.password.SyncopePasswordManagementConf; +import org.apache.syncope.common.lib.to.PasswordManagementTO; +import org.apache.syncope.common.rest.api.service.PasswordManagementService; +import org.apache.syncope.fit.AbstractITCase; +import org.junit.jupiter.api.Test; + +public class PasswordManagementITCase extends AbstractITCase { + + private enum PasswordManagementSupportedType { + SYNCOPE, + LDAP, + JDBC + }; + + private static PasswordManagementTO createPasswordManagement(final PasswordManagementTO passwordManagementTO) { + Response response = PASSWORD_MANAGEMENT_SERVICE.create(passwordManagementTO); + if (response.getStatusInfo().getStatusCode() != Response.Status.CREATED.getStatusCode()) { + Exception ex = CLIENT_FACTORY.getExceptionMapper().fromResponse(response); + if (ex != null) { + throw (RuntimeException) ex; + } + } + return getObject(response.getLocation(), PasswordManagementService.class, passwordManagementTO.getClass()); + } + + private static PasswordManagementTO buildPasswordManagementTO(final PasswordManagementSupportedType type) { + PasswordManagementTO passwordManagementTO = new PasswordManagementTO(); + passwordManagementTO.setKey("Test" + type + "PasswordManagement" + getUUIDString()); + passwordManagementTO.setDescription("A test " + type + " Password Management"); + + PasswordManagementConf conf; + switch (type) { + case SYNCOPE: + conf = new SyncopePasswordManagementConf(); + SyncopePasswordManagementConf.class.cast(conf).setDomain(SyncopeConstants.MASTER_DOMAIN); + passwordManagementTO.setConf(conf); + break; + case LDAP: + conf = new LDAPPasswordManagementConf(); + LDAPPasswordManagementConf.class.cast(conf).setBaseDn("dc=example,dc=org"); + LDAPPasswordManagementConf.class.cast(conf).setSearchFilter("cn={user}"); + LDAPPasswordManagementConf.class.cast(conf).setSubtreeSearch(true); + LDAPPasswordManagementConf.class.cast(conf).setLdapUrl("ldap://localhost:1389"); + LDAPPasswordManagementConf.class.cast(conf).setUsernameAttribute("uid"); + LDAPPasswordManagementConf.class.cast(conf).setBaseDn("cn=Directory Manager,dc=example,dc=org"); + LDAPPasswordManagementConf.class.cast(conf).setBindCredential("Password"); + break; + case JDBC: + conf = new JDBCPasswordManagementConf(); + JDBCPasswordManagementConf.class.cast(conf) + .setSqlFindEmail("SELECT email from users_table where name=?"); + JDBCPasswordManagementConf.class.cast(conf) + .setSqlFindPhone("SELECT phoneNumber from users_table where name=?"); + JDBCPasswordManagementConf.class.cast(conf) + .setSqlFindUser("SELECT * from users_table where name=?"); + JDBCPasswordManagementConf.class.cast(conf) + .setSqlChangePassword("UPDATE users_table SET password=? WHERE name=?"); + break; + default: + break; + } + + return passwordManagementTO; + } + + private static boolean isSpecificConf( + final PasswordManagementConf conf, + final Class clazz) { + return ClassUtils.isAssignable(clazz, conf.getClass()); + } + + @Test + public void list() { + List passwordManagementTOS = PASSWORD_MANAGEMENT_SERVICE.list(); + assertNotNull(passwordManagementTOS); + assertFalse(passwordManagementTOS.isEmpty()); + + assertTrue(passwordManagementTOS.stream().anyMatch( + passwordManagement -> isSpecificConf(passwordManagement.getConf(), + SyncopePasswordManagementConf.class) && passwordManagement.getKey() + .equals("DefaultSyncopePasswordManagement"))); + assertTrue(passwordManagementTOS.stream().anyMatch( + passwordManagement -> isSpecificConf(passwordManagement.getConf(), + LDAPPasswordManagementConf.class) && passwordManagement.getKey() + .equals("DefaultLDAPPasswordManagement"))); + assertTrue(passwordManagementTOS.stream().anyMatch( + passwordManagement -> isSpecificConf(passwordManagement.getConf(), + JDBCPasswordManagementConf.class) && passwordManagement.getKey() + .equals("DefaultJDBCPasswordManagement"))); + } + + @Test + public void getSyncopePasswordManagement() { + PasswordManagementTO passwordManagementTO = PASSWORD_MANAGEMENT_SERVICE.read("DefaultSyncopePasswordManagement"); + + assertNotNull(passwordManagementTO); + assertTrue(StringUtils.isNotBlank(passwordManagementTO.getDescription())); + assertTrue(isSpecificConf(passwordManagementTO.getConf(), SyncopePasswordManagementConf.class)); + } + + @Test + public void getLdapPasswordManagement() { + PasswordManagementTO passwordManagementTO = PASSWORD_MANAGEMENT_SERVICE.read("DefaultLDAPPasswordManagement"); + + assertNotNull(passwordManagementTO); + assertTrue(StringUtils.isNotBlank(passwordManagementTO.getDescription())); + assertTrue(isSpecificConf(passwordManagementTO.getConf(), LDAPPasswordManagementConf.class)); + } + + @Test + public void getJdbcPasswordManagement() { + PasswordManagementTO passwordManagementTO = PASSWORD_MANAGEMENT_SERVICE.read("DefaultJDBCPasswordManagement"); + + assertNotNull(passwordManagementTO); + assertTrue(StringUtils.isNotBlank(passwordManagementTO.getDescription())); + assertTrue(isSpecificConf(passwordManagementTO.getConf(), JDBCPasswordManagementConf.class)); + } + + @Test + public void create() { + EnumSet.allOf(PasswordManagementSupportedType.class).forEach(type -> { + PasswordManagementTO passwordManagementTO = createPasswordManagement(buildPasswordManagementTO(type)); + assertNotNull(passwordManagementTO); + assertTrue(passwordManagementTO.getDescription().contains("A test " + type + " Password Management")); + }); + } + + @Test + public void updateSyncopePasswordManagement() { + PasswordManagementTO syncopePasswordManagementTO = PASSWORD_MANAGEMENT_SERVICE.read("DefaultSyncopePasswordManagement"); + assertNotNull(syncopePasswordManagementTO); + + PasswordManagementTO newSyncopePasswordManagementTO = buildPasswordManagementTO(PasswordManagementSupportedType.SYNCOPE); + newSyncopePasswordManagementTO = createPasswordManagement(newSyncopePasswordManagementTO); + assertNotNull(newSyncopePasswordManagementTO); + + PasswordManagementConf conf = syncopePasswordManagementTO.getConf(); + assertNotNull(conf); + SyncopePasswordManagementConf.class.cast(conf).setDomain("Two"); + newSyncopePasswordManagementTO.setConf(conf); + + // update new password management + PASSWORD_MANAGEMENT_SERVICE.update(newSyncopePasswordManagementTO); + newSyncopePasswordManagementTO = PASSWORD_MANAGEMENT_SERVICE.read(newSyncopePasswordManagementTO.getKey()); + assertNotNull(newSyncopePasswordManagementTO); + + conf = newSyncopePasswordManagementTO.getConf(); + assertEquals("Two", SyncopePasswordManagementConf.class.cast(conf).getDomain()); + } + + @Test + public void updateLdapPasswordManagement() { + PasswordManagementTO ldapPasswordManagementTO = PASSWORD_MANAGEMENT_SERVICE.read("DefaultLDAPPasswordManagement"); + assertNotNull(ldapPasswordManagementTO); + + PasswordManagementTO newLdapPasswordManagementTO = buildPasswordManagementTO(PasswordManagementSupportedType.LDAP); + newLdapPasswordManagementTO = createPasswordManagement(newLdapPasswordManagementTO); + assertNotNull(newLdapPasswordManagementTO); + + PasswordManagementConf conf = ldapPasswordManagementTO.getConf(); + assertNotNull(conf); + LDAPPasswordManagementConf.class.cast(conf).setSubtreeSearch(false); + newLdapPasswordManagementTO.setConf(conf); + + // update new password management + PASSWORD_MANAGEMENT_SERVICE.update(newLdapPasswordManagementTO); + newLdapPasswordManagementTO = PASSWORD_MANAGEMENT_SERVICE.read(newLdapPasswordManagementTO.getKey()); + assertNotNull(newLdapPasswordManagementTO); + + conf = newLdapPasswordManagementTO.getConf(); + assertFalse(LDAPPasswordManagementConf.class.cast(conf).isSubtreeSearch()); + } + + @Test + public void updateJdbcPasswordManagement() { + PasswordManagementTO jdbcPasswordManagementTO = PASSWORD_MANAGEMENT_SERVICE.read("DefaultJDBCPasswordManagement"); + assertNotNull(jdbcPasswordManagementTO); + + PasswordManagementTO newJdbcPasswordManagementTO = buildPasswordManagementTO(PasswordManagementSupportedType.JDBC); + newJdbcPasswordManagementTO = createPasswordManagement(newJdbcPasswordManagementTO); + assertNotNull(newJdbcPasswordManagementTO); + + PasswordManagementConf conf = jdbcPasswordManagementTO.getConf(); + assertNotNull(conf); + JDBCPasswordManagementConf.class.cast(conf).setSqlFindUser("SELECT * from other_table where name=?"); + newJdbcPasswordManagementTO.setConf(conf); + + // update new password management + PASSWORD_MANAGEMENT_SERVICE.update(newJdbcPasswordManagementTO); + newJdbcPasswordManagementTO = PASSWORD_MANAGEMENT_SERVICE.read(newJdbcPasswordManagementTO.getKey()); + assertNotNull(newJdbcPasswordManagementTO); + + conf = newJdbcPasswordManagementTO.getConf(); + assertEquals("SELECT * from other_table where name=?", + JDBCPasswordManagementConf.class.cast(conf).getSqlFindUser()); + } + + @Test + public void delete() throws IOException { + EnumSet.allOf(PasswordManagementSupportedType.class).forEach(type -> { + PasswordManagementTO read = createPasswordManagement(buildPasswordManagementTO(type)); + assertNotNull(read); + + PASSWORD_MANAGEMENT_SERVICE.delete(read.getKey()); + + try { + PASSWORD_MANAGEMENT_SERVICE.read(read.getKey()); + fail("This should not happen"); + } catch (SyncopeClientException e) { + assertNotNull(e); + } + }); + } +} diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PasswordModuleITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PasswordModuleITCase.java deleted file mode 100644 index 81b71eea5b4..00000000000 --- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PasswordModuleITCase.java +++ /dev/null @@ -1,231 +0,0 @@ -package org.apache.syncope.fit.core; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.fail; - -import jakarta.ws.rs.core.Response; -import java.io.IOException; -import java.util.EnumSet; -import java.util.List; -import org.apache.commons.lang3.ClassUtils; -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.password.JDBCPasswordModuleConf; -import org.apache.syncope.common.lib.password.LDAPPasswordModuleConf; -import org.apache.syncope.common.lib.password.PasswordModuleConf; -import org.apache.syncope.common.lib.password.SyncopePasswordModuleConf; -import org.apache.syncope.common.lib.to.PasswordModuleTO; -import org.apache.syncope.common.rest.api.service.PasswordModuleService; -import org.apache.syncope.fit.AbstractITCase; -import org.junit.jupiter.api.Test; - -public class PasswordModuleITCase extends AbstractITCase { - - private enum PasswordModuleSupportedType { - SYNCOPE, - LDAP, - JDBC - }; - - private static PasswordModuleTO createPasswordModule(final PasswordModuleTO passwordModuleTO) { - Response response = PASSWORD_MODULE_SERVICE.create(passwordModuleTO); - if (response.getStatusInfo().getStatusCode() != Response.Status.CREATED.getStatusCode()) { - Exception ex = CLIENT_FACTORY.getExceptionMapper().fromResponse(response); - if (ex != null) { - throw (RuntimeException) ex; - } - } - return getObject(response.getLocation(), PasswordModuleService.class, passwordModuleTO.getClass()); - } - - private static PasswordModuleTO buildPasswordModuleTO(final PasswordModuleSupportedType type) { - PasswordModuleTO passwordModuleTO = new PasswordModuleTO(); - passwordModuleTO.setKey("Test" + type + "PasswordModule" + getUUIDString()); - passwordModuleTO.setDescription("A test " + type + " Password Module"); - - PasswordModuleConf conf; - switch (type) { - case SYNCOPE: - conf = new SyncopePasswordModuleConf(); - SyncopePasswordModuleConf.class.cast(conf).setDomain(SyncopeConstants.MASTER_DOMAIN); - passwordModuleTO.setConf(conf); - break; - case LDAP: - conf = new LDAPPasswordModuleConf(); - LDAPPasswordModuleConf.class.cast(conf).setBaseDn("dc=example,dc=org"); - LDAPPasswordModuleConf.class.cast(conf).setSearchFilter("cn={user}"); - LDAPPasswordModuleConf.class.cast(conf).setSubtreeSearch(true); - LDAPPasswordModuleConf.class.cast(conf).setLdapUrl("ldap://localhost:1389"); - LDAPPasswordModuleConf.class.cast(conf).setUsernameAttribute("uid"); - LDAPPasswordModuleConf.class.cast(conf).setBaseDn("cn=Directory Manager,dc=example,dc=org"); - LDAPPasswordModuleConf.class.cast(conf).setBindCredential("Password"); - break; - case JDBC: - conf = new JDBCPasswordModuleConf(); - JDBCPasswordModuleConf.class.cast(conf) - .setSqlFindEmail("SELECT email from users_table where name=?"); - JDBCPasswordModuleConf.class.cast(conf) - .setSqlFindPhone("SELECT phoneNumber from users_table where name=?"); - JDBCPasswordModuleConf.class.cast(conf) - .setSqlFindUser("SELECT * from users_table where name=?"); - JDBCPasswordModuleConf.class.cast(conf) - .setSqlChangePassword("UPDATE users_table SET password=? WHERE name=?"); - break; - default: - break; - } - - return passwordModuleTO; - } - - private static boolean isSpecificConf( - final PasswordModuleConf conf, - final Class clazz) { - return ClassUtils.isAssignable(clazz, conf.getClass()); - } - - @Test - public void list() { - List passwordModuleTOS = PASSWORD_MODULE_SERVICE.list(); - assertNotNull(passwordModuleTOS); - assertFalse(passwordModuleTOS.isEmpty()); - - assertTrue(passwordModuleTOS.stream().anyMatch( - authModule -> isSpecificConf(authModule.getConf(), SyncopePasswordModuleConf.class) - && authModule.getKey().equals("DefaultSyncopePasswordModule"))); - assertTrue(passwordModuleTOS.stream().anyMatch( - authModule -> isSpecificConf(authModule.getConf(), LDAPPasswordModuleConf.class) - && authModule.getKey().equals("DefaultLDAPPasswordModule"))); - assertTrue(passwordModuleTOS.stream().anyMatch( - authModule -> isSpecificConf(authModule.getConf(), JDBCPasswordModuleConf.class) - && authModule.getKey().equals("DefaultJDBCPasswordModule"))); - } - - @Test - public void getSyncopePasswordModule() { - PasswordModuleTO passwordModuleTO = PASSWORD_MODULE_SERVICE.read("DefaultSyncopePasswordModule"); - - assertNotNull(passwordModuleTO); - assertTrue(StringUtils.isNotBlank(passwordModuleTO.getDescription())); - assertTrue(isSpecificConf(passwordModuleTO.getConf(), SyncopePasswordModuleConf.class)); - } - - @Test - public void getLdapPasswordModule() { - PasswordModuleTO passwordModuleTO = PASSWORD_MODULE_SERVICE.read("DefaultLDAPPasswordModule"); - - assertNotNull(passwordModuleTO); - assertTrue(StringUtils.isNotBlank(passwordModuleTO.getDescription())); - assertTrue(isSpecificConf(passwordModuleTO.getConf(), LDAPPasswordModuleConf.class)); - } - - @Test - public void getJdbcPasswordModule() { - PasswordModuleTO passwordModuleTO = PASSWORD_MODULE_SERVICE.read("DefaultJDBCPasswordModule"); - - assertNotNull(passwordModuleTO); - assertTrue(StringUtils.isNotBlank(passwordModuleTO.getDescription())); - assertTrue(isSpecificConf(passwordModuleTO.getConf(), JDBCPasswordModuleConf.class)); - } - - @Test - public void create() { - EnumSet.allOf(PasswordModuleSupportedType.class).forEach(type -> { - PasswordModuleTO passwordModuleTO = createPasswordModule(buildPasswordModuleTO(type)); - assertNotNull(passwordModuleTO); - assertTrue(passwordModuleTO.getDescription().contains("A test " + type + " Password Module")); - assertTrue(passwordModuleTO.getItems().isEmpty()); - }); - } - - @Test - public void updateSyncopePasswordModule() { - PasswordModuleTO syncopePasswordModuleTO = PASSWORD_MODULE_SERVICE.read("DefaultSyncopePasswordModule"); - assertNotNull(syncopePasswordModuleTO); - - PasswordModuleTO newSyncopePasswordModuleTO = buildPasswordModuleTO(PasswordModuleSupportedType.SYNCOPE); - newSyncopePasswordModuleTO = createPasswordModule(newSyncopePasswordModuleTO); - assertNotNull(newSyncopePasswordModuleTO); - - PasswordModuleConf conf = syncopePasswordModuleTO.getConf(); - assertNotNull(conf); - SyncopePasswordModuleConf.class.cast(conf).setDomain("Two"); - newSyncopePasswordModuleTO.setConf(conf); - - // update new password module - PASSWORD_MODULE_SERVICE.update(newSyncopePasswordModuleTO); - newSyncopePasswordModuleTO = PASSWORD_MODULE_SERVICE.read(newSyncopePasswordModuleTO.getKey()); - assertNotNull(newSyncopePasswordModuleTO); - - conf = newSyncopePasswordModuleTO.getConf(); - assertEquals("Two", SyncopePasswordModuleConf.class.cast(conf).getDomain()); - } - - @Test - public void updateLdapPasswordModule() { - PasswordModuleTO ldapPasswordModuleTO = PASSWORD_MODULE_SERVICE.read("DefaultLDAPPasswordModule"); - assertNotNull(ldapPasswordModuleTO); - - PasswordModuleTO newLdapPasswordModuleTO = buildPasswordModuleTO(PasswordModuleSupportedType.LDAP); - newLdapPasswordModuleTO = createPasswordModule(newLdapPasswordModuleTO); - assertNotNull(newLdapPasswordModuleTO); - - PasswordModuleConf conf = ldapPasswordModuleTO.getConf(); - assertNotNull(conf); - LDAPPasswordModuleConf.class.cast(conf).setSubtreeSearch(false); - newLdapPasswordModuleTO.setConf(conf); - - // update new password module - PASSWORD_MODULE_SERVICE.update(newLdapPasswordModuleTO); - newLdapPasswordModuleTO = PASSWORD_MODULE_SERVICE.read(newLdapPasswordModuleTO.getKey()); - assertNotNull(newLdapPasswordModuleTO); - - conf = newLdapPasswordModuleTO.getConf(); - assertFalse(LDAPPasswordModuleConf.class.cast(conf).isSubtreeSearch()); - } - - @Test - public void updateJdbcPasswordModule() { - PasswordModuleTO jdbcPasswordModuleTO = PASSWORD_MODULE_SERVICE.read("DefaultJDBCPasswordModule"); - assertNotNull(jdbcPasswordModuleTO); - - PasswordModuleTO newJdbcPasswordModuleTO = buildPasswordModuleTO(PasswordModuleSupportedType.JDBC); - newJdbcPasswordModuleTO = createPasswordModule(newJdbcPasswordModuleTO); - assertNotNull(newJdbcPasswordModuleTO); - - PasswordModuleConf conf = jdbcPasswordModuleTO.getConf(); - assertNotNull(conf); - JDBCPasswordModuleConf.class.cast(conf).setSqlFindUser("SELECT * from other_table where name=?"); - newJdbcPasswordModuleTO.setConf(conf); - - // update new password module - PASSWORD_MODULE_SERVICE.update(newJdbcPasswordModuleTO); - newJdbcPasswordModuleTO = PASSWORD_MODULE_SERVICE.read(newJdbcPasswordModuleTO.getKey()); - assertNotNull(newJdbcPasswordModuleTO); - - conf = newJdbcPasswordModuleTO.getConf(); - assertEquals("SELECT * from other_table where name=?", - JDBCPasswordModuleConf.class.cast(conf).getSqlFindUser()); - } - - @Test - public void delete() throws IOException { - EnumSet.allOf(PasswordModuleSupportedType.class).forEach(type -> { - PasswordModuleTO read = createPasswordModule(buildPasswordModuleTO(type)); - assertNotNull(read); - - PASSWORD_MODULE_SERVICE.delete(read.getKey()); - - try { - PASSWORD_MODULE_SERVICE.read(read.getKey()); - fail("This should not happen"); - } catch (SyncopeClientException e) { - assertNotNull(e); - } - }); - } -} diff --git a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WABootstrapConfiguration.java b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WABootstrapConfiguration.java index 79038c20352..066fabbb30c 100644 --- a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WABootstrapConfiguration.java +++ b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WABootstrapConfiguration.java @@ -22,7 +22,7 @@ import org.apache.syncope.wa.bootstrap.mapping.AttrRepoPropertySourceMapper; import org.apache.syncope.wa.bootstrap.mapping.AuthModulePropertySourceMapper; import org.apache.syncope.wa.bootstrap.mapping.DefaultAttrReleaseMapper; -import org.apache.syncope.wa.bootstrap.mapping.PasswordModulePropertySourceMapper; +import org.apache.syncope.wa.bootstrap.mapping.PasswordManagementPropertySourceMapper; import org.apereo.cas.configuration.support.CasConfigurationJasyptCipherExecutor; import org.apereo.cas.util.crypto.CipherExecutor; import org.springframework.beans.factory.annotation.Qualifier; @@ -77,8 +77,9 @@ public AuthModulePropertySourceMapper authModulePropertySourceMapper(final WARes @ConditionalOnMissingBean @Bean - public PasswordModulePropertySourceMapper passwordModulePropertySourceMapper(final WARestClient waRestClient) { - return new PasswordModulePropertySourceMapper(waRestClient); + public PasswordManagementPropertySourceMapper passwordManagementPropertySourceMapper( + final WARestClient waRestClient) { + return new PasswordManagementPropertySourceMapper(waRestClient); } @ConditionalOnMissingBean @@ -100,14 +101,13 @@ public PropertySourceLocator configPropertySourceLocator( final WARestClient waRestClient, final AuthModulePropertySourceMapper authModulePropertySourceMapper, final AttrRepoPropertySourceMapper attrRepoPropertySourceMapper, - final PasswordModulePropertySourceMapper passwordModulePropertySourceMapper, + final PasswordManagementPropertySourceMapper passwordManagementPropertySourceMapper, final AttrReleaseMapper attrReleaseMapper) { return new WAPropertySourceLocator( waRestClient, authModulePropertySourceMapper, - attrRepoPropertySourceMapper, - passwordModulePropertySourceMapper, + attrRepoPropertySourceMapper, passwordManagementPropertySourceMapper, attrReleaseMapper, waConfigurationCipher); } diff --git a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WAPropertySourceLocator.java b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WAPropertySourceLocator.java index ca02a5d110f..4a4418a0834 100644 --- a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WAPropertySourceLocator.java +++ b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WAPropertySourceLocator.java @@ -29,16 +29,17 @@ import org.apache.commons.lang3.tuple.Pair; import org.apache.syncope.client.lib.SyncopeClient; import org.apache.syncope.common.lib.to.OIDCRPClientAppTO; -import org.apache.syncope.common.lib.types.PasswordModuleState; +import org.apache.syncope.common.lib.to.PasswordManagementTO; +import org.apache.syncope.common.lib.types.PasswordManagementState; import org.apache.syncope.common.rest.api.service.AttrRepoService; import org.apache.syncope.common.rest.api.service.AuthModuleService; -import org.apache.syncope.common.rest.api.service.PasswordModuleService; +import org.apache.syncope.common.rest.api.service.PasswordManagementService; import org.apache.syncope.common.rest.api.service.wa.WAClientAppService; import org.apache.syncope.common.rest.api.service.wa.WAConfigService; import org.apache.syncope.wa.bootstrap.mapping.AttrReleaseMapper; import org.apache.syncope.wa.bootstrap.mapping.AttrRepoPropertySourceMapper; import org.apache.syncope.wa.bootstrap.mapping.AuthModulePropertySourceMapper; -import org.apache.syncope.wa.bootstrap.mapping.PasswordModulePropertySourceMapper; +import org.apache.syncope.wa.bootstrap.mapping.PasswordManagementPropertySourceMapper; import org.apereo.cas.configuration.model.support.oidc.OidcDiscoveryProperties; import org.apereo.cas.oidc.claims.OidcCustomScopeAttributeReleasePolicy; import org.apereo.cas.services.ChainingAttributeReleasePolicy; @@ -63,7 +64,7 @@ public class WAPropertySourceLocator implements PropertySourceLocator { protected final AttrRepoPropertySourceMapper attrRepoPropertySourceMapper; - protected final PasswordModulePropertySourceMapper passwordModulePropertySourceMapper; + protected final PasswordManagementPropertySourceMapper passwordManagementPropertySourceMapper; protected final AttrReleaseMapper attrReleaseMapper; @@ -73,14 +74,14 @@ public WAPropertySourceLocator( final WARestClient waRestClient, final AuthModulePropertySourceMapper authModulePropertySourceMapper, final AttrRepoPropertySourceMapper attrRepoPropertySourceMapper, - final PasswordModulePropertySourceMapper passwordModulePropertySourceMapper, + final PasswordManagementPropertySourceMapper passwordManagementPropertySourceMapper, final AttrReleaseMapper attrReleaseMapper, final CipherExecutor configurationCipher) { this.waRestClient = waRestClient; this.authModulePropertySourceMapper = authModulePropertySourceMapper; this.attrRepoPropertySourceMapper = attrRepoPropertySourceMapper; - this.passwordModulePropertySourceMapper = passwordModulePropertySourceMapper; + this.passwordManagementPropertySourceMapper = passwordManagementPropertySourceMapper; this.attrReleaseMapper = attrReleaseMapper; this.configurationCipher = configurationCipher; } @@ -131,13 +132,13 @@ public PropertySource locate(final Environment environment) { properties.putAll(index(map, prefixes)); }); - syncopeClient.getService(PasswordModuleService.class).list().stream().filter( - passwordModuleTO -> PasswordModuleState.ACTIVE.equals(passwordModuleTO.getState())) - .findFirst().ifPresent(passwordModuleTO -> { - LOG.debug("Mapping password module {} ", passwordModuleTO.getKey()); + syncopeClient.getService(PasswordManagementService.class).list() + .stream().filter(PasswordManagementTO::isEnabled).findFirst().ifPresent( + passwordManagementTO -> { + LOG.debug("Mapping password module {} ", passwordManagementTO.getKey()); - Map map = passwordModuleTO.getConf() - .map(passwordModuleTO, passwordModulePropertySourceMapper); + Map map = passwordManagementTO.getConf() + .map(passwordManagementTO, passwordManagementPropertySourceMapper); properties.putAll(index(map, prefixes)); }); diff --git a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/PasswordModulePropertySourceMapper.java b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/PasswordManagementPropertySourceMapper.java similarity index 67% rename from wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/PasswordModulePropertySourceMapper.java rename to wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/PasswordManagementPropertySourceMapper.java index 884f748856b..8dd5aa3ff1a 100644 --- a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/PasswordModulePropertySourceMapper.java +++ b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/PasswordManagementPropertySourceMapper.java @@ -3,28 +3,28 @@ import java.util.Map; import org.apache.commons.lang3.StringUtils; import org.apache.syncope.client.lib.SyncopeClient; -import org.apache.syncope.common.lib.password.JDBCPasswordModuleConf; -import org.apache.syncope.common.lib.password.LDAPPasswordModuleConf; -import org.apache.syncope.common.lib.password.PasswordModuleConf; -import org.apache.syncope.common.lib.password.SyncopePasswordModuleConf; -import org.apache.syncope.common.lib.to.PasswordModuleTO; -import org.apache.syncope.common.lib.types.PasswordModuleState; +import org.apache.syncope.common.lib.password.JDBCPasswordManagementConf; +import org.apache.syncope.common.lib.password.LDAPPasswordManagementConf; +import org.apache.syncope.common.lib.password.PasswordManagementConf; +import org.apache.syncope.common.lib.password.SyncopePasswordManagementConf; +import org.apache.syncope.common.lib.to.PasswordManagementTO; +import org.apache.syncope.common.lib.types.PasswordManagementState; import org.apache.syncope.wa.bootstrap.WARestClient; import org.apereo.cas.configuration.model.support.ldap.AbstractLdapProperties; import org.apereo.cas.configuration.model.support.pm.JdbcPasswordManagementProperties; import org.apereo.cas.configuration.model.support.pm.LdapPasswordManagementProperties; import org.apereo.cas.configuration.model.support.pm.SyncopePasswordManagementProperties; -public class PasswordModulePropertySourceMapper extends PropertySourceMapper implements PasswordModuleConf.Mapper { +public class PasswordManagementPropertySourceMapper extends PropertySourceMapper implements PasswordManagementConf.Mapper { protected final WARestClient waRestClient; - public PasswordModulePropertySourceMapper(final WARestClient waRestClient) { + public PasswordManagementPropertySourceMapper(final WARestClient waRestClient) { this.waRestClient = waRestClient; } @Override - public Map map(final PasswordModuleTO passwordModuleTO, final SyncopePasswordModuleConf conf) { + public Map map(final PasswordManagementTO passwordManagementTO, final SyncopePasswordManagementConf conf) { SyncopeClient syncopeClient = waRestClient.getSyncopeClient(); if (syncopeClient == null) { LOG.warn("Application context is not ready to bootstrap WA configuration"); @@ -40,26 +40,26 @@ public Map map(final PasswordModuleTO passwordModuleTO, final Sy props.setHeaders(conf.getHeaders()); Map mappedProps = prefix("cas.authn.pm.syncope.", WAConfUtils.asMap(props)); - mappedProps.put("cas.authn.pm.syncope.enabled", PasswordModuleState.ACTIVE.equals(passwordModuleTO.getState())); + mappedProps.put("cas.authn.pm.syncope.enabled", passwordManagementTO.isEnabled()); return mappedProps; } @Override - public Map map(final PasswordModuleTO passwordModuleTO, final LDAPPasswordModuleConf conf) { + public Map map(final PasswordManagementTO passwordManagementTO, final LDAPPasswordManagementConf conf) { LdapPasswordManagementProperties props = new LdapPasswordManagementProperties(); - props.setName(passwordModuleTO.getKey()); + props.setName(passwordManagementTO.getKey()); props.setType(AbstractLdapProperties.LdapType.valueOf(conf.getLdapType().name())); props.setUsernameAttribute(conf.getUsernameAttribute()); fill(props, conf); Map mappedProps = prefix("cas.authn.pm.ldap[].", WAConfUtils.asMap(props)); - mappedProps.put("cas.authn.pm.ldap.enabled", PasswordModuleState.ACTIVE.equals(passwordModuleTO.getState())); + mappedProps.put("cas.authn.pm.ldap.enabled", passwordManagementTO.isEnabled()); return mappedProps; } @Override - public Map map(final PasswordModuleTO passwordModuleTO, final JDBCPasswordModuleConf conf) { + public Map map(final PasswordManagementTO passwordManagementTO, final JDBCPasswordManagementConf conf) { JdbcPasswordManagementProperties props = new JdbcPasswordManagementProperties(); props.setSqlChangePassword(conf.getSqlChangePassword()); props.setSqlFindEmail(conf.getSqlFindEmail()); @@ -72,7 +72,7 @@ public Map map(final PasswordModuleTO passwordModuleTO, final JD fill(props, conf); Map mappedProps = prefix("cas.authn.pm.jdbc.", WAConfUtils.asMap(props)); - mappedProps.put("cas.authn.pm.jdbc.enabled", PasswordModuleState.ACTIVE.equals(passwordModuleTO.getState())); + mappedProps.put("cas.authn.pm.jdbc.enabled", passwordManagementTO.isEnabled()); return mappedProps; } } From fd638102ef8c7566985e4175eace4955e80281ff Mon Sep 17 00:00:00 2001 From: alberto bogi Date: Thu, 4 Sep 2025 10:27:41 +0200 Subject: [PATCH 12/20] [SYNCOPE-1901] Definition of a validator that checks if multiple password management configurations are enabled --- .../syncope/client/console/pages/WA.java | 3 +- .../PasswordManagementDirectoryPanel.java | 28 ++++++- .../PasswordManagementWizardBuilder.java | 4 +- ...asswordManagementDirectoryPanel.properties | 2 +- ...wordManagementDirectoryPanel_fr.properties | 2 +- ...dManagementDirectoryPanel_fr_CA.properties | 2 +- ...wordManagementDirectoryPanel_it.properties | 2 +- ...wordManagementDirectoryPanel_ja.properties | 2 +- ...dManagementDirectoryPanel_pt_BR.properties | 2 +- ...wordManagementDirectoryPanel_ru.properties | 2 +- .../AuthModuleWizardBuilder$Profile.html | 7 +- ...sswordManagementWizardBuilder$Profile.html | 2 +- ...ManagementWizardBuilder$Profile.properties | 2 +- ...agementWizardBuilder$Profile_fr.properties | 2 +- ...mentWizardBuilder$Profile_fr_CA.properties | 2 +- ...agementWizardBuilder$Profile_it.properties | 2 +- ...agementWizardBuilder$Profile_ja.properties | 2 +- ...mentWizardBuilder$Profile_pt_BR.properties | 2 +- ...agementWizardBuilder$Profile_ru.properties | 2 +- .../wicket/markup/html/form/ActionLink.java | 3 +- .../markup/html/form/ActionsPanel.properties | 5 ++ .../html/form/ActionsPanel_fr_CA.properties | 5 ++ .../html/form/ActionsPanel_it.properties | 5 ++ .../html/form/ActionsPanel_ja.properties | 5 ++ .../html/form/ActionsPanel_pt_BR.properties | 5 ++ .../html/form/ActionsPanel_ru.properties | 5 ++ .../password/LDAPPasswordManagementConf.java | 2 + .../common/lib/to/PasswordManagementTO.java | 22 ++---- .../common/lib/types/EntityViolationType.java | 3 +- .../core/logic/PasswordManagementLogic.java | 6 +- .../api/dao/PasswordManagementDAO.java | 2 + .../api/entity/am/PasswordManagement.java | 19 +++++ .../validation/PasswordManagementCheck.java | 22 ++++++ .../PasswordManagementValidator.java | 30 +++++++ .../dao/repo/PasswordManagementRepoExt.java | 2 + .../repo/PasswordManagementRepoExtImpl.java | 16 +++- .../jpa/entity/am/JPAPasswordManagement.java | 62 ++------------- .../jpa/inner/PasswordManagementTest.java | 17 +--- .../test/resources/domains/MasterContent.xml | 12 +-- .../persistence/neo4j/PersistenceContext.java | 3 +- .../dao/repo/PasswordManagementRepoExt.java | 2 + .../repo/PasswordManagementRepoExtImpl.java | 26 +++++- .../neo4j/entity/Neo4jEntityFactory.java | 2 +- .../entity/am/Neo4JPasswordManagement.java | 51 ++---------- .../neo4j/inner/PasswordManagementTest.java | 13 +-- .../test/resources/domains/MasterContent.xml | 6 +- .../PasswordManagementDataBinderImpl.java | 79 +------------------ .../fit/core/PasswordManagementITCase.java | 27 ++++--- .../wa/bootstrap/WAPropertySourceLocator.java | 6 +- ...asswordManagementPropertySourceMapper.java | 19 +++-- 50 files changed, 274 insertions(+), 280 deletions(-) create mode 100644 core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/am/PasswordManagement.java create mode 100644 core/persistence-common/src/main/java/org/apache/syncope/core/persistence/common/validation/PasswordManagementCheck.java create mode 100644 core/persistence-common/src/main/java/org/apache/syncope/core/persistence/common/validation/PasswordManagementValidator.java diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/pages/WA.java b/client/am/console/src/main/java/org/apache/syncope/client/console/pages/WA.java index 949321f0988..2d899afd928 100644 --- a/client/am/console/src/main/java/org/apache/syncope/client/console/pages/WA.java +++ b/client/am/console/src/main/java/org/apache/syncope/client/console/pages/WA.java @@ -191,7 +191,8 @@ public Panel getPanel(final String panelId) { @Override public Panel getPanel(final String panelId) { - return new PasswordManagementDirectoryPanel(panelId, passwordManagementRestClient, getPageReference()); + return new PasswordManagementDirectoryPanel( + panelId, passwordManagementRestClient, getPageReference()); } }); } diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel.java b/client/am/console/src/main/java/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel.java index ec686811846..424819ba24d 100644 --- a/client/am/console/src/main/java/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel.java +++ b/client/am/console/src/main/java/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel.java @@ -43,7 +43,8 @@ import org.apache.wicket.model.StringResourceModel; import org.apache.wicket.spring.injection.annot.SpringBean; -public class PasswordManagementDirectoryPanel extends DirectoryPanel { +public class PasswordManagementDirectoryPanel extends DirectoryPanel { private static final long serialVersionUID = 1005345990563741296L; @SpringBean @@ -60,7 +61,8 @@ public PasswordManagementDirectoryPanel( disableCheckBoxes(); - addNewItemPanelBuilder(new PasswordManagementWizardBuilder(new PasswordManagementTO(), restClient, pageRef), true); + addNewItemPanelBuilder(new PasswordManagementWizardBuilder( + new PasswordManagementTO(), restClient, pageRef), true); MetaDataRoleAuthorizationStrategy.authorize(addAjaxLink, RENDER, AMEntitlement.AUTH_MODULE_CREATE); @@ -133,6 +135,28 @@ public void onClick(final AjaxRequestTarget target, final PasswordManagementTO i } }, ActionLink.ActionType.EDIT, AMEntitlement.PASSWORD_MANAGEMENT_UPDATE); + panel.add(new ActionLink<>() { + + private static final long serialVersionUID = -3722207913631435501L; + + @Override + public void onClick(final AjaxRequestTarget target, final PasswordManagementTO ignore) { + try { + model.setObject(restClient.read(model.getObject().getKey())); + Boolean enabled = Boolean.parseBoolean(model.getObject().getEnabled()); + model.getObject().setEnabled(String.valueOf(!enabled)); + restClient.update(model.getObject()); + + SyncopeConsoleSession.get().success(getString(Constants.OPERATION_SUCCEEDED)); + target.add(container); + } catch (Exception e) { + LOG.error("While actioning object {}", model.getObject().getKey(), e); + SyncopeConsoleSession.get().onException(e); + } + ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(target); + } + }, ActionLink.ActionType.ENABLE_PM, AMEntitlement.PASSWORD_MANAGEMENT_UPDATE); + panel.add(new ActionLink<>() { private static final long serialVersionUID = -5432034353017728756L; diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder.java b/client/am/console/src/main/java/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder.java index 8d1045f535d..d4c064786d9 100644 --- a/client/am/console/src/main/java/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder.java +++ b/client/am/console/src/main/java/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder.java @@ -13,7 +13,6 @@ import org.apache.syncope.client.ui.commons.wizards.AjaxWizard; import org.apache.syncope.common.lib.password.PasswordManagementConf; import org.apache.syncope.common.lib.to.PasswordManagementTO; -import org.apache.syncope.common.lib.types.PasswordManagementState; import org.apache.wicket.PageReference; import org.apache.wicket.ajax.AjaxEventBehavior; import org.apache.wicket.ajax.AjaxRequestTarget; @@ -97,8 +96,7 @@ Constants.DESCRIPTION_FIELD_NAME, getString(Constants.DESCRIPTION_FIELD_NAME), add(description); AjaxCheckBoxPanel isEnabled = new AjaxCheckBoxPanel( - "enabled", getString("enabled"), new PropertyModel<>(passwordManagement, "enabled")); - isEnabled.addRequiredLabel(); + "enabled", "enabled", new PropertyModel<>(passwordManagement, "enabled")); add(isEnabled); AjaxDropDownChoicePanel conf = new AjaxDropDownChoicePanel<>("conf", getString("type"), isNew diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel.properties index e6fbb66201d..b31f644f9f3 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel.properties @@ -3,6 +3,6 @@ any.new=New Password Module any.edit=Edit Auth Password Module description=Description type=Type -enabled=Configuration is enabled +enabled=Enabled order=Order menu.history=Configuration history diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_fr.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_fr.properties index e6fbb66201d..b31f644f9f3 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_fr.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_fr.properties @@ -3,6 +3,6 @@ any.new=New Password Module any.edit=Edit Auth Password Module description=Description type=Type -enabled=Configuration is enabled +enabled=Enabled order=Order menu.history=Configuration history diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_fr_CA.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_fr_CA.properties index e6fbb66201d..b31f644f9f3 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_fr_CA.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_fr_CA.properties @@ -3,6 +3,6 @@ any.new=New Password Module any.edit=Edit Auth Password Module description=Description type=Type -enabled=Configuration is enabled +enabled=Enabled order=Order menu.history=Configuration history diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_it.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_it.properties index 9bae4433771..fb8814b6f7b 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_it.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_it.properties @@ -3,6 +3,6 @@ any.new=Nuovo Modulo di Gestione Password any.edit=Aggiorna Modulo di Gestione Password description=Descrizione type=Tipo -enabled=Questa configurazione \u00e8 attiva +enabled=Attiva order=Ordinamento auditHistory.title=Storico delle configurazioni diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_ja.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_ja.properties index e6fbb66201d..b31f644f9f3 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_ja.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_ja.properties @@ -3,6 +3,6 @@ any.new=New Password Module any.edit=Edit Auth Password Module description=Description type=Type -enabled=Configuration is enabled +enabled=Enabled order=Order menu.history=Configuration history diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_pt_BR.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_pt_BR.properties index e6fbb66201d..b31f644f9f3 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_pt_BR.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_pt_BR.properties @@ -3,6 +3,6 @@ any.new=New Password Module any.edit=Edit Auth Password Module description=Description type=Type -enabled=Configuration is enabled +enabled=Enabled order=Order menu.history=Configuration history diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_ru.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_ru.properties index e6fbb66201d..b31f644f9f3 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_ru.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_ru.properties @@ -3,6 +3,6 @@ any.new=New Password Module any.edit=Edit Auth Password Module description=Description type=Type -enabled=Configuration is enabled +enabled=Enabled order=Order menu.history=Configuration history diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Profile.html b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Profile.html index 6ed776f5e9e..7509f1632bc 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Profile.html +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Profile.html @@ -17,11 +17,12 @@ under the License. --> - +
[key]
[description]
-
[enabled]
+
[state]
[order]
[conf]
-
+
+ diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile.html b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile.html index 2746f1142a8..f40b2f5758e 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile.html +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile.html @@ -1,8 +1,8 @@ +
[enabled]
[key]
[description]
-
[enabled]
[conf]
\ No newline at end of file diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile.properties index 2e0c01a7f9e..961305f294a 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile.properties @@ -1,4 +1,4 @@ description=Description configuration=Configuration type=Type -state=State +enabled=Do you want to enable this configuration? diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_fr.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_fr.properties index 2e0c01a7f9e..961305f294a 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_fr.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_fr.properties @@ -1,4 +1,4 @@ description=Description configuration=Configuration type=Type -state=State +enabled=Do you want to enable this configuration? diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_fr_CA.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_fr_CA.properties index 2e0c01a7f9e..961305f294a 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_fr_CA.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_fr_CA.properties @@ -1,4 +1,4 @@ description=Description configuration=Configuration type=Type -state=State +enabled=Do you want to enable this configuration? diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_it.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_it.properties index 427644db502..3cd2809d0be 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_it.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_it.properties @@ -1,4 +1,4 @@ description=Descrizione configuration=Configurazione type=Tipo -state=Stato +enabled=Desideri attivare questa configurazione? diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_ja.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_ja.properties index 2e0c01a7f9e..961305f294a 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_ja.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_ja.properties @@ -1,4 +1,4 @@ description=Description configuration=Configuration type=Type -state=State +enabled=Do you want to enable this configuration? diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_pt_BR.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_pt_BR.properties index 2e0c01a7f9e..961305f294a 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_pt_BR.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_pt_BR.properties @@ -1,4 +1,4 @@ description=Description configuration=Configuration type=Type -state=State +enabled=Do you want to enable this configuration? diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_ru.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_ru.properties index 2e0c01a7f9e..961305f294a 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_ru.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_ru.properties @@ -1,4 +1,4 @@ description=Description configuration=Configuration type=Type -state=State +enabled=Do you want to enable this configuration? diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionLink.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionLink.java index a04d0a9b275..a699703adda 100644 --- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionLink.java +++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionLink.java @@ -110,7 +110,8 @@ public enum ActionType { EDIT_APPROVAL("edit"), VIEW_AUDIT_HISTORY("read"), EXTERNAL_EDITOR("externalEditor"), - EXPLORE_RESOURCE("search"); + EXPLORE_RESOURCE("search"), + ENABLE_PM("update"); private final String actionId; diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel.properties index d7ba2e73999..b0ab8f3ab3d 100644 --- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel.properties +++ b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel.properties @@ -286,3 +286,8 @@ up.title=move up down.alt=down icon down.class=fas fa-arrow-down down.title=move down + +enable_pm.class=fa fa-check +enaple_pm.alt=enable icon +enable_pm.title=enable/disable + diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel_fr_CA.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel_fr_CA.properties index 3169b9293a0..e50c38a01c6 100644 --- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel_fr_CA.properties +++ b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel_fr_CA.properties @@ -230,3 +230,8 @@ down.title=move down live_sync_task.class=fa-solid fa-rotate live_sync_task.title=live sync task live_sync_task.alt=live sync task icon + +enable_pm.class=fa fa-check +enaple_pm.alt=enable icon +enable_pm.title=enable/disable + diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel_it.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel_it.properties index ea1f43d7ad3..e4b2feb851c 100644 --- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel_it.properties +++ b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel_it.properties @@ -285,3 +285,8 @@ down.title=sposta gi\u00f9 live_sync_task.class=fa-solid fa-rotate live_sync_task.title=task di live sync live_sync_task.alt=live sync task icon + +enable_pm.class=fa fa-check +enaple_pm.alt=enable icon +enable_pm.title=abilita/disabilita + diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel_ja.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel_ja.properties index 2fc0a6661fd..4c9d806c5dd 100644 --- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel_ja.properties +++ b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel_ja.properties @@ -286,3 +286,8 @@ down.title=move down live_sync_task.class=fa-solid fa-rotate live_sync_task.title=live sync task live_sync_task.alt=live sync task icon + +enable_pm.class=fa fa-check +enaple_pm.alt=enable icon +enable_pm.title=enable/disable + diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel_pt_BR.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel_pt_BR.properties index b70b246f77e..1a1abd382ba 100644 --- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel_pt_BR.properties +++ b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel_pt_BR.properties @@ -290,3 +290,8 @@ down.title=move down live_sync_task.class=fa-solid fa-rotate live_sync_task.title=live sync task live_sync_task.alt=live sync task icon + +enable_pm.class=fa fa-check +enaple_pm.alt=enable icon +enable_pm.title=enable/disable + diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel_ru.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel_ru.properties index eff41a0fbdb..4149d5b2a83 100644 --- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel_ru.properties +++ b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel_ru.properties @@ -286,3 +286,8 @@ down.title=move down live_sync_task.class=fa-solid fa-rotate live_sync_task.title=live sync task live_sync_task.alt=live sync task icon + +enable_pm.class=fa fa-check +enaple_pm.alt=enable icon +enable_pm.title=enable/disable + diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/LDAPPasswordManagementConf.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/LDAPPasswordManagementConf.java index 22a513fb5b4..0e808045bef 100644 --- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/LDAPPasswordManagementConf.java +++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/LDAPPasswordManagementConf.java @@ -6,6 +6,8 @@ public class LDAPPasswordManagementConf extends AbstractLDAPConf implements PasswordManagementConf { + private static final long serialVersionUID = 3721321025567652223L; + /** * Username attribute required by LDAP. */ diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/to/PasswordManagementTO.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/to/PasswordManagementTO.java index 49f338cea8a..122d25bb7aa 100644 --- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/to/PasswordManagementTO.java +++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/to/PasswordManagementTO.java @@ -1,12 +1,10 @@ package org.apache.syncope.common.lib.to; import jakarta.ws.rs.PathParam; -import java.util.ArrayList; -import java.util.List; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; import org.apache.syncope.common.lib.password.PasswordManagementConf; -import org.apache.syncope.common.lib.types.PasswordManagementState; public class PasswordManagementTO implements EntityTO { @@ -16,9 +14,7 @@ public class PasswordManagementTO implements EntityTO { private String description; - private boolean enabled = false; - -// private final List items = new ArrayList<>(); + private String enabled = Boolean.FALSE.toString(); private PasswordManagementConf conf; @@ -41,18 +37,16 @@ public void setDescription(final String description) { this.description = description; } - public boolean isEnabled() { - return enabled; + public String getEnabled() { + return StringUtils.isNotBlank(enabled) + ? enabled + : Boolean.FALSE.toString(); } - public void setEnabled(boolean enabled) { + public void setEnabled(final String enabled) { this.enabled = enabled; } -// public List getItems() { -// return items; -// } - public PasswordManagementConf getConf() { return conf; } @@ -77,7 +71,6 @@ public boolean equals(final Object obj) { append(key, other.key). append(description, other.description). append(enabled, other.enabled). -// append(items, other.items). append(conf, other.conf). build(); } @@ -87,7 +80,6 @@ public int hashCode() { return new HashCodeBuilder(). append(key). append(description). -// append(items). append(conf). build(); } diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/EntityViolationType.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/EntityViolationType.java index 1a179cba6b8..439cca4e817 100644 --- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/EntityViolationType.java +++ b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/EntityViolationType.java @@ -44,7 +44,8 @@ public enum EntityViolationType { InvalidUsername, InvalidValueList, InvalidRemediation, - MoreThanOneNonNull; + MoreThanOneNonNull, + MoreThanOneEnabled; private String message; diff --git a/core/am/logic/src/main/java/org/apache/syncope/core/logic/PasswordManagementLogic.java b/core/am/logic/src/main/java/org/apache/syncope/core/logic/PasswordManagementLogic.java index 9436e1557e0..efea84f5f6e 100644 --- a/core/am/logic/src/main/java/org/apache/syncope/core/logic/PasswordManagementLogic.java +++ b/core/am/logic/src/main/java/org/apache/syncope/core/logic/PasswordManagementLogic.java @@ -38,7 +38,8 @@ public PasswordManagementTO update(final PasswordManagementTO passwordManagement orElseThrow(() -> new NotFoundException("PasswordManagement " + passwordManagementTO.getKey())); return passwordManagementDataBinder.getPasswordManagementTO( - passwordManagementDAO.save(passwordManagementDataBinder.update(passwordManagement, passwordManagementTO))); + passwordManagementDAO.save(passwordManagementDataBinder + .update(passwordManagement, passwordManagementTO))); } @PreAuthorize("hasRole('" + AMEntitlement.PASSWORD_MANAGEMENT_LIST + "') or hasRole('" @@ -87,7 +88,8 @@ protected PasswordManagementTO resolveReference(final Method method, final Objec } try { - return passwordManagementDataBinder.getPasswordManagementTO(passwordManagementDAO.findById(key).orElseThrow()); + return passwordManagementDataBinder.getPasswordManagementTO(passwordManagementDAO.findById(key) + .orElseThrow()); } catch (Throwable ignore) { LOG.debug("Unresolved reference", ignore); throw new UnresolvedReferenceException(ignore); diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PasswordManagementDAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PasswordManagementDAO.java index 914c17d1d98..e6ccd07497d 100644 --- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PasswordManagementDAO.java +++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PasswordManagementDAO.java @@ -3,4 +3,6 @@ import org.apache.syncope.core.persistence.api.entity.am.PasswordManagement; public interface PasswordManagementDAO extends DAO { + + boolean isAnotherInstanceEnabled(String key); } diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/am/PasswordManagement.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/am/PasswordManagement.java new file mode 100644 index 00000000000..081b30d73ed --- /dev/null +++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/am/PasswordManagement.java @@ -0,0 +1,19 @@ +package org.apache.syncope.core.persistence.api.entity.am; + +import org.apache.syncope.common.lib.password.PasswordManagementConf; +import org.apache.syncope.core.persistence.api.entity.ProvidedKeyEntity; + +public interface PasswordManagement extends ProvidedKeyEntity { + + String getDescription(); + + void setDescription(String description); + + String getEnabled(); + + void setEnabled(String enabled); + + PasswordManagementConf getConf(); + + void setConf(PasswordManagementConf conf); +} diff --git a/core/persistence-common/src/main/java/org/apache/syncope/core/persistence/common/validation/PasswordManagementCheck.java b/core/persistence-common/src/main/java/org/apache/syncope/core/persistence/common/validation/PasswordManagementCheck.java new file mode 100644 index 00000000000..7cc3f0b89ee --- /dev/null +++ b/core/persistence-common/src/main/java/org/apache/syncope/core/persistence/common/validation/PasswordManagementCheck.java @@ -0,0 +1,22 @@ +package org.apache.syncope.core.persistence.common.validation; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ ElementType.TYPE }) +@Retention(RetentionPolicy.RUNTIME) +@Constraint(validatedBy = PasswordManagementValidator.class) +@Documented +public @interface PasswordManagementCheck { + + String message() default "{org.apache.syncope.core.persistence.validation.passwordManagement}"; + + Class[] groups() default {}; + + Class[] payload() default {}; +} diff --git a/core/persistence-common/src/main/java/org/apache/syncope/core/persistence/common/validation/PasswordManagementValidator.java b/core/persistence-common/src/main/java/org/apache/syncope/core/persistence/common/validation/PasswordManagementValidator.java new file mode 100644 index 00000000000..faa98a97631 --- /dev/null +++ b/core/persistence-common/src/main/java/org/apache/syncope/core/persistence/common/validation/PasswordManagementValidator.java @@ -0,0 +1,30 @@ +package org.apache.syncope.core.persistence.common.validation; + +import jakarta.validation.ConstraintValidatorContext; +import org.apache.syncope.common.lib.types.EntityViolationType; +import org.apache.syncope.core.persistence.api.ApplicationContextProvider; +import org.apache.syncope.core.persistence.api.dao.PasswordManagementDAO; +import org.apache.syncope.core.persistence.api.entity.am.PasswordManagement; + +public class PasswordManagementValidator extends AbstractValidator { + + @Override + public boolean isValid(final PasswordManagement passwordManagement, final ConstraintValidatorContext context) { + PasswordManagementDAO passwordManagementDAO = + ApplicationContextProvider.getApplicationContext().getBean(PasswordManagementDAO.class); + context.disableDefaultConstraintViolation(); + + if (!Boolean.parseBoolean(passwordManagement.getEnabled())) { + return true; + } + + boolean isValid = !passwordManagementDAO.isAnotherInstanceEnabled(passwordManagement.getKey()); + if (!isValid) { + context.buildConstraintViolationWithTemplate( + getTemplate(EntityViolationType.MoreThanOneEnabled, + "Enable only one configuration")). + addPropertyNode("key").addConstraintViolation(); + } + return isValid; + } +} diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordManagementRepoExt.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordManagementRepoExt.java index e0f6ec8023d..82e44e9fa38 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordManagementRepoExt.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordManagementRepoExt.java @@ -4,6 +4,8 @@ public interface PasswordManagementRepoExt { + boolean isAnotherInstanceEnabled(String key); + PasswordManagement save(PasswordManagement passwordManagement); void delete(PasswordManagement passwordManagement); diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordManagementRepoExtImpl.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordManagementRepoExtImpl.java index b9e0b116a7b..84c3b88014a 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordManagementRepoExtImpl.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordManagementRepoExtImpl.java @@ -3,6 +3,8 @@ import jakarta.persistence.EntityManager; import org.apache.syncope.core.persistence.api.entity.am.PasswordManagement; import org.apache.syncope.core.persistence.jpa.entity.am.JPAPasswordManagement; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; public class PasswordManagementRepoExtImpl implements PasswordManagementRepoExt { @@ -12,10 +14,22 @@ public PasswordManagementRepoExtImpl(final EntityManager entityManager) { this.entityManager = entityManager; } + @Transactional(readOnly = true, propagation = Propagation.REQUIRES_NEW) + @Override + public boolean isAnotherInstanceEnabled(final String key) { + Long count = entityManager.createQuery( + "SELECT COUNT(pm) FROM " + + JPAPasswordManagement.class.getSimpleName() + + " pm WHERE pm.enabled = 'true' AND pm.id <> :id", + Long.class) + .setParameter("id", key) + .getSingleResult(); + + return count > 0; + } @Override public PasswordManagement save(final PasswordManagement passwordManagement) { - ((JPAPasswordManagement) passwordManagement).list2json(); return entityManager.merge(passwordManagement); } diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/am/JPAPasswordManagement.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/am/JPAPasswordManagement.java index f75cfc1eec6..0b0909c983a 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/am/JPAPasswordManagement.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/am/JPAPasswordManagement.java @@ -1,48 +1,29 @@ package org.apache.syncope.core.persistence.jpa.entity.am; -import com.fasterxml.jackson.core.type.TypeReference; import jakarta.persistence.Entity; -import jakarta.persistence.EnumType; -import jakarta.persistence.Enumerated; import jakarta.persistence.Lob; -import jakarta.persistence.PostLoad; -import jakarta.persistence.PostPersist; -import jakarta.persistence.PostUpdate; -import jakarta.persistence.PrePersist; -import jakarta.persistence.PreUpdate; import jakarta.persistence.Table; -import jakarta.persistence.Transient; import jakarta.validation.constraints.NotNull; -import java.util.ArrayList; -import java.util.List; import org.apache.commons.lang3.StringUtils; import org.apache.syncope.common.lib.password.PasswordManagementConf; -import org.apache.syncope.common.lib.to.Item; -import org.apache.syncope.common.lib.types.PasswordManagementState; import org.apache.syncope.core.persistence.api.entity.am.PasswordManagement; +import org.apache.syncope.core.persistence.common.validation.PasswordManagementCheck; import org.apache.syncope.core.persistence.jpa.entity.AbstractProvidedKeyEntity; import org.apache.syncope.core.provisioning.api.serialization.POJOHelper; @Entity @Table(name = JPAPasswordManagement.TABLE) +@PasswordManagementCheck public class JPAPasswordManagement extends AbstractProvidedKeyEntity implements PasswordManagement { private static final long serialVersionUID = 5457779846065079998L; public static final String TABLE = "PasswordManagement"; - protected static final TypeReference> TYPEREF = new TypeReference>() { - }; - private String description; - private boolean enabled; - - @Lob - private String items; - - @Transient - private final List itemList = new ArrayList<>(); + @NotNull + private String enabled; @Lob private String jsonConf; @@ -58,21 +39,16 @@ public void setDescription(final String description) { } @Override - public boolean isEnabled() { + public String getEnabled() { return enabled; } @Override - public void setEnabled(boolean enabled) { + public void setEnabled(final String enabled) { this.enabled = enabled; } - @Override - public List getItems() { - return itemList; - } - @Override public PasswordManagementConf getConf() { PasswordManagementConf conf = null; @@ -87,30 +63,4 @@ public PasswordManagementConf getConf() { public void setConf(final PasswordManagementConf conf) { jsonConf = POJOHelper.serialize(conf); } - - protected void json2list(final boolean clearFirst) { - if (clearFirst) { - getItems().clear(); - } - if (items != null) { - getItems().addAll(POJOHelper.deserialize(items, TYPEREF)); - } - } - - @PostLoad - public void postLoad() { - json2list(false); - } - - @PostPersist - @PostUpdate - public void postSave() { - json2list(true); - } - - @PrePersist - @PreUpdate - public void list2json() { - items = POJOHelper.serialize(getItems()); - } } diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PasswordManagementTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PasswordManagementTest.java index 20f000b2cf9..19490ae8fcf 100644 --- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PasswordManagementTest.java +++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PasswordManagementTest.java @@ -41,7 +41,8 @@ public void findAll() { @Test public void find() { - PasswordManagement passwordManagement = passwordManagementDAO.findById("DefaultSyncopePasswordManagement").orElseThrow(); + PasswordManagement passwordManagement = passwordManagementDAO.findById("DefaultSyncopePasswordManagement") + .orElseThrow(); assertTrue(passwordManagement.getConf() instanceof SyncopePasswordManagementConf); passwordManagement = passwordManagementDAO.findById("DefaultLDAPPasswordManagement").orElseThrow(); @@ -73,24 +74,12 @@ private void savePasswordManagement(final String key, final PasswordManagementCo module.setKey(key); module.setDescription("A password management module"); module.setConf(conf); - - Item keyMapping = new Item(); - keyMapping.setIntAttrName("uid"); - keyMapping.setExtAttrName("username"); - module.getItems().add(keyMapping); - - Item fullnameMapping = new Item(); - fullnameMapping.setIntAttrName("cn"); - fullnameMapping.setExtAttrName("fullname"); - module.getItems().add(fullnameMapping); - + module.setEnabled(Boolean.FALSE.toString()); module = passwordManagementDAO.save(module); - entityManager.flush(); assertNotNull(module); assertNotNull(module.getKey()); assertEquals(module, passwordManagementDAO.findById(module.getKey()).orElseThrow()); - assertEquals(2, module.getItems().size()); } @Test diff --git a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml index a69024507d7..c74b527d790 100644 --- a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml +++ b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml @@ -92,14 +92,14 @@ under the License. + jsonConf='{"_class":"org.apache.syncope.common.lib.password.SyncopePasswordManagementConf","domain":"Master","searchFilter":"username={user}","basicAuthUsername":"admin","basicAuthPassword":"password", "headers":{}}' + enabled="true"/> + jsonConf='{ "_class": "org.apache.syncope.common.lib.password.LDAPPasswordManagementConf","usernameAttribute":"uid","bindDn": "${testds.bindDn}","bindCredential":"${testds.password}","ldapUrl":"ldap://localhost:${testds.port}","searchFilter":"cn={user}","baseDn":"ou=People,${testds.rootDn}","subtreeSearch":true}' + enabled="false"/> + jsonConf='{"_class":"org.apache.syncope.common.lib.password.JDBCPasswordManagementConf","sql":"SELECT * FROM users_table WHERE name=?","dialect":"org.hibernate.dialect.H2Dialect","driverClass":"org.h2.Driver","url":"jdbc:h2:tcp://localhost:9092/mem:authdb;DB_CLOSE_DELAY=-1","user":"sa","password":"sa","defaultCatalog":null,"defaultSchema":null,"healthQuery":null,"idleTimeout":600.000000000,"dataSourceName":null,"minPoolSize":6,"maxPoolSize":18,"maxPoolWait":2.000000000,"poolSuspension":false,"poolTimeoutMillis":1000,"poolLeakThreshold":6.000000000,"sqlChangePassword":"UPDATE users_table SET password=? WHERE name=?","sqlFindEmail":"SELECT email FROM users_table WHERE name=?","sqlFindPhone":"SELECT phoneNumber FROM users_table WHERE name=?","sqlFindUser":"SELECT * FROM users_table WHERE name=?","sqlGetSecurityQuestions":null,"sqlUpdateSecurityQuestions":null,"sqlUnlockAccount":null,"sqlDeleteSecurityQuestions":null}' + enabled="false"/> $id " + + "RETURN count(pm) AS cnt") + .bindAll(Map.of("id", key)) + .fetch() + .one() + .map(record -> ((Number) record.get("cnt")).longValue()) + .orElse(0L); + + return count > 0; + } + @Override public PasswordManagement save(final PasswordManagement passwordManagement) { - ((Neo4JPasswordManagement) passwordManagement).list2json(); PasswordManagement saved = neo4jTemplate.save(nodeValidator.validate(passwordManagement)); - ((Neo4JPasswordManagement) saved).postSave(); return saved; } diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/Neo4jEntityFactory.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/Neo4jEntityFactory.java index bbbb25c6c23..f7879cab9be 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/Neo4jEntityFactory.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/Neo4jEntityFactory.java @@ -95,13 +95,13 @@ import org.apache.syncope.core.persistence.api.entity.user.UMembership; import org.apache.syncope.core.persistence.api.entity.user.URelationship; import org.apache.syncope.core.persistence.api.entity.user.User; +import org.apache.syncope.core.persistence.neo4j.entity.am.Neo4JPasswordManagement; import org.apache.syncope.core.persistence.neo4j.entity.am.Neo4jAttrRepo; import org.apache.syncope.core.persistence.neo4j.entity.am.Neo4jAuthModule; import org.apache.syncope.core.persistence.neo4j.entity.am.Neo4jAuthProfile; import org.apache.syncope.core.persistence.neo4j.entity.am.Neo4jCASSPClientApp; import org.apache.syncope.core.persistence.neo4j.entity.am.Neo4jOIDCJWKS; import org.apache.syncope.core.persistence.neo4j.entity.am.Neo4jOIDCRPClientApp; -import org.apache.syncope.core.persistence.neo4j.entity.am.Neo4JPasswordManagement; import org.apache.syncope.core.persistence.neo4j.entity.am.Neo4jSAML2IdPEntity; import org.apache.syncope.core.persistence.neo4j.entity.am.Neo4jSAML2SPClientApp; import org.apache.syncope.core.persistence.neo4j.entity.am.Neo4jWAConfigEntry; diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4JPasswordManagement.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4JPasswordManagement.java index c04baa3d815..d1b168af9ac 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4JPasswordManagement.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/am/Neo4JPasswordManagement.java @@ -1,38 +1,26 @@ package org.apache.syncope.core.persistence.neo4j.entity.am; -import com.fasterxml.jackson.core.type.TypeReference; import jakarta.validation.constraints.NotNull; -import java.util.ArrayList; -import java.util.List; import org.apache.commons.lang3.StringUtils; import org.apache.syncope.common.lib.password.PasswordManagementConf; -import org.apache.syncope.common.lib.to.Item; -import org.apache.syncope.common.lib.types.PasswordManagementState; import org.apache.syncope.core.persistence.api.entity.am.PasswordManagement; +import org.apache.syncope.core.persistence.common.validation.PasswordManagementCheck; import org.apache.syncope.core.persistence.neo4j.entity.AbstractProvidedKeyNode; import org.apache.syncope.core.provisioning.api.serialization.POJOHelper; -import org.springframework.data.annotation.Transient; import org.springframework.data.neo4j.core.schema.Node; -import org.springframework.data.neo4j.core.schema.PostLoad; @Node(Neo4JPasswordManagement.NODE) +@PasswordManagementCheck public class Neo4JPasswordManagement extends AbstractProvidedKeyNode implements PasswordManagement { private static final long serialVersionUID = 5457779846065079998L; public static final String NODE = "PasswordManagement"; - protected static final TypeReference> TYPEREF = new TypeReference>() { - }; - private String description; - private boolean enabled; - - private String items; - - @Transient - private final List itemList = new ArrayList<>(); + @NotNull + private String enabled; private String jsonConf; @@ -47,20 +35,15 @@ public void setDescription(final String description) { } @Override - public boolean isEnabled() { + public String getEnabled() { return enabled; } @Override - public void setEnabled(final boolean enabled) { + public void setEnabled(final String enabled) { this.enabled = enabled; } - @Override - public List getItems() { - return itemList; - } - @Override public PasswordManagementConf getConf() { PasswordManagementConf conf = null; @@ -75,26 +58,4 @@ public PasswordManagementConf getConf() { public void setConf(final PasswordManagementConf conf) { jsonConf = POJOHelper.serialize(conf); } - - protected void json2list(final boolean clearFirst) { - if (clearFirst) { - getItems().clear(); - } - if (items != null) { - getItems().addAll(POJOHelper.deserialize(items, TYPEREF)); - } - } - - @PostLoad - public void postLoad() { - json2list(false); - } - - public void postSave() { - json2list(true); - } - - public void list2json() { - items = POJOHelper.serialize(getItems()); - } } diff --git a/core/persistence-neo4j/src/test/java/org/apache/syncope/core/persistence/neo4j/inner/PasswordManagementTest.java b/core/persistence-neo4j/src/test/java/org/apache/syncope/core/persistence/neo4j/inner/PasswordManagementTest.java index cbce67dcd16..b8473ae3108 100644 --- a/core/persistence-neo4j/src/test/java/org/apache/syncope/core/persistence/neo4j/inner/PasswordManagementTest.java +++ b/core/persistence-neo4j/src/test/java/org/apache/syncope/core/persistence/neo4j/inner/PasswordManagementTest.java @@ -74,23 +74,12 @@ private void savePasswordManagement(final String key, final PasswordManagementCo module.setKey(key); module.setDescription("A password management module"); module.setConf(conf); - - Item keyMapping = new Item(); - keyMapping.setIntAttrName("uid"); - keyMapping.setExtAttrName("username"); - module.getItems().add(keyMapping); - - Item fullnameMapping = new Item(); - fullnameMapping.setIntAttrName("cn"); - fullnameMapping.setExtAttrName("fullname"); - module.getItems().add(fullnameMapping); - + module.setEnabled(Boolean.FALSE.toString()); module = passwordManagementDAO.save(module); assertNotNull(module); assertNotNull(module.getKey()); assertEquals(module, passwordManagementDAO.findById(module.getKey()).orElseThrow()); - assertEquals(2, module.getItems().size()); } @Test diff --git a/core/persistence-neo4j/src/test/resources/domains/MasterContent.xml b/core/persistence-neo4j/src/test/resources/domains/MasterContent.xml index 2fc95ad7bb8..ac3ba847c25 100644 --- a/core/persistence-neo4j/src/test/resources/domains/MasterContent.xml +++ b/core/persistence-neo4j/src/test/resources/domains/MasterContent.xml @@ -95,11 +95,11 @@ under the License. jsonConf='{"_class":"org.apache.syncope.common.lib.password.SyncopePasswordManagementConf","domain":"Master","searchFilter":"username={user}","basicAuthUsername":"admin","basicAuthPassword":"password", "headers":{}}' enabled="true"/> + jsonConf='{"_class":"org.apache.syncope.common.lib.password.JDBCPasswordManagementConf","sql":"SELECT * FROM users_table WHERE name=?","dialect":"org.hibernate.dialect.H2Dialect","driverClass":"org.h2.Driver","url":"jdbc:h2:tcp://localhost:9092/mem:authdb;DB_CLOSE_DELAY=-1","user":"sa","password":"sa","defaultCatalog":null,"defaultSchema":null,"healthQuery":null,"idleTimeout":600.000000000,"dataSourceName":null,"minPoolSize":6,"maxPoolSize":18,"maxPoolWait":2.000000000,"poolSuspension":false,"poolTimeoutMillis":1000,"poolLeakThreshold":6.000000000,"sqlChangePassword":"UPDATE users_table SET password=? WHERE name=?","sqlFindEmail":"SELECT email FROM users_table WHERE name=?","sqlFindPhone":"SELECT phoneNumber FROM users_table WHERE name=?","sqlFindUser":"SELECT * FROM users_table WHERE name=?","sqlGetSecurityQuestions":null,"sqlUpdateSecurityQuestions":null,"sqlUnlockAccount":null,"sqlDeleteSecurityQuestions":null}' + enabled="false"/> { -// if (itemTO == null) { -// LOG.error("Null {}", Item.class.getSimpleName()); -// invalidMapping.getElements().add("Null " + Item.class.getSimpleName()); -// } else if (itemTO.getIntAttrName() == null) { -// requiredValuesMissing.getElements().add("intAttrName"); -// scce.addException(requiredValuesMissing); -// } else { -// // no mandatory condition implies mandatory condition false -// if (!JexlUtils.isExpressionValid(itemTO.getMandatoryCondition() == null -// ? "false" : itemTO.getMandatoryCondition())) { -// -// SyncopeClientException invalidMandatoryCondition = -// SyncopeClientException.build(ClientExceptionType.InvalidValues); -// invalidMandatoryCondition.getElements().add(itemTO.getMandatoryCondition()); -// scce.addException(invalidMandatoryCondition); -// } -// -// Item item = new Item(); -// item.setIntAttrName(itemTO.getIntAttrName()); -// item.setExtAttrName(itemTO.getExtAttrName()); -// item.setMandatoryCondition(itemTO.getMandatoryCondition()); -// item.setConnObjectKey(itemTO.isConnObjectKey()); -// item.setPassword(itemTO.isPassword()); -// item.setPropagationJEXLTransformer(itemTO.getPropagationJEXLTransformer()); -// item.setPullJEXLTransformer(itemTO.getPullJEXLTransformer()); -// passwordManagement.getItems().add(item); -// } -// }); -// -// if (!invalidMapping.getElements().isEmpty()) { -// scce.addException(invalidMapping); -// } -// if (scce.hasExceptions()) { -// throw scce; -// } -// } - -// protected void populateItems(final PasswordManagement passwordManagement, final PasswordManagementTO passwordManagementTO) { -// passwordManagement.getItems().forEach(item -> { -// Item itemTO = new Item(); -// itemTO.setIntAttrName(item.getIntAttrName()); -// itemTO.setExtAttrName(item.getExtAttrName()); -// itemTO.setMandatoryCondition(item.getMandatoryCondition()); -// itemTO.setConnObjectKey(item.isConnObjectKey()); -// itemTO.setPassword(item.isPassword()); -// itemTO.setPropagationJEXLTransformer(item.getPropagationJEXLTransformer()); -// itemTO.setPullJEXLTransformer(item.getPullJEXLTransformer()); -// itemTO.setPurpose(MappingPurpose.NONE); -// -// passwordManagementTO.getItems().add(itemTO); -// }); -// } - @Override public PasswordManagement create(final PasswordManagementTO passwordManagementTO) { PasswordManagement passwordManagement = entityFactory.newEntity(PasswordManagement.class); @@ -92,14 +25,12 @@ public PasswordManagement create(final PasswordManagementTO passwordManagementTO } @Override - public PasswordManagement update(final PasswordManagement passwordManagement, final PasswordManagementTO passwordManagementTO) { + public PasswordManagement update(final PasswordManagement passwordManagement, + final PasswordManagementTO passwordManagementTO) { passwordManagement.setDescription(passwordManagementTO.getDescription()); - passwordManagement.setEnabled(passwordManagementTO.isEnabled()); + passwordManagement.setEnabled(passwordManagementTO.getEnabled()); passwordManagement.setConf(passwordManagementTO.getConf()); - passwordManagement.getItems().clear(); -// populateItems(passwordManagementTO, passwordManagement); - return passwordManagement; } @@ -109,11 +40,9 @@ public PasswordManagementTO getPasswordManagementTO(final PasswordManagement pas passwordManagementTO.setKey(passwordManagement.getKey()); passwordManagementTO.setDescription(passwordManagement.getDescription()); - passwordManagementTO.setEnabled(passwordManagement.isEnabled()); + passwordManagementTO.setEnabled(passwordManagement.getEnabled()); passwordManagementTO.setConf(passwordManagement.getConf()); -// populateItems(passwordManagement, passwordManagementTO); - return passwordManagementTO; } } diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PasswordManagementITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PasswordManagementITCase.java index b505b3d66ac..ca5cd373b1e 100644 --- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PasswordManagementITCase.java +++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PasswordManagementITCase.java @@ -110,7 +110,8 @@ public void list() { @Test public void getSyncopePasswordManagement() { - PasswordManagementTO passwordManagementTO = PASSWORD_MANAGEMENT_SERVICE.read("DefaultSyncopePasswordManagement"); + PasswordManagementTO passwordManagementTO = + PASSWORD_MANAGEMENT_SERVICE.read("DefaultSyncopePasswordManagement"); assertNotNull(passwordManagementTO); assertTrue(StringUtils.isNotBlank(passwordManagementTO.getDescription())); @@ -119,7 +120,8 @@ public void getSyncopePasswordManagement() { @Test public void getLdapPasswordManagement() { - PasswordManagementTO passwordManagementTO = PASSWORD_MANAGEMENT_SERVICE.read("DefaultLDAPPasswordManagement"); + PasswordManagementTO passwordManagementTO = + PASSWORD_MANAGEMENT_SERVICE.read("DefaultLDAPPasswordManagement"); assertNotNull(passwordManagementTO); assertTrue(StringUtils.isNotBlank(passwordManagementTO.getDescription())); @@ -128,7 +130,8 @@ public void getLdapPasswordManagement() { @Test public void getJdbcPasswordManagement() { - PasswordManagementTO passwordManagementTO = PASSWORD_MANAGEMENT_SERVICE.read("DefaultJDBCPasswordManagement"); + PasswordManagementTO passwordManagementTO = + PASSWORD_MANAGEMENT_SERVICE.read("DefaultJDBCPasswordManagement"); assertNotNull(passwordManagementTO); assertTrue(StringUtils.isNotBlank(passwordManagementTO.getDescription())); @@ -146,10 +149,12 @@ public void create() { @Test public void updateSyncopePasswordManagement() { - PasswordManagementTO syncopePasswordManagementTO = PASSWORD_MANAGEMENT_SERVICE.read("DefaultSyncopePasswordManagement"); + PasswordManagementTO syncopePasswordManagementTO = + PASSWORD_MANAGEMENT_SERVICE.read("DefaultSyncopePasswordManagement"); assertNotNull(syncopePasswordManagementTO); - PasswordManagementTO newSyncopePasswordManagementTO = buildPasswordManagementTO(PasswordManagementSupportedType.SYNCOPE); + PasswordManagementTO newSyncopePasswordManagementTO = + buildPasswordManagementTO(PasswordManagementSupportedType.SYNCOPE); newSyncopePasswordManagementTO = createPasswordManagement(newSyncopePasswordManagementTO); assertNotNull(newSyncopePasswordManagementTO); @@ -169,10 +174,12 @@ public void updateSyncopePasswordManagement() { @Test public void updateLdapPasswordManagement() { - PasswordManagementTO ldapPasswordManagementTO = PASSWORD_MANAGEMENT_SERVICE.read("DefaultLDAPPasswordManagement"); + PasswordManagementTO ldapPasswordManagementTO = + PASSWORD_MANAGEMENT_SERVICE.read("DefaultLDAPPasswordManagement"); assertNotNull(ldapPasswordManagementTO); - PasswordManagementTO newLdapPasswordManagementTO = buildPasswordManagementTO(PasswordManagementSupportedType.LDAP); + PasswordManagementTO newLdapPasswordManagementTO = + buildPasswordManagementTO(PasswordManagementSupportedType.LDAP); newLdapPasswordManagementTO = createPasswordManagement(newLdapPasswordManagementTO); assertNotNull(newLdapPasswordManagementTO); @@ -192,10 +199,12 @@ public void updateLdapPasswordManagement() { @Test public void updateJdbcPasswordManagement() { - PasswordManagementTO jdbcPasswordManagementTO = PASSWORD_MANAGEMENT_SERVICE.read("DefaultJDBCPasswordManagement"); + PasswordManagementTO jdbcPasswordManagementTO = + PASSWORD_MANAGEMENT_SERVICE.read("DefaultJDBCPasswordManagement"); assertNotNull(jdbcPasswordManagementTO); - PasswordManagementTO newJdbcPasswordManagementTO = buildPasswordManagementTO(PasswordManagementSupportedType.JDBC); + PasswordManagementTO newJdbcPasswordManagementTO = + buildPasswordManagementTO(PasswordManagementSupportedType.JDBC); newJdbcPasswordManagementTO = createPasswordManagement(newJdbcPasswordManagementTO); assertNotNull(newJdbcPasswordManagementTO); diff --git a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WAPropertySourceLocator.java b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WAPropertySourceLocator.java index 4a4418a0834..e4cfb76bf58 100644 --- a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WAPropertySourceLocator.java +++ b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WAPropertySourceLocator.java @@ -29,8 +29,6 @@ import org.apache.commons.lang3.tuple.Pair; import org.apache.syncope.client.lib.SyncopeClient; import org.apache.syncope.common.lib.to.OIDCRPClientAppTO; -import org.apache.syncope.common.lib.to.PasswordManagementTO; -import org.apache.syncope.common.lib.types.PasswordManagementState; import org.apache.syncope.common.rest.api.service.AttrRepoService; import org.apache.syncope.common.rest.api.service.AuthModuleService; import org.apache.syncope.common.rest.api.service.PasswordManagementService; @@ -133,8 +131,8 @@ public PropertySource locate(final Environment environment) { }); syncopeClient.getService(PasswordManagementService.class).list() - .stream().filter(PasswordManagementTO::isEnabled).findFirst().ifPresent( - passwordManagementTO -> { + .stream().filter(pm -> Boolean.parseBoolean(pm.getEnabled())).findFirst() + .ifPresent(passwordManagementTO -> { LOG.debug("Mapping password module {} ", passwordManagementTO.getKey()); Map map = passwordManagementTO.getConf() diff --git a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/PasswordManagementPropertySourceMapper.java b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/PasswordManagementPropertySourceMapper.java index 8dd5aa3ff1a..df52e2967e5 100644 --- a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/PasswordManagementPropertySourceMapper.java +++ b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/PasswordManagementPropertySourceMapper.java @@ -8,14 +8,14 @@ import org.apache.syncope.common.lib.password.PasswordManagementConf; import org.apache.syncope.common.lib.password.SyncopePasswordManagementConf; import org.apache.syncope.common.lib.to.PasswordManagementTO; -import org.apache.syncope.common.lib.types.PasswordManagementState; import org.apache.syncope.wa.bootstrap.WARestClient; import org.apereo.cas.configuration.model.support.ldap.AbstractLdapProperties; import org.apereo.cas.configuration.model.support.pm.JdbcPasswordManagementProperties; import org.apereo.cas.configuration.model.support.pm.LdapPasswordManagementProperties; import org.apereo.cas.configuration.model.support.pm.SyncopePasswordManagementProperties; -public class PasswordManagementPropertySourceMapper extends PropertySourceMapper implements PasswordManagementConf.Mapper { +public class PasswordManagementPropertySourceMapper extends PropertySourceMapper + implements PasswordManagementConf.Mapper { protected final WARestClient waRestClient; @@ -24,7 +24,8 @@ public PasswordManagementPropertySourceMapper(final WARestClient waRestClient) { } @Override - public Map map(final PasswordManagementTO passwordManagementTO, final SyncopePasswordManagementConf conf) { + public Map map(final PasswordManagementTO passwordManagementTO, + final SyncopePasswordManagementConf conf) { SyncopeClient syncopeClient = waRestClient.getSyncopeClient(); if (syncopeClient == null) { LOG.warn("Application context is not ready to bootstrap WA configuration"); @@ -40,12 +41,13 @@ public Map map(final PasswordManagementTO passwordManagementTO, props.setHeaders(conf.getHeaders()); Map mappedProps = prefix("cas.authn.pm.syncope.", WAConfUtils.asMap(props)); - mappedProps.put("cas.authn.pm.syncope.enabled", passwordManagementTO.isEnabled()); + mappedProps.put("cas.authn.pm.syncope.enabled", passwordManagementTO.getEnabled()); return mappedProps; } @Override - public Map map(final PasswordManagementTO passwordManagementTO, final LDAPPasswordManagementConf conf) { + public Map map(final PasswordManagementTO passwordManagementTO, + final LDAPPasswordManagementConf conf) { LdapPasswordManagementProperties props = new LdapPasswordManagementProperties(); props.setName(passwordManagementTO.getKey()); props.setType(AbstractLdapProperties.LdapType.valueOf(conf.getLdapType().name())); @@ -54,12 +56,13 @@ public Map map(final PasswordManagementTO passwordManagementTO, fill(props, conf); Map mappedProps = prefix("cas.authn.pm.ldap[].", WAConfUtils.asMap(props)); - mappedProps.put("cas.authn.pm.ldap.enabled", passwordManagementTO.isEnabled()); + mappedProps.put("cas.authn.pm.ldap.enabled", passwordManagementTO.getEnabled()); return mappedProps; } @Override - public Map map(final PasswordManagementTO passwordManagementTO, final JDBCPasswordManagementConf conf) { + public Map map(final PasswordManagementTO passwordManagementTO, + final JDBCPasswordManagementConf conf) { JdbcPasswordManagementProperties props = new JdbcPasswordManagementProperties(); props.setSqlChangePassword(conf.getSqlChangePassword()); props.setSqlFindEmail(conf.getSqlFindEmail()); @@ -72,7 +75,7 @@ public Map map(final PasswordManagementTO passwordManagementTO, fill(props, conf); Map mappedProps = prefix("cas.authn.pm.jdbc.", WAConfUtils.asMap(props)); - mappedProps.put("cas.authn.pm.jdbc.enabled", passwordManagementTO.isEnabled()); + mappedProps.put("cas.authn.pm.jdbc.enabled", passwordManagementTO.getEnabled()); return mappedProps; } } From fe7e34f4cc48d2209d3f923f434febc9ec7a29bb Mon Sep 17 00:00:00 2001 From: alberto bogi Date: Thu, 4 Sep 2025 14:52:20 +0200 Subject: [PATCH 13/20] [SYNCOPE-1901] Add password management configuration for REST source --- .../password/LDAPPasswordManagementConf.java | 3 +- .../lib/password/PasswordManagementConf.java | 2 + .../password/RESTPasswordManagementConf.java | 172 ++++++++++++++++++ .../SyncopePasswordManagementConf.java | 3 +- .../jpa/inner/PasswordManagementTest.java | 58 +++++- .../test/resources/domains/MasterContent.xml | 3 + .../neo4j/inner/PasswordManagementTest.java | 50 ++++- .../test/resources/domains/MasterContent.xml | 3 + .../fit/core/PasswordManagementITCase.java | 73 +++++++- ...asswordManagementPropertySourceMapper.java | 24 +++ wa/starter/pom.xml | 4 + .../syncope/wa/starter/config/WAContext.java | 34 +++- 12 files changed, 401 insertions(+), 28 deletions(-) create mode 100644 common/am/lib/src/main/java/org/apache/syncope/common/lib/password/RESTPasswordManagementConf.java diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/LDAPPasswordManagementConf.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/LDAPPasswordManagementConf.java index 0e808045bef..c1c7c21487d 100644 --- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/LDAPPasswordManagementConf.java +++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/LDAPPasswordManagementConf.java @@ -21,7 +21,8 @@ public void setUsernameAttribute(final String usernameAttribute) { this.usernameAttribute = usernameAttribute; } - @Override public Map map(final PasswordManagementTO passwordManagementTO, final Mapper mapper) { + @Override + public Map map(final PasswordManagementTO passwordManagementTO, final Mapper mapper) { return mapper.map(passwordManagementTO, this); } } diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/PasswordManagementConf.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/PasswordManagementConf.java index 9d0a29c79fb..b8567b34565 100644 --- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/PasswordManagementConf.java +++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/PasswordManagementConf.java @@ -17,6 +17,8 @@ interface Mapper { Map map(PasswordManagementTO passwordManagementTO, JDBCPasswordManagementConf conf); + Map map(PasswordManagementTO passwordManagementTO, RESTPasswordManagementConf conf); + } Map map(PasswordManagementTO passwordManagementTO, Mapper mapper); diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/RESTPasswordManagementConf.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/RESTPasswordManagementConf.java new file mode 100644 index 00000000000..95087d0b936 --- /dev/null +++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/RESTPasswordManagementConf.java @@ -0,0 +1,172 @@ +package org.apache.syncope.common.lib.password; + +import java.util.HashMap; +import java.util.Map; +import org.apache.syncope.common.lib.to.PasswordManagementTO; + +public class RESTPasswordManagementConf implements PasswordManagementConf { + + private static final long serialVersionUID = 7262269548010007815L; + + /** + * Password for Basic-Auth at the password management endpoints. + */ + private String endpointPassword; + + /** + * Endpoint URL to use when unlocking account. + */ + private String endpointUrlAccountUnlock; + + /** + * Endpoint URL to use when updating passwords. + */ + private String endpointUrlChange; + + /** + * Endpoint URL to use when locating email addresses. + */ + private String endpointUrlEmail; + + /** + * Endpoint URL to use when locating phone numbers. + */ + private String endpointUrlPhone; + + /** + * Endpoint URL to use when locating security questions. + */ + private String endpointUrlSecurityQuestions; + + /** + * Endpoint URL to use when locating user names. + */ + private String endpointUrlUser; + + /** + * Endpoint URL to use when locating usernames. + */ + private String endpointUsername; + + /** + * Field name for oldPassword field when password change requests are submitted. + */ + private String fieldNamePasswordOld = "oldPassword"; + + /** + * Field name for password field when password change requests are submitted. + */ + private String fieldNamePassword = "password"; + + /** + * Field name for username field when password change requests are submitted. + */ + private String fieldNameUser = "username"; + + /** + * Additional headers to be included in REST API calls for password management. + * The map keys are header names and the corresponding values are header values. + */ + private Map headers = new HashMap<>(); + + public String getEndpointPassword() { + return endpointPassword; + } + + public void setEndpointPassword(String endpointPassword) { + this.endpointPassword = endpointPassword; + } + + public String getEndpointUrlAccountUnlock() { + return endpointUrlAccountUnlock; + } + + public void setEndpointUrlAccountUnlock(String endpointUrlAccountUnlock) { + this.endpointUrlAccountUnlock = endpointUrlAccountUnlock; + } + + public String getEndpointUrlChange() { + return endpointUrlChange; + } + + public void setEndpointUrlChange(String endpointUrlChange) { + this.endpointUrlChange = endpointUrlChange; + } + + public String getEndpointUrlEmail() { + return endpointUrlEmail; + } + + public void setEndpointUrlEmail(String endpointUrlEmail) { + this.endpointUrlEmail = endpointUrlEmail; + } + + public String getEndpointUrlPhone() { + return endpointUrlPhone; + } + + public void setEndpointUrlPhone(String endpointUrlPhone) { + this.endpointUrlPhone = endpointUrlPhone; + } + + public String getEndpointUrlSecurityQuestions() { + return endpointUrlSecurityQuestions; + } + + public void setEndpointUrlSecurityQuestions(String endpointUrlSecurityQuestions) { + this.endpointUrlSecurityQuestions = endpointUrlSecurityQuestions; + } + + public String getEndpointUrlUser() { + return endpointUrlUser; + } + + public void setEndpointUrlUser(String endpointUrlUser) { + this.endpointUrlUser = endpointUrlUser; + } + + public String getEndpointUsername() { + return endpointUsername; + } + + public void setEndpointUsername(String endpointUsername) { + this.endpointUsername = endpointUsername; + } + + public String getFieldNamePasswordOld() { + return fieldNamePasswordOld; + } + + public void setFieldNamePasswordOld(String fieldNamePasswordOld) { + this.fieldNamePasswordOld = fieldNamePasswordOld; + } + + public String getFieldNamePassword() { + return fieldNamePassword; + } + + public void setFieldNamePassword(String fieldNamePassword) { + this.fieldNamePassword = fieldNamePassword; + } + + public String getFieldNameUser() { + return fieldNameUser; + } + + public void setFieldNameUser(String fieldNameUser) { + this.fieldNameUser = fieldNameUser; + } + + public Map getHeaders() { + return headers; + } + + public void setHeaders(Map headers) { + this.headers = headers; + } + + @Override + public Map map(PasswordManagementTO passwordManagementTO, Mapper mapper) { + return mapper.map(passwordManagementTO, this); + } +} diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/SyncopePasswordManagementConf.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/SyncopePasswordManagementConf.java index f7fee820b11..0dce2e617cc 100644 --- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/SyncopePasswordManagementConf.java +++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/SyncopePasswordManagementConf.java @@ -74,7 +74,8 @@ public void setHeaders(final Map headers) { this.headers = headers; } - @Override public Map map(final PasswordManagementTO passwordManagementTO, final Mapper mapper) { + @Override + public Map map(final PasswordManagementTO passwordManagementTO, final Mapper mapper) { return mapper.map(passwordManagementTO, this); } } diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PasswordManagementTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PasswordManagementTest.java index 19490ae8fcf..f8a0a9f4da0 100644 --- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PasswordManagementTest.java +++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PasswordManagementTest.java @@ -2,6 +2,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -10,8 +11,8 @@ import org.apache.syncope.common.lib.password.JDBCPasswordManagementConf; import org.apache.syncope.common.lib.password.LDAPPasswordManagementConf; import org.apache.syncope.common.lib.password.PasswordManagementConf; +import org.apache.syncope.common.lib.password.RESTPasswordManagementConf; import org.apache.syncope.common.lib.password.SyncopePasswordManagementConf; -import org.apache.syncope.common.lib.to.Item; import org.apache.syncope.core.persistence.api.dao.PasswordManagementDAO; import org.apache.syncope.core.persistence.api.entity.am.PasswordManagement; import org.apache.syncope.core.persistence.jpa.AbstractTest; @@ -36,20 +37,23 @@ public void findAll() { List modules = passwordManagementDAO.findAll(); assertNotNull(modules); assertFalse(modules.isEmpty()); - assertEquals(3, modules.size()); + assertEquals(4, modules.size()); } @Test public void find() { PasswordManagement passwordManagement = passwordManagementDAO.findById("DefaultSyncopePasswordManagement") .orElseThrow(); - assertTrue(passwordManagement.getConf() instanceof SyncopePasswordManagementConf); + assertInstanceOf(SyncopePasswordManagementConf.class, passwordManagement.getConf()); passwordManagement = passwordManagementDAO.findById("DefaultLDAPPasswordManagement").orElseThrow(); - assertTrue(passwordManagement.getConf() instanceof LDAPPasswordManagementConf); + assertInstanceOf(LDAPPasswordManagementConf.class, passwordManagement.getConf()); passwordManagement = passwordManagementDAO.findById("DefaultJDBCPasswordManagement").orElseThrow(); - assertTrue(passwordManagement.getConf() instanceof JDBCPasswordManagementConf); + assertInstanceOf(JDBCPasswordManagementConf.class, passwordManagement.getConf()); + + passwordManagement = passwordManagementDAO.findById("DefaultRESTPasswordManagement").orElseThrow(); + assertInstanceOf(RESTPasswordManagementConf.class, passwordManagement.getConf()); } @Test @@ -67,6 +71,10 @@ public void findByType() { passwordManagement -> isSpecificConf(passwordManagement.getConf(), JDBCPasswordManagementConf.class) && passwordManagement.getKey().equals("DefaultJDBCPasswordManagement"))); + assertTrue(passwordManagements.stream().anyMatch( + passwordManagement -> isSpecificConf(passwordManagement.getConf(), + RESTPasswordManagementConf.class) + && passwordManagement.getKey().equals("DefaultRESTPasswordManagement"))); } private void savePasswordManagement(final String key, final PasswordManagementConf conf) { @@ -91,7 +99,7 @@ public void saveWithSyncopeModule() { } @Test - public void saveWithLdapModule() { + public void saveWithLDAPModule() { LDAPPasswordManagementConf conf = new LDAPPasswordManagementConf(); conf.setBaseDn("dc=example,dc=org"); conf.setSearchFilter("cn={user}"); @@ -104,7 +112,7 @@ public void saveWithLdapModule() { } @Test - public void saveWithJdbcModule() { + public void saveWithJDBCModule() { JDBCPasswordManagementConf conf = new JDBCPasswordManagementConf(); conf.setSqlFindEmail("SELECT email from users_table where name=?"); conf.setSqlFindPhone("SELECT phoneNumber from users_table where name=?"); @@ -114,6 +122,23 @@ public void saveWithJdbcModule() { savePasswordManagement("JDBCPasswordManagementTest", conf); } + @Test + public void saveWithRESTModule() { + RESTPasswordManagementConf conf = new RESTPasswordManagementConf(); + conf.setEndpointPassword("password"); + conf.setEndpointUrlAccountUnlock("http://localhost:9443/syncope-fit-build-tools/cxf/rest/unlockAccount"); + conf.setEndpointUrlChange("http://localhost:9443/syncope-fit-build-tools/cxf/rest/changePassword"); + conf.setEndpointUrlEmail("http://localhost:9443/syncope-fit-build-tools/cxf/rest/findEmail"); + conf.setEndpointUrlPhone("http://localhost:9443/syncope-fit-build-tools/cxf/rest/findPhone"); + conf.setEndpointUrlSecurityQuestions("http://localhost:9443/syncope-fit-build-tools/cxf/rest/securityQuestions"); + conf.setEndpointUsername("http://localhost:9443/syncope-fit-build-tools/cxf/rest/findUser"); + conf.setFieldNamePasswordOld("oldPassword"); + conf.setFieldNamePassword("password"); + conf.setEndpointUsername("username"); + + savePasswordManagement("RESTPasswordManagementTest", conf); + } + @Test public void updateWithSyncopeModule() { PasswordManagement module = passwordManagementDAO.findById("DefaultSyncopePasswordManagement").orElseThrow(); @@ -131,7 +156,7 @@ public void updateWithSyncopeModule() { } @Test - public void updateWithLdapModule() { + public void updateWithLDAPModule() { PasswordManagement module = passwordManagementDAO.findById("DefaultLDAPPasswordManagement").orElseThrow(); PasswordManagementConf conf = module.getConf(); @@ -165,6 +190,23 @@ public void updateWithJDBCModule() { JDBCPasswordManagementConf.class.cast(found.getConf()).getSqlFindUser()); } + @Test + public void updateWithRESTModule() { + PasswordManagement module = passwordManagementDAO.findById("DefaultRESTPasswordManagement").orElseThrow(); + + PasswordManagementConf conf = module.getConf(); + RESTPasswordManagementConf.class.cast(conf).setFieldNamePasswordOld("changedOldPassword"); + module.setConf(conf); + + module = passwordManagementDAO.save(module); + assertNotNull(module); + assertNotNull(module.getKey()); + + PasswordManagement found = passwordManagementDAO.findById(module.getKey()).orElseThrow(); + assertEquals("changedOldPassword", + RESTPasswordManagementConf.class.cast(found.getConf()).getFieldNamePasswordOld()); + } + @Test public void delete() { assertTrue(passwordManagementDAO.findById("DefaultSyncopePasswordManagement").isPresent()); diff --git a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml index c74b527d790..06f1c2d7c4c 100644 --- a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml +++ b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml @@ -100,6 +100,9 @@ under the License. + modules = passwordManagementDAO.findAll(); assertNotNull(modules); assertFalse(modules.isEmpty()); - assertEquals(3, modules.size()); + assertEquals(4, modules.size()); } @Test public void find() { PasswordManagement passwordManagement = passwordManagementDAO.findById("DefaultSyncopePasswordManagement") .orElseThrow(); - assertTrue(passwordManagement.getConf() instanceof SyncopePasswordManagementConf); + assertInstanceOf(SyncopePasswordManagementConf.class, passwordManagement.getConf()); passwordManagement = passwordManagementDAO.findById("DefaultLDAPPasswordManagement").orElseThrow(); - assertTrue(passwordManagement.getConf() instanceof LDAPPasswordManagementConf); + assertInstanceOf(LDAPPasswordManagementConf.class, passwordManagement.getConf()); passwordManagement = passwordManagementDAO.findById("DefaultJDBCPasswordManagement").orElseThrow(); - assertTrue(passwordManagement.getConf() instanceof JDBCPasswordManagementConf); + assertInstanceOf(JDBCPasswordManagementConf.class, passwordManagement.getConf()); } @Test @@ -91,7 +93,7 @@ public void saveWithSyncopeModule() { } @Test - public void saveWithLdapModule() { + public void saveWithLDAPModule() { LDAPPasswordManagementConf conf = new LDAPPasswordManagementConf(); conf.setBaseDn("dc=example,dc=org"); conf.setSearchFilter("cn={user}"); @@ -104,7 +106,7 @@ public void saveWithLdapModule() { } @Test - public void saveWithJdbcModule() { + public void saveWithJDBCModule() { JDBCPasswordManagementConf conf = new JDBCPasswordManagementConf(); conf.setSqlFindEmail("SELECT email from users_table where name=?"); conf.setSqlFindPhone("SELECT phoneNumber from users_table where name=?"); @@ -114,6 +116,23 @@ public void saveWithJdbcModule() { savePasswordManagement("JDBCPasswordManagementTest", conf); } + @Test + public void saveWithRESTModule() { + RESTPasswordManagementConf conf = new RESTPasswordManagementConf(); + conf.setEndpointPassword("password"); + conf.setEndpointUrlAccountUnlock("http://localhost:9443/syncope-fit-build-tools/cxf/rest/unlockAccount"); + conf.setEndpointUrlChange("http://localhost:9443/syncope-fit-build-tools/cxf/rest/changePassword"); + conf.setEndpointUrlEmail("http://localhost:9443/syncope-fit-build-tools/cxf/rest/findEmail"); + conf.setEndpointUrlPhone("http://localhost:9443/syncope-fit-build-tools/cxf/rest/findPhone"); + conf.setEndpointUrlSecurityQuestions("http://localhost:9443/syncope-fit-build-tools/cxf/rest/securityQuestions"); + conf.setEndpointUsername("http://localhost:9443/syncope-fit-build-tools/cxf/rest/findUser"); + conf.setFieldNamePasswordOld("oldPassword"); + conf.setFieldNamePassword("password"); + conf.setEndpointUsername("username"); + + savePasswordManagement("RESTPasswordManagementTest", conf); + } + @Test public void updateWithSyncopeModule() { PasswordManagement module = passwordManagementDAO.findById("DefaultSyncopePasswordManagement").orElseThrow(); @@ -131,7 +150,7 @@ public void updateWithSyncopeModule() { } @Test - public void updateWithLdapModule() { + public void updateWithLDAPModule() { PasswordManagement module = passwordManagementDAO.findById("DefaultLDAPPasswordManagement").orElseThrow(); PasswordManagementConf conf = module.getConf(); @@ -165,6 +184,23 @@ public void updateWithJDBCModule() { JDBCPasswordManagementConf.class.cast(found.getConf()).getSqlFindUser()); } + @Test + public void updateWithRESTModule() { + PasswordManagement module = passwordManagementDAO.findById("DefaultRESTPasswordManagement").orElseThrow(); + + PasswordManagementConf conf = module.getConf(); + RESTPasswordManagementConf.class.cast(conf).setFieldNamePasswordOld("changedOldPassword"); + module.setConf(conf); + + module = passwordManagementDAO.save(module); + assertNotNull(module); + assertNotNull(module.getKey()); + + PasswordManagement found = passwordManagementDAO.findById(module.getKey()).orElseThrow(); + assertEquals("changedOldPassword", + RESTPasswordManagementConf.class.cast(found.getConf()).getFieldNamePasswordOld()); + } + @Test public void delete() { assertTrue(passwordManagementDAO.findById("DefaultSyncopePasswordManagement").isPresent()); diff --git a/core/persistence-neo4j/src/test/resources/domains/MasterContent.xml b/core/persistence-neo4j/src/test/resources/domains/MasterContent.xml index ac3ba847c25..ae485f70745 100644 --- a/core/persistence-neo4j/src/test/resources/domains/MasterContent.xml +++ b/core/persistence-neo4j/src/test/resources/domains/MasterContent.xml @@ -100,6 +100,9 @@ under the License. + isSpecificConf(passwordManagement.getConf(), JDBCPasswordManagementConf.class) && passwordManagement.getKey() .equals("DefaultJDBCPasswordManagement"))); + assertTrue(passwordManagementTOS.stream().anyMatch( + passwordManagement -> isSpecificConf(passwordManagement.getConf(), + RESTPasswordManagementConf.class) && passwordManagement.getKey() + .equals("DefaultRESTPasswordManagement"))); } @Test @@ -119,7 +144,7 @@ public void getSyncopePasswordManagement() { } @Test - public void getLdapPasswordManagement() { + public void getLDAPPasswordManagement() { PasswordManagementTO passwordManagementTO = PASSWORD_MANAGEMENT_SERVICE.read("DefaultLDAPPasswordManagement"); @@ -129,7 +154,7 @@ public void getLdapPasswordManagement() { } @Test - public void getJdbcPasswordManagement() { + public void getJDBCPasswordManagement() { PasswordManagementTO passwordManagementTO = PASSWORD_MANAGEMENT_SERVICE.read("DefaultJDBCPasswordManagement"); @@ -138,6 +163,16 @@ public void getJdbcPasswordManagement() { assertTrue(isSpecificConf(passwordManagementTO.getConf(), JDBCPasswordManagementConf.class)); } + @Test + public void getRESTPasswordManagement() { + PasswordManagementTO passwordManagementTO = + PASSWORD_MANAGEMENT_SERVICE.read("DefaultRESTPasswordManagement"); + + assertNotNull(passwordManagementTO); + assertTrue(StringUtils.isNotBlank(passwordManagementTO.getDescription())); + assertTrue(isSpecificConf(passwordManagementTO.getConf(), RESTPasswordManagementConf.class)); + } + @Test public void create() { EnumSet.allOf(PasswordManagementSupportedType.class).forEach(type -> { @@ -173,7 +208,7 @@ public void updateSyncopePasswordManagement() { } @Test - public void updateLdapPasswordManagement() { + public void updateLDAPPasswordManagement() { PasswordManagementTO ldapPasswordManagementTO = PASSWORD_MANAGEMENT_SERVICE.read("DefaultLDAPPasswordManagement"); assertNotNull(ldapPasswordManagementTO); @@ -198,7 +233,7 @@ public void updateLdapPasswordManagement() { } @Test - public void updateJdbcPasswordManagement() { + public void updateJDBCPasswordManagement() { PasswordManagementTO jdbcPasswordManagementTO = PASSWORD_MANAGEMENT_SERVICE.read("DefaultJDBCPasswordManagement"); assertNotNull(jdbcPasswordManagementTO); @@ -223,6 +258,32 @@ public void updateJdbcPasswordManagement() { JDBCPasswordManagementConf.class.cast(conf).getSqlFindUser()); } + @Test + public void updateRESTPasswordManagement() { + PasswordManagementTO restPasswordManagementTO = + PASSWORD_MANAGEMENT_SERVICE.read("DefaultRESTPasswordManagement"); + assertNotNull(restPasswordManagementTO); + + PasswordManagementTO newRestPasswordManagementTO = + buildPasswordManagementTO(PasswordManagementSupportedType.REST); + newRestPasswordManagementTO = createPasswordManagement(newRestPasswordManagementTO); + assertNotNull(newRestPasswordManagementTO); + + PasswordManagementConf conf = restPasswordManagementTO.getConf(); + assertNotNull(conf); + RESTPasswordManagementConf.class.cast(conf).setFieldNamePasswordOld("changedOldPassword"); + newRestPasswordManagementTO.setConf(conf); + + // update new password management + PASSWORD_MANAGEMENT_SERVICE.update(newRestPasswordManagementTO); + newRestPasswordManagementTO = PASSWORD_MANAGEMENT_SERVICE.read(newRestPasswordManagementTO.getKey()); + assertNotNull(newRestPasswordManagementTO); + + conf = newRestPasswordManagementTO.getConf(); + assertEquals("changedOldPassword", + RESTPasswordManagementConf.class.cast(conf).getFieldNamePasswordOld()); + } + @Test public void delete() throws IOException { EnumSet.allOf(PasswordManagementSupportedType.class).forEach(type -> { diff --git a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/PasswordManagementPropertySourceMapper.java b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/PasswordManagementPropertySourceMapper.java index df52e2967e5..3fed7de0b20 100644 --- a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/PasswordManagementPropertySourceMapper.java +++ b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/PasswordManagementPropertySourceMapper.java @@ -6,12 +6,14 @@ import org.apache.syncope.common.lib.password.JDBCPasswordManagementConf; import org.apache.syncope.common.lib.password.LDAPPasswordManagementConf; import org.apache.syncope.common.lib.password.PasswordManagementConf; +import org.apache.syncope.common.lib.password.RESTPasswordManagementConf; import org.apache.syncope.common.lib.password.SyncopePasswordManagementConf; import org.apache.syncope.common.lib.to.PasswordManagementTO; import org.apache.syncope.wa.bootstrap.WARestClient; import org.apereo.cas.configuration.model.support.ldap.AbstractLdapProperties; import org.apereo.cas.configuration.model.support.pm.JdbcPasswordManagementProperties; import org.apereo.cas.configuration.model.support.pm.LdapPasswordManagementProperties; +import org.apereo.cas.configuration.model.support.pm.RestfulPasswordManagementProperties; import org.apereo.cas.configuration.model.support.pm.SyncopePasswordManagementProperties; public class PasswordManagementPropertySourceMapper extends PropertySourceMapper @@ -78,4 +80,26 @@ public Map map(final PasswordManagementTO passwordManagementTO, mappedProps.put("cas.authn.pm.jdbc.enabled", passwordManagementTO.getEnabled()); return mappedProps; } + + @Override + public Map map(final PasswordManagementTO passwordManagementTO, + final RESTPasswordManagementConf conf) { + RestfulPasswordManagementProperties props = new RestfulPasswordManagementProperties(); + props.setEndpointPassword(conf.getEndpointPassword()); + props.setEndpointUrlAccountUnlock(conf.getEndpointUrlAccountUnlock()); + props.setEndpointUrlChange(conf.getEndpointUrlChange()); + props.setEndpointUrlEmail(conf.getEndpointUrlEmail()); + props.setEndpointUrlPhone(conf.getEndpointUrlPhone()); + props.setEndpointUrlSecurityQuestions(conf.getEndpointUrlSecurityQuestions()); + props.setEndpointUrlUser(conf.getEndpointUrlUser()); + props.setEndpointUsername(conf.getEndpointUsername()); + props.setFieldNamePasswordOld(conf.getFieldNamePasswordOld()); + props.setFieldNamePassword(conf.getFieldNamePassword()); + props.setFieldNameUser(conf.getFieldNameUser()); + props.setHeaders(conf.getHeaders()); + + Map mappedProps = prefix("cas.authn.pm.rest.", WAConfUtils.asMap(props)); + mappedProps.put("cas.authn.pm.rest.enabled", passwordManagementTO.getEnabled()); + return mappedProps; + } } diff --git a/wa/starter/pom.xml b/wa/starter/pom.xml index 0cfe588d52b..10a0128d525 100644 --- a/wa/starter/pom.xml +++ b/wa/starter/pom.xml @@ -173,6 +173,10 @@ under the License. org.apereo.cas cas-server-support-pm-jdbc
+ + org.apereo.cas + cas-server-support-pm-rest + org.apereo.cas cas-server-support-reports diff --git a/wa/starter/src/main/java/org/apache/syncope/wa/starter/config/WAContext.java b/wa/starter/src/main/java/org/apache/syncope/wa/starter/config/WAContext.java index aef845491a7..cae14bd9019 100644 --- a/wa/starter/src/main/java/org/apache/syncope/wa/starter/config/WAContext.java +++ b/wa/starter/src/main/java/org/apache/syncope/wa/starter/config/WAContext.java @@ -23,6 +23,7 @@ import io.swagger.v3.oas.models.info.Contact; import io.swagger.v3.oas.models.info.Info; import io.swagger.v3.oas.models.security.SecurityScheme; +import java.io.Serial; import java.io.Serializable; import java.util.ArrayList; import java.util.List; @@ -85,6 +86,7 @@ import org.apereo.cas.pm.PasswordManagementService; import org.apereo.cas.pm.impl.NoOpPasswordManagementService; import org.apereo.cas.pm.jdbc.JdbcPasswordManagementService; +import org.apereo.cas.pm.rest.RestPasswordManagementService; import org.apereo.cas.services.ServiceRegistryExecutionPlanConfigurer; import org.apereo.cas.services.ServiceRegistryListener; import org.apereo.cas.support.events.CasEventRepository; @@ -120,6 +122,7 @@ import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.provisioning.InMemoryUserDetailsManager; import org.springframework.transaction.support.TransactionOperations; +import org.springframework.web.client.RestTemplate; @Configuration(proxyBeanMethods = false) public class WAContext { @@ -356,7 +359,7 @@ public OneTimeTokenCredentialRepository googleAuthenticatorAccountRegistry( public PasswordManagementService syncopePasswordChangeService( final CasConfigurationProperties casProperties, @Qualifier("passwordManagementCipherExecutor") - final CipherExecutor passwordManagementCipherExecutor, + final CipherExecutor passwordManagementCipherExecutor, @Qualifier(PasswordHistoryService.BEAN_NAME) final PasswordHistoryService passwordHistoryService) { PasswordManagementProperties pm = casProperties.getAuthn().getPm(); @@ -374,7 +377,7 @@ public PasswordManagementService syncopePasswordChangeService( public PasswordManagementService ldapPasswordChangeService( final CasConfigurationProperties casProperties, @Qualifier("passwordManagementCipherExecutor") - final CipherExecutor passwordManagementCipherExecutor, + final CipherExecutor passwordManagementCipherExecutor, @Qualifier(PasswordHistoryService.BEAN_NAME) final PasswordHistoryService passwordHistoryService) { List ldaps = casProperties.getAuthn().getPm().getLdap(); @@ -400,7 +403,7 @@ public PasswordManagementService jdbcPasswordChangeService( @Qualifier("jdbcPasswordManagementTransactionTemplate") final TransactionOperations jdbcPasswordManagementTransactionTemplate, @Qualifier("passwordManagementCipherExecutor") - final CipherExecutor passwordManagementCipherExecutor, + final CipherExecutor passwordManagementCipherExecutor, @Qualifier(PasswordHistoryService.BEAN_NAME) final PasswordHistoryService passwordHistoryService) { JdbcPasswordManagementProperties jdbc = casProperties.getAuthn().getPm().getJdbc(); @@ -414,13 +417,27 @@ public PasswordManagementService jdbcPasswordChangeService( return new NoOpPasswordManagementService(passwordManagementCipherExecutor, casProperties); } + @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) + @Bean + public PasswordManagementService restPasswordChangeService( + @Qualifier("passwordChangeServiceRestTemplate") + final RestTemplate passwordChangeServiceRestTemplate, + final CasConfigurationProperties casProperties, + @Qualifier("passwordManagementCipherExecutor") + final CipherExecutor passwordManagementCipherExecutor, + @Qualifier(PasswordHistoryService.BEAN_NAME) + final PasswordHistoryService passwordHistoryService) { + return new RestPasswordManagementService(passwordManagementCipherExecutor, + casProperties, passwordChangeServiceRestTemplate, passwordHistoryService); + } + @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) @Bean public PasswordManagementService passwordChangeService( final ConfigurableApplicationContext applicationContext, final CasConfigurationProperties casProperties, @Qualifier("passwordManagementCipherExecutor") - final CipherExecutor passwordManagementCipherExecutor, + final CipherExecutor passwordManagementCipherExecutor, @Qualifier(PasswordHistoryService.BEAN_NAME) final PasswordHistoryService passwordHistoryService, @Qualifier("syncopePasswordChangeService") @@ -428,7 +445,9 @@ public PasswordManagementService passwordChangeService( @Qualifier("ldapPasswordChangeService") final PasswordManagementService ldapPasswordManagementService, @Qualifier("jdbcPasswordChangeService") - final PasswordManagementService jdbcPasswordManagementService) { + final PasswordManagementService jdbcPasswordManagementService, + @Qualifier("restPasswordChangeService") + final PasswordManagementService restPasswordManagementService) { if (applicationContext.getEnvironment() .getProperty("cas.authn.pm.syncope.enabled", Boolean.class, Boolean.FALSE)) { @@ -445,6 +464,11 @@ public PasswordManagementService passwordChangeService( return jdbcPasswordManagementService; } + if (applicationContext.getEnvironment() + .getProperty("cas.authn.pm.rest.enabled", Boolean.class, Boolean.FALSE)) { + return restPasswordManagementService; + } + return new NoOpPasswordManagementService(passwordManagementCipherExecutor, casProperties); } From 17f2d14763e0e5fe6ea7bc82875c50027abb04e4 Mon Sep 17 00:00:00 2001 From: alberto bogi Date: Thu, 4 Sep 2025 15:38:56 +0200 Subject: [PATCH 14/20] [SYNCOPE-1901] Update apache syncope documentation --- .../reference-guide/concepts/concepts.adoc | 2 + .../concepts/passwordmanagement.adoc | 52 +++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 src/main/asciidoc/reference-guide/concepts/passwordmanagement.adoc diff --git a/src/main/asciidoc/reference-guide/concepts/concepts.adoc b/src/main/asciidoc/reference-guide/concepts/concepts.adoc index d3d3606e5c5..b2e15b34220 100644 --- a/src/main/asciidoc/reference-guide/concepts/concepts.adoc +++ b/src/main/asciidoc/reference-guide/concepts/concepts.adoc @@ -50,6 +50,8 @@ include::authenticationmodules.adoc[] include::attributerepositories.adoc[] +include::passwordmanagement.adoc[] + include::clientapplications.adoc[] include::domains.adoc[] diff --git a/src/main/asciidoc/reference-guide/concepts/passwordmanagement.adoc b/src/main/asciidoc/reference-guide/concepts/passwordmanagement.adoc new file mode 100644 index 00000000000..f167145fd55 --- /dev/null +++ b/src/main/asciidoc/reference-guide/concepts/passwordmanagement.adoc @@ -0,0 +1,52 @@ +// +// 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. +// +=== Password Management + +Password Management allows handling the password update flow of a user authenticated via <> +according to rules defined by a single configured password management module (only one module can be used at a time). + +Several password management modules are provided: + +** https://apereo.github.io/cas/development/password_management/Password-Management-LDAP.html[LDAP^] +** https://apereo.github.io/cas/development/password_management/Password-Management-JDBC.html[JDBC^] +** https://apereo.github.io/cas/development/password_management/Password-Management-REST.html[REST^] +** https://apereo.github.io/cas/development/password_management/Password-Management-ApacheSyncope.html[Syncope^] + +[TIP] +==== +Custom password management modules can be provided by implementing the +ifeval::["{snapshotOrRelease}" == "release"] +https://github.com/apache/syncope/blob/syncope-{docVersion}/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/PasswordManagementConf.java[PasswordManagementConf^] +endif::[] +ifeval::["{snapshotOrRelease}" == "snapshot"] +https://github.com/apache/syncope/blob/master/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/PasswordManagementConf.java[PasswordManagementConf^] +endif::[] +interface and extending appropriately the +ifeval::["{snapshotOrRelease}" == "release"] +https://github.com/apache/syncope/blob/syncope-{docVersion}/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WAPropertySourceLocator.java[WAPropertySourceLocator^] +endif::[] +ifeval::["{snapshotOrRelease}" == "snapshot"] +https://github.com/apache/syncope/blob/master/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WAPropertySourceLocator.java[WAPropertySourceLocator^] +endif::[] +class. +==== + +[NOTE] +Password Management is dynamically translated into +https://apereo.github.io/cas/development/password_management/Password-Management.html[CAS Password Management^] configuration. From 46a603e08047867a8cede78463e66b94ca3cdd16 Mon Sep 17 00:00:00 2001 From: alberto bogi Date: Thu, 4 Sep 2025 15:49:02 +0200 Subject: [PATCH 15/20] [SYNCOPE-1901] Checkstyle --- .../password/RESTPasswordManagementConf.java | 26 +++++++++---------- .../jpa/inner/PasswordManagementTest.java | 3 ++- .../repo/PasswordManagementRepoExtImpl.java | 2 +- .../neo4j/inner/PasswordManagementTest.java | 4 +-- .../syncope/wa/starter/config/WAContext.java | 1 - 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/RESTPasswordManagementConf.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/RESTPasswordManagementConf.java index 95087d0b936..feda1d9e80c 100644 --- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/RESTPasswordManagementConf.java +++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/RESTPasswordManagementConf.java @@ -73,7 +73,7 @@ public String getEndpointPassword() { return endpointPassword; } - public void setEndpointPassword(String endpointPassword) { + public void setEndpointPassword(final String endpointPassword) { this.endpointPassword = endpointPassword; } @@ -81,7 +81,7 @@ public String getEndpointUrlAccountUnlock() { return endpointUrlAccountUnlock; } - public void setEndpointUrlAccountUnlock(String endpointUrlAccountUnlock) { + public void setEndpointUrlAccountUnlock(final String endpointUrlAccountUnlock) { this.endpointUrlAccountUnlock = endpointUrlAccountUnlock; } @@ -89,7 +89,7 @@ public String getEndpointUrlChange() { return endpointUrlChange; } - public void setEndpointUrlChange(String endpointUrlChange) { + public void setEndpointUrlChange(final String endpointUrlChange) { this.endpointUrlChange = endpointUrlChange; } @@ -97,7 +97,7 @@ public String getEndpointUrlEmail() { return endpointUrlEmail; } - public void setEndpointUrlEmail(String endpointUrlEmail) { + public void setEndpointUrlEmail(final String endpointUrlEmail) { this.endpointUrlEmail = endpointUrlEmail; } @@ -105,7 +105,7 @@ public String getEndpointUrlPhone() { return endpointUrlPhone; } - public void setEndpointUrlPhone(String endpointUrlPhone) { + public void setEndpointUrlPhone(final String endpointUrlPhone) { this.endpointUrlPhone = endpointUrlPhone; } @@ -113,7 +113,7 @@ public String getEndpointUrlSecurityQuestions() { return endpointUrlSecurityQuestions; } - public void setEndpointUrlSecurityQuestions(String endpointUrlSecurityQuestions) { + public void setEndpointUrlSecurityQuestions(final String endpointUrlSecurityQuestions) { this.endpointUrlSecurityQuestions = endpointUrlSecurityQuestions; } @@ -121,7 +121,7 @@ public String getEndpointUrlUser() { return endpointUrlUser; } - public void setEndpointUrlUser(String endpointUrlUser) { + public void setEndpointUrlUser(final String endpointUrlUser) { this.endpointUrlUser = endpointUrlUser; } @@ -129,7 +129,7 @@ public String getEndpointUsername() { return endpointUsername; } - public void setEndpointUsername(String endpointUsername) { + public void setEndpointUsername(final String endpointUsername) { this.endpointUsername = endpointUsername; } @@ -137,7 +137,7 @@ public String getFieldNamePasswordOld() { return fieldNamePasswordOld; } - public void setFieldNamePasswordOld(String fieldNamePasswordOld) { + public void setFieldNamePasswordOld(final String fieldNamePasswordOld) { this.fieldNamePasswordOld = fieldNamePasswordOld; } @@ -145,7 +145,7 @@ public String getFieldNamePassword() { return fieldNamePassword; } - public void setFieldNamePassword(String fieldNamePassword) { + public void setFieldNamePassword(final String fieldNamePassword) { this.fieldNamePassword = fieldNamePassword; } @@ -153,7 +153,7 @@ public String getFieldNameUser() { return fieldNameUser; } - public void setFieldNameUser(String fieldNameUser) { + public void setFieldNameUser(final String fieldNameUser) { this.fieldNameUser = fieldNameUser; } @@ -161,12 +161,12 @@ public Map getHeaders() { return headers; } - public void setHeaders(Map headers) { + public void setHeaders(final Map headers) { this.headers = headers; } @Override - public Map map(PasswordManagementTO passwordManagementTO, Mapper mapper) { + public Map map(final PasswordManagementTO passwordManagementTO, final Mapper mapper) { return mapper.map(passwordManagementTO, this); } } diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PasswordManagementTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PasswordManagementTest.java index f8a0a9f4da0..f340b32b994 100644 --- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PasswordManagementTest.java +++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PasswordManagementTest.java @@ -130,7 +130,8 @@ public void saveWithRESTModule() { conf.setEndpointUrlChange("http://localhost:9443/syncope-fit-build-tools/cxf/rest/changePassword"); conf.setEndpointUrlEmail("http://localhost:9443/syncope-fit-build-tools/cxf/rest/findEmail"); conf.setEndpointUrlPhone("http://localhost:9443/syncope-fit-build-tools/cxf/rest/findPhone"); - conf.setEndpointUrlSecurityQuestions("http://localhost:9443/syncope-fit-build-tools/cxf/rest/securityQuestions"); + conf.setEndpointUrlSecurityQuestions( + "http://localhost:9443/syncope-fit-build-tools/cxf/rest/securityQuestions"); conf.setEndpointUsername("http://localhost:9443/syncope-fit-build-tools/cxf/rest/findUser"); conf.setFieldNamePasswordOld("oldPassword"); conf.setFieldNamePassword("password"); diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/PasswordManagementRepoExtImpl.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/PasswordManagementRepoExtImpl.java index 8519653c989..ee7f493ac57 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/PasswordManagementRepoExtImpl.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/PasswordManagementRepoExtImpl.java @@ -30,7 +30,7 @@ public PasswordManagementRepoExtImpl( @Override public boolean isAnotherInstanceEnabled(final String key) { Long count = neo4jClient.query( - "MATCH (pm:" + Neo4JPasswordManagement.NODE +") " + "MATCH (pm:" + Neo4JPasswordManagement.NODE + ") " + "WHERE pm.enabled = 'true' AND pm.id <> $id " + "RETURN count(pm) AS cnt") .bindAll(Map.of("id", key)) diff --git a/core/persistence-neo4j/src/test/java/org/apache/syncope/core/persistence/neo4j/inner/PasswordManagementTest.java b/core/persistence-neo4j/src/test/java/org/apache/syncope/core/persistence/neo4j/inner/PasswordManagementTest.java index 336cbbaf76b..1b4a63831c8 100644 --- a/core/persistence-neo4j/src/test/java/org/apache/syncope/core/persistence/neo4j/inner/PasswordManagementTest.java +++ b/core/persistence-neo4j/src/test/java/org/apache/syncope/core/persistence/neo4j/inner/PasswordManagementTest.java @@ -13,7 +13,6 @@ import org.apache.syncope.common.lib.password.PasswordManagementConf; import org.apache.syncope.common.lib.password.RESTPasswordManagementConf; import org.apache.syncope.common.lib.password.SyncopePasswordManagementConf; -import org.apache.syncope.common.lib.to.Item; import org.apache.syncope.core.persistence.api.dao.PasswordManagementDAO; import org.apache.syncope.core.persistence.api.entity.am.PasswordManagement; import org.apache.syncope.core.persistence.neo4j.AbstractTest; @@ -124,7 +123,8 @@ public void saveWithRESTModule() { conf.setEndpointUrlChange("http://localhost:9443/syncope-fit-build-tools/cxf/rest/changePassword"); conf.setEndpointUrlEmail("http://localhost:9443/syncope-fit-build-tools/cxf/rest/findEmail"); conf.setEndpointUrlPhone("http://localhost:9443/syncope-fit-build-tools/cxf/rest/findPhone"); - conf.setEndpointUrlSecurityQuestions("http://localhost:9443/syncope-fit-build-tools/cxf/rest/securityQuestions"); + conf.setEndpointUrlSecurityQuestions( + "http://localhost:9443/syncope-fit-build-tools/cxf/rest/securityQuestions"); conf.setEndpointUsername("http://localhost:9443/syncope-fit-build-tools/cxf/rest/findUser"); conf.setFieldNamePasswordOld("oldPassword"); conf.setFieldNamePassword("password"); diff --git a/wa/starter/src/main/java/org/apache/syncope/wa/starter/config/WAContext.java b/wa/starter/src/main/java/org/apache/syncope/wa/starter/config/WAContext.java index cae14bd9019..82ec32b0738 100644 --- a/wa/starter/src/main/java/org/apache/syncope/wa/starter/config/WAContext.java +++ b/wa/starter/src/main/java/org/apache/syncope/wa/starter/config/WAContext.java @@ -23,7 +23,6 @@ import io.swagger.v3.oas.models.info.Contact; import io.swagger.v3.oas.models.info.Info; import io.swagger.v3.oas.models.security.SecurityScheme; -import java.io.Serial; import java.io.Serializable; import java.util.ArrayList; import java.util.List; From 74100e9d37d2d7b4aba7e08ac710ee3edb00c989 Mon Sep 17 00:00:00 2001 From: alberto bogi Date: Thu, 4 Sep 2025 17:52:35 +0200 Subject: [PATCH 16/20] [SYNCOPE-1901] Fix CodeQL issues: remove unused parameter and replace boxed Boolean with primitive --- .../client/console/panels/PasswordManagementDirectoryPanel.java | 2 +- .../java/org/apache/syncope/wa/starter/config/WAContext.java | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel.java b/client/am/console/src/main/java/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel.java index 424819ba24d..32833bcd09d 100644 --- a/client/am/console/src/main/java/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel.java +++ b/client/am/console/src/main/java/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel.java @@ -143,7 +143,7 @@ public void onClick(final AjaxRequestTarget target, final PasswordManagementTO i public void onClick(final AjaxRequestTarget target, final PasswordManagementTO ignore) { try { model.setObject(restClient.read(model.getObject().getKey())); - Boolean enabled = Boolean.parseBoolean(model.getObject().getEnabled()); + boolean enabled = Boolean.parseBoolean(model.getObject().getEnabled()); model.getObject().setEnabled(String.valueOf(!enabled)); restClient.update(model.getObject()); diff --git a/wa/starter/src/main/java/org/apache/syncope/wa/starter/config/WAContext.java b/wa/starter/src/main/java/org/apache/syncope/wa/starter/config/WAContext.java index 82ec32b0738..0c9024e1292 100644 --- a/wa/starter/src/main/java/org/apache/syncope/wa/starter/config/WAContext.java +++ b/wa/starter/src/main/java/org/apache/syncope/wa/starter/config/WAContext.java @@ -437,8 +437,6 @@ public PasswordManagementService passwordChangeService( final CasConfigurationProperties casProperties, @Qualifier("passwordManagementCipherExecutor") final CipherExecutor passwordManagementCipherExecutor, - @Qualifier(PasswordHistoryService.BEAN_NAME) - final PasswordHistoryService passwordHistoryService, @Qualifier("syncopePasswordChangeService") final PasswordManagementService syncopePasswordManagementService, @Qualifier("ldapPasswordChangeService") From a16fa806675b7ce1cc15a8bf746d52eeaed3caca Mon Sep 17 00:00:00 2001 From: alberto bogi Date: Fri, 5 Sep 2025 12:33:05 +0200 Subject: [PATCH 17/20] [SYNCOPE-1901] Fix unresolved comments --- .../PasswordManagementDirectoryPanel.java | 24 ++++++++++-- .../rest/PasswordManagementRestClient.java | 18 +++++++++ .../PasswordManagementWizardBuilder.java | 18 +++++++++ .../client/console/pages/WA_it.properties | 2 +- ...asswordManagementDirectoryPanel.properties | 21 ++++++++-- ...wordManagementDirectoryPanel_fr.properties | 21 ++++++++-- ...dManagementDirectoryPanel_fr_CA.properties | 22 +++++++++-- ...wordManagementDirectoryPanel_it.properties | 17 +++++++- ...wordManagementDirectoryPanel_ja.properties | 22 +++++++++-- ...dManagementDirectoryPanel_pt_BR.properties | 21 ++++++++-- ...wordManagementDirectoryPanel_ru.properties | 21 ++++++++-- .../AuthModuleWizardBuilder$Profile.html | 14 +++---- ...ManagementWizardBuilder$Configuration.html | 18 +++++++++ ...mentWizardBuilder$Configuration.properties | 7 ---- ...tWizardBuilder$Configuration_fr.properties | 7 ---- ...zardBuilder$Configuration_fr_CA.properties | 7 ---- ...tWizardBuilder$Configuration_it.properties | 7 ---- ...tWizardBuilder$Configuration_ja.properties | 7 ---- ...zardBuilder$Configuration_pt_BR.properties | 7 ---- ...tWizardBuilder$Configuration_ru.properties | 7 ---- ...sswordManagementWizardBuilder$Profile.html | 18 +++++++++ ...ManagementWizardBuilder$Profile.properties | 17 +++++++- ...agementWizardBuilder$Profile_fr.properties | 17 +++++++- ...mentWizardBuilder$Profile_fr_CA.properties | 17 +++++++- ...agementWizardBuilder$Profile_it.properties | 17 +++++++- ...agementWizardBuilder$Profile_ja.properties | 17 +++++++- ...mentWizardBuilder$Profile_pt_BR.properties | 17 +++++++- ...agementWizardBuilder$Profile_ru.properties | 17 +++++++- .../wicket/markup/html/form/ActionLink.java | 3 +- .../password/JDBCPasswordManagementConf.java | 18 +++++++++ .../password/LDAPPasswordManagementConf.java | 18 +++++++++ .../lib/password/PasswordManagementConf.java | 18 +++++++++ .../password/RESTPasswordManagementConf.java | 18 +++++++++ .../SyncopePasswordManagementConf.java | 18 +++++++++ .../common/lib/to/PasswordManagementTO.java | 29 ++++++++++---- .../lib/types/PasswordManagementState.java | 14 ------- .../service/PasswordManagementService.java | 18 +++++++++ .../core/logic/PasswordManagementLogic.java | 18 +++++++++ .../PasswordManagementServiceImpl.java | 18 +++++++++ .../api/dao/PasswordManagementDAO.java | 18 +++++++++ .../api/entity/am/PasswordManagement.java | 22 ++++++++++- .../validation/PasswordManagementCheck.java | 18 +++++++++ .../PasswordManagementValidator.java | 20 +++++++++- .../jpa/dao/repo/PasswordManagementRepo.java | 18 +++++++++ .../dao/repo/PasswordManagementRepoExt.java | 18 +++++++++ .../repo/PasswordManagementRepoExtImpl.java | 18 +++++++++ .../jpa/entity/am/JPAPasswordManagement.java | 24 ++++++++++-- .../jpa/inner/PasswordManagementTest.java | 20 +++++++++- .../test/resources/domains/MasterContent.xml | 8 ++-- .../dao/repo/PasswordManagementRepo.java | 18 +++++++++ .../dao/repo/PasswordManagementRepoExt.java | 18 +++++++++ .../repo/PasswordManagementRepoExtImpl.java | 18 +++++++++ .../entity/am/Neo4JPasswordManagement.java | 24 ++++++++++-- .../neo4j/inner/PasswordManagementTest.java | 20 +++++++++- .../test/resources/domains/MasterContent.xml | 10 ++--- .../data/PasswordManagementDataBinder.java | 18 +++++++++ .../PasswordManagementDataBinderImpl.java | 22 ++++++++++- .../fit/core/PasswordManagementITCase.java | 18 +++++++++ .../wa/bootstrap/WAPropertySourceLocator.java | 3 +- ...asswordManagementPropertySourceMapper.java | 26 +++++++++++-- wa/starter/pom.xml | 39 ++++++++----------- wa/starter/src/main/resources/wa.properties | 2 - .../wa/starter/SyncopeCoreTestingServer.java | 39 +++++++++++++++++++ 63 files changed, 914 insertions(+), 160 deletions(-) delete mode 100644 client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Configuration.properties delete mode 100644 client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Configuration_fr.properties delete mode 100644 client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Configuration_fr_CA.properties delete mode 100644 client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Configuration_it.properties delete mode 100644 client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Configuration_ja.properties delete mode 100644 client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Configuration_pt_BR.properties delete mode 100644 client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Configuration_ru.properties delete mode 100644 common/am/lib/src/main/java/org/apache/syncope/common/lib/types/PasswordManagementState.java diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel.java b/client/am/console/src/main/java/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel.java index 32833bcd09d..c2f5da6c395 100644 --- a/client/am/console/src/main/java/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel.java +++ b/client/am/console/src/main/java/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel.java @@ -1,3 +1,21 @@ +/* + * 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.client.console.panels; import de.agilecoders.wicket.core.markup.html.bootstrap.dialog.Modal; @@ -143,8 +161,8 @@ public void onClick(final AjaxRequestTarget target, final PasswordManagementTO i public void onClick(final AjaxRequestTarget target, final PasswordManagementTO ignore) { try { model.setObject(restClient.read(model.getObject().getKey())); - boolean enabled = Boolean.parseBoolean(model.getObject().getEnabled()); - model.getObject().setEnabled(String.valueOf(!enabled)); + boolean enabled = model.getObject().isEnabled(); + model.getObject().setEnabled(!enabled); restClient.update(model.getObject()); SyncopeConsoleSession.get().success(getString(Constants.OPERATION_SUCCEEDED)); @@ -155,7 +173,7 @@ public void onClick(final AjaxRequestTarget target, final PasswordManagementTO i } ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(target); } - }, ActionLink.ActionType.ENABLE_PM, AMEntitlement.PASSWORD_MANAGEMENT_UPDATE); + }, ActionLink.ActionType.ENABLE, AMEntitlement.PASSWORD_MANAGEMENT_UPDATE); panel.add(new ActionLink<>() { diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/rest/PasswordManagementRestClient.java b/client/am/console/src/main/java/org/apache/syncope/client/console/rest/PasswordManagementRestClient.java index bb8945b764a..667d13e8b7a 100644 --- a/client/am/console/src/main/java/org/apache/syncope/client/console/rest/PasswordManagementRestClient.java +++ b/client/am/console/src/main/java/org/apache/syncope/client/console/rest/PasswordManagementRestClient.java @@ -1,3 +1,21 @@ +/* + * 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.client.console.rest; import java.util.List; diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder.java b/client/am/console/src/main/java/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder.java index d4c064786d9..54f459ee531 100644 --- a/client/am/console/src/main/java/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder.java +++ b/client/am/console/src/main/java/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder.java @@ -1,3 +1,21 @@ +/* + * 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.client.console.wizards; import java.io.Serializable; diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_it.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_it.properties index e497a18a676..561eca964d2 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_it.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/pages/WA_it.properties @@ -16,7 +16,7 @@ # under the License. wa=WA authModules=Moduli di Autenticazione -passwordManagements=Password Management +passwordManagements=Gestione Password clientApps=Applicazioni Client config=Parametri sessions=Sessioni diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel.properties index b31f644f9f3..acbd8a9ef84 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel.properties @@ -1,6 +1,21 @@ -any.edit=Edit Parameter ${key} -any.new=New Password Module -any.edit=Edit Auth Password Module +# 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. +any.new=New Password Management +any.edit=Edit Password Management description=Description type=Type enabled=Enabled diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_fr.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_fr.properties index b31f644f9f3..acbd8a9ef84 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_fr.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_fr.properties @@ -1,6 +1,21 @@ -any.edit=Edit Parameter ${key} -any.new=New Password Module -any.edit=Edit Auth Password Module +# 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. +any.new=New Password Management +any.edit=Edit Password Management description=Description type=Type enabled=Enabled diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_fr_CA.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_fr_CA.properties index b31f644f9f3..b5c7096ac86 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_fr_CA.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_fr_CA.properties @@ -1,6 +1,22 @@ -any.edit=Edit Parameter ${key} -any.new=New Password Module -any.edit=Edit Auth Password Module +# 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. +any.new=New Password Management +any.edit=Edit Password Management + description=Description type=Type enabled=Enabled diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_it.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_it.properties index fb8814b6f7b..f5be2349ce6 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_it.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_it.properties @@ -1,4 +1,19 @@ -any.edit=Modifica parametro ${key} +# 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. any.new=Nuovo Modulo di Gestione Password any.edit=Aggiorna Modulo di Gestione Password description=Descrizione diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_ja.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_ja.properties index b31f644f9f3..b5c7096ac86 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_ja.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_ja.properties @@ -1,6 +1,22 @@ -any.edit=Edit Parameter ${key} -any.new=New Password Module -any.edit=Edit Auth Password Module +# 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. +any.new=New Password Management +any.edit=Edit Password Management + description=Description type=Type enabled=Enabled diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_pt_BR.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_pt_BR.properties index b31f644f9f3..acbd8a9ef84 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_pt_BR.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_pt_BR.properties @@ -1,6 +1,21 @@ -any.edit=Edit Parameter ${key} -any.new=New Password Module -any.edit=Edit Auth Password Module +# 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. +any.new=New Password Management +any.edit=Edit Password Management description=Description type=Type enabled=Enabled diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_ru.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_ru.properties index b31f644f9f3..acbd8a9ef84 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_ru.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel_ru.properties @@ -1,6 +1,21 @@ -any.edit=Edit Parameter ${key} -any.new=New Password Module -any.edit=Edit Auth Password Module +# 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. +any.new=New Password Management +any.edit=Edit Password Management description=Description type=Type enabled=Enabled diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Profile.html b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Profile.html index 7509f1632bc..c5bf7e1bdf8 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Profile.html +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Profile.html @@ -17,12 +17,12 @@ under the License. --> - -
[key]
-
[description]
-
[state]
-
[order]
-
[conf]
-
+ +
[key]
+
[description]
+
[state]
+
[order]
+
[conf]
+
diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Configuration.html b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Configuration.html index b7ba12c53ed..38545ff1d34 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Configuration.html +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Configuration.html @@ -1,3 +1,21 @@ + diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Configuration.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Configuration.properties deleted file mode 100644 index d58df7d7a4f..00000000000 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Configuration.properties +++ /dev/null @@ -1,7 +0,0 @@ -plainAttrs=Plain Attributes -derAttrs=Derived Attributes -features=Features -matchingCond=Matching Condition -userMatchingCond=User Matching Condition -groupMatchingCond=Group Matching Condition -anyObjectMatchingCond=AnyObject Matching Condition diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Configuration_fr.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Configuration_fr.properties deleted file mode 100644 index d58df7d7a4f..00000000000 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Configuration_fr.properties +++ /dev/null @@ -1,7 +0,0 @@ -plainAttrs=Plain Attributes -derAttrs=Derived Attributes -features=Features -matchingCond=Matching Condition -userMatchingCond=User Matching Condition -groupMatchingCond=Group Matching Condition -anyObjectMatchingCond=AnyObject Matching Condition diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Configuration_fr_CA.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Configuration_fr_CA.properties deleted file mode 100644 index d58df7d7a4f..00000000000 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Configuration_fr_CA.properties +++ /dev/null @@ -1,7 +0,0 @@ -plainAttrs=Plain Attributes -derAttrs=Derived Attributes -features=Features -matchingCond=Matching Condition -userMatchingCond=User Matching Condition -groupMatchingCond=Group Matching Condition -anyObjectMatchingCond=AnyObject Matching Condition diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Configuration_it.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Configuration_it.properties deleted file mode 100644 index c318f44bfcc..00000000000 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Configuration_it.properties +++ /dev/null @@ -1,7 +0,0 @@ -plainAttrs=Attributi -derAttrs=Attributi Derivati -features=Features -matchingCond=Condizione di matching -userMatchingCond=Condizione di matching utente -groupMatchingCond=Condizione di matching gruppo -anyObjectMatchingCond=Condizione di matching any diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Configuration_ja.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Configuration_ja.properties deleted file mode 100644 index d58df7d7a4f..00000000000 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Configuration_ja.properties +++ /dev/null @@ -1,7 +0,0 @@ -plainAttrs=Plain Attributes -derAttrs=Derived Attributes -features=Features -matchingCond=Matching Condition -userMatchingCond=User Matching Condition -groupMatchingCond=Group Matching Condition -anyObjectMatchingCond=AnyObject Matching Condition diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Configuration_pt_BR.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Configuration_pt_BR.properties deleted file mode 100644 index d58df7d7a4f..00000000000 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Configuration_pt_BR.properties +++ /dev/null @@ -1,7 +0,0 @@ -plainAttrs=Plain Attributes -derAttrs=Derived Attributes -features=Features -matchingCond=Matching Condition -userMatchingCond=User Matching Condition -groupMatchingCond=Group Matching Condition -anyObjectMatchingCond=AnyObject Matching Condition diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Configuration_ru.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Configuration_ru.properties deleted file mode 100644 index d58df7d7a4f..00000000000 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Configuration_ru.properties +++ /dev/null @@ -1,7 +0,0 @@ -plainAttrs=Plain Attributes -derAttrs=Derived Attributes -features=Features -matchingCond=Matching Condition -userMatchingCond=User Matching Condition -groupMatchingCond=Group Matching Condition -anyObjectMatchingCond=AnyObject Matching Condition diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile.html b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile.html index f40b2f5758e..5351f400b25 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile.html +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile.html @@ -1,3 +1,21 @@ +
[enabled]
diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile.properties index 961305f294a..18cf102c424 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile.properties @@ -1,4 +1,19 @@ +# 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. description=Description configuration=Configuration type=Type -enabled=Do you want to enable this configuration? diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_fr.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_fr.properties index 961305f294a..18cf102c424 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_fr.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_fr.properties @@ -1,4 +1,19 @@ +# 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. description=Description configuration=Configuration type=Type -enabled=Do you want to enable this configuration? diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_fr_CA.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_fr_CA.properties index 961305f294a..18cf102c424 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_fr_CA.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_fr_CA.properties @@ -1,4 +1,19 @@ +# 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. description=Description configuration=Configuration type=Type -enabled=Do you want to enable this configuration? diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_it.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_it.properties index 3cd2809d0be..98514ae0b53 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_it.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_it.properties @@ -1,4 +1,19 @@ +# 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. description=Descrizione configuration=Configurazione type=Tipo -enabled=Desideri attivare questa configurazione? diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_ja.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_ja.properties index 961305f294a..18cf102c424 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_ja.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_ja.properties @@ -1,4 +1,19 @@ +# 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. description=Description configuration=Configuration type=Type -enabled=Do you want to enable this configuration? diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_pt_BR.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_pt_BR.properties index 961305f294a..18cf102c424 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_pt_BR.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_pt_BR.properties @@ -1,4 +1,19 @@ +# 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. description=Description configuration=Configuration type=Type -enabled=Do you want to enable this configuration? diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_ru.properties b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_ru.properties index 961305f294a..18cf102c424 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_ru.properties +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/PasswordManagementWizardBuilder$Profile_ru.properties @@ -1,4 +1,19 @@ +# 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. description=Description configuration=Configuration type=Type -enabled=Do you want to enable this configuration? diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionLink.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionLink.java index a699703adda..a04d0a9b275 100644 --- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionLink.java +++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionLink.java @@ -110,8 +110,7 @@ public enum ActionType { EDIT_APPROVAL("edit"), VIEW_AUDIT_HISTORY("read"), EXTERNAL_EDITOR("externalEditor"), - EXPLORE_RESOURCE("search"), - ENABLE_PM("update"); + EXPLORE_RESOURCE("search"); private final String actionId; diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/JDBCPasswordManagementConf.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/JDBCPasswordManagementConf.java index 441f9aafe80..3aa832abf93 100644 --- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/JDBCPasswordManagementConf.java +++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/JDBCPasswordManagementConf.java @@ -1,3 +1,21 @@ +/* + * 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.common.lib.password; import java.util.Map; diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/LDAPPasswordManagementConf.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/LDAPPasswordManagementConf.java index c1c7c21487d..06d51382d80 100644 --- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/LDAPPasswordManagementConf.java +++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/LDAPPasswordManagementConf.java @@ -1,3 +1,21 @@ +/* + * 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.common.lib.password; import java.util.Map; diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/PasswordManagementConf.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/PasswordManagementConf.java index b8567b34565..81756e41905 100644 --- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/PasswordManagementConf.java +++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/PasswordManagementConf.java @@ -1,3 +1,21 @@ +/* + * 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.common.lib.password; import com.fasterxml.jackson.annotation.JsonTypeInfo; diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/RESTPasswordManagementConf.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/RESTPasswordManagementConf.java index feda1d9e80c..a4d0b3ea98f 100644 --- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/RESTPasswordManagementConf.java +++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/RESTPasswordManagementConf.java @@ -1,3 +1,21 @@ +/* + * 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.common.lib.password; import java.util.HashMap; diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/SyncopePasswordManagementConf.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/SyncopePasswordManagementConf.java index 0dce2e617cc..18c9d1e906a 100644 --- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/SyncopePasswordManagementConf.java +++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/SyncopePasswordManagementConf.java @@ -1,3 +1,21 @@ +/* + * 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.common.lib.password; import java.util.HashMap; diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/to/PasswordManagementTO.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/to/PasswordManagementTO.java index 122d25bb7aa..8e4b23b6a44 100644 --- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/to/PasswordManagementTO.java +++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/to/PasswordManagementTO.java @@ -1,7 +1,24 @@ +/* + * 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.common.lib.to; import jakarta.ws.rs.PathParam; -import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; import org.apache.syncope.common.lib.password.PasswordManagementConf; @@ -14,7 +31,7 @@ public class PasswordManagementTO implements EntityTO { private String description; - private String enabled = Boolean.FALSE.toString(); + private boolean enabled = false; private PasswordManagementConf conf; @@ -37,13 +54,11 @@ public void setDescription(final String description) { this.description = description; } - public String getEnabled() { - return StringUtils.isNotBlank(enabled) - ? enabled - : Boolean.FALSE.toString(); + public boolean isEnabled() { + return enabled; } - public void setEnabled(final String enabled) { + public void setEnabled(final boolean enabled) { this.enabled = enabled; } diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/types/PasswordManagementState.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/types/PasswordManagementState.java deleted file mode 100644 index b9343593ea0..00000000000 --- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/types/PasswordManagementState.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.apache.syncope.common.lib.types; - -public enum PasswordManagementState { - /** - * Active password management configuration, - * This password management is used for CAS reset password flow. - */ - ACTIVE, - /** - * Disabled password management configuration, - * and is invoked by default automatically. - */ - DISABLED -} diff --git a/common/am/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/PasswordManagementService.java b/common/am/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/PasswordManagementService.java index 7dd54e2fc7a..b1a95e8cdf3 100644 --- a/common/am/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/PasswordManagementService.java +++ b/common/am/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/PasswordManagementService.java @@ -1,3 +1,21 @@ +/* + * 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.common.rest.api.service; import io.swagger.v3.oas.annotations.Parameter; diff --git a/core/am/logic/src/main/java/org/apache/syncope/core/logic/PasswordManagementLogic.java b/core/am/logic/src/main/java/org/apache/syncope/core/logic/PasswordManagementLogic.java index efea84f5f6e..1d9347b3b6c 100644 --- a/core/am/logic/src/main/java/org/apache/syncope/core/logic/PasswordManagementLogic.java +++ b/core/am/logic/src/main/java/org/apache/syncope/core/logic/PasswordManagementLogic.java @@ -1,3 +1,21 @@ +/* + * 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.logic; import java.lang.reflect.Method; diff --git a/core/am/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/PasswordManagementServiceImpl.java b/core/am/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/PasswordManagementServiceImpl.java index 346ba7237d0..628a8c6b990 100644 --- a/core/am/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/PasswordManagementServiceImpl.java +++ b/core/am/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/PasswordManagementServiceImpl.java @@ -1,3 +1,21 @@ +/* + * 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.rest.cxf.service; import jakarta.ws.rs.core.Response; diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PasswordManagementDAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PasswordManagementDAO.java index e6ccd07497d..3af82e9ea0a 100644 --- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PasswordManagementDAO.java +++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PasswordManagementDAO.java @@ -1,3 +1,21 @@ +/* + * 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.persistence.api.dao; import org.apache.syncope.core.persistence.api.entity.am.PasswordManagement; diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/am/PasswordManagement.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/am/PasswordManagement.java index 081b30d73ed..248489487bc 100644 --- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/am/PasswordManagement.java +++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/am/PasswordManagement.java @@ -1,3 +1,21 @@ +/* + * 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.persistence.api.entity.am; import org.apache.syncope.common.lib.password.PasswordManagementConf; @@ -9,9 +27,9 @@ public interface PasswordManagement extends ProvidedKeyEntity { void setDescription(String description); - String getEnabled(); + boolean isEnabled(); - void setEnabled(String enabled); + void setEnabled(boolean enabled); PasswordManagementConf getConf(); diff --git a/core/persistence-common/src/main/java/org/apache/syncope/core/persistence/common/validation/PasswordManagementCheck.java b/core/persistence-common/src/main/java/org/apache/syncope/core/persistence/common/validation/PasswordManagementCheck.java index 7cc3f0b89ee..97fed27516a 100644 --- a/core/persistence-common/src/main/java/org/apache/syncope/core/persistence/common/validation/PasswordManagementCheck.java +++ b/core/persistence-common/src/main/java/org/apache/syncope/core/persistence/common/validation/PasswordManagementCheck.java @@ -1,3 +1,21 @@ +/* + * 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.persistence.common.validation; import jakarta.validation.Constraint; diff --git a/core/persistence-common/src/main/java/org/apache/syncope/core/persistence/common/validation/PasswordManagementValidator.java b/core/persistence-common/src/main/java/org/apache/syncope/core/persistence/common/validation/PasswordManagementValidator.java index faa98a97631..b693d07f391 100644 --- a/core/persistence-common/src/main/java/org/apache/syncope/core/persistence/common/validation/PasswordManagementValidator.java +++ b/core/persistence-common/src/main/java/org/apache/syncope/core/persistence/common/validation/PasswordManagementValidator.java @@ -1,3 +1,21 @@ +/* + * 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.persistence.common.validation; import jakarta.validation.ConstraintValidatorContext; @@ -14,7 +32,7 @@ public boolean isValid(final PasswordManagement passwordManagement, final Constr ApplicationContextProvider.getApplicationContext().getBean(PasswordManagementDAO.class); context.disableDefaultConstraintViolation(); - if (!Boolean.parseBoolean(passwordManagement.getEnabled())) { + if (!passwordManagement.isEnabled()) { return true; } diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordManagementRepo.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordManagementRepo.java index 4351e45ac32..8c0ccc9e257 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordManagementRepo.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordManagementRepo.java @@ -1,3 +1,21 @@ +/* + * 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.persistence.jpa.dao.repo; import org.apache.syncope.core.persistence.api.dao.PasswordManagementDAO; diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordManagementRepoExt.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordManagementRepoExt.java index 82e44e9fa38..4357406d05b 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordManagementRepoExt.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordManagementRepoExt.java @@ -1,3 +1,21 @@ +/* + * 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.persistence.jpa.dao.repo; import org.apache.syncope.core.persistence.api.entity.am.PasswordManagement; diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordManagementRepoExtImpl.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordManagementRepoExtImpl.java index 84c3b88014a..842c3d99f94 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordManagementRepoExtImpl.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/repo/PasswordManagementRepoExtImpl.java @@ -1,3 +1,21 @@ +/* + * 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.persistence.jpa.dao.repo; import jakarta.persistence.EntityManager; diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/am/JPAPasswordManagement.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/am/JPAPasswordManagement.java index 0b0909c983a..416e16e9703 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/am/JPAPasswordManagement.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/am/JPAPasswordManagement.java @@ -1,3 +1,21 @@ +/* + * 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.persistence.jpa.entity.am; import jakarta.persistence.Entity; @@ -23,7 +41,7 @@ public class JPAPasswordManagement extends AbstractProvidedKeyEntity implements private String description; @NotNull - private String enabled; + private boolean enabled; @Lob private String jsonConf; @@ -39,12 +57,12 @@ public void setDescription(final String description) { } @Override - public String getEnabled() { + public boolean isEnabled() { return enabled; } @Override - public void setEnabled(final String enabled) { + public void setEnabled(final boolean enabled) { this.enabled = enabled; } diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PasswordManagementTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PasswordManagementTest.java index f340b32b994..67ae5e807d5 100644 --- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PasswordManagementTest.java +++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PasswordManagementTest.java @@ -1,3 +1,21 @@ +/* + * 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.persistence.jpa.inner; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -82,7 +100,7 @@ private void savePasswordManagement(final String key, final PasswordManagementCo module.setKey(key); module.setDescription("A password management module"); module.setConf(conf); - module.setEnabled(Boolean.FALSE.toString()); + module.setEnabled(false); module = passwordManagementDAO.save(module); assertNotNull(module); diff --git a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml index 06f1c2d7c4c..247abcb59f3 100644 --- a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml +++ b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml @@ -93,16 +93,16 @@ under the License. + enabled="1"/> + enabled="0"/> + enabled="0"/> + enabled="0"/> + enabled="1"/> + jsonConf='{ "_class": "org.apache.syncope.common.lib.password.LDAPPasswordManagementConf","usernameAttribute":"uid","bindDn": "${testds.bindDn}","bindCredential":"${testds.password}","ldapUrl":"ldap://localhost:${testds.port}","searchFilter":"cn={user}","baseDn":"ou=People,${testds.rootDn}","subtreeSearch":true}' + enabled="0"/> + enabled="0"/> + enabled="0"/> locate(final Environment environment) { }); syncopeClient.getService(PasswordManagementService.class).list() - .stream().filter(pm -> Boolean.parseBoolean(pm.getEnabled())).findFirst() + .stream().filter(PasswordManagementTO::isEnabled).findFirst() .ifPresent(passwordManagementTO -> { LOG.debug("Mapping password module {} ", passwordManagementTO.getKey()); diff --git a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/PasswordManagementPropertySourceMapper.java b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/PasswordManagementPropertySourceMapper.java index 3fed7de0b20..bb63328eb9d 100644 --- a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/PasswordManagementPropertySourceMapper.java +++ b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/PasswordManagementPropertySourceMapper.java @@ -1,3 +1,21 @@ +/* + * 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.wa.bootstrap.mapping; import java.util.Map; @@ -43,7 +61,7 @@ public Map map(final PasswordManagementTO passwordManagementTO, props.setHeaders(conf.getHeaders()); Map mappedProps = prefix("cas.authn.pm.syncope.", WAConfUtils.asMap(props)); - mappedProps.put("cas.authn.pm.syncope.enabled", passwordManagementTO.getEnabled()); + mappedProps.put("cas.authn.pm.syncope.enabled", passwordManagementTO.isEnabled()); return mappedProps; } @@ -58,7 +76,7 @@ public Map map(final PasswordManagementTO passwordManagementTO, fill(props, conf); Map mappedProps = prefix("cas.authn.pm.ldap[].", WAConfUtils.asMap(props)); - mappedProps.put("cas.authn.pm.ldap.enabled", passwordManagementTO.getEnabled()); + mappedProps.put("cas.authn.pm.ldap.enabled", passwordManagementTO.isEnabled()); return mappedProps; } @@ -77,7 +95,7 @@ public Map map(final PasswordManagementTO passwordManagementTO, fill(props, conf); Map mappedProps = prefix("cas.authn.pm.jdbc.", WAConfUtils.asMap(props)); - mappedProps.put("cas.authn.pm.jdbc.enabled", passwordManagementTO.getEnabled()); + mappedProps.put("cas.authn.pm.jdbc.enabled", passwordManagementTO.isEnabled()); return mappedProps; } @@ -99,7 +117,7 @@ public Map map(final PasswordManagementTO passwordManagementTO, props.setHeaders(conf.getHeaders()); Map mappedProps = prefix("cas.authn.pm.rest.", WAConfUtils.asMap(props)); - mappedProps.put("cas.authn.pm.rest.enabled", passwordManagementTO.getEnabled()); + mappedProps.put("cas.authn.pm.rest.enabled", passwordManagementTO.isEnabled()); return mappedProps; } } diff --git a/wa/starter/pom.xml b/wa/starter/pom.xml index 10a0128d525..f80a58d4478 100644 --- a/wa/starter/pom.xml +++ b/wa/starter/pom.xml @@ -161,22 +161,6 @@ under the License. org.apereo.cas cas-server-support-ldap
- - org.apereo.cas - cas-server-support-jdbc - - - org.apereo.cas - cas-server-support-pm-ldap - - - org.apereo.cas - cas-server-support-pm-jdbc - - - org.apereo.cas - cas-server-support-pm-rest - org.apereo.cas cas-server-support-reports @@ -421,15 +405,26 @@ under the License. + + org.pac4j + pac4j-oidc + org.apereo.cas cas-server-support-pm-core - - org.pac4j - pac4j-oidc + org.apereo.cas + cas-server-support-pm-ldap + + + org.apereo.cas + cas-server-support-pm-jdbc + + + org.apereo.cas + cas-server-support-pm-rest @@ -438,15 +433,15 @@ under the License. org.springframework.boot - spring-boot-starter-security + spring-boot-starter-actuator org.springframework.boot - spring-boot-starter-validation + spring-boot-starter-security org.springframework.boot - spring-boot-starter-actuator + spring-boot-starter-validation diff --git a/wa/starter/src/main/resources/wa.properties b/wa/starter/src/main/resources/wa.properties index 666db9b8f1b..b661ee9554b 100644 --- a/wa/starter/src/main/resources/wa.properties +++ b/wa/starter/src/main/resources/wa.properties @@ -143,5 +143,3 @@ management.metrics.enable.process.start.time=true ## # Spring Boot Actuator Database Health Check Configuration management.health.db.enabled=false - - diff --git a/wa/starter/src/test/java/org/apache/syncope/wa/starter/SyncopeCoreTestingServer.java b/wa/starter/src/test/java/org/apache/syncope/wa/starter/SyncopeCoreTestingServer.java index 929d15f9206..17ca8fe4879 100644 --- a/wa/starter/src/test/java/org/apache/syncope/wa/starter/SyncopeCoreTestingServer.java +++ b/wa/starter/src/test/java/org/apache/syncope/wa/starter/SyncopeCoreTestingServer.java @@ -38,6 +38,7 @@ import org.apache.syncope.common.lib.to.AuditEventTO; import org.apache.syncope.common.lib.to.AuthModuleTO; import org.apache.syncope.common.lib.to.PagedResult; +import org.apache.syncope.common.lib.to.PasswordManagementTO; import org.apache.syncope.common.lib.types.ClientAppType; import org.apache.syncope.common.lib.types.OpEvent; import org.apache.syncope.common.lib.wa.GoogleMfaAuthToken; @@ -47,6 +48,7 @@ import org.apache.syncope.common.rest.api.service.AttrRepoService; import org.apache.syncope.common.rest.api.service.AuditService; import org.apache.syncope.common.rest.api.service.AuthModuleService; +import org.apache.syncope.common.rest.api.service.PasswordManagementService; import org.apache.syncope.common.rest.api.service.wa.GoogleMfaAuthTokenService; import org.apache.syncope.common.rest.api.service.wa.ImpersonationService; import org.apache.syncope.common.rest.api.service.wa.WAClientAppService; @@ -63,6 +65,8 @@ public class SyncopeCoreTestingServer implements ApplicationListener ATTR_REPOS = new ArrayList<>(); + public static final List PASSWORD_MANAGEMENTS = new ArrayList<>(); + public static final List CLIENT_APPS = new ArrayList<>(); public static final List CONFIG = new ArrayList<>(); @@ -129,6 +133,37 @@ public void delete(final String key) { } } + protected static class StubPasswordManagementService implements PasswordManagementService { + + @Override + public PasswordManagementTO read(final String key) { + return PASSWORD_MANAGEMENTS.stream().filter(pm -> Objects.equals(key, pm.getKey())). + findFirst().orElseThrow(() -> new NotFoundException("Password Management with key " + key)); + } + + @Override + public List list() { + return PASSWORD_MANAGEMENTS; + } + + @Override + public Response create(final PasswordManagementTO passwordManagementTO) { + PASSWORD_MANAGEMENTS.add(passwordManagementTO); + return Response.created(null).build(); + } + + @Override + public void update(final PasswordManagementTO passwordManagementTO) { + delete(passwordManagementTO.getKey()); + create(passwordManagementTO); + } + + @Override + public void delete(final String key) { + PASSWORD_MANAGEMENTS.removeIf(pm -> Objects.equals(key, pm.getKey())); + } + } + protected static class StubWAClientAppService implements WAClientAppService { @Override @@ -329,6 +364,7 @@ public void onApplicationEvent(final ContextRefreshedEvent event) { AuditService.class, AuthModuleService.class, AttrRepoService.class, + PasswordManagementService.class, WAClientAppService.class, WAConfigService.class, GoogleMfaAuthTokenService.class, @@ -342,6 +378,9 @@ public void onApplicationEvent(final ContextRefreshedEvent event) { sf.setResourceProvider( AttrRepoService.class, new SingletonResourceProvider(new StubAttrRepoService(), true)); + sf.setResourceProvider( + PasswordManagementService.class, + new SingletonResourceProvider(new StubPasswordManagementService(), true)); sf.setResourceProvider( WAClientAppService.class, new SingletonResourceProvider(new StubWAClientAppService(), true)); From a53d441f2ca9406c400e2fbc2e7f6ab8c689064e Mon Sep 17 00:00:00 2001 From: alberto bogi Date: Fri, 5 Sep 2025 12:59:26 +0200 Subject: [PATCH 18/20] [SYNCOPE-1901] Restore ActionsPanel properties --- .../wizards/AuthModuleWizardBuilder$Profile.html | 15 +++++++-------- .../markup/html/form/ActionsPanel.properties | 5 ----- .../html/form/ActionsPanel_fr_CA.properties | 5 ----- .../markup/html/form/ActionsPanel_it.properties | 5 ----- .../markup/html/form/ActionsPanel_ja.properties | 5 ----- .../html/form/ActionsPanel_pt_BR.properties | 5 ----- .../markup/html/form/ActionsPanel_ru.properties | 5 ----- 7 files changed, 7 insertions(+), 38 deletions(-) diff --git a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Profile.html b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Profile.html index c5bf7e1bdf8..ec6f0108f63 100644 --- a/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Profile.html +++ b/client/am/console/src/main/resources/org/apache/syncope/client/console/wizards/AuthModuleWizardBuilder$Profile.html @@ -17,12 +17,11 @@ under the License. --> - -
[key]
-
[description]
-
[state]
-
[order]
-
[conf]
-
+ +
[key]
+
[description]
+
[state]
+
[order]
+
[conf]
+
- diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel.properties index b0ab8f3ab3d..d7ba2e73999 100644 --- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel.properties +++ b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel.properties @@ -286,8 +286,3 @@ up.title=move up down.alt=down icon down.class=fas fa-arrow-down down.title=move down - -enable_pm.class=fa fa-check -enaple_pm.alt=enable icon -enable_pm.title=enable/disable - diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel_fr_CA.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel_fr_CA.properties index e50c38a01c6..3169b9293a0 100644 --- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel_fr_CA.properties +++ b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel_fr_CA.properties @@ -230,8 +230,3 @@ down.title=move down live_sync_task.class=fa-solid fa-rotate live_sync_task.title=live sync task live_sync_task.alt=live sync task icon - -enable_pm.class=fa fa-check -enaple_pm.alt=enable icon -enable_pm.title=enable/disable - diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel_it.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel_it.properties index e4b2feb851c..ea1f43d7ad3 100644 --- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel_it.properties +++ b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel_it.properties @@ -285,8 +285,3 @@ down.title=sposta gi\u00f9 live_sync_task.class=fa-solid fa-rotate live_sync_task.title=task di live sync live_sync_task.alt=live sync task icon - -enable_pm.class=fa fa-check -enaple_pm.alt=enable icon -enable_pm.title=abilita/disabilita - diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel_ja.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel_ja.properties index 4c9d806c5dd..2fc0a6661fd 100644 --- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel_ja.properties +++ b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel_ja.properties @@ -286,8 +286,3 @@ down.title=move down live_sync_task.class=fa-solid fa-rotate live_sync_task.title=live sync task live_sync_task.alt=live sync task icon - -enable_pm.class=fa fa-check -enaple_pm.alt=enable icon -enable_pm.title=enable/disable - diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel_pt_BR.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel_pt_BR.properties index 1a1abd382ba..b70b246f77e 100644 --- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel_pt_BR.properties +++ b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel_pt_BR.properties @@ -290,8 +290,3 @@ down.title=move down live_sync_task.class=fa-solid fa-rotate live_sync_task.title=live sync task live_sync_task.alt=live sync task icon - -enable_pm.class=fa fa-check -enaple_pm.alt=enable icon -enable_pm.title=enable/disable - diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel_ru.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel_ru.properties index 4149d5b2a83..eff41a0fbdb 100644 --- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel_ru.properties +++ b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionsPanel_ru.properties @@ -286,8 +286,3 @@ down.title=move down live_sync_task.class=fa-solid fa-rotate live_sync_task.title=live sync task live_sync_task.alt=live sync task icon - -enable_pm.class=fa fa-check -enaple_pm.alt=enable icon -enable_pm.title=enable/disable - From 9fd496ee3d44a478499697ab7d5a4262b31ebaed Mon Sep 17 00:00:00 2001 From: alberto bogi Date: Tue, 14 Oct 2025 11:51:31 +0200 Subject: [PATCH 19/20] [SYNCOPE-1901] Reflow --- .../client/console/AMConsoleContext.java | 8 +-- ...lassPathScanImplementationContributor.java | 8 +-- .../syncope/client/console/pages/WA.java | 18 ++--- .../PasswordManagementDirectoryPanel.java | 8 ++- .../password/RESTPasswordManagementConf.java | 6 +- .../SyncopePasswordManagementConf.java | 6 +- .../common/lib/types/AMEntitlement.java | 20 +++--- .../service/PasswordManagementService.java | 18 ++--- .../syncope/core/logic/AMLogicContext.java | 17 ++--- .../core/logic/PasswordManagementLogic.java | 25 ++++--- .../core/rest/cxf/AMRESTCXFContext.java | 8 +-- .../PasswordManagementServiceImpl.java | 14 ++-- .../validation/PasswordManagementCheck.java | 2 +- .../PasswordManagementValidator.java | 13 ++-- .../persistence/jpa/PersistenceContext.java | 19 ++--- .../dao/repo/PasswordManagementRepoExt.java | 6 -- .../repo/PasswordManagementRepoExtImpl.java | 20 +----- .../jpa/entity/AbstractEntityFactory.java | 4 +- .../jpa/inner/PasswordManagementTest.java | 9 +-- .../persistence/neo4j/PersistenceContext.java | 20 +++--- .../repo/PasswordManagementRepoExtImpl.java | 18 +++-- .../neo4j/entity/Neo4jEntityFactory.java | 4 +- .../neo4j/inner/PasswordManagementTest.java | 10 +-- .../java/ProvisioningContext.java | 8 +-- .../PasswordManagementDataBinderImpl.java | 8 +-- .../apache/syncope/fit/AbstractITCase.java | 6 +- .../fit/core/PasswordManagementITCase.java | 11 ++- .../concepts/passwordmanagement.adoc | 14 ++-- .../bootstrap/WABootstrapConfiguration.java | 11 +-- .../wa/bootstrap/WAPropertySourceLocator.java | 17 +++-- ...asswordManagementPropertySourceMapper.java | 41 ++++++----- .../syncope/wa/starter/config/WAContext.java | 70 ++++++++++++------- wa/starter/src/main/resources/wa.properties | 4 -- 33 files changed, 234 insertions(+), 237 deletions(-) diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/AMConsoleContext.java b/client/am/console/src/main/java/org/apache/syncope/client/console/AMConsoleContext.java index 2766573414d..0bbfee1e3b8 100644 --- a/client/am/console/src/main/java/org/apache/syncope/client/console/AMConsoleContext.java +++ b/client/am/console/src/main/java/org/apache/syncope/client/console/AMConsoleContext.java @@ -66,14 +66,14 @@ public AccessPolicyConfProvider accessPolicyConfProvider() { @ConditionalOnMissingBean @Bean - public AttrRepoRestClient attrRepoRestClient() { - return new AttrRepoRestClient(); + public AuthModuleRestClient authModuleRestClient() { + return new AuthModuleRestClient(); } @ConditionalOnMissingBean @Bean - public AuthModuleRestClient authModuleRestClient() { - return new AuthModuleRestClient(); + public AttrRepoRestClient attrRepoRestClient() { + return new AttrRepoRestClient(); } @ConditionalOnMissingBean diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/init/AMClassPathScanImplementationContributor.java b/client/am/console/src/main/java/org/apache/syncope/client/console/init/AMClassPathScanImplementationContributor.java index d945603db84..c5c00fec217 100644 --- a/client/am/console/src/main/java/org/apache/syncope/client/console/init/AMClassPathScanImplementationContributor.java +++ b/client/am/console/src/main/java/org/apache/syncope/client/console/init/AMClassPathScanImplementationContributor.java @@ -36,8 +36,8 @@ public class AMClassPathScanImplementationContributor implements ClassPathScanIm @Override public void extend(final ClassPathScanningCandidateComponentProvider scanner) { scanner.addIncludeFilter(new AssignableTypeFilter(AuthModuleConf.class)); - scanner.addIncludeFilter(new AssignableTypeFilter(PasswordManagementConf.class)); scanner.addIncludeFilter(new AssignableTypeFilter(AttrRepoConf.class)); + scanner.addIncludeFilter(new AssignableTypeFilter(PasswordManagementConf.class)); scanner.addIncludeFilter(new AssignableTypeFilter(AccessPolicyConf.class)); scanner.addIncludeFilter(new AssignableTypeFilter(AttrReleasePolicyConf.class)); scanner.addIncludeFilter(new AssignableTypeFilter(AuthPolicyConf.class)); @@ -49,12 +49,12 @@ public Optional getLabel(final Class clazz) { if (AuthModuleConf.class.isAssignableFrom(clazz)) { return Optional.of(AuthModuleConf.class.getName()); } - if (PasswordManagementConf.class.isAssignableFrom(clazz)) { - return Optional.of(PasswordManagementConf.class.getName()); - } if (AttrRepoConf.class.isAssignableFrom(clazz)) { return Optional.of(AttrRepoConf.class.getName()); } + if (PasswordManagementConf.class.isAssignableFrom(clazz)) { + return Optional.of(PasswordManagementConf.class.getName()); + } if (AccessPolicyConf.class.isAssignableFrom(clazz)) { return Optional.of(AccessPolicyConf.class.getName()); } diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/pages/WA.java b/client/am/console/src/main/java/org/apache/syncope/client/console/pages/WA.java index 0e5535bf1a5..944dc94d3fe 100644 --- a/client/am/console/src/main/java/org/apache/syncope/client/console/pages/WA.java +++ b/client/am/console/src/main/java/org/apache/syncope/client/console/pages/WA.java @@ -85,10 +85,10 @@ public class WA extends BasePage { protected AuthModuleRestClient authModuleRestClient; @SpringBean - protected PasswordManagementRestClient passwordManagementRestClient; + protected AttrRepoRestClient attrRepoRestClient; @SpringBean - protected AttrRepoRestClient attrRepoRestClient; + protected PasswordManagementRestClient passwordManagementRestClient; @SpringBean protected SAML2IdPEntityRestClient saml2IdPEntityRestClient; @@ -188,27 +188,27 @@ public Panel getPanel(final String panelId) { }); } - if (SyncopeConsoleSession.get().owns(AMEntitlement.PASSWORD_MANAGEMENT_LIST)) { - tabs.add(new AbstractTab(new ResourceModel("passwordManagements")) { + if (SyncopeConsoleSession.get().owns(AMEntitlement.ATTR_REPO_LIST)) { + tabs.add(new AbstractTab(new ResourceModel("attrRepos")) { private static final long serialVersionUID = 5211692813425391144L; @Override public Panel getPanel(final String panelId) { - return new PasswordManagementDirectoryPanel( - panelId, passwordManagementRestClient, getPageReference()); + return new AttrRepoDirectoryPanel(panelId, attrRepoRestClient, getPageReference()); } }); } - if (SyncopeConsoleSession.get().owns(AMEntitlement.ATTR_REPO_LIST)) { - tabs.add(new AbstractTab(new ResourceModel("attrRepos")) { + if (SyncopeConsoleSession.get().owns(AMEntitlement.PASSWORD_MANAGEMENT_LIST)) { + tabs.add(new AbstractTab(new ResourceModel("passwordManagements")) { private static final long serialVersionUID = 5211692813425391144L; @Override public Panel getPanel(final String panelId) { - return new AttrRepoDirectoryPanel(panelId, attrRepoRestClient, getPageReference()); + return new PasswordManagementDirectoryPanel( + panelId, passwordManagementRestClient, getPageReference()); } }); } diff --git a/client/am/console/src/main/java/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel.java b/client/am/console/src/main/java/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel.java index c2f5da6c395..21bca4d97a8 100644 --- a/client/am/console/src/main/java/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel.java +++ b/client/am/console/src/main/java/org/apache/syncope/client/console/panels/PasswordManagementDirectoryPanel.java @@ -31,6 +31,7 @@ import org.apache.syncope.client.console.commons.DirectoryDataProvider; import org.apache.syncope.client.console.commons.SortableDataProviderComparator; import org.apache.syncope.client.console.pages.BasePage; +import org.apache.syncope.client.console.panels.PasswordManagementDirectoryPanel.PasswordManagementProvider; import org.apache.syncope.client.console.rest.AuditRestClient; import org.apache.syncope.client.console.rest.PasswordManagementRestClient; import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.BooleanPropertyColumn; @@ -61,8 +62,9 @@ import org.apache.wicket.model.StringResourceModel; import org.apache.wicket.spring.injection.annot.SpringBean; -public class PasswordManagementDirectoryPanel extends DirectoryPanel { +public class PasswordManagementDirectoryPanel extends DirectoryPanel< + PasswordManagementTO, PasswordManagementTO, PasswordManagementProvider, PasswordManagementRestClient> { + private static final long serialVersionUID = 1005345990563741296L; @SpringBean @@ -128,7 +130,7 @@ public void populateItem( item.add(new Label(componentId, rowModel.getObject().getConf() == null ? StringUtils.EMPTY : StringUtils.substringBefore( - rowModel.getObject().getConf().getClass().getSimpleName(), "PasswordManagementConf"))); + rowModel.getObject().getConf().getClass().getSimpleName(), "PasswordManagementConf"))); } }); columns.add(new BooleanPropertyColumn<>( diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/RESTPasswordManagementConf.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/RESTPasswordManagementConf.java index a4d0b3ea98f..efdeaa635f4 100644 --- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/RESTPasswordManagementConf.java +++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/RESTPasswordManagementConf.java @@ -85,7 +85,7 @@ public class RESTPasswordManagementConf implements PasswordManagementConf { * Additional headers to be included in REST API calls for password management. * The map keys are header names and the corresponding values are header values. */ - private Map headers = new HashMap<>(); + private final Map headers = new HashMap<>(); public String getEndpointPassword() { return endpointPassword; @@ -179,10 +179,6 @@ public Map getHeaders() { return headers; } - public void setHeaders(final Map headers) { - this.headers = headers; - } - @Override public Map map(final PasswordManagementTO passwordManagementTO, final Mapper mapper) { return mapper.map(passwordManagementTO, this); diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/SyncopePasswordManagementConf.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/SyncopePasswordManagementConf.java index 18c9d1e906a..85bcfe922e8 100644 --- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/SyncopePasswordManagementConf.java +++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/password/SyncopePasswordManagementConf.java @@ -50,7 +50,7 @@ public class SyncopePasswordManagementConf implements PasswordManagementConf { * send and include in the request. Key in the map should be the header name * and the value in the map should be the header value. */ - private Map headers = new HashMap<>(); + private final Map headers = new HashMap<>(); public String getDomain() { return domain; @@ -88,10 +88,6 @@ public Map getHeaders() { return headers; } - public void setHeaders(final Map headers) { - this.headers = headers; - } - @Override public Map map(final PasswordManagementTO passwordManagementTO, final Mapper mapper) { return mapper.map(passwordManagementTO, this); diff --git a/common/am/lib/src/main/java/org/apache/syncope/common/lib/types/AMEntitlement.java b/common/am/lib/src/main/java/org/apache/syncope/common/lib/types/AMEntitlement.java index 80f7b9b30eb..12b334ec42a 100644 --- a/common/am/lib/src/main/java/org/apache/syncope/common/lib/types/AMEntitlement.java +++ b/common/am/lib/src/main/java/org/apache/syncope/common/lib/types/AMEntitlement.java @@ -58,16 +58,6 @@ public final class AMEntitlement { public static final String AUTH_MODULE_DELETE = "AUTH_MODULE_DELETE"; - public static final String PASSWORD_MANAGEMENT_LIST = "PASSWORD_MANAGEMENT_LIST"; - - public static final String PASSWORD_MANAGEMENT_CREATE = "PASSWORD_MANAGEMENT_CREATE"; - - public static final String PASSWORD_MANAGEMENT_READ = "PASSWORD_MANAGEMENT_READ"; - - public static final String PASSWORD_MANAGEMENT_UPDATE = "PASSWORD_MANAGEMENT_UPDATE"; - - public static final String PASSWORD_MANAGEMENT_DELETE = "PASSWORD_MANAGEMENT_DELETE"; - public static final String ATTR_REPO_LIST = "ATTR_REPO_LIST"; public static final String ATTR_REPO_CREATE = "ATTR_REPO_CREATE"; @@ -78,6 +68,16 @@ public final class AMEntitlement { public static final String ATTR_REPO_DELETE = "ATTR_REPO_DELETE"; + public static final String PASSWORD_MANAGEMENT_LIST = "PASSWORD_MANAGEMENT_LIST"; + + public static final String PASSWORD_MANAGEMENT_CREATE = "PASSWORD_MANAGEMENT_CREATE"; + + public static final String PASSWORD_MANAGEMENT_READ = "PASSWORD_MANAGEMENT_READ"; + + public static final String PASSWORD_MANAGEMENT_UPDATE = "PASSWORD_MANAGEMENT_UPDATE"; + + public static final String PASSWORD_MANAGEMENT_DELETE = "PASSWORD_MANAGEMENT_DELETE"; + public static final String SAML2_IDP_ENTITY_SET = "SAML2_IDP_ENTITY_SET"; public static final String SAML2_IDP_ENTITY_LIST = "SAML2_IDP_ENTITY_LIST"; diff --git a/common/am/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/PasswordManagementService.java b/common/am/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/PasswordManagementService.java index b1a95e8cdf3..36e3166ea22 100644 --- a/common/am/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/PasswordManagementService.java +++ b/common/am/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/PasswordManagementService.java @@ -48,8 +48,8 @@ */ @Tag(name = "PasswordManagement") @SecurityRequirements({ - @SecurityRequirement(name = "BasicAuthentication"), - @SecurityRequirement(name = "Bearer") }) + @SecurityRequirement(name = "BasicAuthentication"), + @SecurityRequirement(name = "Bearer") }) @Path("passwordManagement") public interface PasswordManagementService extends JAXRSService { @@ -82,12 +82,12 @@ public interface PasswordManagementService extends JAXRSService { @ApiResponses( @ApiResponse(responseCode = "201", description = "PasswordManagement successfully created", headers = { - @Header(name = RESTHeaders.RESOURCE_KEY, schema = - @Schema(type = "string"), - description = "UUID generated for the entity created"), - @Header(name = HttpHeaders.LOCATION, schema = - @Schema(type = "string"), - description = "URL of the entity created") })) + @Header(name = RESTHeaders.RESOURCE_KEY, schema = + @Schema(type = "string"), + description = "UUID generated for the entity created"), + @Header(name = HttpHeaders.LOCATION, schema = + @Schema(type = "string"), + description = "URL of the entity created") })) @POST @Consumes({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML }) @Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML }) @@ -99,7 +99,7 @@ public interface PasswordManagementService extends JAXRSService { * @param passwordManagementTO PasswordManagement to replace existing password management module */ @Parameter(name = "key", description = "PasswordManagement's key", in = ParameterIn.PATH, schema = - @Schema(type = "string")) + @Schema(type = "string")) @ApiResponses( @ApiResponse(responseCode = "204", description = "Operation was successful")) @PUT diff --git a/core/am/logic/src/main/java/org/apache/syncope/core/logic/AMLogicContext.java b/core/am/logic/src/main/java/org/apache/syncope/core/logic/AMLogicContext.java index eeb57b75803..fa90c9a81b2 100644 --- a/core/am/logic/src/main/java/org/apache/syncope/core/logic/AMLogicContext.java +++ b/core/am/logic/src/main/java/org/apache/syncope/core/logic/AMLogicContext.java @@ -73,14 +73,6 @@ public AuthModuleLogic authModuleLogic( return new AuthModuleLogic(binder, authModuleDAO); } - @ConditionalOnMissingBean - @Bean - public PasswordManagementLogic passwordManagementLogic( - final PasswordManagementDataBinder passwordManagementDataBinder, - final PasswordManagementDAO passwordManagementDAO) { - return new PasswordManagementLogic(passwordManagementDataBinder, passwordManagementDAO); - } - @ConditionalOnMissingBean @Bean public AttrRepoLogic attrRepoLogic( @@ -90,6 +82,15 @@ public AttrRepoLogic attrRepoLogic( return new AttrRepoLogic(binder, attrRepoDAO); } + @ConditionalOnMissingBean + @Bean + public PasswordManagementLogic passwordManagementLogic( + final PasswordManagementDataBinder passwordManagementDataBinder, + final PasswordManagementDAO passwordManagementDAO) { + + return new PasswordManagementLogic(passwordManagementDataBinder, passwordManagementDAO); + } + @ConditionalOnMissingBean @Bean public AuthProfileLogic authProfileLogic( diff --git a/core/am/logic/src/main/java/org/apache/syncope/core/logic/PasswordManagementLogic.java b/core/am/logic/src/main/java/org/apache/syncope/core/logic/PasswordManagementLogic.java index 1d9347b3b6c..29951b52a1a 100644 --- a/core/am/logic/src/main/java/org/apache/syncope/core/logic/PasswordManagementLogic.java +++ b/core/am/logic/src/main/java/org/apache/syncope/core/logic/PasswordManagementLogic.java @@ -34,20 +34,21 @@ public class PasswordManagementLogic extends AbstractTransactionalLogic { - protected final PasswordManagementDataBinder passwordManagementDataBinder; + protected final PasswordManagementDataBinder binder; protected final PasswordManagementDAO passwordManagementDAO; - public PasswordManagementLogic(final PasswordManagementDataBinder passwordManagementDataBinder, + public PasswordManagementLogic( + final PasswordManagementDataBinder passwordManagementDataBinder, final PasswordManagementDAO passwordManagementDAO) { - this.passwordManagementDataBinder = passwordManagementDataBinder; + + this.binder = passwordManagementDataBinder; this.passwordManagementDAO = passwordManagementDAO; } @PreAuthorize("hasRole('" + AMEntitlement.PASSWORD_MANAGEMENT_CREATE + "')") public PasswordManagementTO create(final PasswordManagementTO passwordManagementTO) { - return passwordManagementDataBinder.getPasswordManagementTO( - passwordManagementDAO.save(passwordManagementDataBinder.create(passwordManagementTO))); + return binder.getPasswordManagementTO(passwordManagementDAO.save(binder.create(passwordManagementTO))); } @PreAuthorize("hasRole('" + AMEntitlement.PASSWORD_MANAGEMENT_UPDATE + "')") @@ -55,9 +56,8 @@ public PasswordManagementTO update(final PasswordManagementTO passwordManagement PasswordManagement passwordManagement = passwordManagementDAO.findById(passwordManagementTO.getKey()). orElseThrow(() -> new NotFoundException("PasswordManagement " + passwordManagementTO.getKey())); - return passwordManagementDataBinder.getPasswordManagementTO( - passwordManagementDAO.save(passwordManagementDataBinder - .update(passwordManagement, passwordManagementTO))); + return binder.getPasswordManagementTO( + passwordManagementDAO.save(binder.update(passwordManagement, passwordManagementTO))); } @PreAuthorize("hasRole('" + AMEntitlement.PASSWORD_MANAGEMENT_LIST + "') or hasRole('" @@ -65,7 +65,7 @@ public PasswordManagementTO update(final PasswordManagementTO passwordManagement @Transactional(readOnly = true) public List list() { return passwordManagementDAO.findAll().stream() - .map(passwordManagementDataBinder::getPasswordManagementTO).toList(); + .map(binder::getPasswordManagementTO).toList(); } @PreAuthorize("hasRole('" + AMEntitlement.PASSWORD_MANAGEMENT_READ + "')") @@ -74,7 +74,7 @@ public PasswordManagementTO read(final String key) { PasswordManagement passwordManagement = passwordManagementDAO.findById(key). orElseThrow(() -> new NotFoundException("PasswordManagement " + key)); - return passwordManagementDataBinder.getPasswordManagementTO(passwordManagement); + return binder.getPasswordManagementTO(passwordManagement); } @PreAuthorize("hasRole('" + AMEntitlement.PASSWORD_MANAGEMENT_DELETE + "')") @@ -82,7 +82,7 @@ public PasswordManagementTO delete(final String key) { PasswordManagement passwordManagement = passwordManagementDAO.findById(key). orElseThrow(() -> new NotFoundException("PasswordManagement " + key)); - PasswordManagementTO deleted = passwordManagementDataBinder.getPasswordManagementTO(passwordManagement); + PasswordManagementTO deleted = binder.getPasswordManagementTO(passwordManagement); passwordManagementDAO.delete(passwordManagement); return deleted; @@ -106,8 +106,7 @@ protected PasswordManagementTO resolveReference(final Method method, final Objec } try { - return passwordManagementDataBinder.getPasswordManagementTO(passwordManagementDAO.findById(key) - .orElseThrow()); + return binder.getPasswordManagementTO(passwordManagementDAO.findById(key).orElseThrow()); } catch (Throwable ignore) { LOG.debug("Unresolved reference", ignore); throw new UnresolvedReferenceException(ignore); diff --git a/core/am/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/AMRESTCXFContext.java b/core/am/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/AMRESTCXFContext.java index 76de34ecaaa..41bcebdf7d5 100644 --- a/core/am/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/AMRESTCXFContext.java +++ b/core/am/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/AMRESTCXFContext.java @@ -82,14 +82,14 @@ public AuthModuleService authModuleService(final AuthModuleLogic authModuleLogic @ConditionalOnMissingBean @Bean - public PasswordManagementService passwordManagementService(final PasswordManagementLogic passwordManagementLogic) { - return new PasswordManagementServiceImpl(passwordManagementLogic); + public AttrRepoService attrRepoService(final AttrRepoLogic attrRepoLogic) { + return new AttrRepoServiceImpl(attrRepoLogic); } @ConditionalOnMissingBean @Bean - public AttrRepoService attrRepoService(final AttrRepoLogic attrRepoLogic) { - return new AttrRepoServiceImpl(attrRepoLogic); + public PasswordManagementService passwordManagementService(final PasswordManagementLogic passwordManagementLogic) { + return new PasswordManagementServiceImpl(passwordManagementLogic); } @ConditionalOnMissingBean diff --git a/core/am/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/PasswordManagementServiceImpl.java b/core/am/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/PasswordManagementServiceImpl.java index 628a8c6b990..5627c66548b 100644 --- a/core/am/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/PasswordManagementServiceImpl.java +++ b/core/am/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/PasswordManagementServiceImpl.java @@ -28,25 +28,25 @@ public class PasswordManagementServiceImpl extends AbstractService implements PasswordManagementService { - protected final PasswordManagementLogic passwordManagementLogic; + protected final PasswordManagementLogic logic; public PasswordManagementServiceImpl(final PasswordManagementLogic passwordManagementLogic) { - this.passwordManagementLogic = passwordManagementLogic; + this.logic = passwordManagementLogic; } @Override public PasswordManagementTO read(final String key) { - return passwordManagementLogic.read(key); + return logic.read(key); } @Override public List list() { - return passwordManagementLogic.list(); + return logic.list(); } @Override public Response create(final PasswordManagementTO passwordManagementTO) { - PasswordManagementTO passwordManagement = passwordManagementLogic.create(passwordManagementTO); + PasswordManagementTO passwordManagement = logic.create(passwordManagementTO); URI location = uriInfo.getAbsolutePathBuilder().path(passwordManagement.getKey()).build(); return Response.created(location). header(RESTHeaders.RESOURCE_KEY, passwordManagement.getKey()). @@ -55,11 +55,11 @@ public Response create(final PasswordManagementTO passwordManagementTO) { @Override public void update(final PasswordManagementTO passwordManagementTO) { - passwordManagementLogic.update(passwordManagementTO); + logic.update(passwordManagementTO); } @Override public void delete(final String key) { - passwordManagementLogic.delete(key); + logic.delete(key); } } diff --git a/core/persistence-common/src/main/java/org/apache/syncope/core/persistence/common/validation/PasswordManagementCheck.java b/core/persistence-common/src/main/java/org/apache/syncope/core/persistence/common/validation/PasswordManagementCheck.java index 97fed27516a..09ee5f069fe 100644 --- a/core/persistence-common/src/main/java/org/apache/syncope/core/persistence/common/validation/PasswordManagementCheck.java +++ b/core/persistence-common/src/main/java/org/apache/syncope/core/persistence/common/validation/PasswordManagementCheck.java @@ -32,7 +32,7 @@ @Documented public @interface PasswordManagementCheck { - String message() default "{org.apache.syncope.core.persistence.validation.passwordManagement}"; + String message() default "{org.apache.syncope.core.persistence.validation.passwordmanagement}"; Class[] groups() default {}; diff --git a/core/persistence-common/src/main/java/org/apache/syncope/core/persistence/common/validation/PasswordManagementValidator.java b/core/persistence-common/src/main/java/org/apache/syncope/core/persistence/common/validation/PasswordManagementValidator.java index b693d07f391..662eb656096 100644 --- a/core/persistence-common/src/main/java/org/apache/syncope/core/persistence/common/validation/PasswordManagementValidator.java +++ b/core/persistence-common/src/main/java/org/apache/syncope/core/persistence/common/validation/PasswordManagementValidator.java @@ -28,20 +28,19 @@ public class PasswordManagementValidator extends AbstractValidator :id", - Long.class) - .setParameter("id", key) - .getSingleResult(); - + "SELECT COUNT(pm) FROM " + JPAPasswordManagement.class.getSimpleName() + " pm " + + "WHERE pm.enabled = 'true' AND pm.id <> :id", Long.class).setParameter("id", key).getSingleResult(); return count > 0; } - - @Override - public PasswordManagement save(final PasswordManagement passwordManagement) { - return entityManager.merge(passwordManagement); - } - - @Override - public void delete(final PasswordManagement passwordManagement) { - entityManager.remove(passwordManagement); - } } diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractEntityFactory.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractEntityFactory.java index 1002f9c764d..1dfbc28225e 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractEntityFactory.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractEntityFactory.java @@ -264,10 +264,10 @@ public E newEntity(final Class reference) { result = (E) new JPASRARoute(); } else if (reference.equals(AuthModule.class)) { result = (E) new JPAAuthModule(); - } else if (reference.equals(PasswordManagement.class)) { - result = (E) new JPAPasswordManagement(); } else if (reference.equals(AttrRepo.class)) { result = (E) new JPAAttrRepo(); + } else if (reference.equals(PasswordManagement.class)) { + result = (E) new JPAPasswordManagement(); } else if (reference.equals(AuthPolicy.class)) { result = (E) new JPAAuthPolicy(); } else if (reference.equals(AccessPolicy.class)) { diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PasswordManagementTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PasswordManagementTest.java index 67ae5e807d5..967bedac437 100644 --- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PasswordManagementTest.java +++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PasswordManagementTest.java @@ -44,6 +44,7 @@ public class PasswordManagementTest extends AbstractTest { private static boolean isSpecificConf( final PasswordManagementConf conf, final Class clazz) { + return ClassUtils.isAssignable(clazz, conf.getClass()); } @@ -80,19 +81,19 @@ public void findByType() { assertTrue(passwordManagements.stream().anyMatch( passwordManagement -> isSpecificConf(passwordManagement.getConf(), SyncopePasswordManagementConf.class) - && passwordManagement.getKey().equals("DefaultSyncopePasswordManagement"))); + && passwordManagement.getKey().equals("DefaultSyncopePasswordManagement"))); assertTrue(passwordManagements.stream().anyMatch( passwordManagement -> isSpecificConf(passwordManagement.getConf(), LDAPPasswordManagementConf.class) - && passwordManagement.getKey().equals("DefaultLDAPPasswordManagement"))); + && passwordManagement.getKey().equals("DefaultLDAPPasswordManagement"))); assertTrue(passwordManagements.stream().anyMatch( passwordManagement -> isSpecificConf(passwordManagement.getConf(), JDBCPasswordManagementConf.class) - && passwordManagement.getKey().equals("DefaultJDBCPasswordManagement"))); + && passwordManagement.getKey().equals("DefaultJDBCPasswordManagement"))); assertTrue(passwordManagements.stream().anyMatch( passwordManagement -> isSpecificConf(passwordManagement.getConf(), RESTPasswordManagementConf.class) - && passwordManagement.getKey().equals("DefaultRESTPasswordManagement"))); + && passwordManagement.getKey().equals("DefaultRESTPasswordManagement"))); } private void savePasswordManagement(final String key, final PasswordManagementConf conf) { diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/PersistenceContext.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/PersistenceContext.java index f3c417842c8..1acec809aac 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/PersistenceContext.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/PersistenceContext.java @@ -677,15 +677,6 @@ public AuthModuleRepoExt authModuleRepoExt( return new AuthModuleRepoExtImpl(policyDAO, neo4jTemplate, nodeValidator); } - @ConditionalOnMissingBean - @Bean - public PasswordManagementRepoExt passwordManagementRepoExt( - final Neo4jTemplate neo4jTemplate, - final Neo4jClient neo4jClient, - final NodeValidator nodeValidator) { - return new PasswordManagementRepoExtImpl(neo4jTemplate, neo4jClient, nodeValidator); - } - @ConditionalOnMissingBean @Bean public AuthModuleDAO authModuleDAO( @@ -695,11 +686,22 @@ public AuthModuleDAO authModuleDAO( return neo4jRepositoryFactory.getRepository(AuthModuleRepo.class, authModuleRepoExt); } + @ConditionalOnMissingBean + @Bean + public PasswordManagementRepoExt passwordManagementRepoExt( + final Neo4jTemplate neo4jTemplate, + final Neo4jClient neo4jClient, + final NodeValidator nodeValidator) { + + return new PasswordManagementRepoExtImpl(neo4jTemplate, neo4jClient, nodeValidator); + } + @ConditionalOnMissingBean @Bean public PasswordManagementDAO passwordManagementDAO( final SyncopeNeo4jRepositoryFactory neo4jRepositoryFactory, final PasswordManagementRepoExt passwordManagementRepoExt) { + return neo4jRepositoryFactory.getRepository(PasswordManagementRepo.class, passwordManagementRepoExt); } diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/PasswordManagementRepoExtImpl.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/PasswordManagementRepoExtImpl.java index 4e8351f6e98..674cf0f1247 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/PasswordManagementRepoExtImpl.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/dao/repo/PasswordManagementRepoExtImpl.java @@ -39,6 +39,7 @@ public PasswordManagementRepoExtImpl( final Neo4jTemplate neo4jTemplate, final Neo4jClient neo4jClient, final NodeValidator nodeValidator) { + this.neo4jTemplate = neo4jTemplate; this.neo4jClient = neo4jClient; this.nodeValidator = nodeValidator; @@ -48,22 +49,19 @@ public PasswordManagementRepoExtImpl( @Override public boolean isAnotherInstanceEnabled(final String key) { Long count = neo4jClient.query( - "MATCH (pm:" + Neo4JPasswordManagement.NODE + ") " - + "WHERE pm.enabled = 'true' AND pm.id <> $id " - + "RETURN count(pm) AS cnt") - .bindAll(Map.of("id", key)) - .fetch() - .one() - .map(record -> ((Number) record.get("cnt")).longValue()) - .orElse(0L); + "MATCH (pm:" + Neo4JPasswordManagement.NODE + ") " + + "WHERE pm.enabled = 'true' AND pm.id <> $id " + + "RETURN count(pm) AS cnt"). + bindAll(Map.of("id", key)).fetch().one(). + map(record -> ((Number) record.get("cnt")).longValue()). + orElse(0L); return count > 0; } @Override public PasswordManagement save(final PasswordManagement passwordManagement) { - PasswordManagement saved = neo4jTemplate.save(nodeValidator.validate(passwordManagement)); - return saved; + return neo4jTemplate.save(nodeValidator.validate(passwordManagement)); } @Override diff --git a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/Neo4jEntityFactory.java b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/Neo4jEntityFactory.java index f7879cab9be..5cf942a10f7 100644 --- a/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/Neo4jEntityFactory.java +++ b/core/persistence-neo4j/src/main/java/org/apache/syncope/core/persistence/neo4j/entity/Neo4jEntityFactory.java @@ -265,10 +265,10 @@ public E newEntity(final Class reference) { result = (E) new Neo4jSRARoute(); } else if (reference.equals(AuthModule.class)) { result = (E) new Neo4jAuthModule(); - } else if (reference.equals(PasswordManagement.class)) { - result = (E) new Neo4JPasswordManagement(); } else if (reference.equals(AttrRepo.class)) { result = (E) new Neo4jAttrRepo(); + } else if (reference.equals(PasswordManagement.class)) { + result = (E) new Neo4JPasswordManagement(); } else if (reference.equals(AuthPolicy.class)) { result = (E) new Neo4jAuthPolicy(); } else if (reference.equals(AccessPolicy.class)) { diff --git a/core/persistence-neo4j/src/test/java/org/apache/syncope/core/persistence/neo4j/inner/PasswordManagementTest.java b/core/persistence-neo4j/src/test/java/org/apache/syncope/core/persistence/neo4j/inner/PasswordManagementTest.java index d1f13f1c056..ab03275a80f 100644 --- a/core/persistence-neo4j/src/test/java/org/apache/syncope/core/persistence/neo4j/inner/PasswordManagementTest.java +++ b/core/persistence-neo4j/src/test/java/org/apache/syncope/core/persistence/neo4j/inner/PasswordManagementTest.java @@ -44,6 +44,7 @@ public class PasswordManagementTest extends AbstractTest { private static boolean isSpecificConf( final PasswordManagementConf conf, final Class clazz) { + return ClassUtils.isAssignable(clazz, conf.getClass()); } @@ -77,15 +78,14 @@ public void findByType() { assertTrue(passwordManagements.stream().anyMatch( passwordManagement -> isSpecificConf(passwordManagement.getConf(), SyncopePasswordManagementConf.class) - && passwordManagement.getKey().equals("DefaultSyncopePasswordManagement"))); + && passwordManagement.getKey().equals("DefaultSyncopePasswordManagement"))); assertTrue(passwordManagements.stream().anyMatch( passwordManagement -> isSpecificConf(passwordManagement.getConf(), LDAPPasswordManagementConf.class) - && passwordManagement.getKey().equals("DefaultLDAPPasswordManagement"))); + && passwordManagement.getKey().equals("DefaultLDAPPasswordManagement"))); assertTrue(passwordManagements.stream().anyMatch( - passwordManagement -> isSpecificConf(passwordManagement.getConf(), - JDBCPasswordManagementConf.class) - && passwordManagement.getKey().equals("DefaultJDBCPasswordManagement"))); + passwordManagement -> isSpecificConf(passwordManagement.getConf(), JDBCPasswordManagementConf.class) + && passwordManagement.getKey().equals("DefaultJDBCPasswordManagement"))); } private void savePasswordManagement(final String key, final PasswordManagementConf conf) { diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/ProvisioningContext.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/ProvisioningContext.java index ef556189722..3f2980226a7 100644 --- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/ProvisioningContext.java +++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/ProvisioningContext.java @@ -761,14 +761,14 @@ public AuthModuleDataBinder authModuleDataBinder(final EntityFactory entityFacto @ConditionalOnMissingBean @Bean - public PasswordManagementDataBinder passwordManagementDataBinder(final EntityFactory entityFactory) { - return new PasswordManagementDataBinderImpl(entityFactory); + public AttrRepoDataBinder attrRepoDataBinder(final EntityFactory entityFactory) { + return new AttrRepoDataBinderImpl(entityFactory); } @ConditionalOnMissingBean @Bean - public AttrRepoDataBinder attrRepoDataBinder(final EntityFactory entityFactory) { - return new AttrRepoDataBinderImpl(entityFactory); + public PasswordManagementDataBinder passwordManagementDataBinder(final EntityFactory entityFactory) { + return new PasswordManagementDataBinderImpl(entityFactory); } @ConditionalOnMissingBean diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/PasswordManagementDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/PasswordManagementDataBinderImpl.java index a948647fc5e..235a2036366 100644 --- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/PasswordManagementDataBinderImpl.java +++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/PasswordManagementDataBinderImpl.java @@ -22,13 +22,9 @@ import org.apache.syncope.core.persistence.api.entity.EntityFactory; import org.apache.syncope.core.persistence.api.entity.am.PasswordManagement; import org.apache.syncope.core.provisioning.api.data.PasswordManagementDataBinder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; public class PasswordManagementDataBinderImpl implements PasswordManagementDataBinder { - protected static final Logger LOG = LoggerFactory.getLogger(PasswordManagementDataBinder.class); - protected final EntityFactory entityFactory; public PasswordManagementDataBinderImpl(final EntityFactory entityFactory) { @@ -43,8 +39,10 @@ public PasswordManagement create(final PasswordManagementTO passwordManagementTO } @Override - public PasswordManagement update(final PasswordManagement passwordManagement, + public PasswordManagement update( + final PasswordManagement passwordManagement, final PasswordManagementTO passwordManagementTO) { + passwordManagement.setDescription(passwordManagementTO.getDescription()); passwordManagement.setEnabled(passwordManagementTO.isEnabled()); passwordManagement.setConf(passwordManagementTO.getConf()); diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java index 4285ad6e40f..ade6ce52d60 100644 --- a/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java +++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java @@ -355,10 +355,10 @@ public void initialize(final ConfigurableApplicationContext ctx) { protected static AuthModuleService AUTH_MODULE_SERVICE; - protected static PasswordManagementService PASSWORD_MANAGEMENT_SERVICE; - protected static AttrRepoService ATTR_REPO_SERVICE; + protected static PasswordManagementService PASSWORD_MANAGEMENT_SERVICE; + protected static SecurityQuestionService SECURITY_QUESTION_SERVICE; protected static ImplementationService IMPLEMENTATION_SERVICE; @@ -598,8 +598,8 @@ public static void restSetup() { SCIM_CONF_SERVICE = ADMIN_CLIENT.getService(SCIMConfService.class); CLIENT_APP_SERVICE = ADMIN_CLIENT.getService(ClientAppService.class); AUTH_MODULE_SERVICE = ADMIN_CLIENT.getService(AuthModuleService.class); - PASSWORD_MANAGEMENT_SERVICE = ADMIN_CLIENT.getService(PasswordManagementService.class); ATTR_REPO_SERVICE = ADMIN_CLIENT.getService(AttrRepoService.class); + PASSWORD_MANAGEMENT_SERVICE = ADMIN_CLIENT.getService(PasswordManagementService.class); SAML2IDP_ENTITY_SERVICE = ADMIN_CLIENT.getService(SAML2IdPEntityService.class); AUTH_PROFILE_SERVICE = ADMIN_CLIENT.getService(AuthProfileService.class); OIDC_JWKS_SERVICE = ADMIN_CLIENT.getService(OIDCJWKSService.class); diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PasswordManagementITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PasswordManagementITCase.java index f6e33ee882a..4be19614249 100644 --- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PasswordManagementITCase.java +++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PasswordManagementITCase.java @@ -49,6 +49,7 @@ private enum PasswordManagementSupportedType { LDAP, JDBC, REST + }; private static PasswordManagementTO createPasswordManagement(final PasswordManagementTO passwordManagementTO) { @@ -67,12 +68,13 @@ private static PasswordManagementTO buildPasswordManagementTO(final PasswordMana passwordManagementTO.setKey("Test" + type + "PasswordManagement" + getUUIDString()); passwordManagementTO.setDescription("A test " + type + " Password Management"); - PasswordManagementConf conf; + PasswordManagementConf conf = null; switch (type) { case SYNCOPE: conf = new SyncopePasswordManagementConf(); SyncopePasswordManagementConf.class.cast(conf).setDomain(SyncopeConstants.MASTER_DOMAIN); break; + case LDAP: conf = new LDAPPasswordManagementConf(); LDAPPasswordManagementConf.class.cast(conf).setBaseDn("dc=example,dc=org"); @@ -83,6 +85,7 @@ private static PasswordManagementTO buildPasswordManagementTO(final PasswordMana LDAPPasswordManagementConf.class.cast(conf).setBaseDn("cn=Directory Manager,dc=example,dc=org"); LDAPPasswordManagementConf.class.cast(conf).setBindCredential("Password"); break; + case JDBC: conf = new JDBCPasswordManagementConf(); JDBCPasswordManagementConf.class.cast(conf) @@ -94,6 +97,7 @@ private static PasswordManagementTO buildPasswordManagementTO(final PasswordMana JDBCPasswordManagementConf.class.cast(conf) .setSqlChangePassword("UPDATE users_table SET password=? WHERE name=?"); break; + case REST: conf = new RESTPasswordManagementConf(); RESTPasswordManagementConf.class.cast(conf).setEndpointPassword("password"); @@ -112,9 +116,9 @@ private static PasswordManagementTO buildPasswordManagementTO(final PasswordMana RESTPasswordManagementConf.class.cast(conf).setFieldNamePasswordOld("oldPassword"); RESTPasswordManagementConf.class.cast(conf).setFieldNamePassword("password"); RESTPasswordManagementConf.class.cast(conf).setEndpointUsername("username"); - default: - conf = null; break; + + default: } passwordManagementTO.setConf(conf); @@ -124,6 +128,7 @@ private static PasswordManagementTO buildPasswordManagementTO(final PasswordMana private static boolean isSpecificConf( final PasswordManagementConf conf, final Class clazz) { + return ClassUtils.isAssignable(clazz, conf.getClass()); } diff --git a/src/main/asciidoc/reference-guide/concepts/passwordmanagement.adoc b/src/main/asciidoc/reference-guide/concepts/passwordmanagement.adoc index f167145fd55..b1e4a4014f9 100644 --- a/src/main/asciidoc/reference-guide/concepts/passwordmanagement.adoc +++ b/src/main/asciidoc/reference-guide/concepts/passwordmanagement.adoc @@ -19,14 +19,14 @@ === Password Management Password Management allows handling the password update flow of a user authenticated via <> -according to rules defined by a single configured password management module (only one module can be used at a time). +according to rules defined by a single configured password management module (only one module can be active at a time). -Several password management modules are provided: +Some password management modules are provided: -** https://apereo.github.io/cas/development/password_management/Password-Management-LDAP.html[LDAP^] -** https://apereo.github.io/cas/development/password_management/Password-Management-JDBC.html[JDBC^] -** https://apereo.github.io/cas/development/password_management/Password-Management-REST.html[REST^] -** https://apereo.github.io/cas/development/password_management/Password-Management-ApacheSyncope.html[Syncope^] +* https://apereo.github.io/cas/7.2.x/password_management/Password-Management-LDAP.html[LDAP^] +* https://apereo.github.io/cas/7.2.x/password_management/Password-Management-JDBC.html[JDBC^] +* https://apereo.github.io/cas/7.2.x/password_management/Password-Management-REST.html[REST^] +* https://apereo.github.io/cas/7.2.x/password_management/Password-Management-ApacheSyncope.html[Syncope^] [TIP] ==== @@ -49,4 +49,4 @@ class. [NOTE] Password Management is dynamically translated into -https://apereo.github.io/cas/development/password_management/Password-Management.html[CAS Password Management^] configuration. +https://apereo.github.io/cas/7.2.x/password_management/Password-Management.html[CAS Password Management^] configuration. diff --git a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WABootstrapConfiguration.java b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WABootstrapConfiguration.java index 066fabbb30c..c78f86ae792 100644 --- a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WABootstrapConfiguration.java +++ b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WABootstrapConfiguration.java @@ -77,15 +77,16 @@ public AuthModulePropertySourceMapper authModulePropertySourceMapper(final WARes @ConditionalOnMissingBean @Bean - public PasswordManagementPropertySourceMapper passwordManagementPropertySourceMapper( - final WARestClient waRestClient) { - return new PasswordManagementPropertySourceMapper(waRestClient); + public AttrRepoPropertySourceMapper attrRepoPropertySourceMapper(final WARestClient waRestClient) { + return new AttrRepoPropertySourceMapper(waRestClient); } @ConditionalOnMissingBean @Bean - public AttrRepoPropertySourceMapper attrRepoPropertySourceMapper(final WARestClient waRestClient) { - return new AttrRepoPropertySourceMapper(waRestClient); + public PasswordManagementPropertySourceMapper passwordManagementPropertySourceMapper( + final WARestClient waRestClient) { + + return new PasswordManagementPropertySourceMapper(waRestClient); } @ConditionalOnMissingBean diff --git a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WAPropertySourceLocator.java b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WAPropertySourceLocator.java index 11dd7d8be5a..6f3f3e7a087 100644 --- a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WAPropertySourceLocator.java +++ b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/WAPropertySourceLocator.java @@ -131,15 +131,14 @@ public PropertySource locate(final Environment environment) { properties.putAll(index(map, prefixes)); }); - syncopeClient.getService(PasswordManagementService.class).list() - .stream().filter(PasswordManagementTO::isEnabled).findFirst() - .ifPresent(passwordManagementTO -> { - LOG.debug("Mapping password module {} ", passwordManagementTO.getKey()); + syncopeClient.getService(PasswordManagementService.class).list().stream(). + filter(PasswordManagementTO::isEnabled).findFirst().ifPresent(passwordManagementTO -> { + LOG.debug("Mapping password module {} ", passwordManagementTO.getKey()); - Map map = passwordManagementTO.getConf() - .map(passwordManagementTO, passwordManagementPropertySourceMapper); - properties.putAll(index(map, prefixes)); - }); + Map map = passwordManagementTO.getConf(). + map(passwordManagementTO, passwordManagementPropertySourceMapper); + properties.putAll(index(map, prefixes)); + }); Set customClaims = syncopeClient.getService(WAClientAppService.class).list().stream(). filter(app -> app.getClientAppTO() instanceof OIDCRPClientAppTO && app.getAttrReleasePolicy() != null). @@ -168,7 +167,7 @@ public PropertySource locate(final Environment environment) { Stream.concat(new OidcDiscoveryProperties().getClaims().stream(), customClaims.stream()). collect(Collectors.joining(","))); properties.put("cas.authn.oidc.core.user-defined-scopes.syncope", - String.join(",", customClaims)); + String.join(",", customClaims)); } syncopeClient.getService(WAConfigService.class).list().forEach(attr -> properties.put( diff --git a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/PasswordManagementPropertySourceMapper.java b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/PasswordManagementPropertySourceMapper.java index bb63328eb9d..7b1c909512d 100644 --- a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/PasswordManagementPropertySourceMapper.java +++ b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/PasswordManagementPropertySourceMapper.java @@ -44,8 +44,10 @@ public PasswordManagementPropertySourceMapper(final WARestClient waRestClient) { } @Override - public Map map(final PasswordManagementTO passwordManagementTO, + public Map map( + final PasswordManagementTO passwordManagementTO, final SyncopePasswordManagementConf conf) { + SyncopeClient syncopeClient = waRestClient.getSyncopeClient(); if (syncopeClient == null) { LOG.warn("Application context is not ready to bootstrap WA configuration"); @@ -60,14 +62,16 @@ public Map map(final PasswordManagementTO passwordManagementTO, props.setSearchFilter(conf.getSearchFilter()); props.setHeaders(conf.getHeaders()); - Map mappedProps = prefix("cas.authn.pm.syncope.", WAConfUtils.asMap(props)); - mappedProps.put("cas.authn.pm.syncope.enabled", passwordManagementTO.isEnabled()); - return mappedProps; + Map mapped = prefix("cas.authn.pm.syncope.", WAConfUtils.asMap(props)); + mapped.put("cas.authn.pm.syncope.enabled", passwordManagementTO.isEnabled()); + return mapped; } @Override - public Map map(final PasswordManagementTO passwordManagementTO, + public Map map( + final PasswordManagementTO passwordManagementTO, final LDAPPasswordManagementConf conf) { + LdapPasswordManagementProperties props = new LdapPasswordManagementProperties(); props.setName(passwordManagementTO.getKey()); props.setType(AbstractLdapProperties.LdapType.valueOf(conf.getLdapType().name())); @@ -75,14 +79,16 @@ public Map map(final PasswordManagementTO passwordManagementTO, fill(props, conf); - Map mappedProps = prefix("cas.authn.pm.ldap[].", WAConfUtils.asMap(props)); - mappedProps.put("cas.authn.pm.ldap.enabled", passwordManagementTO.isEnabled()); - return mappedProps; + Map mapped = prefix("cas.authn.pm.ldap[].", WAConfUtils.asMap(props)); + mapped.put("cas.authn.pm.ldap.enabled", passwordManagementTO.isEnabled()); + return mapped; } @Override - public Map map(final PasswordManagementTO passwordManagementTO, + public Map map( + final PasswordManagementTO passwordManagementTO, final JDBCPasswordManagementConf conf) { + JdbcPasswordManagementProperties props = new JdbcPasswordManagementProperties(); props.setSqlChangePassword(conf.getSqlChangePassword()); props.setSqlFindEmail(conf.getSqlFindEmail()); @@ -94,14 +100,17 @@ public Map map(final PasswordManagementTO passwordManagementTO, props.setSqlUnlockAccount(conf.getSqlUnlockAccount()); fill(props, conf); - Map mappedProps = prefix("cas.authn.pm.jdbc.", WAConfUtils.asMap(props)); - mappedProps.put("cas.authn.pm.jdbc.enabled", passwordManagementTO.isEnabled()); - return mappedProps; + Map mapped = prefix("cas.authn.pm.jdbc.", WAConfUtils.asMap(props)); + mapped.put("cas.authn.pm.jdbc.enabled", passwordManagementTO.isEnabled()); + mapped.put("management.health.db.enabled", "false"); + return mapped; } @Override - public Map map(final PasswordManagementTO passwordManagementTO, + public Map map( + final PasswordManagementTO passwordManagementTO, final RESTPasswordManagementConf conf) { + RestfulPasswordManagementProperties props = new RestfulPasswordManagementProperties(); props.setEndpointPassword(conf.getEndpointPassword()); props.setEndpointUrlAccountUnlock(conf.getEndpointUrlAccountUnlock()); @@ -116,8 +125,8 @@ public Map map(final PasswordManagementTO passwordManagementTO, props.setFieldNameUser(conf.getFieldNameUser()); props.setHeaders(conf.getHeaders()); - Map mappedProps = prefix("cas.authn.pm.rest.", WAConfUtils.asMap(props)); - mappedProps.put("cas.authn.pm.rest.enabled", passwordManagementTO.isEnabled()); - return mappedProps; + Map mapped = prefix("cas.authn.pm.rest.", WAConfUtils.asMap(props)); + mapped.put("cas.authn.pm.rest.enabled", passwordManagementTO.isEnabled()); + return mapped; } } diff --git a/wa/starter/src/main/java/org/apache/syncope/wa/starter/config/WAContext.java b/wa/starter/src/main/java/org/apache/syncope/wa/starter/config/WAContext.java index 0cf1fcaddaa..a328f98b2af 100644 --- a/wa/starter/src/main/java/org/apache/syncope/wa/starter/config/WAContext.java +++ b/wa/starter/src/main/java/org/apache/syncope/wa/starter/config/WAContext.java @@ -27,6 +27,7 @@ import java.io.Serializable; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; import javax.sql.DataSource; @@ -75,8 +76,6 @@ import org.apereo.cas.authentication.surrogate.SurrogateAuthenticationService; import org.apereo.cas.configuration.CasConfigurationProperties; import org.apereo.cas.configuration.model.support.mfa.gauth.LdapGoogleAuthenticatorMultifactorProperties; -import org.apereo.cas.configuration.model.support.pm.JdbcPasswordManagementProperties; -import org.apereo.cas.configuration.model.support.pm.LdapPasswordManagementProperties; import org.apereo.cas.configuration.model.support.pm.PasswordManagementProperties; import org.apereo.cas.gauth.CasGoogleAuthenticator; import org.apereo.cas.gauth.credential.LdapGoogleAuthenticatorTokenCredentialRepository; @@ -378,6 +377,7 @@ public PasswordManagementService syncopePasswordChangeService( final CipherExecutor passwordManagementCipherExecutor, @Qualifier(PasswordHistoryService.BEAN_NAME) final PasswordHistoryService passwordHistoryService) { + PasswordManagementProperties pm = casProperties.getAuthn().getPm(); if (pm.getCore().isEnabled() && pm.getSyncope().isDefined()) { return new SyncopePasswordManagementService( @@ -385,6 +385,7 @@ public PasswordManagementService syncopePasswordChangeService( casProperties, passwordHistoryService); } + return new NoOpPasswordManagementService(passwordManagementCipherExecutor, casProperties); } @@ -396,16 +397,22 @@ public PasswordManagementService ldapPasswordChangeService( final CipherExecutor passwordManagementCipherExecutor, @Qualifier(PasswordHistoryService.BEAN_NAME) final PasswordHistoryService passwordHistoryService) { - List ldaps = casProperties.getAuthn().getPm().getLdap(); - if (!ldaps.isEmpty() && StringUtils.isNotBlank(ldaps.get(0).getLdapUrl())) { - ConcurrentHashMap connectionFactoryMap = - new ConcurrentHashMap(); - ldaps.forEach(ldap -> connectionFactoryMap.put( + + PasswordManagementProperties pm = casProperties.getAuthn().getPm(); + if (pm.getCore().isEnabled() + && !pm.getLdap().isEmpty() && StringUtils.isNotBlank(pm.getLdap().getFirst().getLdapUrl())) { + + Map connectionFactoryMap = new ConcurrentHashMap<>(); + pm.getLdap().forEach(ldap -> connectionFactoryMap.put( ldap.getLdapUrl(), LdapUtils.newLdaptiveConnectionFactory(ldap))); - return new LdapPasswordManagementService(passwordManagementCipherExecutor, casProperties, - passwordHistoryService, connectionFactoryMap); + return new LdapPasswordManagementService( + passwordManagementCipherExecutor, + casProperties, + passwordHistoryService, + connectionFactoryMap); } + return new NoOpPasswordManagementService(passwordManagementCipherExecutor, casProperties); } @@ -413,7 +420,7 @@ public PasswordManagementService ldapPasswordChangeService( @Bean public PasswordManagementService jdbcPasswordChangeService( final CasConfigurationProperties casProperties, - final ConfigurableApplicationContext applicationContext, + final ConfigurableApplicationContext ctx, @Qualifier("jdbcPasswordManagementDataSource") final DataSource jdbcPasswordManagementDataSource, @Qualifier("jdbcPasswordManagementTransactionTemplate") @@ -422,14 +429,19 @@ public PasswordManagementService jdbcPasswordChangeService( final CipherExecutor passwordManagementCipherExecutor, @Qualifier(PasswordHistoryService.BEAN_NAME) final PasswordHistoryService passwordHistoryService) { - JdbcPasswordManagementProperties jdbc = casProperties.getAuthn().getPm().getJdbc(); - if (StringUtils.isNotBlank(jdbc.getUrl())) { + + PasswordManagementProperties pm = casProperties.getAuthn().getPm(); + if (pm.getCore().isEnabled() && StringUtils.isNotBlank(pm.getJdbc().getUrl())) { PasswordEncoder encoder = PasswordEncoderUtils.newPasswordEncoder( - casProperties.getAuthn().getPm().getJdbc().getPasswordEncoder(), applicationContext); - return new JdbcPasswordManagementService(passwordManagementCipherExecutor, - casProperties, jdbcPasswordManagementDataSource, - jdbcPasswordManagementTransactionTemplate, passwordHistoryService, encoder); + pm.getJdbc().getPasswordEncoder(), ctx); + return new JdbcPasswordManagementService( + passwordManagementCipherExecutor, + casProperties, + jdbcPasswordManagementDataSource, + jdbcPasswordManagementTransactionTemplate, + passwordHistoryService, encoder); } + return new NoOpPasswordManagementService(passwordManagementCipherExecutor, casProperties); } @@ -443,14 +455,22 @@ public PasswordManagementService restPasswordChangeService( final CipherExecutor passwordManagementCipherExecutor, @Qualifier(PasswordHistoryService.BEAN_NAME) final PasswordHistoryService passwordHistoryService) { - return new RestPasswordManagementService(passwordManagementCipherExecutor, - casProperties, passwordChangeServiceRestTemplate, passwordHistoryService); + + if (casProperties.getAuthn().getPm().getCore().isEnabled()) { + return new RestPasswordManagementService( + passwordManagementCipherExecutor, + casProperties, + passwordChangeServiceRestTemplate, + passwordHistoryService); + } + + return new NoOpPasswordManagementService(passwordManagementCipherExecutor, casProperties); } @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT) @Bean public PasswordManagementService passwordChangeService( - final ConfigurableApplicationContext applicationContext, + final ConfigurableApplicationContext ctx, final CasConfigurationProperties casProperties, @Qualifier("passwordManagementCipherExecutor") final CipherExecutor passwordManagementCipherExecutor, @@ -463,23 +483,19 @@ public PasswordManagementService passwordChangeService( @Qualifier("restPasswordChangeService") final PasswordManagementService restPasswordManagementService) { - if (applicationContext.getEnvironment() - .getProperty("cas.authn.pm.syncope.enabled", Boolean.class, Boolean.FALSE)) { + if (ctx.getEnvironment().getProperty("cas.authn.pm.syncope.enabled", Boolean.class, Boolean.FALSE)) { return syncopePasswordManagementService; } - if (applicationContext.getEnvironment() - .getProperty("cas.authn.pm.ldap.enabled", Boolean.class, Boolean.FALSE)) { + if (ctx.getEnvironment().getProperty("cas.authn.pm.ldap.enabled", Boolean.class, Boolean.FALSE)) { return ldapPasswordManagementService; } - if (applicationContext.getEnvironment() - .getProperty("cas.authn.pm.jdbc.enabled", Boolean.class, Boolean.FALSE)) { + if (ctx.getEnvironment().getProperty("cas.authn.pm.jdbc.enabled", Boolean.class, Boolean.FALSE)) { return jdbcPasswordManagementService; } - if (applicationContext.getEnvironment() - .getProperty("cas.authn.pm.rest.enabled", Boolean.class, Boolean.FALSE)) { + if (ctx.getEnvironment().getProperty("cas.authn.pm.rest.enabled", Boolean.class, Boolean.FALSE)) { return restPasswordManagementService; } diff --git a/wa/starter/src/main/resources/wa.properties b/wa/starter/src/main/resources/wa.properties index b23143be5c0..8c75802d348 100644 --- a/wa/starter/src/main/resources/wa.properties +++ b/wa/starter/src/main/resources/wa.properties @@ -139,7 +139,3 @@ management.metrics.enable.system.cpu=true management.metrics.enable.process.cpu=true management.metrics.enable.process.uptime=true management.metrics.enable.process.start.time=true - -## -# Spring Boot Actuator Database Health Check Configuration -management.health.db.enabled=false From 8ae6aa412638c61a4e44ad5bcf0080b033116783 Mon Sep 17 00:00:00 2001 From: alberto bogi Date: Tue, 14 Oct 2025 12:26:13 +0200 Subject: [PATCH 20/20] [SYNCOPE-1901] Reflow --- .../mapping/PasswordManagementPropertySourceMapper.java | 1 - .../org/apache/syncope/wa/starter/SyncopeWAApplication.java | 6 ++++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/PasswordManagementPropertySourceMapper.java b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/PasswordManagementPropertySourceMapper.java index 7b1c909512d..d1dbbc5cd97 100644 --- a/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/PasswordManagementPropertySourceMapper.java +++ b/wa/bootstrap/src/main/java/org/apache/syncope/wa/bootstrap/mapping/PasswordManagementPropertySourceMapper.java @@ -102,7 +102,6 @@ public Map map( Map mapped = prefix("cas.authn.pm.jdbc.", WAConfUtils.asMap(props)); mapped.put("cas.authn.pm.jdbc.enabled", passwordManagementTO.isEnabled()); - mapped.put("management.health.db.enabled", "false"); return mapped; } diff --git a/wa/starter/src/main/java/org/apache/syncope/wa/starter/SyncopeWAApplication.java b/wa/starter/src/main/java/org/apache/syncope/wa/starter/SyncopeWAApplication.java index fb9cdfe8c05..5a438833b50 100644 --- a/wa/starter/src/main/java/org/apache/syncope/wa/starter/SyncopeWAApplication.java +++ b/wa/starter/src/main/java/org/apache/syncope/wa/starter/SyncopeWAApplication.java @@ -29,6 +29,7 @@ import org.apereo.cas.support.saml.idp.metadata.generator.SamlIdPMetadataGenerator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.boot.actuate.autoconfigure.jdbc.DataSourceHealthContributorAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration; import org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration; @@ -65,12 +66,13 @@ GsonAutoConfiguration.class, JmxAutoConfiguration.class, DataSourceAutoConfiguration.class, + DataSourceHealthContributorAutoConfiguration.class, + DataSourceTransactionManagerAutoConfiguration.class, RedisAutoConfiguration.class, + RedisRepositoriesAutoConfiguration.class, MongoAutoConfiguration.class, MongoDataAutoConfiguration.class, CassandraAutoConfiguration.class, - DataSourceTransactionManagerAutoConfiguration.class, - RedisRepositoriesAutoConfiguration.class, CasGoogleAuthenticatorLdapAutoConfiguration.class }) @EnableConfigurationProperties({ WAProperties.class, CasConfigurationProperties.class })