/* * (C) Copyright 2015 Nuxeo SA (http://nuxeo.com/) and others. * * Licensed 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. * * Contributors: * Nuxeo - initial API and implementation * */ package org.nuxeo.scim.server.jaxrs.usermanager; import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletResponse; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; import javax.ws.rs.core.UriInfo; import org.nuxeo.ecm.core.api.ClientException; import org.nuxeo.ecm.core.api.DocumentModel; import org.nuxeo.ecm.core.api.DocumentModelList; import org.nuxeo.ecm.directory.DirectoryException; import org.nuxeo.ecm.directory.Session; import org.nuxeo.ecm.directory.api.DirectoryService; import org.nuxeo.ecm.webengine.WebException; import org.nuxeo.ecm.webengine.model.WebObject; import org.nuxeo.runtime.api.Framework; import org.nuxeo.scim.server.jaxrs.marshalling.GroupResponse; import com.unboundid.scim.data.GroupResource; import com.unboundid.scim.sdk.Resources; /** * Simple Resource class used to expose the SCIM API on Users endpoint * * @author tiry * @since 7.4 */ @WebObject(type = "groups") @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) public class SCIMGroupWebObject extends BaseUMObject { @Override protected String getPrefix() { return "/Groups"; } protected GroupResource resolveGroupRessource(String uid) { try { DocumentModel groupModel = um.getGroupModel(uid); if (groupModel != null) { return mapper.getGroupResourceFromNuxeoGroup(groupModel); } } catch (Exception e) { log.error("Error while resolving User", e); } return null; } @GET @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML + "; qs=0.9" }) public Resources<GroupResource> getGroups(@Context UriInfo uriInfo) { Map<String, List<String>> params = uriInfo.getQueryParameters(); // filter Map<String, Serializable> filter = new HashMap<>(); List<String> filters = params.get("filter"); if (filters != null && filters.size() > 0) { String[] filterParts = filters.get(0).split(" "); if (filterParts[1].equals("eq")) { String key = filterParts[0]; if (key.equals("userName")) { key = "username"; } String value = filterParts[2]; if (value.startsWith("\"")) { value = value.substring(1, value.length() - 2); } filter.put(key, value); } } // sort List<String> sortCol = params.get("sortBy"); List<String> sortType = params.get("sortOrder"); // XXX mapping Map<String, String> orderBy = new HashMap<>(); if (sortCol != null && sortCol.size() > 0) { String order = "asc"; if (sortType != null && sortType.size() > 0) { if (sortType.get(0).equalsIgnoreCase("descending")) { order = "desc"; } orderBy.put(sortCol.get(0), order); } } int startIndex = 1; if (params.get("startIndex") != null) { startIndex = Integer.parseInt(params.get("startIndex").get(0)); } int count = 10; if (params.get("count") != null) { count = Integer.parseInt(params.get("count").get(0)); } try { String directoryName = um.getGroupDirectoryName(); DirectoryService ds = Framework.getLocalService(DirectoryService.class); Session dSession = null; DocumentModelList groupModels = null; try { dSession = ds.open(directoryName); groupModels = dSession.query(filter, null, orderBy, true, count, startIndex - 1); } finally { dSession.close(); } List<GroupResource> groupResources = new ArrayList<>(); for (DocumentModel groupModel : groupModels) { groupResources.add(mapper.getGroupResourceFromNuxeoGroup(groupModel)); } return new Resources<>(groupResources, groupResources.size(), startIndex); } catch (Exception e) { log.error("Error while getting Groups", e); } return null; } @Path("{uid}") @GET @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) public GroupResource getGroupResource(@Context UriInfo uriInfo, @PathParam("uid") String uid) { return resolveGroupRessource(uid); } @Path("{uid}.xml") @GET @Produces(MediaType.APPLICATION_XML) public GroupResource getGroupResourceAsXml(@Context UriInfo uriInfo, @PathParam("uid") String uid) { return getGroupResource(uriInfo, uid); } @Path("{uid}.json") @GET @Produces(MediaType.APPLICATION_JSON) public GroupResource getUserResourceAsJSON(@Context UriInfo uriInfo, @PathParam("uid") String uid) { return getGroupResource(uriInfo, uid); } @POST @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) public Response createGroup(@Context UriInfo uriInfo, GroupResource group, @Context final HttpServletResponse response) { try { checkUpdateGuardPreconditions(); return doCreateGroup(group, fixeMediaType); } catch (ClientException e) { throw WebException.wrap(e); } } @PUT @Path("{uid}") @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) public Response updateGroup(@Context UriInfo uriInfo, @PathParam("uid") String uid, GroupResource user) { try { checkUpdateGuardPreconditions(); return doUpdateGroup(uid, user, fixeMediaType); } catch (ClientException e) { throw WebException.wrap(e); } } protected Response doUpdateGroup(String uid, GroupResource group, MediaType mt) { try { DocumentModel groupModel = mapper.updateGroupModelFromGroupResource(uid, group); if (groupModel != null) { GroupResource groupResource = mapper.getGroupResourceFromNuxeoGroup(groupModel); return GroupResponse.updated(groupResource, mt); } } catch (Exception e) { log.error("Unable to update Group", e); } return null; } protected Response doCreateGroup(GroupResource group, MediaType mt) { try { DocumentModel newGroup = mapper.createGroupModelFromGroupResource(group); GroupResource groupResource = mapper.getGroupResourceFromNuxeoGroup(newGroup); return GroupResponse.created(groupResource, mt); } catch (Exception e) { log.error("Unable to create Group", e); } return null; } @Path("{uid}") @DELETE public Response deleteGroupResource(@Context UriInfo uriInfo, @PathParam("uid") String uid) { try { um.deleteGroup(uid); return Response.ok().build(); } catch (DirectoryException e) { return Response.status(Status.NOT_FOUND).build(); } } }