001/*
002 * (C) Copyright 2015 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Nuxeo - initial API and implementation
018 *
019 */
020
021package org.nuxeo.scim.server.jaxrs.usermanager;
022
023import java.io.Serializable;
024import java.util.ArrayList;
025import java.util.HashMap;
026import java.util.List;
027import java.util.Map;
028
029import javax.servlet.http.HttpServletResponse;
030import javax.ws.rs.Consumes;
031import javax.ws.rs.DELETE;
032import javax.ws.rs.GET;
033import javax.ws.rs.POST;
034import javax.ws.rs.PUT;
035import javax.ws.rs.Path;
036import javax.ws.rs.PathParam;
037import javax.ws.rs.Produces;
038import javax.ws.rs.core.Context;
039import javax.ws.rs.core.MediaType;
040import javax.ws.rs.core.Response;
041import javax.ws.rs.core.Response.Status;
042import javax.ws.rs.core.UriInfo;
043
044import org.nuxeo.ecm.core.api.DocumentModel;
045import org.nuxeo.ecm.core.api.DocumentModelList;
046import org.nuxeo.ecm.directory.DirectoryException;
047import org.nuxeo.ecm.directory.Session;
048import org.nuxeo.ecm.directory.api.DirectoryService;
049import org.nuxeo.ecm.webengine.model.WebObject;
050import org.nuxeo.runtime.api.Framework;
051import org.nuxeo.scim.server.jaxrs.marshalling.GroupResponse;
052
053import com.unboundid.scim.data.GroupResource;
054import com.unboundid.scim.sdk.Resources;
055
056/**
057 * Simple Resource class used to expose the SCIM API on Users endpoint
058 *
059 * @author tiry
060 * @since 7.4
061 */
062
063@WebObject(type = "groups")
064@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
065public class SCIMGroupWebObject extends BaseUMObject {
066
067    @Override
068    protected String getPrefix() {
069        return "/Groups";
070    }
071
072    protected GroupResource resolveGroupRessource(String uid) {
073
074        try {
075            DocumentModel groupModel = um.getGroupModel(uid);
076            if (groupModel != null) {
077                return mapper.getGroupResourceFromNuxeoGroup(groupModel);
078            }
079        } catch (Exception e) {
080            log.error("Error while resolving User", e);
081        }
082        return null;
083    }
084
085    @GET
086    @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML + "; qs=0.9" })
087    public Resources<GroupResource> getGroups(@Context UriInfo uriInfo) {
088
089        Map<String, List<String>> params = uriInfo.getQueryParameters();
090
091        // filter
092        Map<String, Serializable> filter = new HashMap<>();
093        List<String> filters = params.get("filter");
094        if (filters != null && filters.size() > 0) {
095            String[] filterParts = filters.get(0).split(" ");
096            if (filterParts[1].equals("eq")) {
097                String key = filterParts[0];
098                if (key.equals("userName")) {
099                    key = "username";
100                }
101                String value = filterParts[2];
102                if (value.startsWith("\"")) {
103                    value = value.substring(1, value.length() - 2);
104                }
105                filter.put(key, value);
106            }
107        }
108
109        // sort
110        List<String> sortCol = params.get("sortBy");
111        List<String> sortType = params.get("sortOrder");
112        // XXX mapping
113        Map<String, String> orderBy = new HashMap<>();
114        if (sortCol != null && sortCol.size() > 0) {
115            String order = "asc";
116            if (sortType != null && sortType.size() > 0) {
117                if (sortType.get(0).equalsIgnoreCase("descending")) {
118                    order = "desc";
119                }
120                orderBy.put(sortCol.get(0), order);
121            }
122        }
123        int startIndex = 1;
124        if (params.get("startIndex") != null) {
125            startIndex = Integer.parseInt(params.get("startIndex").get(0));
126        }
127        int count = 10;
128        if (params.get("count") != null) {
129            count = Integer.parseInt(params.get("count").get(0));
130        }
131
132        try {
133            String directoryName = um.getGroupDirectoryName();
134
135            DirectoryService ds = Framework.getService(DirectoryService.class);
136
137            Session dSession = null;
138            DocumentModelList groupModels = null;
139            try {
140                dSession = ds.open(directoryName);
141                groupModels = dSession.query(filter, null, orderBy, true, count, startIndex - 1);
142            } finally {
143                dSession.close();
144            }
145
146            List<GroupResource> groupResources = new ArrayList<>();
147            for (DocumentModel groupModel : groupModels) {
148                groupResources.add(mapper.getGroupResourceFromNuxeoGroup(groupModel));
149            }
150            return new Resources<>(groupResources, groupResources.size(), startIndex);
151        } catch (Exception e) {
152            log.error("Error while getting Groups", e);
153        }
154        return null;
155    }
156
157    @Path("{uid}")
158    @GET
159    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
160    public GroupResource getGroupResource(@Context UriInfo uriInfo, @PathParam("uid") String uid) {
161        return resolveGroupRessource(uid);
162
163    }
164
165    @Path("{uid}.xml")
166    @GET
167    @Produces(MediaType.APPLICATION_XML)
168    public GroupResource getGroupResourceAsXml(@Context UriInfo uriInfo, @PathParam("uid") String uid) {
169        return getGroupResource(uriInfo, uid);
170    }
171
172    @Path("{uid}.json")
173    @GET
174    @Produces(MediaType.APPLICATION_JSON)
175    public GroupResource getUserResourceAsJSON(@Context UriInfo uriInfo, @PathParam("uid") String uid) {
176        return getGroupResource(uriInfo, uid);
177    }
178
179    @POST
180    @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
181    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
182    public Response createGroup(@Context UriInfo uriInfo, GroupResource group,
183            @Context final HttpServletResponse response) {
184        checkUpdateGuardPreconditions();
185        return doCreateGroup(group, fixeMediaType);
186    }
187
188    @PUT
189    @Path("{uid}")
190    @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
191    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
192    public Response updateGroup(@Context UriInfo uriInfo, @PathParam("uid") String uid, GroupResource user) {
193        checkUpdateGuardPreconditions();
194        return doUpdateGroup(uid, user, fixeMediaType);
195    }
196
197    protected Response doUpdateGroup(String uid, GroupResource group, MediaType mt) {
198
199        try {
200            DocumentModel groupModel = mapper.updateGroupModelFromGroupResource(uid, group);
201            if (groupModel != null) {
202                GroupResource groupResource = mapper.getGroupResourceFromNuxeoGroup(groupModel);
203                return GroupResponse.updated(groupResource, mt);
204            }
205        } catch (Exception e) {
206            log.error("Unable to update Group", e);
207        }
208        return null;
209    }
210
211    protected Response doCreateGroup(GroupResource group, MediaType mt) {
212
213        try {
214            DocumentModel newGroup = mapper.createGroupModelFromGroupResource(group);
215            GroupResource groupResource = mapper.getGroupResourceFromNuxeoGroup(newGroup);
216            return GroupResponse.created(groupResource, mt);
217        } catch (Exception e) {
218            log.error("Unable to create Group", e);
219        }
220        return null;
221    }
222
223    @Path("{uid}")
224    @DELETE
225    public Response deleteGroupResource(@Context UriInfo uriInfo, @PathParam("uid") String uid) {
226        try {
227            um.deleteGroup(uid);
228            return Response.ok().build();
229        } catch (DirectoryException e) {
230            return Response.status(Status.NOT_FOUND).build();
231        }
232    }
233
234}