From 73c423d3e1b4f3300b84c1a51d6f798adfdfd228 Mon Sep 17 00:00:00 2001 From: zapata Date: Wed, 5 Mar 2003 04:33:29 +0000 Subject: [PATCH] - Improved user edit support - Support for optional encrypted password storage --- bundles/admin_en.properties | 3 +- source/mir/module/AbstractModule.java | 5 +- source/mir/servlet/ServletModule.java | 24 +- .../localizer/MirAdminInterfaceLocalizer.java | 22 ++ .../basic/MirBasicAdminInterfaceLocalizer.java | 4 + source/mircoders/module/ModuleUsers.java | 230 +++++++++------- source/mircoders/servlet/ServletModuleUsers.java | 295 +++++++++++++-------- templates/admin/user.template | 127 +++++---- 8 files changed, 439 insertions(+), 271 deletions(-) diff --git a/bundles/admin_en.properties b/bundles/admin_en.properties index 61dc5a19..aae640d5 100755 --- a/bundles/admin_en.properties +++ b/bundles/admin_en.properties @@ -1,6 +1,6 @@ ########## admin ########## # language: english -# $Id: admin_en.properties,v 1.36 2003/03/04 22:00:51 zapata Exp $ +# $Id: admin_en.properties,v 1.37 2003/03/05 04:33:29 zapata Exp $ languagename=English @@ -309,6 +309,7 @@ topiclist.htmltitle=topiclist user.htmltitle=User user.login=Login user.password=Password +user.password2=Password (confirmation) user.admin=Admin userlist.htmltitle=Users diff --git a/source/mir/module/AbstractModule.java b/source/mir/module/AbstractModule.java index 2324e19a..0a70fca2 100755 --- a/source/mir/module/AbstractModule.java +++ b/source/mir/module/AbstractModule.java @@ -169,7 +169,8 @@ public class AbstractModule { theEntity.setStorage(theStorage); theEntity.setValues(theValues); return theEntity.insert(); - } catch (Exception e) { + } + catch (Exception e) { throw new ModuleException(e.toString()); } } @@ -184,7 +185,7 @@ public class AbstractModule { try { Entity theEntity = theStorage.selectById((String)theValues.get("id")); if (theEntity == null) - throw new ModuleException("Kein Objekt mit id in Datenbank id: " + theValues.get("id")); + throw new ModuleException("No object found with id " + theValues.get("id")); theEntity.setValues(theValues); theEntity.update(); return theEntity.getId(); diff --git a/source/mir/servlet/ServletModule.java b/source/mir/servlet/ServletModule.java index 3d67860d..265fb974 100755 --- a/source/mir/servlet/ServletModule.java +++ b/source/mir/servlet/ServletModule.java @@ -193,7 +193,7 @@ public abstract class ServletModule { * @param res Http-Response, die vom Dispatcher durchgereicht wird */ public void add(HttpServletRequest req, HttpServletResponse res) - throws ServletModuleException { + throws ServletModuleException, ServletModuleUserException { try { SimpleHash mergeData = new SimpleHash(); @@ -233,7 +233,7 @@ public abstract class ServletModule { * */ - public void delete(HttpServletRequest req, HttpServletResponse res) throws ServletModuleException { + public void delete(HttpServletRequest req, HttpServletResponse res) throws ServletModuleException, ServletModuleUserException { try { String idParam = req.getParameter("id"); @@ -288,10 +288,22 @@ public abstract class ServletModule { * @param res Http-Response, die vom Dispatcher durchgereicht wird */ public void edit(HttpServletRequest req, HttpServletResponse res) - throws ServletModuleException { + throws ServletModuleException, ServletModuleUserException { + edit(req, res, req.getParameter("id")); + } + + /** + * edit(req,res) - generische Editmethode. Wennn die Funktionalitaet + * nicht reicht, muss sie in der abgeleiteten ServletModule-Klasse + * ueberschreiben werden. + * + * @param req Http-Request, das vom Dispatcher durchgereicht wird + * @param res Http-Response, die vom Dispatcher durchgereicht wird + */ + public void edit(HttpServletRequest aRequest, HttpServletResponse aResponse, String anIdentifier) + throws ServletModuleException, ServletModuleUserException { try { - String idParam = req.getParameter("id"); - deliver(req, res, mainModule.getById(idParam), templateObjektString); + deliver(aRequest, aResponse, mainModule.getById(anIdentifier), templateObjektString); } catch (ModuleException e) { throw new ServletModuleException(e.getMessage()); @@ -308,7 +320,7 @@ public abstract class ServletModule { */ public void update(HttpServletRequest req, HttpServletResponse res) - throws ServletModuleException { + throws ServletModuleException, ServletModuleUserException { try { String idParam = req.getParameter("id"); Map withValues = getIntersectingValues(req, mainModule.getStorageObject()); diff --git a/source/mircoders/localizer/MirAdminInterfaceLocalizer.java b/source/mircoders/localizer/MirAdminInterfaceLocalizer.java index 3cff9956..8afb19f3 100755 --- a/source/mircoders/localizer/MirAdminInterfaceLocalizer.java +++ b/source/mircoders/localizer/MirAdminInterfaceLocalizer.java @@ -54,9 +54,31 @@ public interface MirAdminInterfaceLocalizer { */ public void initializeArticle(Map anArticle); + /** + * Allows passwords to be stored encrypted in the database. Just implement this + * function and return a digest of the supplied password. This function should always + * return the same digest for the same password. + * + * @param aPassword The password to be digested + * @return The digested password + */ + public String makePasswordDigest(String aPassword); + + + /** + * + * @return + */ public List simpleCommentOperations(); + + /** + * + * @param aName + * @return + */ public MirSimpleEntityOperation simpleCommentOperationForName(String aName); + public List simpleArticleOperations(); public MirSimpleEntityOperation simpleArticleOperationForName(String aName); diff --git a/source/mircoders/localizer/basic/MirBasicAdminInterfaceLocalizer.java b/source/mircoders/localizer/basic/MirBasicAdminInterfaceLocalizer.java index 06c32001..1d871589 100755 --- a/source/mircoders/localizer/basic/MirBasicAdminInterfaceLocalizer.java +++ b/source/mircoders/localizer/basic/MirBasicAdminInterfaceLocalizer.java @@ -72,6 +72,10 @@ public class MirBasicAdminInterfaceLocalizer implements MirAdminInterfaceLocaliz addSimpleCommentOperation(new ModifyCommentFieldOperation("hide", "is_published", "0")); } + public String makePasswordDigest(String aPassword) { + return aPassword; + } + public void initializeArticle(Map anArticle) { anArticle.put("is_published", "0"); anArticle.put("date", StringUtil.date2webdbDate(new GregorianCalendar())); diff --git a/source/mircoders/module/ModuleUsers.java b/source/mircoders/module/ModuleUsers.java index 07bf5b2f..4310dc9d 100755 --- a/source/mircoders/module/ModuleUsers.java +++ b/source/mircoders/module/ModuleUsers.java @@ -1,96 +1,136 @@ -/* - * Copyright (C) 2001, 2002 The Mir-coders group - * - * This file is part of Mir. - * - * Mir is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * Mir is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Mir; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * In addition, as a special exception, The Mir-coders gives permission to link - * the code of this program with the com.oreilly.servlet library, any library - * licensed under the Apache Software License, The Sun (tm) Java Advanced - * Imaging library (JAI), The Sun JIMI library (or with modified versions of - * the above that use the same license as the above), and distribute linked - * combinations including the two. You must obey the GNU General Public - * License in all respects for all of the code used other than the above - * mentioned libraries. If you modify this file, you may extend this exception - * to your version of the file, but you are not obligated to do so. If you do - * not wish to do so, delete this exception statement from your version. - */ - -package mircoders.module; - -import mir.entity.EntityList; -import mir.log.LoggerWrapper; -import mir.module.AbstractModule; -import mir.module.ModuleException; -import mir.storage.StorageObject; -import mir.storage.StorageObjectFailure; -import mircoders.entity.EntityUsers; -import mircoders.storage.DatabaseUsers; -import freemarker.template.SimpleList; - - -/* - * Users Module - - * - * - * @author RK - */ - -public class ModuleUsers extends AbstractModule -{ - static LoggerWrapper logger = new LoggerWrapper("Module.Users"); - - public ModuleUsers(StorageObject theStorage) - { - if (theStorage == null) - logger.warn("StorageObject was null!"); - - this.theStorage = theStorage; - } - - /** - * login method - */ - - public EntityUsers getUserForLogin(String user, String password) throws ModuleException - { - String whereString = "login='" +user + "' and password='"+ password + "' and is_admin='1'"; - EntityList userList = getByWhereClause(whereString, -1); - if (userList != null && userList.getCount()==1) - return (EntityUsers)userList.elementAt(0); - else - return null; - } - - public EntityList getUsers(String whereClause, int offset, int limit) throws ModuleException - { - try { - return theStorage.selectByWhereClause(whereClause, null, offset, limit); - } - catch (StorageObjectFailure e){ - throw new ModuleException(e.toString()); - } - } - - public SimpleList getUsersAsSimpleList() throws ModuleException { - try { - return ((DatabaseUsers)theStorage).getPopupData(); - } - catch(StorageObjectFailure e) { - throw new ModuleException(e.toString()); - } - } +/* + * Copyright (C) 2001, 2002 The Mir-coders group + * + * This file is part of Mir. + * + * Mir is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Mir is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Mir; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, The Mir-coders gives permission to link + * the code of this program with the com.oreilly.servlet library, any library + * licensed under the Apache Software License, The Sun (tm) Java Advanced + * Imaging library (JAI), The Sun JIMI library (or with modified versions of + * the above that use the same license as the above), and distribute linked + * combinations including the two. You must obey the GNU General Public + * License in all respects for all of the code used other than the above + * mentioned libraries. If you modify this file, you may extend this exception + * to your version of the file, but you are not obligated to do so. If you do + * not wish to do so, delete this exception statement from your version. + */ + +package mircoders.module; + +import java.util.Map; +import java.util.HashMap; + +import mir.entity.EntityList; +import mir.log.LoggerWrapper; +import mir.module.AbstractModule; +import mir.module.ModuleException; +import mir.storage.StorageObject; +import mir.storage.StorageObjectFailure; +import mir.util.JDBCStringRoutines; + +import mircoders.entity.EntityUsers; +import mircoders.storage.DatabaseUsers; +import mircoders.global.MirGlobal; +import mircoders.localizer.MirAdminInterfaceLocalizer; +import mircoders.localizer.MirLocalizer; + + +/* + * Users Module - + * + * + * @author RK + */ + +public class ModuleUsers extends AbstractModule +{ + static LoggerWrapper logger = new LoggerWrapper("Module.Users"); + + public ModuleUsers(StorageObject theStorage) + { + if (theStorage == null) + logger.warn("ModuleUsers(): StorageObject was null!"); + + this.theStorage = theStorage; + } + + /** + * Authenticate and lookup a user + * + * @param user The user to lookup + * @param password The password + * @return The authenticated user, or null if the user + * doesn't exist, or the supplied password is invalid. + * @throws ModuleException + */ + + public EntityUsers getUserForLogin(String user, String password) throws ModuleException + { + try { + String whereString = + "login='" + JDBCStringRoutines.escapeStringLiteral(user) + "' " + + "and password='" + JDBCStringRoutines.escapeStringLiteral( + MirGlobal.localizer().adminInterface().makePasswordDigest(password)) + + "' " + + "and is_admin='1'"; + + EntityList userList = getByWhereClause(whereString, -1); + + if (userList != null && userList.getCount() == 1) + return (EntityUsers) userList.elementAt(0); + else + return null; + } + catch (Throwable t) { + throw new ModuleException(t.getMessage()); + } + } + + private Map digestPassword(Map aValues) throws ModuleException { + Map result = aValues; + + try { + if (aValues.containsKey("password")) { + result = new HashMap(); + result.putAll(aValues); + result.put("password", + MirGlobal.localizer().adminInterface(). + makePasswordDigest( (String) aValues.get("password"))); + } + } + catch (Throwable t) { + throw new ModuleException("ModuleUsers.add: " + t.getMessage()); + } + + return result; + } + + public String add (Map theValues) throws ModuleException { + return super.add(digestPassword(theValues)); + } + + /** + * Standardfunktion, um einen Datensatz via StorageObject zu aktualisieren + * @param theValues Hash mit Spalte/Wert-Paaren + * @return Id des eingef?gten Objekts + * @exception ModuleException + */ + public String set (Map theValues) throws ModuleException { + return super.set(digestPassword(theValues)); + } + } \ No newline at end of file diff --git a/source/mircoders/servlet/ServletModuleUsers.java b/source/mircoders/servlet/ServletModuleUsers.java index 15b455fb..b7506df1 100755 --- a/source/mircoders/servlet/ServletModuleUsers.java +++ b/source/mircoders/servlet/ServletModuleUsers.java @@ -1,113 +1,182 @@ -/* - * Copyright (C) 2001, 2002 The Mir-coders group - * - * This file is part of Mir. - * - * Mir is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * Mir is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Mir; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * In addition, as a special exception, The Mir-coders gives permission to link - * the code of this program with the com.oreilly.servlet library, any library - * licensed under the Apache Software License, The Sun (tm) Java Advanced - * Imaging library (JAI), The Sun JIMI library (or with modified versions of - * the above that use the same license as the above), and distribute linked - * combinations including the two. You must obey the GNU General Public - * License in all respects for all of the code used other than the above - * mentioned libraries. If you modify this file, you may extend this exception - * to your version of the file, but you are not obligated to do so. If you do - * not wish to do so, delete this exception statement from your version. - */ - -package mircoders.servlet; - -import java.util.Map; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import mir.log.LoggerWrapper; -import mir.module.ModuleException; -import mir.servlet.ServletModule; -import mir.servlet.ServletModuleException; -import mir.storage.StorageObjectFailure; -import mircoders.module.ModuleUsers; -import mircoders.storage.DatabaseUsers; -import freemarker.template.SimpleHash; - -/* - * ServletModuleUsers - - * liefert HTML fuer Users - * - * - * @author RK - */ - -public class ServletModuleUsers extends mir.servlet.ServletModule -{ - private static ServletModuleUsers instance = new ServletModuleUsers(); - public static ServletModule getInstance() { return instance; } - - private ServletModuleUsers() { - super(); - logger = new LoggerWrapper("ServletModule.Users"); - - templateListString = configuration.getString("ServletModule.Users.ListTemplate"); - templateObjektString = configuration.getString("ServletModule.Users.ObjektTemplate"); - templateConfirmString = configuration.getString("ServletModule.Users.ConfirmTemplate"); - - try { - mainModule = new ModuleUsers(DatabaseUsers.getInstance()); - } - catch (StorageObjectFailure e) { - logger.debug("initialization of ServletModuleUsers failed!: " + e.getMessage()); - } - } - - public void edit(HttpServletRequest req, HttpServletResponse res) throws ServletModuleException - { - String idParam = req.getParameter("id"); - - if (idParam == null) - throw new ServletModuleException("ServletModuleUser.edit: invalid call: (id) not specified"); - - try { - deliver(req, res, mainModule.getById(idParam), templateObjektString); - } - catch (ModuleException e) { - throw new ServletModuleException(e.toString()); - } - } - - public void add(HttpServletRequest req, HttpServletResponse res) - throws ServletModuleException - { - try { - SimpleHash mergeData = new SimpleHash(); - mergeData.put("new", "1"); - deliver(req, res, mergeData, templateObjektString); - } - catch (Exception e) { throw new ServletModuleException(e.toString());} - } - - public void insert(HttpServletRequest req, HttpServletResponse res) - throws ServletModuleException - { - try { - Map withValues = getIntersectingValues(req, mainModule.getStorageObject()); - String id = mainModule.add(withValues); - deliver(req, res, mainModule.getById(id), templateObjektString); - } - catch (Exception e) { throw new ServletModuleException(e.toString());} - } -} +/* + * Copyright (C) 2001, 2002 The Mir-coders group + * + * This file is part of Mir. + * + * Mir is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Mir is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Mir; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, The Mir-coders gives permission to link + * the code of this program with the com.oreilly.servlet library, any library + * licensed under the Apache Software License, The Sun (tm) Java Advanced + * Imaging library (JAI), The Sun JIMI library (or with modified versions of + * the above that use the same license as the above), and distribute linked + * combinations including the two. You must obey the GNU General Public + * License in all respects for all of the code used other than the above + * mentioned libraries. If you modify this file, you may extend this exception + * to your version of the file, but you are not obligated to do so. If you do + * not wish to do so, delete this exception statement from your version. + */ + +package mircoders.servlet; + +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import freemarker.template.SimpleHash; + +import mir.log.LoggerWrapper; +import mir.module.ModuleException; +import mir.servlet.ServletModule; +import mir.servlet.ServletModuleException; +import mir.servlet.ServletModuleUserException; +import mir.storage.StorageObjectFailure; +import mir.util.HTTPRequestParser; + +import mircoders.module.ModuleUsers; +import mircoders.storage.DatabaseUsers; + +/* + * ServletModuleUsers - + * liefert HTML fuer Users + * + * + * @author RK + */ + +public class ServletModuleUsers extends ServletModule +{ + private static ServletModuleUsers instance = new ServletModuleUsers(); + public static ServletModule getInstance() { return instance; } + + private ServletModuleUsers() { + super(); + logger = new LoggerWrapper("ServletModule.Users"); + + templateListString = configuration.getString("ServletModule.Users.ListTemplate"); + templateObjektString = configuration.getString("ServletModule.Users.ObjektTemplate"); + templateConfirmString = configuration.getString("ServletModule.Users.ConfirmTemplate"); + + try { + mainModule = new ModuleUsers(DatabaseUsers.getInstance()); + } + catch (StorageObjectFailure e) { + logger.debug("initialization of ServletModuleUsers failed!: " + e.getMessage()); + } + } + + public void edit(HttpServletRequest req, HttpServletResponse res) throws ServletModuleException + { + String idParam = req.getParameter("id"); + + if (idParam == null) + throw new ServletModuleException("ServletModuleUser.edit: invalid call: (id) not specified"); + + try { + deliver(req, res, mainModule.getById(idParam), templateObjektString); + } + catch (ModuleException e) { + throw new ServletModuleException(e.toString()); + } + } + + public void add(HttpServletRequest req, HttpServletResponse res) + throws ServletModuleException + { + try { + SimpleHash mergeData = new SimpleHash(); + mergeData.put("new", "1"); + deliver(req, res, mergeData, templateObjektString); + } + catch (Exception e) { throw new ServletModuleException(e.toString());} + } + + public String checkPassword(HTTPRequestParser aRequestParser) throws ServletModuleException, ServletModuleUserException + { + if ( (aRequestParser.getParameter("newpassword") != null && + aRequestParser.getParameter("newpassword").length() > 0) || + (aRequestParser.getParameter("newpassword2") != null && + aRequestParser.getParameter("newpassword2").length() > 0) + ) { + String newPassword = aRequestParser.getParameterWithDefault("newpassword", ""); + String newPassword2 = aRequestParser.getParameterWithDefault("newpassword2", ""); + + if (newPassword.length() == 0 || newPassword2.length() == 0) { + throw new ServletModuleUserException( + "The new password must be entered twice!"); + } + + if (!newPassword.equals(newPassword2)) { + throw new ServletModuleUserException( + "New password differes from confirmation"); + } + + return newPassword; + } + else + return null; + } + + public void insert(HttpServletRequest aRequest, HttpServletResponse aResponse) + throws ServletModuleException + { + try { + HTTPRequestParser requestParser = new HTTPRequestParser(aRequest); + Map withValues = getIntersectingValues(aRequest, mainModule.getStorageObject()); + + String newPassword=checkPassword(requestParser); + if (newPassword!=null) + withValues.put("password", newPassword); + else + throw new ServletModuleUserException("Password is empty"); + + String id = mainModule.add(withValues); + if (requestParser.hasParameter("returnurl")) + redirect(aResponse, requestParser.getParameter("returnurl")); + else + list(aRequest, aResponse); + } + catch (Exception e) { + throw new ServletModuleException(e.toString()); + } + } + + public void update(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleException, ServletModuleUserException + { + try { + HTTPRequestParser requestParser = new HTTPRequestParser(aRequest); + + Map withValues = getIntersectingValues(aRequest, mainModule.getStorageObject()); + + String newPassword=checkPassword(requestParser); + if (newPassword!=null) + withValues.put("password", newPassword); + + mainModule.set(withValues); + + if (requestParser.hasParameter("returnurl")) + redirect(aResponse, requestParser.getParameter("returnurl")); + else + list(aRequest, aResponse); + } + catch (Throwable t) { + throw new ServletModuleException("ServletModuleUsers: " + t.getMessage()); + } + + } + + +} diff --git a/templates/admin/user.template b/templates/admin/user.template index 078413ef..1ddfaf3e 100755 --- a/templates/admin/user.template +++ b/templates/admin/user.template @@ -1,59 +1,78 @@ - - ${config["Mir.Name"]} | ${lang("user.htmltitle")} - - + + ${config["Mir.Name"]} | ${lang("user.htmltitle")} + + - + - -
- - - - - - - + - - - - - - - - - - - - - - - - -
- ${lang("user.login")}: - -
- ${lang("user.password")}: - -
- - ${lang("user.admin")}: - - - checked> -
- - - - - - - -
- - - +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + ${lang("user.login")}: + + + +
+ + ${lang("user.password")}: + + + +
+ + ${lang("user.password2")}: + + + +
+ + ${lang("user.admin")}: + + + checked> +
+ + + + + + + +
+
+ + + + -- 2.11.0