28521ab02e7b2ba58eab206805a420b92f71bd08
[mir.git] / source / mircoders / servlet / ServletModuleUsers.java
1 /*
2  * Copyright (C) 2001, 2002 The Mir-coders group
3  *
4  * This file is part of Mir.
5  *
6  * Mir 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 2 of the License, or
9  * (at your option) any later version.
10  *
11  * Mir 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 Mir; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  * In addition, as a special exception, The Mir-coders gives permission to link
21  * the code of this program with  any library licensed under the Apache Software License,
22  * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library
23  * (or with modified versions of the above that use the same license as the above),
24  * and distribute linked combinations including the two.  You must obey the
25  * GNU General Public License in all respects for all of the code used other than
26  * the above mentioned libraries.  If you modify this file, you may extend this
27  * exception to your version of the file, but you are not obligated to do so.
28  * If you do not wish to do so, delete this exception statement from your version.
29  */
30
31 package mircoders.servlet;
32
33 import java.util.HashMap;
34 import java.util.Iterator;
35 import java.util.List;
36 import java.util.Locale;
37 import java.util.Map;
38
39 import javax.servlet.http.HttpServletRequest;
40 import javax.servlet.http.HttpServletResponse;
41
42 import mir.entity.adapter.EntityAdapterModel;
43 import mir.entity.adapter.EntityIteratorAdapter;
44 import mir.log.LoggerWrapper;
45 import mir.servlet.ServletModule;
46 import mir.servlet.ServletModuleExc;
47 import mir.servlet.ServletModuleFailure;
48 import mir.servlet.ServletModuleUserExc;
49 import mir.util.CachingRewindableIterator;
50 import mir.util.HTTPRequestParser;
51 import mir.util.URLBuilder;
52 import mircoders.entity.EntityUsers;
53 import mircoders.global.MirGlobal;
54 import mircoders.module.ModuleUsers;
55 import mircoders.storage.DatabaseUsers;
56
57 /**
58  *
59  *
60  */
61 public class ServletModuleUsers extends ServletModule
62 {
63   private static ServletModuleUsers instance = new ServletModuleUsers();
64   public static ServletModule getInstance() { return instance; }
65   protected ModuleUsers usersModule;
66
67   private ServletModuleUsers() {
68     super();
69     logger = new LoggerWrapper("ServletModule.Users");
70
71     try {
72       model = MirGlobal.localizer().dataModel().adapterModel();
73       definition = "user";
74       usersModule = new ModuleUsers(DatabaseUsers.getInstance());
75       mainModule = usersModule;
76     }
77     catch (Throwable e) {
78       logger.debug("initialization of ServletModuleUsers failed!: " + e.getMessage());
79     }
80   }
81
82   public void edit(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc
83   {
84     String idParam = aRequest.getParameter("id");
85
86     if (idParam == null)
87       throw new ServletModuleExc("ServletModuleUser.edit: invalid call: (id) not specified");
88
89     try {
90       EntityUsers user = (EntityUsers) mainModule.getById(idParam);
91       MirGlobal.accessControl().user().assertMayEditUser(ServletHelper.getUser(aRequest), user);
92
93       showUser(idParam, false, aRequest, aResponse);
94     }
95     catch (Throwable e) {
96       throw new ServletModuleFailure(e);
97     }
98   }
99
100   public void add(HttpServletRequest aRequest, HttpServletResponse aResponse)
101       throws ServletModuleExc
102   {
103     try {
104       MirGlobal.accessControl().user().assertMayAddUsers(ServletHelper.getUser(aRequest));
105
106       showUser(null, false, aRequest, aResponse);
107     }
108     catch (Throwable e) {
109       throw new ServletModuleFailure(e);
110     }
111   }
112
113   public String validatePassword(EntityUsers aUser, HTTPRequestParser aRequestParser) throws ServletModuleExc, ServletModuleUserExc, ServletModuleFailure
114   {
115     if ( (aRequestParser.getParameter("newpassword") != null &&
116           aRequestParser.getParameter("newpassword").length() > 0) ||
117          (aRequestParser.getParameter("newpassword2") != null &&
118           aRequestParser.getParameter("newpassword2").length() > 0)
119         ) {
120       String newPassword = aRequestParser.getParameterWithDefault("newpassword", "");
121       String newPassword2 = aRequestParser.getParameterWithDefault("newpassword2", "");
122       String oldPassword = aRequestParser.getParameterWithDefault("oldpassword", "");
123
124       try {
125         if (!usersModule.checkUserPassword(aUser, oldPassword)) {
126           throw new ServletModuleUserExc("user.error.incorrectpassword", new String[] {});
127         }
128       }
129       catch (Throwable t) {
130         throw new ServletModuleFailure(t);
131       }
132
133
134       if (newPassword.length() == 0 || newPassword2.length() == 0) {
135         throw new ServletModuleUserExc("user.error.missingpasswords", new String[] {});
136       }
137
138       if (!newPassword.equals(newPassword2)) {
139         throw new ServletModuleUserExc("user.error.passwordmismatch", new String[] {});
140       }
141
142       return newPassword;
143     }
144     else
145       return null;
146   }
147
148   public void insert(HttpServletRequest aRequest, HttpServletResponse aResponse)
149       throws ServletModuleExc, ServletModuleUserExc, ServletModuleFailure
150   {
151     try {
152       MirGlobal.accessControl().user().assertMayAddUsers(ServletHelper.getUser(aRequest));
153
154       HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
155       Map withValues = getIntersectingValues(aRequest, mainModule.getStorageObject());
156
157       String newPassword=validatePassword(ServletHelper.getUser(aRequest), requestParser);
158       if (newPassword!=null)
159         withValues.put("password", newPassword);
160       else
161         throw new ServletModuleUserExc("user.error.missingpassword", new String[] {});
162
163       String id = mainModule.add(withValues);
164
165       logAdminUsage(aRequest, id, "object added");
166
167       if (requestParser.hasParameter("returnurl"))
168         redirect(aResponse, requestParser.getParameter("returnurl"));
169       else
170         list(aRequest, aResponse);
171     }
172     catch (Throwable e) {
173       throw new ServletModuleFailure(e);
174     }
175   }
176
177   public void update(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc, ServletModuleUserExc, ServletModuleFailure
178   {
179     try {
180       HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
181       String id = requestParser.getParameter("id");
182       EntityUsers user = (EntityUsers) mainModule.getById(id);
183       MirGlobal.accessControl().user().assertMayEditUser(ServletHelper.getUser(aRequest), user);
184
185       Map withValues = getIntersectingValues(aRequest, mainModule.getStorageObject());
186       if (!withValues.containsKey("is_admin"))
187         withValues.put("is_admin","0");
188       if (!withValues.containsKey("is_disabled"))
189         withValues.put("is_disabled","0");
190
191       String newPassword=validatePassword(ServletHelper.getUser(aRequest), requestParser);
192       if (newPassword!=null)
193         withValues.put("password", MirGlobal.localizer().adminInterface().makePasswordDigest(newPassword));
194
195       mainModule.set(withValues);
196
197       logAdminUsage(aRequest, id, "object modified");
198
199       if (requestParser.hasParameter("returnurl"))
200         redirect(aResponse, requestParser.getParameter("returnurl"));
201       else
202         list(aRequest, aResponse);
203     }
204     catch (Throwable e) {
205       throw new ServletModuleFailure(e);
206     }
207   }
208
209   public void updatepassword(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc, ServletModuleUserExc, ServletModuleFailure
210   {
211     try {
212       HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
213       String id = requestParser.getParameter("id");
214       EntityUsers user = (EntityUsers) mainModule.getById(id);
215       MirGlobal.accessControl().user().assertMayChangeUserPassword(ServletHelper.getUser(aRequest), user);
216
217       String newPassword=validatePassword(ServletHelper.getUser(aRequest), requestParser);
218       if (newPassword!=null) {
219         user.setFieldValue("password", MirGlobal.localizer().adminInterface().makePasswordDigest(newPassword));
220         user.update();
221
222         logAdminUsage(aRequest, id, "password changed");
223
224         // hackish: to make sure the cached logged in user is up-to-date:
225         ServletHelper.setUser(aRequest, (EntityUsers) mainModule.getById(ServletHelper.getUser(aRequest).getId()));
226       }
227
228       if (requestParser.hasParameter("returnurl"))
229         redirect(aResponse, requestParser.getParameter("returnurl"));
230       else
231         redirect(aResponse, "");
232     }
233     catch (Throwable e) {
234       throw new ServletModuleFailure(e);
235     }
236   }
237
238   public void list(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc
239   {
240     HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
241
242     int offset = requestParser.getIntegerWithDefault("offset", 0);
243
244     returnUserList(aRequest, aResponse, offset);
245   }
246
247   public void returnUserList(
248        HttpServletRequest aRequest,
249        HttpServletResponse aResponse,
250        int anOffset) throws ServletModuleExc {
251
252 // ML: to be deleted, support for 3 extra vars to be added
253     HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
254     URLBuilder urlBuilder = new URLBuilder();
255     EntityAdapterModel model;
256     int count;
257
258     try {
259       Map responseData = ServletHelper.makeGenerationData(aRequest, aResponse, new Locale[] { getLocale(aRequest), getFallbackLocale(aRequest)});
260       model = MirGlobal.localizer().dataModel().adapterModel();
261
262       Object userList =
263           new CachingRewindableIterator(
264             new EntityIteratorAdapter( "", "login", nrEntitiesPerListPage,
265                MirGlobal.localizer().dataModel().adapterModel(), "user", nrEntitiesPerListPage, anOffset)
266       );
267
268       responseData.put("nexturl", null);
269       responseData.put("prevurl", null);
270
271       count=mainModule.getSize("");
272
273       urlBuilder.setValue("module", "Users");
274       urlBuilder.setValue("do", "list");
275
276       urlBuilder.setValue("offset", anOffset);
277       responseData.put("offset" , new Integer(anOffset).toString());
278       responseData.put("thisurl" , urlBuilder.getQuery());
279
280       if (count>=anOffset+nrEntitiesPerListPage) {
281         urlBuilder.setValue("offset", (anOffset + nrEntitiesPerListPage));
282         responseData.put("nexturl" , urlBuilder.getQuery());
283       }
284
285       if (anOffset>0) {
286         urlBuilder.setValue("offset", Math.max(anOffset - nrEntitiesPerListPage, 0));
287         responseData.put("prevurl" , urlBuilder.getQuery());
288       }
289
290       responseData.put("users", userList);
291       responseData.put("mayDeleteUsers", new Boolean(MirGlobal.accessControl().user().mayDeleteUsers(ServletHelper.getUser(aRequest))));
292       responseData.put("mayAddUsers", new Boolean(MirGlobal.accessControl().user().mayAddUsers(ServletHelper.getUser(aRequest))));
293       responseData.put("mayEditUsers", new Boolean(MirGlobal.accessControl().user().mayEditUsers(ServletHelper.getUser(aRequest))));
294
295       responseData.put("from" , Integer.toString(anOffset+1));
296       responseData.put("count", Integer.toString(count));
297       responseData.put("to", Integer.toString(Math.min(anOffset+nrEntitiesPerListPage, count)));
298       responseData.put("offset" , Integer.toString(anOffset));
299
300       ServletHelper.generateResponse(aResponse.getWriter(), responseData, listGenerator);
301     }
302     catch (Throwable e) {
303       throw new ServletModuleFailure(e);
304     }
305   }
306
307   public void showUser(String anId, boolean anOnlyPassword, HttpServletRequest aRequest, HttpServletResponse aResponse)
308       throws ServletModuleExc {
309     try {
310       HTTPRequestParser requestParser = new HTTPRequestParser(aRequest);
311       Map responseData = ServletHelper.makeGenerationData(aRequest, aResponse, new Locale[] { getLocale(aRequest), getFallbackLocale(aRequest)});
312       EntityAdapterModel model = MirGlobal.localizer().dataModel().adapterModel();
313       Map user;
314       URLBuilder urlBuilder = new URLBuilder();
315
316       urlBuilder.setValue("module", "Users");
317       if (anOnlyPassword)
318         urlBuilder.setValue("do", "changepassword");
319       else
320         urlBuilder.setValue("do", "edit");
321       urlBuilder.setValue("id", anId);
322       urlBuilder.setValue("returnurl", requestParser.getParameter("returnurl"));
323
324       if (anId!=null) {
325         responseData.put("new", Boolean.FALSE);
326         user = model.makeEntityAdapter("user", mainModule.getById(anId));
327       }
328       else {
329         List fields = DatabaseUsers.getInstance().getFields();
330         responseData.put("new", Boolean.TRUE);
331         user = new HashMap();
332         Iterator i = fields.iterator();
333         while (i.hasNext()) {
334           user.put(i.next(), null);
335         }
336
337         MirGlobal.localizer().adminInterface().initializeArticle(user);
338       }
339       responseData.put("user", user);
340       responseData.put("passwordonly", new Boolean(anOnlyPassword));
341
342       responseData.put("returnurl", requestParser.getParameter("returnurl"));
343       responseData.put("thisurl", urlBuilder.getQuery());
344
345       ServletHelper.generateResponse(aResponse.getWriter(), responseData, editGenerator);
346     }
347     catch (Throwable e) {
348       throw new ServletModuleFailure(e);
349     }
350   }
351
352   public void delete(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleUserExc, ServletModuleExc, ServletModuleFailure {
353     try {
354       EntityUsers user = (EntityUsers) mainModule.getById(aRequest.getParameter("id"));
355
356       MirGlobal.accessControl().user().assertMayDeleteUser(ServletHelper.getUser(aRequest), user);
357
358       super.delete(aRequest, aResponse);
359     }
360     catch (Throwable t) {
361       throw new ServletModuleFailure(t);
362     }
363   }
364
365   public void changepassword(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc
366   {
367     String idParam = aRequest.getParameter("id");
368
369     if (idParam == null)
370       throw new ServletModuleExc("ServletModuleUser.edit: invalid call: (id) not specified");
371
372     try {
373       EntityUsers user = (EntityUsers) mainModule.getById(idParam);
374       MirGlobal.accessControl().user().assertMayChangeUserPassword(ServletHelper.getUser(aRequest), user);
375
376       showUser(idParam, true, aRequest, aResponse);
377     }
378     catch (Throwable e) {
379       throw new ServletModuleFailure(e);
380     }
381   }
382 }
383