Return-Path: X-Original-To: apmail-syncope-commits-archive@www.apache.org Delivered-To: apmail-syncope-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 9761017D13 for ; Fri, 11 Sep 2015 12:52:59 +0000 (UTC) Received: (qmail 24609 invoked by uid 500); 11 Sep 2015 12:52:59 -0000 Delivered-To: apmail-syncope-commits-archive@syncope.apache.org Received: (qmail 24543 invoked by uid 500); 11 Sep 2015 12:52:59 -0000 Mailing-List: contact commits-help@syncope.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@syncope.apache.org Delivered-To: mailing list commits@syncope.apache.org Received: (qmail 24527 invoked by uid 99); 11 Sep 2015 12:52:59 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 11 Sep 2015 12:52:59 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 35D9DDFA69; Fri, 11 Sep 2015 12:52:59 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: ilgrosso@apache.org To: commits@syncope.apache.org Date: Fri, 11 Sep 2015 12:53:00 -0000 Message-Id: <2f65eb138fe246749dc7b7e042c6ac39@git.apache.org> In-Reply-To: <2583b9c48bf34f3584c4483ff089b213@git.apache.org> References: <2583b9c48bf34f3584c4483ff089b213@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [2/2] syncope git commit: [SYNCOPE-693][SYNCOPE-692] Changing search to work only in paginated mode and adding support for external resource browsing [SYNCOPE-693][SYNCOPE-692] Changing search to work only in paginated mode and adding support for external resource browsing Project: http://git-wip-us.apache.org/repos/asf/syncope/repo Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/02456545 Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/02456545 Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/02456545 Branch: refs/heads/master Commit: 02456545bf191847ed4c4cf69d63f9ff500ea888 Parents: 0098875 Author: Francesco Chicchiriccò Authored: Fri Sep 11 14:52:46 2015 +0200 Committer: Francesco Chicchiriccò Committed: Fri Sep 11 14:52:46 2015 +0200 ---------------------------------------------------------------------- .../client/lib/RestClientExceptionMapper.java | 5 +- .../syncope/client/lib/SyncopeClient.java | 11 ++ .../builders/ConnObjectTOListQueryBuilder.java | 48 +++++++ .../common/lib/to/PagedConnObjectTOResult.java | 120 +++++++++++++++++ .../syncope/common/lib/types/Entitlement.java | 4 +- .../rest/api/beans/ConnObjectTOListQuery.java | 84 ++++++++++++ .../common/rest/api/service/JAXRSService.java | 2 + .../rest/api/service/ResourceService.java | 28 +++- .../syncope/core/logic/ResourceLogic.java | 81 ++++++++--- .../test/resources/domains/MasterContent.xml | 2 +- .../src/test/resources/domains/TwoContent.xml | 2 +- .../core/provisioning/api/Connector.java | 53 ++++++-- .../java/ConnIdBundleManagerImpl.java | 7 +- .../provisioning/java/ConnectorFacadeProxy.java | 133 ++++++++++++------- .../core/provisioning/java/sync/SyncUtils.java | 16 ++- .../rest/cxf/service/ResourceServiceImpl.java | 38 ++++++ .../fit/core/reference/ResourceITCase.java | 94 ++++++++++--- pom.xml | 4 +- 18 files changed, 623 insertions(+), 109 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/syncope/blob/02456545/client/lib/src/main/java/org/apache/syncope/client/lib/RestClientExceptionMapper.java ---------------------------------------------------------------------- diff --git a/client/lib/src/main/java/org/apache/syncope/client/lib/RestClientExceptionMapper.java b/client/lib/src/main/java/org/apache/syncope/client/lib/RestClientExceptionMapper.java index 7a88245..afc0f69 100644 --- a/client/lib/src/main/java/org/apache/syncope/client/lib/RestClientExceptionMapper.java +++ b/client/lib/src/main/java/org/apache/syncope/client/lib/RestClientExceptionMapper.java @@ -71,7 +71,10 @@ public class RestClientExceptionMapper implements ExceptionMapper, Re : message); } else if (statusCode == Response.Status.BAD_REQUEST.getStatusCode()) { // 3. Map SC_BAD_REQUEST - ex = new BadRequestException(); + String message = response.getHeaderString(RESTHeaders.ERROR_INFO); + ex = StringUtils.isBlank(message) + ? new BadRequestException() + : new BadRequestException(message); } else { // 4. All other codes are mapped to runtime exception with HTTP code information ex = new WebServiceException(String.format("Remote exception with status code: %s", http://git-wip-us.apache.org/repos/asf/syncope/blob/02456545/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClient.java ---------------------------------------------------------------------- diff --git a/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClient.java b/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClient.java index b744dc1..683c0a7 100644 --- a/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClient.java +++ b/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClient.java @@ -33,6 +33,7 @@ import org.apache.cxf.jaxrs.client.WebClient; import org.apache.syncope.client.lib.builders.ListQueryBuilder; import org.apache.syncope.client.lib.builders.AnyListQueryBuilder; import org.apache.syncope.client.lib.builders.AnySearchQueryBuilder; +import org.apache.syncope.client.lib.builders.ConnObjectTOListQueryBuilder; import org.apache.syncope.common.lib.search.AnyObjectFiqlSearchConditionBuilder; import org.apache.syncope.common.lib.search.OrderByClauseBuilder; import org.apache.syncope.common.lib.search.GroupFiqlSearchConditionBuilder; @@ -138,6 +139,16 @@ public class SyncopeClient { } /** + * Returns a new instance of {@link ConnObjectTOListQueryBuilder}, for assisted building of some service's + * {@code list()} arguments. + * + * @return default instance of {@link ConnObjectTOListQueryBuilder} + */ + public static ConnObjectTOListQueryBuilder getConnObjectTOListQueryBuilder() { + return new ConnObjectTOListQueryBuilder(); + } + + /** * Creates an instance of the given service class, with configured content type and authentication. * * @param any service class http://git-wip-us.apache.org/repos/asf/syncope/blob/02456545/client/lib/src/main/java/org/apache/syncope/client/lib/builders/ConnObjectTOListQueryBuilder.java ---------------------------------------------------------------------- diff --git a/client/lib/src/main/java/org/apache/syncope/client/lib/builders/ConnObjectTOListQueryBuilder.java b/client/lib/src/main/java/org/apache/syncope/client/lib/builders/ConnObjectTOListQueryBuilder.java new file mode 100644 index 0000000..619f391 --- /dev/null +++ b/client/lib/src/main/java/org/apache/syncope/client/lib/builders/ConnObjectTOListQueryBuilder.java @@ -0,0 +1,48 @@ +/* + * 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.lib.builders; + +import org.apache.syncope.common.rest.api.beans.ConnObjectTOListQuery; + +public class ConnObjectTOListQueryBuilder { + + private final ConnObjectTOListQuery instance = new ConnObjectTOListQuery(); + + public ConnObjectTOListQueryBuilder size(final Integer size) { + instance.setSize(size); + + return this; + } + + public ConnObjectTOListQueryBuilder pagedResultsCookie(final String pagedResultsCookie) { + instance.setPagedResultsCookie(pagedResultsCookie); + + return this; + } + + public ConnObjectTOListQueryBuilder orderBy(final String orderBy) { + instance.setOrderBy(orderBy); + + return this; + } + + public ConnObjectTOListQuery build() { + return instance; + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/02456545/common/lib/src/main/java/org/apache/syncope/common/lib/to/PagedConnObjectTOResult.java ---------------------------------------------------------------------- diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/PagedConnObjectTOResult.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/PagedConnObjectTOResult.java new file mode 100644 index 0000000..33e4c5d --- /dev/null +++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/PagedConnObjectTOResult.java @@ -0,0 +1,120 @@ +/* + * 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 com.fasterxml.jackson.annotation.JsonProperty; +import java.net.URI; +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementWrapper; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; +import org.apache.syncope.common.lib.AbstractBaseBean; + +@XmlRootElement(name = "pagedConnObjectResult") +@XmlType +public class PagedConnObjectTOResult extends AbstractBaseBean { + + private static final long serialVersionUID = -2832908019064402976L; + + private URI next; + + private final List result = new ArrayList<>(); + + private String pagedResultsCookie; + + private int remainingPagedResults = -1; + + private boolean allResultsReturned = true; + + public URI getNext() { + return next; + } + + public void setNext(final URI next) { + this.next = next; + } + + /** + * Returns the opaque cookie which should be used with the next paged results search request. + * + * @return The opaque cookie which should be used with the next paged results search request, or {@code null} if + * paged results were not requested, or if there are not more pages to be returned. + */ + public String getPagedResultsCookie() { + return pagedResultsCookie; + } + + /** + * @param pagedResultsCookie The opaque cookie which should be used with the next paged results search request, or + * {@code null} if paged results were not requested, or if there are not more pages to be returned. + */ + public void setPagedResultsCookie(final String pagedResultsCookie) { + this.pagedResultsCookie = pagedResultsCookie; + } + + /** + * Returns an estimate of the total number of remaining results to be returned in subsequent paged results search + * requests. + * + * @return An estimate of the total number of remaining results to be returned in subsequent paged results search + * requests, or {@code -1} if paged results were not requested, or if the total number of remaining results is + * unknown. + */ + public int getRemainingPagedResults() { + return remainingPagedResults; + } + + /** + * @param remainingPagedResults An estimate of the total number of remaining results to be returned in subsequent + * paged results search requests, or {@code -1} if paged results were not requested, or if the total number of + * remaining results is unknown. + */ + public void setRemainingPagedResults(final int remainingPagedResults) { + this.remainingPagedResults = remainingPagedResults; + } + + /** + * Returns a flag indicating whether all the results that match a search query were returned. + * + * @return true if the search returned all the results that match the query, false if the returned + * result is not complete, e.g. if the server returned only part of the results due to server limits, errors, etc. + */ + public boolean isAllResultsReturned() { + return allResultsReturned; + } + + /** + * @param allResultsReturned Set to true if the search returned all the results that match the query. Set to false + * if the returned result is not complete, e.g. if the server returned only part of the results due to server + * limits, errors, etc. + */ + public void setAllResultsReturned(final boolean allResultsReturned) { + this.allResultsReturned = allResultsReturned; + } + + @XmlElementWrapper(name = "result") + @XmlElement(name = "item") + @JsonProperty("result") + public List getResult() { + return result; + } + +} http://git-wip-us.apache.org/repos/asf/syncope/blob/02456545/common/lib/src/main/java/org/apache/syncope/common/lib/types/Entitlement.java ---------------------------------------------------------------------- diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/types/Entitlement.java b/common/lib/src/main/java/org/apache/syncope/common/lib/types/Entitlement.java index 5a4ea81..406b805 100644 --- a/common/lib/src/main/java/org/apache/syncope/common/lib/types/Entitlement.java +++ b/common/lib/src/main/java/org/apache/syncope/common/lib/types/Entitlement.java @@ -140,7 +140,9 @@ public final class Entitlement { public static final String RESOURCE_DELETE = "RESOURCE_DELETE"; - public static final String RESOURCE_GETCONNECTOROBJECT = "RESOURCE_GETCONNECTOROBJECT"; + public static final String RESOURCE_GET_CONNOBJECT = "RESOURCE_GET_CONNOBJECT"; + + public static final String RESOURCE_LIST_CONNOBJECT = "RESOURCE_LIST_CONNOBJECT"; public static final String CONNECTOR_LIST = "CONNECTOR_LIST"; http://git-wip-us.apache.org/repos/asf/syncope/blob/02456545/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/ConnObjectTOListQuery.java ---------------------------------------------------------------------- diff --git a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/ConnObjectTOListQuery.java b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/ConnObjectTOListQuery.java new file mode 100644 index 0000000..32a7359 --- /dev/null +++ b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/ConnObjectTOListQuery.java @@ -0,0 +1,84 @@ +/* + * 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.beans; + +import java.io.Serializable; +import javax.validation.constraints.Min; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.QueryParam; +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.apache.commons.lang3.builder.ReflectionToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import org.apache.syncope.common.rest.api.service.JAXRSService; + +public class ConnObjectTOListQuery implements Serializable { + + private static final long serialVersionUID = -371488230250055359L; + + private Integer size; + + private String pagedResultsCookie; + + private String orderBy; + + public Integer getSize() { + return size; + } + + @Min(1) + @QueryParam(JAXRSService.PARAM_SIZE) + @DefaultValue("25") + public void setSize(final Integer size) { + this.size = size; + } + + public String getPagedResultsCookie() { + return pagedResultsCookie; + } + + @QueryParam(JAXRSService.PARAM_CONNID_PAGED_RESULTS_COOKIE) + public void setPagedResultsCookie(final String pagedResultsCookie) { + this.pagedResultsCookie = pagedResultsCookie; + } + + @QueryParam(JAXRSService.PARAM_ORDERBY) + public String getOrderBy() { + return orderBy; + } + + public void setOrderBy(final String orderBy) { + this.orderBy = orderBy; + } + + @Override + public boolean equals(final Object obj) { + return EqualsBuilder.reflectionEquals(this, obj); + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public String toString() { + return ReflectionToStringBuilder.toString(this, ToStringStyle.MULTI_LINE_STYLE); + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/02456545/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/JAXRSService.java ---------------------------------------------------------------------- diff --git a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/JAXRSService.java b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/JAXRSService.java index c6c73d5..fb9cec0 100644 --- a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/JAXRSService.java +++ b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/JAXRSService.java @@ -30,4 +30,6 @@ public interface JAXRSService { String PARAM_DETAILS = "details"; + String PARAM_CONNID_PAGED_RESULTS_COOKIE = "connIdPagedResultsCookie"; + } http://git-wip-us.apache.org/repos/asf/syncope/blob/02456545/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/ResourceService.java ---------------------------------------------------------------------- diff --git a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/ResourceService.java b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/ResourceService.java index f15bcd5..14bb19f 100644 --- a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/ResourceService.java +++ b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/ResourceService.java @@ -20,6 +20,7 @@ package org.apache.syncope.common.rest.api.service; import java.util.List; import javax.validation.constraints.NotNull; +import javax.ws.rs.BeanParam; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.GET; @@ -33,10 +34,12 @@ import javax.ws.rs.core.Response; import org.apache.syncope.common.lib.to.BulkAction; import org.apache.syncope.common.lib.to.BulkActionResult; import org.apache.syncope.common.lib.to.ConnObjectTO; +import org.apache.syncope.common.lib.to.PagedConnObjectTOResult; import org.apache.syncope.common.lib.to.ResourceTO; import org.apache.syncope.common.lib.types.ResourceDeassociationActionType; import org.apache.syncope.common.lib.wrap.AnyKey; import org.apache.syncope.common.lib.wrap.BooleanWrap; +import org.apache.syncope.common.rest.api.beans.ConnObjectTOListQuery; /** * REST operations for external resources. @@ -47,7 +50,7 @@ public interface ResourceService extends JAXRSService { /** * Returns connector object from the external resource, for the given type and key. * - * @param key Name of resource to read connector object from + * @param key name of resource to read connector object from * @param anyTypeKey any object type * @param anyKey any object key * @return connector object from the external resource, for the given type and key @@ -55,8 +58,27 @@ public interface ResourceService extends JAXRSService { @GET @Path("{key}/{anyTypeKey}/{anyKey}") @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) - ConnObjectTO readConnObject(@NotNull @PathParam("key") String key, - @NotNull @PathParam("anyTypeKey") String anyTypeKey, @NotNull @PathParam("anyKey") Long anyKey); + ConnObjectTO readConnObject( + @NotNull @PathParam("key") String key, + @NotNull @PathParam("anyTypeKey") String anyTypeKey, + @NotNull @PathParam("anyKey") Long anyKey); + + /** + * Returns a paged list of connector objects from external resource, for the given type, matching + * page/size conditions. + * + * @param key name of resource to read connector object from + * @param anyTypeKey any object type + * @param listQuery query conditions + * @return connector objects from the external resource, for the given type + */ + @GET + @Path("{key}/{anyTypeKey}") + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) + PagedConnObjectTOResult listConnObjects( + @NotNull @PathParam("key") String key, + @NotNull @PathParam("anyTypeKey") String anyTypeKey, + @BeanParam ConnObjectTOListQuery listQuery); /** * Returns the resource with matching name. http://git-wip-us.apache.org/repos/asf/syncope/blob/02456545/core/logic/src/main/java/org/apache/syncope/core/logic/ResourceLogic.java ---------------------------------------------------------------------- diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/ResourceLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/ResourceLogic.java index f95f7ed..ce2fb2e 100644 --- a/core/logic/src/main/java/org/apache/syncope/core/logic/ResourceLogic.java +++ b/core/logic/src/main/java/org/apache/syncope/core/logic/ResourceLogic.java @@ -26,6 +26,10 @@ import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.Transformer; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.ImmutableTriple; +import org.apache.commons.lang3.tuple.Pair; +import org.apache.commons.lang3.tuple.Triple; import org.apache.syncope.common.lib.SyncopeClientException; import org.apache.syncope.common.lib.to.ConnObjectTO; import org.apache.syncope.common.lib.to.ResourceTO; @@ -48,6 +52,7 @@ import org.apache.syncope.core.misc.ConnObjectUtils; import org.apache.syncope.core.misc.MappingUtils; import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO; import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO; +import org.apache.syncope.core.persistence.api.dao.search.OrderByClause; import org.apache.syncope.core.persistence.api.entity.Any; import org.apache.syncope.core.persistence.api.entity.AnyType; import org.apache.syncope.core.persistence.api.entity.resource.Provision; @@ -55,7 +60,9 @@ import org.identityconnectors.framework.common.objects.Attribute; import org.identityconnectors.framework.common.objects.AttributeUtil; import org.identityconnectors.framework.common.objects.ConnectorObject; import org.identityconnectors.framework.common.objects.Name; +import org.identityconnectors.framework.common.objects.SearchResult; import org.identityconnectors.framework.common.objects.Uid; +import org.identityconnectors.framework.spi.SearchResultsHandler; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.stereotype.Component; @@ -172,9 +179,9 @@ public class ResourceLogic extends AbstractTransactionalLogic { }, new ArrayList()); } - @PreAuthorize("hasRole('" + Entitlement.RESOURCE_GETCONNECTOROBJECT + "')") - @Transactional(readOnly = true) - public ConnObjectTO readConnObject(final String resourceKey, final String anyTypeKey, final Long key) { + private Triple connObjectInit( + final String resourceKey, final String anyTypeKey) { + ExternalResource resource = resourceDAO.find(resourceKey); if (resource == null) { throw new NotFoundException("Resource '" + resourceKey + "'"); @@ -188,31 +195,41 @@ public class ResourceLogic extends AbstractTransactionalLogic { throw new NotFoundException("Provision on resource '" + resourceKey + "' for type '" + anyTypeKey + "'"); } - Any any = anyType.getKind() == AnyTypeKind.USER - ? userDAO.find(key) - : anyType.getKind() == AnyTypeKind.ANY_OBJECT - ? anyObjectDAO.find(key) - : groupDAO.find(key); + return ImmutableTriple.of(resource, anyType, provision); + } + + @PreAuthorize("hasRole('" + Entitlement.RESOURCE_GET_CONNOBJECT + "')") + @Transactional(readOnly = true) + public ConnObjectTO readConnObject(final String key, final String anyTypeKey, final Long anyKey) { + Triple init = connObjectInit(key, anyTypeKey); + + Any any = init.getMiddle().getKind() == AnyTypeKind.USER + ? userDAO.find(anyKey) + : init.getMiddle().getKind() == AnyTypeKind.ANY_OBJECT + ? anyObjectDAO.find(anyKey) + : groupDAO.find(anyKey); if (any == null) { - throw new NotFoundException(anyType + " " + key); + throw new NotFoundException(init.getMiddle() + " " + anyKey); } - MappingItem connObjectKeyItem = MappingUtils.getConnObjectKeyItem(provision); + MappingItem connObjectKeyItem = MappingUtils.getConnObjectKeyItem(init.getRight()); if (connObjectKeyItem == null) { throw new NotFoundException( - "ConnObjectKey mapping for " + anyType + " " + key + " on resource '" + resourceKey + "'"); + "ConnObjectKey mapping for " + init.getMiddle() + " " + anyKey + " on resource '" + key + "'"); } - String connObjectKeyValue = MappingUtils.getConnObjectKeyValue(any, provision); + String connObjectKeyValue = MappingUtils.getConnObjectKeyValue(any, init.getRight()); - Connector connector = connFactory.getConnector(resource); + Connector connector = connFactory.getConnector(init.getLeft()); ConnectorObject connectorObject = connector.getObject( - provision.getObjectClass(), new Uid(connObjectKeyValue), - connector.getOperationOptions(MappingUtils.getMappingItems(provision, MappingPurpose.BOTH))); + init.getRight().getObjectClass(), + new Uid(connObjectKeyValue), + connector.getOperationOptions(MappingUtils.getMappingItems(init.getRight(), MappingPurpose.BOTH))); if (connectorObject == null) { - throw new NotFoundException("Object " + connObjectKeyValue + " with class " + provision.getObjectClass() - + " not found on resource " + resourceKey); + throw new NotFoundException( + "Object " + connObjectKeyValue + " with class " + init.getRight().getObjectClass() + + " not found on resource " + key); } - final Set attributes = connectorObject.getAttributes(); + Set attributes = connectorObject.getAttributes(); if (AttributeUtil.find(Uid.NAME, attributes) == null) { attributes.add(connectorObject.getUid()); } @@ -223,6 +240,34 @@ public class ResourceLogic extends AbstractTransactionalLogic { return connObjectUtils.getConnObjectTO(connectorObject); } + @PreAuthorize("hasRole('" + Entitlement.RESOURCE_LIST_CONNOBJECT + "')") + @Transactional(readOnly = true) + public Pair> listConnObjects(final String key, final String anyTypeKey, + final Integer size, final String pagedResultsCookie, final List orderBy) { + + Triple init = connObjectInit(key, anyTypeKey); + + Connector connector = connFactory.getConnector(init.getLeft()); + + final SearchResult[] searchResult = new SearchResult[1]; + final List connObjects = new ArrayList<>(); + connector.search(init.getRight().getObjectClass(), null, new SearchResultsHandler() { + + @Override + public void handleResult(final SearchResult result) { + searchResult[0] = result; + } + + @Override + public boolean handle(final ConnectorObject connectorObject) { + connObjects.add(connObjectUtils.getConnObjectTO(connectorObject)); + return true; + } + }, size, pagedResultsCookie, orderBy); + + return ImmutablePair.of(searchResult[0], connObjects); + } + @PreAuthorize("hasRole('" + Entitlement.CONNECTOR_READ + "')") @Transactional(readOnly = true) public boolean check(final ResourceTO resourceTO) { http://git-wip-us.apache.org/repos/asf/syncope/blob/02456545/core/persistence-jpa/src/test/resources/domains/MasterContent.xml ---------------------------------------------------------------------- diff --git a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml index a17002b..5c61a22 100644 --- a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml +++ b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml @@ -558,7 +558,7 @@ under the License. location="${connid.location}" connectorName="net.tirasa.connid.bundles.ldap.LdapConnector" version="${connid.ldap.version}" - jsonConf='[{"schema":{"name":"synchronizePasswords","displayName":"Enable Password Synchronization","helpMessage":"If true, the connector will synchronize passwords. The Password Capture Plugin needs to be installed for password synchronization to work.","type":"boolean","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["false"]},{"schema":{"name":"maintainLdapGroupMembership","displayName":"Maintain LDAP Group Membership","helpMessage":"When enabled and a user is renamed or deleted, update any LDAP groups to which the user belongs to reflect the new name. Otherwise, the LDAP resource must maintain referential integrity with respect to group membership.","type":"boolean","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["true"]},{"schema":{"name":"host","displayName":"Host","helpMessage":"The name or IP address of the host where the LDAP server is running.","type":"jav a.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["localhost"]},{"schema":{"name":"passwordHashAlgorithm","displayName":"Password Hash Algorithm","helpMessage":"Indicates the algorithm that the Identity system should use to hash the password. Currently supported values are SSHA, SHA, SSHA1, and SHA1. A blank value indicates that the system will not hash passwords. This will cause cleartext passwords to be stored in LDAP unless the LDAP server performs the hash (Netscape Directory Server and iPlanet Directory Server do).","type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["SHA"]},{"schema":{"name":"blockSize","displayName":"Block Size","helpMessage":"The maximum number of accounts that can be in a block when retrieving accounts in blocks.","type":"int","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"valu es":[]},{"schema":{"name":"useBlocks","displayName":"Use Blocks","helpMessage":"When performing operations on large numbers of accounts, the accounts are processed in blocks to reduce the amount of memory used by the operation. Select this option to process accounts in blocks.","type":"boolean","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":[false]},{"schema":{"name":"usePagedResultControl","displayName":"Use Paged Result Control","helpMessage":"When enabled, the LDAP Paged Results control is preferred over the VLV control when retrieving accounts.","type":"boolean","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["false"]},{"schema":{"name":"port","displayName":"TCP Port","helpMessage":"TCP/IP port number used to communicate with the LDAP server.","type":"int","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":[1389]},{"schema":{"nam e":"vlvSortAttribute","displayName":"VLV Sort Attribute","helpMessage":"Specify the sort attribute to use for VLV indexes on the resource.","type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":[]},{"schema":{"name":"statusManagementClass","displayName":"Status management class ","helpMessage":"Class to be used to manage enabled/disabled status. If no class is specified then identity status management wont be possible.","type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["net.tirasa.connid.bundles.ldap.commons.AttributeStatusManagement"]},{"schema":{"name":"accountObjectClasses","displayName":"Account Object Classes","helpMessage":"The object class or classes that will be used when creating new user objects in the LDAP tree. When entering more than one object class, each entry should be on its own line; do not use commas or semi-colons to s eparate multiple object classes. Some object classes may require that you specify all object classes in the class hierarchy.","type":"[Ljava.lang.String;","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["inetOrgPerson"]},{"schema":{"name":"accountUserNameAttributes","displayName":"Account User Name Attributes","helpMessage":"Attribute or attributes which holds the account user name. They will be used when authenticating to find the LDAP entry for the user name to authenticate.","type":"[Ljava.lang.String;","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["uid"]},{"schema":{"name":"baseContextsToSynchronize","displayName":"Base Contexts to Synchronize","helpMessage":"One or more starting points in the LDAP tree that will be used to determine if a change should be synchronized. The base contexts attribute will be used to synchronize a change if this property is not set.","type":"[Lja va.lang.String;","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["ou=people,o=isp","ou=groups,o=isp"]},{"schema":{"name":"accountSynchronizationFilter","displayName":"LDAP Filter for Accounts to Synchronize","helpMessage":"An optional LDAP filter for the objects to synchronize. Because the change log is for all objects, this filter updates only objects that match the specified filter. If you specify a filter, an object will be synchronized only if it matches the filter and includes a synchronized object class.","type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":[]},{"schema":{"name":"removeLogEntryObjectClassFromFilter","displayName":"Remove Log Entry Object Class from Filter","helpMessage":"If this property is set (the default), the filter used to fetch change log entries does not contain the \"changeLogEntry\" object class, expecting that there are no entri es of other object types in the change log.","type":"boolean","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["false"]},{"schema":{"name":"passwordDecryptionKey","displayName":"Password Decryption Key","helpMessage":"The key to decrypt passwords with when performing password synchronization.","type":"org.identityconnectors.common.security.GuardedByteArray","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":[]},{"schema":{"name":"readSchema","displayName":"Read Schema","helpMessage":"If true, the connector will read the schema from the server. If false, the connector will provide a default schema based on the object classes in the configuration. This property must be true in order to use extended object classes.","type":"boolean","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["false"]},{"schema":{"name":"ssl","displayName":"SSL","hel pMessage":"Select the check box to connect to the LDAP server using SSL.","type":"boolean","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["false"]},{"schema":{"name":"passwordAttributeToSynchronize","displayName":"Password Attribute to Synchronize","helpMessage":"The name of the password attribute to synchronize when performing password synchronization.","type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":[]},{"schema":{"name":"accountSearchFilter","displayName":"LDAP Filter for Retrieving Accounts","helpMessage":"An optional LDAP filter to control which accounts are returned from the LDAP resource. If no filter is specified, only accounts that include all specified object classes are returned.","type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["uid=*"]},{"schema":{"name":"passwordDec ryptionInitializationVector","displayName":"Password Decryption Initialization Vector","helpMessage":"The initialization vector to decrypt passwords with when performing password synchronization.","type":"org.identityconnectors.common.security.GuardedByteArray","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":[]},{"schema":{"name":"groupMemberAttribute","displayName":"Group Member Attribute","helpMessage":"The name of the group attribute that will be updated with the distinguished name of the user when the user is added to the group.","type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":[]},{"schema":{"name":"failover","displayName":"Failover Servers","helpMessage":"List all servers that should be used for failover in case the preferred server fails. If the preferred server fails, JNDI will connect to the next available server in the list. List all servers in the form of \"ldap://ldap.example.com:389/\", which follows the standard LDAP v3 URLs described in RFC 2255. Only the host and port parts of the URL are relevant in this setting.","type":"[Ljava.lang.String;","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":[]},{"schema":{"name":"modifiersNamesToFilterOut","displayName":"Filter Out Changes By","helpMessage":"The names (DNs) of directory administrators to filter from the changes. Changes with the attribute \"modifiersName\" that match entries in this list will be filtered out. The standard value is the administrator name used by this adapter, to prevent loops. Entries should be of the format \"cn=Directory Manager\".","type":"[Ljava.lang.String;","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":[]},{"schema":{"name":"groupNameAttributes","displayName":"Group Name Attributes","helpMessage":"Attribute or attributes which holds the group nam e.","type":"[Ljava.lang.String;","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["cn"]},{"schema":{"name":"uidAttribute","displayName":"Uid Attribute","helpMessage":"The name of the LDAP attribute which is mapped to the Uid attribute.","type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["cn"]},{"schema":{"name":"respectResourcePasswordPolicyChangeAfterReset","displayName":"Respect Resource Password Policy Change-After-Reset","helpMessage":"When this resource is specified in a Login Module (i.e., this resource is a pass-through authentication target) and the resource password policy is configured for change-after-reset, a user whose resource account password has been administratively reset will be required to change that password after successfully authenticating.","type":"boolean","required":false,"order":0,"confidential":false,"defaultValues":null},"overrida ble":false,"values":["false"]},{"schema":{"name":"filterWithOrInsteadOfAnd","displayName":"Filter with Or Instead of And","helpMessage":"Normally the the filter used to fetch change log entries is an and-based filter retrieving an interval of change entries. If this property is set, the filter will or together the required change numbers instead.","type":"boolean","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["false"]},{"schema":{"name":"principal","displayName":"Principal","helpMessage":"The distinguished name with which to authenticate to the LDAP server.","type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["uid=admin,ou=system"]},{"schema":{"name":"changeLogBlockSize","displayName":"Change Log Block Size","helpMessage":"The number of change log entries to fetch per query.","type":"int","required":true,"order":0,"confidential":false,"defaultValues":null}, "overridable":false,"values":[100]},{"schema":{"name":"baseContexts","displayName":"Base Contexts","helpMessage":"One or more starting points in the LDAP tree that will be used when searching the tree. Searches are performed when discovering users from the LDAP server or when looking for the groups of which a user is a member.","type":"[Ljava.lang.String;","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["ou=people,o=isp","ou=groups,o=isp"]},{"schema":{"name":"passwordAttribute","displayName":"Password Attribute","helpMessage":"The name of the LDAP attribute which holds the password. When changing an user password, the new password is set to this attribute.","type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["userpassword"]},{"schema":{"name":"changeNumberAttribute","displayName":"Change Number Attribute","helpMessage":"The name of the change number attribute in the change log entry.","type":"java.lang.String","required":true,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["changeNumber"]},{"schema":{"name":"objectClassesToSynchronize","displayName":"Object Classes to Synchronize","helpMessage":"The object classes to synchronize. The change log is for all objects; this filters updates to just the listed object classes. You should not list the superclasses of an object class unless you intend to synchronize objects with any of the superclass values. For example, if only \"inetOrgPerson\" objects should be synchronized, but the superclasses of \"inetOrgPerson\" (\"person\", \"organizationalperson\" and \"top\") should be filtered out, then list only \"inetOrgPerson\" here. All objects in LDAP are subclassed from \"top\". For this reason, you should never list \"top\", otherwise no object would be filtered.","type":"[Ljava.lang.String;","required":true,"order":0,"confidential":false,"defaultValues":null}, "overridable":false,"values":["inetOrgPerson","groupOfUniqueNames"]},{"schema":{"name":"credentials","displayName":"Password","helpMessage":"Password for the principal.","type":"org.identityconnectors.common.security.GuardedString","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["secret"]},{"schema":{"name":"attributesToSynchronize","displayName":"Attributes to Synchronize","helpMessage":"The names of the attributes to synchronize. This ignores updates from the change log if they do not update any of the named attributes. For example, if only \"department\" is listed, then only changes that affect \"department\" will be processed. All other updates are ignored. If blank (the default), then all changes are processed.","type":"[Ljava.lang.String;","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":[]},{"schema":{"name":"maintainPosixGroupMembership","displayName":"Maintain POSIX Group M embership","helpMessage":"When enabled and a user is renamed or deleted, update any POSIX groups to which the user belongs to reflect the new name. Otherwise, the LDAP resource must maintain referential integrity with respect to group membership.","type":"boolean","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["false"]}]'/> + jsonConf='[{"schema":{"name":"synchronizePasswords","displayName":"Enable Password Synchronization","helpMessage":"If true, the connector will synchronize passwords. The Password Capture Plugin needs to be installed for password synchronization to work.","type":"boolean","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["false"]},{"schema":{"name":"maintainLdapGroupMembership","displayName":"Maintain LDAP Group Membership","helpMessage":"When enabled and a user is renamed or deleted, update any LDAP groups to which the user belongs to reflect the new name. Otherwise, the LDAP resource must maintain referential integrity with respect to group membership.","type":"boolean","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["true"]},{"schema":{"name":"host","displayName":"Host","helpMessage":"The name or IP address of the host where the LDAP server is running.","type":"jav a.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["localhost"]},{"schema":{"name":"passwordHashAlgorithm","displayName":"Password Hash Algorithm","helpMessage":"Indicates the algorithm that the Identity system should use to hash the password. Currently supported values are SSHA, SHA, SSHA1, and SHA1. A blank value indicates that the system will not hash passwords. This will cause cleartext passwords to be stored in LDAP unless the LDAP server performs the hash (Netscape Directory Server and iPlanet Directory Server do).","type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["SHA"]},{"schema":{"name":"port","displayName":"TCP Port","helpMessage":"TCP/IP port number used to communicate with the LDAP server.","type":"int","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":[1389]},{"schema":{"name":"vlvSo rtAttribute","displayName":"VLV Sort Attribute","helpMessage":"Specify the sort attribute to use for VLV indexes on the resource.","type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":[]},{"schema":{"name":"statusManagementClass","displayName":"Status management class ","helpMessage":"Class to be used to manage enabled/disabled status. If no class is specified then identity status management wont be possible.","type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["net.tirasa.connid.bundles.ldap.commons.AttributeStatusManagement"]},{"schema":{"name":"accountObjectClasses","displayName":"Account Object Classes","helpMessage":"The object class or classes that will be used when creating new user objects in the LDAP tree. When entering more than one object class, each entry should be on its own line; do not use commas or semi-colons to separate m ultiple object classes. Some object classes may require that you specify all object classes in the class hierarchy.","type":"[Ljava.lang.String;","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["inetOrgPerson"]},{"schema":{"name":"accountUserNameAttributes","displayName":"Account User Name Attributes","helpMessage":"Attribute or attributes which holds the account user name. They will be used when authenticating to find the LDAP entry for the user name to authenticate.","type":"[Ljava.lang.String;","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["uid"]},{"schema":{"name":"baseContextsToSynchronize","displayName":"Base Contexts to Synchronize","helpMessage":"One or more starting points in the LDAP tree that will be used to determine if a change should be synchronized. The base contexts attribute will be used to synchronize a change if this property is not set.","type":"[Ljava.lang.S tring;","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["ou=people,o=isp","ou=groups,o=isp"]},{"schema":{"name":"accountSynchronizationFilter","displayName":"LDAP Filter for Accounts to Synchronize","helpMessage":"An optional LDAP filter for the objects to synchronize. Because the change log is for all objects, this filter updates only objects that match the specified filter. If you specify a filter, an object will be synchronized only if it matches the filter and includes a synchronized object class.","type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":[]},{"schema":{"name":"removeLogEntryObjectClassFromFilter","displayName":"Remove Log Entry Object Class from Filter","helpMessage":"If this property is set (the default), the filter used to fetch change log entries does not contain the \"changeLogEntry\" object class, expecting that there are no entries of oth er object types in the change log.","type":"boolean","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["false"]},{"schema":{"name":"passwordDecryptionKey","displayName":"Password Decryption Key","helpMessage":"The key to decrypt passwords with when performing password synchronization.","type":"org.identityconnectors.common.security.GuardedByteArray","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":[]},{"schema":{"name":"readSchema","displayName":"Read Schema","helpMessage":"If true, the connector will read the schema from the server. If false, the connector will provide a default schema based on the object classes in the configuration. This property must be true in order to use extended object classes.","type":"boolean","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["false"]},{"schema":{"name":"ssl","displayName":"SSL","helpMessage" :"Select the check box to connect to the LDAP server using SSL.","type":"boolean","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["false"]},{"schema":{"name":"passwordAttributeToSynchronize","displayName":"Password Attribute to Synchronize","helpMessage":"The name of the password attribute to synchronize when performing password synchronization.","type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":[]},{"schema":{"name":"accountSearchFilter","displayName":"LDAP Filter for Retrieving Accounts","helpMessage":"An optional LDAP filter to control which accounts are returned from the LDAP resource. If no filter is specified, only accounts that include all specified object classes are returned.","type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["uid=*"]},{"schema":{"name":"passwordDecryptionIn itializationVector","displayName":"Password Decryption Initialization Vector","helpMessage":"The initialization vector to decrypt passwords with when performing password synchronization.","type":"org.identityconnectors.common.security.GuardedByteArray","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":[]},{"schema":{"name":"groupMemberAttribute","displayName":"Group Member Attribute","helpMessage":"The name of the group attribute that will be updated with the distinguished name of the user when the user is added to the group.","type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":[]},{"schema":{"name":"failover","displayName":"Failover Servers","helpMessage":"List all servers that should be used for failover in case the preferred server fails. If the preferred server fails, JNDI will connect to the next available server in the list. List all servers in the form of \"ldap://ldap.example.com:389/\", which follows the standard LDAP v3 URLs described in RFC 2255. Only the host and port parts of the URL are relevant in this setting.","type":"[Ljava.lang.String;","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":[]},{"schema":{"name":"modifiersNamesToFilterOut","displayName":"Filter Out Changes By","helpMessage":"The names (DNs) of directory administrators to filter from the changes. Changes with the attribute \"modifiersName\" that match entries in this list will be filtered out. The standard value is the administrator name used by this adapter, to prevent loops. Entries should be of the format \"cn=Directory Manager\".","type":"[Ljava.lang.String;","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":[]},{"schema":{"name":"groupNameAttributes","displayName":"Group Name Attributes","helpMessage":"Attribute or attributes which holds the group name.","type ":"[Ljava.lang.String;","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["cn"]},{"schema":{"name":"uidAttribute","displayName":"Uid Attribute","helpMessage":"The name of the LDAP attribute which is mapped to the Uid attribute.","type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["cn"]},{"schema":{"name":"respectResourcePasswordPolicyChangeAfterReset","displayName":"Respect Resource Password Policy Change-After-Reset","helpMessage":"When this resource is specified in a Login Module (i.e., this resource is a pass-through authentication target) and the resource password policy is configured for change-after-reset, a user whose resource account password has been administratively reset will be required to change that password after successfully authenticating.","type":"boolean","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":fals e,"values":["false"]},{"schema":{"name":"filterWithOrInsteadOfAnd","displayName":"Filter with Or Instead of And","helpMessage":"Normally the the filter used to fetch change log entries is an and-based filter retrieving an interval of change entries. If this property is set, the filter will or together the required change numbers instead.","type":"boolean","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["false"]},{"schema":{"name":"principal","displayName":"Principal","helpMessage":"The distinguished name with which to authenticate to the LDAP server.","type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["uid=admin,ou=system"]},{"schema":{"name":"changeLogBlockSize","displayName":"Change Log Block Size","helpMessage":"The number of change log entries to fetch per query.","type":"int","required":true,"order":0,"confidential":false,"defaultValues":null},"overrida ble":false,"values":[100]},{"schema":{"name":"baseContexts","displayName":"Base Contexts","helpMessage":"One or more starting points in the LDAP tree that will be used when searching the tree. Searches are performed when discovering users from the LDAP server or when looking for the groups of which a user is a member.","type":"[Ljava.lang.String;","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["ou=people,o=isp","ou=groups,o=isp"]},{"schema":{"name":"passwordAttribute","displayName":"Password Attribute","helpMessage":"The name of the LDAP attribute which holds the password. When changing an user password, the new password is set to this attribute.","type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["userpassword"]},{"schema":{"name":"changeNumberAttribute","displayName":"Change Number Attribute","helpMessage":"The name of the change number attribute in the c hange log entry.","type":"java.lang.String","required":true,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["changeNumber"]},{"schema":{"name":"objectClassesToSynchronize","displayName":"Object Classes to Synchronize","helpMessage":"The object classes to synchronize. The change log is for all objects; this filters updates to just the listed object classes. You should not list the superclasses of an object class unless you intend to synchronize objects with any of the superclass values. For example, if only \"inetOrgPerson\" objects should be synchronized, but the superclasses of \"inetOrgPerson\" (\"person\", \"organizationalperson\" and \"top\") should be filtered out, then list only \"inetOrgPerson\" here. All objects in LDAP are subclassed from \"top\". For this reason, you should never list \"top\", otherwise no object would be filtered.","type":"[Ljava.lang.String;","required":true,"order":0,"confidential":false,"defaultValues":null},"overrida ble":false,"values":["inetOrgPerson","groupOfUniqueNames"]},{"schema":{"name":"credentials","displayName":"Password","helpMessage":"Password for the principal.","type":"org.identityconnectors.common.security.GuardedString","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["secret"]},{"schema":{"name":"attributesToSynchronize","displayName":"Attributes to Synchronize","helpMessage":"The names of the attributes to synchronize. This ignores updates from the change log if they do not update any of the named attributes. For example, if only \"department\" is listed, then only changes that affect \"department\" will be processed. All other updates are ignored. If blank (the default), then all changes are processed.","type":"[Ljava.lang.String;","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":[]},{"schema":{"name":"maintainPosixGroupMembership","displayName":"Maintain POSIX Group Membership ","helpMessage":"When enabled and a user is renamed or deleted, update any POSIX groups to which the user belongs to reflect the new name. Otherwise, the LDAP resource must maintain referential integrity with respect to group membership.","type":"boolean","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["false"]}]'/>