/* * (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.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.UserResponse; import com.unboundid.scim.data.UserResource; 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 = "users") @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) public class SCIMUserWebObject extends BaseUMObject { @Override protected String getPrefix() { return "/Users"; } protected UserResource resolveUserRessource(String uid) { try { DocumentModel userModel = um.getUserModel(uid); if (userModel != null) { return mapper.getUserResourceFromNuxeoUser(userModel); } } 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<UserResource> getUsers(@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.getUserDirectoryName(); DirectoryService ds = Framework.getLocalService(DirectoryService.class); Session dSession = null; DocumentModelList userModels = null; try { dSession = ds.open(directoryName); userModels = dSession.query(filter, null, orderBy, true, count, startIndex - 1); } finally { dSession.close(); } List<UserResource> userResources = new ArrayList<>(); for (DocumentModel userModel : userModels) { userResources.add(mapper.getUserResourceFromNuxeoUser(userModel)); } return new Resources<>(userResources, userResources.size(), startIndex); } catch (Exception e) { log.error("Error while getting Users", e); } return null; } @Path("{uid}") @GET @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) public UserResource getUserResource(@Context UriInfo uriInfo, @PathParam("uid") String uid) { return resolveUserRessource(uid); } @Path("{uid}.xml") @GET @Produces(MediaType.APPLICATION_XML) public UserResource getUserResourceAsXml(@Context UriInfo uriInfo, @PathParam("uid") String uid) { return getUserResource(uriInfo, uid); } @Path("{uid}.json") @GET @Produces(MediaType.APPLICATION_JSON) public UserResource getUserResourceAsJSON(@Context UriInfo uriInfo, @PathParam("uid") String uid) { return getUserResource(uriInfo, uid); } @POST @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) public Response createUser(UserResource user) { return doCreateUserResponse(user, fixeMediaType); } protected Response doCreateUserResponse(UserResource user, MediaType mt) { try { checkUpdateGuardPreconditions(); return UserResponse.created(doCreateUser(user), mt); } catch (ClientException e) { throw WebException.wrap(e); } } protected UserResource doCreateUser(UserResource user) { try { DocumentModel newUser = mapper.createNuxeoUserFromUserResource(user); UserResource resource = mapper.getUserResourceFromNuxeoUser(newUser); return resource; } catch (Exception e) { log.error("Unable to create User", e); } return null; } @PUT @Path("{uid}") @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) public Response updateUser(@Context UriInfo uriInfo, @PathParam("uid") String uid, UserResource user) { try { checkUpdateGuardPreconditions(); return doUpdateUser(uid, user, fixeMediaType); } catch (ClientException e) { throw WebException.wrap(e); } } protected Response doUpdateUser(String uid, UserResource user, MediaType mt) { try { DocumentModel userModel = mapper.updateNuxeoUserFromUserResource(uid, user); if (userModel != null) { UserResource userResource = mapper.getUserResourceFromNuxeoUser(userModel); return UserResponse.updated(userResource, mt); } } catch (Exception e) { log.error("Unable to create User", e); } return null; } @Path("{uid}") @DELETE public Response deleteUserResource(@Context UriInfo uriInfo, @PathParam("uid") String uid) { try { um.deleteUser(uid); return Response.ok().build(); } catch (DirectoryException e) { return Response.status(Status.NOT_FOUND).build(); } } }