Repository: syncope Updated Branches: refs/heads/2_0_X 7a437c0f6 -> fa2ed7303 refs/heads/master 5e83b3787 -> 07c7e777a
[SYNCOPE-152] SCIM search via POST Project: http://git-wip-us.apache.org/repos/asf/syncope/repo Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/fa2ed730 Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/fa2ed730 Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/fa2ed730 Branch: refs/heads/2_0_X Commit: fa2ed73036d6c75b2dca0aea0e764f0e68938d81 Parents: 7a437c0 Author: Francesco Chicchiriccò <[email protected]> Authored: Wed Nov 15 15:08:14 2017 +0100 Committer: Francesco Chicchiriccò <[email protected]> Committed: Wed Nov 15 15:08:19 2017 +0100 ---------------------------------------------------------------------- .../syncope/core/logic/SCIMDataBinder.java | 10 +- .../syncope/ext/scimv2/api/data/SCIMGroup.java | 5 +- .../ext/scimv2/api/data/SCIMSearchRequest.java | 96 ++++++++++++++++++++ .../ext/scimv2/api/service/SearchService.java | 17 +++- .../syncope/ext/scimv2/api/type/Resource.java | 1 + .../ext/scimv2/cxf/service/AbstractService.java | 41 ++++++--- .../scimv2/cxf/service/GroupServiceImpl.java | 22 ++++- .../ext/scimv2/cxf/service/UserServiceImpl.java | 24 ++++- .../org/apache/syncope/fit/core/SCIMITCase.java | 20 ++++ 9 files changed, 208 insertions(+), 28 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/syncope/blob/fa2ed730/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/SCIMDataBinder.java ---------------------------------------------------------------------- diff --git a/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/SCIMDataBinder.java b/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/SCIMDataBinder.java index e3b3140..3dd3615 100644 --- a/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/SCIMDataBinder.java +++ b/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/SCIMDataBinder.java @@ -18,6 +18,7 @@ */ package org.apache.syncope.core.logic; +import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -101,9 +102,15 @@ public class SCIMDataBinder { public SCIMUser toSCIMUser(final UserTO userTO, final String location) { SCIMConf conf = confManager.get(); + List<String> schemas = new ArrayList<>(); + schemas.add(Resource.User.schema()); + if (conf.getEnterpriseUserConf() != null) { + schemas.add(Resource.EnterpriseUser.schema()); + } + SCIMUser user = new SCIMUser( userTO.getKey(), - Collections.singletonList(Resource.User.schema()), + schemas, new Meta( Resource.User, userTO.getCreationDate(), @@ -356,7 +363,6 @@ public class SCIMDataBinder { public SCIMGroup toSCIMGroup(final GroupTO groupTO, final String location) { SCIMGroup group = new SCIMGroup( groupTO.getKey(), - Collections.singletonList(Resource.Group.schema()), new Meta( Resource.Group, groupTO.getCreationDate(), http://git-wip-us.apache.org/repos/asf/syncope/blob/fa2ed730/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMGroup.java ---------------------------------------------------------------------- diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMGroup.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMGroup.java index 0657476..7bafd4b 100644 --- a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMGroup.java +++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMGroup.java @@ -22,7 +22,9 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import org.apache.syncope.ext.scimv2.api.type.Resource; @JsonPropertyOrder({ "schemas", "id", "externalId", "displayName", "members", "meta" }) public class SCIMGroup extends SCIMResource { @@ -36,11 +38,10 @@ public class SCIMGroup extends SCIMResource { @JsonCreator(mode = JsonCreator.Mode.PROPERTIES) public SCIMGroup( @JsonProperty("id") final String id, - @JsonProperty("schemas") final List<String> schemas, @JsonProperty("meta") final Meta meta, @JsonProperty("displayName") final String displayName) { - super(id, schemas, meta); + super(id, Collections.singletonList(Resource.Group.schema()), meta); this.displayName = displayName; } http://git-wip-us.apache.org/repos/asf/syncope/blob/fa2ed730/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMSearchRequest.java ---------------------------------------------------------------------- diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMSearchRequest.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMSearchRequest.java new file mode 100644 index 0000000..570ee3a --- /dev/null +++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMSearchRequest.java @@ -0,0 +1,96 @@ +/* + * 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.ext.scimv2.api.data; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.apache.syncope.ext.scimv2.api.type.Resource; +import org.apache.syncope.ext.scimv2.api.type.SortOrder; + +public class SCIMSearchRequest extends SCIMBean { + + private static final long serialVersionUID = 5759362928661983543L; + + private final List<String> schemas = Arrays.asList(Resource.SearchRequest.schema()); + + private final List<String> attributes = new ArrayList<>(); + + private final List<String> excludedAttributes = new ArrayList<>(); + + private final String filter; + + private final String sortBy; + + private final SortOrder sortOrder; + + private final Integer startIndex; + + private final Integer count; + + @JsonCreator(mode = JsonCreator.Mode.PROPERTIES) + public SCIMSearchRequest( + @JsonProperty("filter") final String filter, + @JsonProperty("sortBy") final String sortBy, + @JsonProperty("sortOrder") final SortOrder sortOrder, + @JsonProperty("startIndex") final Integer startIndex, + @JsonProperty("count") final Integer count) { + + this.filter = filter; + this.sortBy = sortBy; + this.sortOrder = sortOrder; + this.startIndex = startIndex; + this.count = count; + } + + public List<String> getSchemas() { + return schemas; + } + + public List<String> getAttributes() { + return attributes; + } + + public List<String> getExcludedAttributes() { + return excludedAttributes; + } + + public String getFilter() { + return filter; + } + + public String getSortBy() { + return sortBy; + } + + public SortOrder getSortOrder() { + return sortOrder; + } + + public Integer getStartIndex() { + return startIndex; + } + + public Integer getCount() { + return count; + } + +} http://git-wip-us.apache.org/repos/asf/syncope/blob/fa2ed730/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/SearchService.java ---------------------------------------------------------------------- diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/SearchService.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/SearchService.java index fcd4789..d6cbaf5 100644 --- a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/SearchService.java +++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/SearchService.java @@ -19,12 +19,16 @@ package org.apache.syncope.ext.scimv2.api.service; import java.util.List; +import javax.ws.rs.Consumes; import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import org.apache.syncope.ext.scimv2.api.SCIMConstants; import org.apache.syncope.ext.scimv2.api.data.ListResponse; import org.apache.syncope.ext.scimv2.api.data.SCIMResource; +import org.apache.syncope.ext.scimv2.api.data.SCIMSearchRequest; import org.apache.syncope.ext.scimv2.api.type.SortOrder; public interface SearchService<R extends SCIMResource> { @@ -32,10 +36,17 @@ public interface SearchService<R extends SCIMResource> { @GET @Produces({ SCIMConstants.APPLICATION_SCIM_JSON }) ListResponse<R> search( - @QueryParam("startIndex") Integer startIndex, - @QueryParam("count") Integer count, + @QueryParam("attributes") List<String> attributes, + @QueryParam("excludedAttributes") List<String> excludedAttributes, @QueryParam("filter") String filter, @QueryParam("sortBy") String sortBy, @QueryParam("sortOrder") SortOrder sortOrder, - @QueryParam("attributes") List<String> attributes); + @QueryParam("startIndex") Integer startIndex, + @QueryParam("count") Integer count); + + @POST + @Path(".search") + @Produces({ SCIMConstants.APPLICATION_SCIM_JSON }) + @Consumes({ SCIMConstants.APPLICATION_SCIM_JSON }) + ListResponse<R> search(SCIMSearchRequest request); } http://git-wip-us.apache.org/repos/asf/syncope/blob/fa2ed730/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/type/Resource.java ---------------------------------------------------------------------- diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/type/Resource.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/type/Resource.java index 8fb2bde..7800b68 100644 --- a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/type/Resource.java +++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/type/Resource.java @@ -26,6 +26,7 @@ public enum Resource { User("urn:ietf:params:scim:schemas:core:2.0:User"), EnterpriseUser("urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"), Group("urn:ietf:params:scim:schemas:core:2.0:Group"), + SearchRequest("urn:ietf:params:scim:api:messages:2.0:SearchRequest"), ListResponse("urn:ietf:params:scim:api:messages:2.0:ListResponse"), Error("urn:ietf:params:scim:api:messages:2.0:Error"); http://git-wip-us.apache.org/repos/asf/syncope/blob/fa2ed730/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/AbstractService.java ---------------------------------------------------------------------- diff --git a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/AbstractService.java b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/AbstractService.java index 5eeca49..4274041 100644 --- a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/AbstractService.java +++ b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/AbstractService.java @@ -39,6 +39,7 @@ import org.apache.syncope.core.persistence.api.dao.search.OrderByClause; import org.apache.syncope.core.spring.ApplicationContextProvider; import org.apache.syncope.ext.scimv2.api.data.ListResponse; import org.apache.syncope.ext.scimv2.api.data.SCIMResource; +import org.apache.syncope.ext.scimv2.api.data.SCIMSearchRequest; import org.apache.syncope.ext.scimv2.api.type.Resource; import org.apache.syncope.ext.scimv2.api.type.SortOrder; import org.slf4j.Logger; @@ -104,27 +105,26 @@ abstract class AbstractService<R extends SCIMResource> implements SearchService< @SuppressWarnings("unchecked") protected ListResponse<R> doSearch( final Resource type, - final Integer startIndex, - final Integer count, - final String filter, - final String sortBy, - final SortOrder sortOrder, - final List<String> attributes) { + final SCIMSearchRequest request) { if (type == null) { throw new UnsupportedOperationException(); } + int startIndex = request.getStartIndex() == null || request.getStartIndex() <= 1 + ? 1 + : (request.getStartIndex() / AnyDAO.DEFAULT_PAGE_SIZE) + 1; + Pair<Integer, ? extends List<? extends AnyTO>> result = anyLogic(type).search( - StringUtils.isBlank(filter) ? null : SearchCondConverter.convert(filter), - startIndex == null || startIndex <= 1 ? 1 : (startIndex / AnyDAO.DEFAULT_PAGE_SIZE) + 1, + StringUtils.isBlank(request.getFilter()) ? null : SearchCondConverter.convert(request.getFilter()), + startIndex, AnyDAO.DEFAULT_PAGE_SIZE, Collections.<OrderByClause>emptyList(), SyncopeConstants.ROOT_REALM, false); ListResponse<R> response = new ListResponse<>( - result.getLeft(), startIndex == null || startIndex <= 1 ? 1 : startIndex, AnyDAO.DEFAULT_PAGE_SIZE); + result.getLeft(), startIndex == 1 ? 1 : startIndex - 1, AnyDAO.DEFAULT_PAGE_SIZE); for (AnyTO anyTO : result.getRight()) { SCIMResource resource = null; @@ -148,13 +148,28 @@ abstract class AbstractService<R extends SCIMResource> implements SearchService< @Override public ListResponse<R> search( - final Integer startIndex, - final Integer count, + final List<String> attributes, + final List<String> excludedAttributes, final String filter, final String sortBy, final SortOrder sortOrder, - final List<String> attributes) { + final Integer startIndex, + final Integer count) { - return doSearch(null, startIndex, count, filter, sortBy, sortOrder, attributes); + SCIMSearchRequest request = new SCIMSearchRequest(filter, sortBy, sortOrder, startIndex, count); + if (attributes != null) { + request.getAttributes().addAll(attributes); + } + if (excludedAttributes != null) { + request.getExcludedAttributes().addAll(excludedAttributes); + } + + return doSearch(null, request); } + + @Override + public ListResponse<R> search(final SCIMSearchRequest request) { + return doSearch(null, request); + } + } http://git-wip-us.apache.org/repos/asf/syncope/blob/fa2ed730/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/GroupServiceImpl.java ---------------------------------------------------------------------- diff --git a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/GroupServiceImpl.java b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/GroupServiceImpl.java index d03b57c..fdc47aa 100644 --- a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/GroupServiceImpl.java +++ b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/GroupServiceImpl.java @@ -23,6 +23,7 @@ import java.util.UUID; import javax.ws.rs.core.Response; import org.apache.syncope.ext.scimv2.api.data.ListResponse; import org.apache.syncope.ext.scimv2.api.data.SCIMGroup; +import org.apache.syncope.ext.scimv2.api.data.SCIMSearchRequest; import org.apache.syncope.ext.scimv2.api.service.GroupService; import org.apache.syncope.ext.scimv2.api.type.Resource; import org.apache.syncope.ext.scimv2.api.type.SortOrder; @@ -58,14 +59,27 @@ public class GroupServiceImpl extends AbstractService<SCIMGroup> implements Grou @Override public ListResponse<SCIMGroup> search( - final Integer startIndex, - final Integer count, + final List<String> attributes, + final List<String> excludedAttributes, final String filter, final String sortBy, final SortOrder sortOrder, - final List<String> attributes) { + final Integer startIndex, + final Integer count) { + + SCIMSearchRequest request = new SCIMSearchRequest(filter, sortBy, sortOrder, startIndex, count); + if (attributes != null) { + request.getAttributes().addAll(attributes); + } + if (excludedAttributes != null) { + request.getExcludedAttributes().addAll(excludedAttributes); + } - return doSearch(Resource.Group, startIndex, count, filter, sortBy, sortOrder, attributes); + return doSearch(Resource.Group, request); } + @Override + public ListResponse<SCIMGroup> search(final SCIMSearchRequest request) { + return doSearch(Resource.Group, request); + } } http://git-wip-us.apache.org/repos/asf/syncope/blob/fa2ed730/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/UserServiceImpl.java ---------------------------------------------------------------------- diff --git a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/UserServiceImpl.java b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/UserServiceImpl.java index 67b9b47..0f98362 100644 --- a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/UserServiceImpl.java +++ b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/service/UserServiceImpl.java @@ -22,6 +22,7 @@ import java.util.List; import java.util.UUID; import javax.ws.rs.core.Response; import org.apache.syncope.ext.scimv2.api.data.ListResponse; +import org.apache.syncope.ext.scimv2.api.data.SCIMSearchRequest; import org.apache.syncope.ext.scimv2.api.data.SCIMUser; import org.apache.syncope.ext.scimv2.api.service.UserService; import org.apache.syncope.ext.scimv2.api.type.Resource; @@ -58,13 +59,28 @@ public class UserServiceImpl extends AbstractService<SCIMUser> implements UserSe @Override public ListResponse<SCIMUser> search( - final Integer startIndex, - final Integer count, + final List<String> attributes, + final List<String> excludedAttributes, final String filter, final String sortBy, final SortOrder sortOrder, - final List<String> attributes) { + final Integer startIndex, + final Integer count) { - return doSearch(Resource.User, startIndex, count, filter, sortBy, sortOrder, attributes); + SCIMSearchRequest request = new SCIMSearchRequest(filter, sortBy, sortOrder, startIndex, count); + if (attributes != null) { + request.getAttributes().addAll(attributes); + } + if (excludedAttributes != null) { + request.getExcludedAttributes().addAll(excludedAttributes); + } + + return doSearch(Resource.User, request); } + + @Override + public ListResponse<SCIMUser> search(final SCIMSearchRequest request) { + return doSearch(Resource.User, request); + } + } http://git-wip-us.apache.org/repos/asf/syncope/blob/fa2ed730/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SCIMITCase.java ---------------------------------------------------------------------- diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SCIMITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SCIMITCase.java index cabe7f8..ca15f05 100644 --- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SCIMITCase.java +++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SCIMITCase.java @@ -71,6 +71,7 @@ public class SCIMITCase extends AbstractITCase { private WebClient webClient() { return WebClient.create(SCIM_ADDRESS, Arrays.asList(new JacksonSCIMJsonProvider())). accept(SCIMConstants.APPLICATION_SCIM_JSON_TYPE). + type(SCIMConstants.APPLICATION_SCIM_JSON_TYPE). header(HttpHeaders.AUTHORIZATION, "Bearer " + adminClient.getJWT()); } @@ -225,6 +226,25 @@ public class SCIMITCase extends AbstractITCase { SCIMGroup additional = groups.getResources().get(0); assertEquals("additional", additional.getDisplayName()); + // eq via POST + String request = "{" + + " \"schemas\": [\"urn:ietf:params:scim:api:messages:2.0:SearchRequest\"]," + + " \"filter\": \"displayName eq \\\"additional\\\"\"" + + " }"; + response = webClient().path("Groups").path("/.search").post(request); + assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); + assertEquals( + SCIMConstants.APPLICATION_SCIM_JSON, + StringUtils.substringBefore(response.getHeaderString(HttpHeaders.CONTENT_TYPE), ";")); + + groups = response.readEntity(new GenericType<ListResponse<SCIMGroup>>() { + }); + assertNotNull(groups); + assertEquals(1, groups.getTotalResults()); + + additional = groups.getResources().get(0); + assertEquals("additional", additional.getDisplayName()); + // gt UserTO newUser = userService.create(UserITCase.getUniqueSampleTO("[email protected]")).readEntity( new GenericType<ProvisioningResult<UserTO>>() {
