Fix bug: Delete user didn't work for group with international name.
[pithos] / src / gr / ebs / gss / server / rest / GroupsHandler.java
1 /*
2  * Copyright 2008, 2009 Electronic Business Systems Ltd.
3  *
4  * This file is part of GSS.
5  *
6  * GSS is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * GSS is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with GSS.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 package gr.ebs.gss.server.rest;
20
21 import gr.ebs.gss.client.exceptions.DuplicateNameException;
22 import gr.ebs.gss.client.exceptions.InsufficientPermissionsException;
23 import gr.ebs.gss.client.exceptions.ObjectNotFoundException;
24 import gr.ebs.gss.client.exceptions.RpcException;
25 import gr.ebs.gss.server.domain.User;
26 import gr.ebs.gss.server.domain.dto.GroupDTO;
27 import gr.ebs.gss.server.domain.dto.UserDTO;
28
29 import java.io.IOException;
30 import java.net.URLDecoder;
31 import java.net.URLEncoder;
32 import java.util.List;
33
34 import javax.servlet.http.HttpServletRequest;
35 import javax.servlet.http.HttpServletResponse;
36
37 import org.apache.commons.logging.Log;
38 import org.apache.commons.logging.LogFactory;
39 import org.json.JSONArray;
40 import org.json.JSONException;
41 import org.json.JSONObject;
42
43
44 /**
45  * A class that handles operations on the 'groups' namespace.
46  *
47  * @author past
48  */
49 public class GroupsHandler extends RequestHandler {
50         /**
51          * The logger.
52          */
53         private static Log logger = LogFactory.getLog(GroupsHandler.class);
54
55     /**
56      * Serve the groups namespace for the user.
57      *
58      * @param req The servlet request we are processing
59      * @param resp The servlet response we are processing
60      * @throws IOException if an input/output error occurs
61          */
62         void serveGroups(HttpServletRequest req, HttpServletResponse resp) throws IOException {
63         String parentUrl = getContextPath(req, true);
64         String path = getInnerPath(req, PATH_GROUPS);
65                 if (path.equals(""))
66                         path = "/";
67
68         User user = getUser(req);
69         User owner = getOwner(req);
70         if (!owner.equals(user)) {
71                 resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
72                 return;
73         }
74         if (path.equals("/"))
75                         // Request to serve all groups
76                 try {
77                 List<GroupDTO> groups = getService().getGroups(owner.getId());
78                 JSONArray json = new JSONArray();
79                 for (GroupDTO group: groups) {
80                         JSONObject j = new JSONObject();
81                         j.put("name", group.getName()).
82                                 put("uri", parentUrl + URLEncoder.encode(group.getName(),"UTF-8"));
83                                 json.put(j);
84                 }
85
86                 sendJson(req, resp, json.toString());
87                 } catch (ObjectNotFoundException e) {
88                         logger.error("User not found", e);
89                         resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
90                         return;
91                 } catch (RpcException e) {
92                         logger.error("", e);
93                         resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
94                         return;
95                 } catch (JSONException e) {
96                         logger.error("", e);
97                         resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
98                         return;
99                         }
100                 else {
101                 // Chop any trailing slash
102                 path = path.endsWith("/")? path.substring(0, path.length()-1): path;
103                 // Chop any leading slash
104                 path = path.startsWith("/")? path.substring(1): path;
105                 int slash = path.indexOf('/');
106                         try {
107                         if (slash != -1) {
108                                 // Request to serve group member
109                                 if (logger.isDebugEnabled())
110                                         logger.debug("Serving member " + path.substring(slash + 1) +
111                                                                 " from group " + path.substring(0, slash));
112                                 GroupDTO group = getService().getGroup(owner.getId(), URLDecoder.decode(path.substring(0, slash),"UTF-8"));
113                                 for (UserDTO u: group.getMembers())
114                                         if (u.getUsername().equals(path.substring(slash + 1))) {
115                                                 // Build the proper parent URL
116                                                 String pathInfo = req.getPathInfo();
117                                                 parentUrl = parentUrl.replaceFirst(pathInfo, "");
118                                         JSONObject json = new JSONObject();
119                                         json.put("username", u.getUsername()).put("name", u.getName()).
120                                                         put("home", parentUrl + u.getUsername());
121
122                                         sendJson(req, resp, json.toString());
123                                         }
124                         } else {
125                                 // Request to serve group
126                                 if (logger.isDebugEnabled())
127                                         logger.debug("Serving group " + path);
128                                 GroupDTO group = getService().getGroup(owner.getId(), URLDecoder.decode(path,"UTF-8"));
129                                 JSONArray json = new JSONArray();
130                                 for (UserDTO u: group.getMembers())
131                                         json.put(parentUrl + u.getUsername());
132
133                                 sendJson(req, resp, json.toString());
134                         }
135                         } catch (ObjectNotFoundException e) {
136                         logger.error("", e);
137                         resp.sendError(HttpServletResponse.SC_NOT_FOUND, e.getMessage());
138                         return;
139                         } catch (RpcException e) {
140                         logger.error("", e);
141                         resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
142                         return;
143                         } catch (JSONException e) {
144                                 logger.error("", e);
145                                 resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
146                                 return;
147                         }
148         }
149         // Workaround for IE's broken caching behavior.
150                 resp.setHeader("Expires", "-1");
151         }
152
153         /**
154          * Handle POST requests in the groups namespace.
155          *
156      * @param req The servlet request we are processing
157      * @param resp The servlet response we are processing
158      * @throws IOException if an input/output error occurs
159          */
160         void postGroup(HttpServletRequest req, HttpServletResponse resp) throws IOException {
161         // Identify the requested resource path
162         String path = getInnerPath(req, PATH_GROUPS);
163                 if (path.equals(""))
164                         path = "/";
165
166                 try {
167                 User user = getUser(req);
168                 User owner = getOwner(req);
169                 if (!owner.equals(user))
170                         throw new InsufficientPermissionsException("User " + user.getUsername()
171                                                 + " does not have permission to modify the groups owned by "
172                                                 + owner.getUsername());
173                 if (path.equals("/")) {
174                         // Request to add group
175                         String group = req.getParameter(GROUP_PARAMETER);
176                         if (logger.isDebugEnabled())
177                                 logger.debug("Adding group " + group);
178                                         getService().createGroup(owner.getId(), group);
179                                 resp.setStatus(HttpServletResponse.SC_CREATED);
180                 } else {
181                         // Request to add group member
182                         String username = req.getParameter(USERNAME_PARAMETER);
183                         // Chop any trailing slash
184                         path = path.endsWith("/")? path.substring(0, path.length()-1): path;
185                         // Chop any leading slash
186                         path = path.startsWith("/")? path.substring(1): path;
187                         if (logger.isDebugEnabled())
188                                 logger.debug("Adding member " + username +
189                                                         " to group " + path);
190                         GroupDTO group = getService().getGroup(owner.getId(), URLDecoder.decode(path,"UTF-8"));
191                         User member = getService().findUser(username);
192                         if (member == null) {
193                                 resp.sendError(HttpServletResponse.SC_NOT_FOUND, "User " + username + " not found");
194                                 return;
195                         }
196                         getService().addUserToGroup(owner.getId(), group.getId(), member.getId());
197                         resp.setStatus(HttpServletResponse.SC_CREATED);
198                 }
199                 // Workaround for IE's broken caching behavior.
200                         resp.setHeader("Expires", "-1");
201                 } catch (ObjectNotFoundException e) {
202                         resp.sendError(HttpServletResponse.SC_NOT_FOUND, e.getMessage());
203                 } catch (DuplicateNameException e) {
204                         resp.sendError(HttpServletResponse.SC_CONFLICT, e.getMessage());
205                 } catch (RpcException e) {
206                         logger.error("", e);
207                         resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
208                 } catch (InsufficientPermissionsException e) {
209                         resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, e.getMessage());
210                 }
211         }
212
213         /**
214          * Handle DELETE requests in the groups namespace.
215          *
216      * @param req The servlet request we are processing
217      * @param resp The servlet response we are processing
218      * @throws IOException if an input/output error occurs
219          */
220         void deleteGroup(HttpServletRequest req, HttpServletResponse resp) throws IOException {
221         String path = getInnerPath(req, PATH_GROUPS);
222                 if (path.equals(""))
223                         path = "/";
224
225         if (path.equals("/"))
226                         resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, METHOD_GET + ", " + METHOD_POST);
227                 else {
228                 // Chop any trailing slash
229                 path = path.endsWith("/")? path.substring(0, path.length()-1): path;
230                 // Chop any leading slash
231                 path = path.startsWith("/")? path.substring(1): path;
232                 int slash = path.indexOf('/');
233                 try {
234                 User user = getUser(req);
235                 User owner = getOwner(req);
236                 if (!owner.equals(user))
237                         throw new InsufficientPermissionsException("User " + user.getUsername()
238                                                 + " does not have permission to modify the groups owned by "
239                                                 + owner.getUsername());
240                 if (slash != -1) {
241                         // Request to delete group member
242                         if (logger.isDebugEnabled())
243                                 logger.debug("Removing member " + path.substring(slash + 1) +
244                                                         " from group " + path.substring(0, slash));
245                         GroupDTO group = getService().getGroup(owner.getId(), URLDecoder.decode(path.substring(0, slash),"UTF-8"));
246                         for (UserDTO u: group.getMembers())
247                                 if (u.getUsername().equals(path.substring(slash + 1)))
248                                         getService().removeMemberFromGroup(owner.getId(), group.getId(), u.getId());
249                 } else {
250                         if (logger.isDebugEnabled())
251                                 logger.debug("Removing group " + path);
252                                 GroupDTO group = getService().getGroup(owner.getId(), URLDecoder.decode(path,"UTF-8"));
253                                 getService().deleteGroup(owner.getId(), group.getId());
254                 }
255                         resp.setStatus(HttpServletResponse.SC_NO_CONTENT);
256                         // Workaround for IE's broken caching behavior.
257                         resp.setHeader("Expires", "-1");
258                 } catch (RpcException e) {
259                         logger.error("", e);
260                         resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
261                 } catch (ObjectNotFoundException e) {
262                         resp.sendError(HttpServletResponse.SC_NOT_FOUND, e.getMessage());
263                         } catch (InsufficientPermissionsException e) {
264                                 resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, e.getMessage());
265                         }
266         }
267         }
268
269 }