/* MailmanListCustom.java Custom plug-in for managing fields in the MailmanList object type. Created: 25 June 1999 Module By: Jonathan Abbey, jonabbey@arlut.utexas.edu ----------------------------------------------------------------------- Ganymede Directory Management System Copyright (C) 1996-2014 The University of Texas at Austin Ganymede is a registered trademark of The University of Texas at Austin Contact information Author Email: ganymede_author@arlut.utexas.edu Email mailing list: ganymede@arlut.utexas.edu US Mail: Computer Science Division Applied Research Laboratories The University of Texas at Austin PO Box 8029, Austin TX 78713-8029 Telephone: (512) 835-3200 This program 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. This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */ package arlut.csd.ganymede.gasharl; import java.util.Vector; import arlut.csd.ganymede.common.GanyPermissionsException; import arlut.csd.ganymede.common.Invid; import arlut.csd.ganymede.common.NotLoggedInException; import arlut.csd.ganymede.common.ReturnVal; import arlut.csd.ganymede.common.SchemaConstants; import arlut.csd.ganymede.server.DBEditObject; import arlut.csd.ganymede.server.DBEditSet; import arlut.csd.ganymede.server.DBField; import arlut.csd.ganymede.server.DBObject; import arlut.csd.ganymede.server.DBObjectBase; import arlut.csd.ganymede.server.DBSession; import arlut.csd.ganymede.server.Ganymede; import arlut.csd.ganymede.server.GanymedeSession; import arlut.csd.ganymede.server.StringDBField; /*------------------------------------------------------------------------------ class MailmanListCustom ------------------------------------------------------------------------------*/ /** * Custom plug-in for managing fields in the MailmanList object type. */ public class MailmanListCustom extends DBEditObject implements SchemaConstants, MailmanListSchema { /** * * Customization Constructor * */ public MailmanListCustom(DBObjectBase objectBase) { super(objectBase); } /** * * Create new object constructor * */ public MailmanListCustom(DBObjectBase objectBase, Invid invid, DBEditSet editset) { super(objectBase, invid, editset); } /** * * Check-out constructor, used by DBObject.createShadow() * to pull out an object for editing. * */ public MailmanListCustom(DBObject original, DBEditSet editset) { super(original, editset); } /** * <p>Customization method to control whether a specified field * is required to be defined at commit time for a given object.</p> * * <p>To be overridden on necessity in DBEditObject subclasses.</p> * * <p>Note that this method will not be called if the controlling * GanymedeSession's enableOversight is turned off, as in * bulk loading.</p> * * <p>Note as well that the designated label field for objects are * always required, whatever this method returns, and that this * requirement holds without regard to the GanymedeSession's * enableOversight value.</p> * * <p><b>*PSEUDOSTATIC*</b></p> */ @Override public boolean fieldRequired(DBObject object, short fieldid) { switch (fieldid) { case MailmanListSchema.NAME: case MailmanListSchema.OWNEREMAIL: case MailmanListSchema.PASSWORD: case MailmanListSchema.SERVER: case MailmanListSchema.ALIASES: return true; } return false; } /** * <p>This method is the hook that DBEditObject subclasses use to interpose * {@link arlut.csd.ganymede.server.GanymediatorWizard wizards} when a field's * value is being changed.</p> * * <p>Whenever a field is changed in this object, this method will be * called with details about the change. This method can refuse to * perform the operation, it can make changes to other objects in * the database in response to the requested operation, or it can * choose to allow the operation to continue as requested.</p> * * <p>In the latter two cases, the wizardHook code may specify a list * of fields and/or objects that the client may need to update in * order to maintain a consistent view of the database.</p> * * <p>If server-local code has called * {@link arlut.csd.ganymede.server.GanymedeSession#enableOversight(boolean) * enableOversight(false)}, * this method will never be * called. This mode of operation is intended only for initial * bulk-loading of the database.</p> * * <p>This method may also be bypassed when server-side code uses * setValueLocal() and the like to make changes in the database.</p> * * <p>This method is called before the finalize*() methods.. the finalize*() * methods is where last minute cascading changes should be performed.. * Note as well that wizardHook() is called before the namespace checking * for the proposed value is performed, while the finalize*() methods are * called after the namespace checking.</p> * * <p>The operation parameter will be a small integer, and should hold one of the * following values:</p> * * <dl> * <dt>1 - SETVAL</dt> * <dd>This operation is used whenever a simple scalar field is having * it's value set. param1 will be the value being placed into the field.</dd> * <dt>2 - SETELEMENT</dt> * <dd>This operation is used whenever a value in a vector field is being * set. param1 will be an Integer holding the element index, and * param2 will be the value being set.</dd> * <dt>3 - ADDELEMENT</dt> * <dd>This operation is used whenever a value is being added to the * end of a vector field. param1 will be the value being added.</dd> * <dt>4 - DELELEMENT</dt> * <dd>This operation is used whenever a value in a vector field is being * deleted. param1 will be an Integer holding the element index.</dd> * <dt>5 - ADDELEMENTS</dt> * <dd>This operation is used whenever a set of elements is being * added to a vector field en masse. param1 will be a Vector containing * the values that are being added.</dd> * <dt>6 - DELELEMENTS</dt> * <dd>This operation is used whenever a set of elements is being * deleted from a vector field en masse. param1 will be a Vector containing * the values that are being deleted.</dd> * <dt>7 - SETPASSPLAIN</dt> * <dd>This operation is used when a password field is having its password * set using a plaintext source. param1 will be a String containing the * submitted password, or null if the password is being cleared.</dd> * <dt>8 - SETPASSCRYPT</dt> * <dd>This operation is used when a password field is having its password * set using a UNIX crypt() hashed source. param1 will be a String containing the * submitted hashed password, or null if the password is being cleared.</dd> * <dt>9 - SETPASSMD5</dt> * <dd>This operation is used when a password field is having its password * set using an md5Ccrypt() hashed source. param1 will be a String containing the * submitted hashed password, or null if the password is being cleared.</dd> * <dt>10 - SETPASSWINHASHES</dt> * <dd>This operation is used when a password field is having its password * set using Windows style password hashes. param1 will be the password in * LANMAN hash form, param2 will be the password in NT Unicode MD4 hash * form. Either or both of param1 and param2 may be null.</dd> * <dt>11 - SETPASSAPACHEMD5</dt> * <dd>This operation is used when a password field is having its * password set using the Apache variant of the md5crypt algorithm. * param1 will be the password in Apache md5crypt hash form, or null * if the password hash is being cleared. param2 will be null.</dd> * <dt>12 - SETPASSSSHA</dt> * <dd>This operation is used when a password field is having its * password set using the OpenLDAP-style SSHA password hash. param1 * will be the password in SSHA form, or null if the password is * being cleared. param2 will be null.</dd> * <dt>13 - SETPASS_SHAUNIXCRYPT</dt> * <dd>This operation is used when a password field is having its * password set using Ulrich Drepper's SHA256 or SHA512 Unix Crypt * algorithms. param1 will be the password in SHA Unix Crypt form, * or null if the password is being cleared. param2 will be * null.</dd> * <dt>14 - SETPASS_BCRYPT</dt> * <dd>This operation is used when a password field is having its * password set using the OpenBSD-style BCrypt password hash. param1 * will be the password in BCrypt form, or null if the password is * being cleared. param2 will be null.</dd> * </dl> * * <p>To be overridden on necessity in DBEditObject subclasses.</p> * * @return null if the operation is approved without comment, or a * ReturnVal object indicating success or failure, objects and * fields to be rescanned by the client, and a doNormalProcessing * flag that will indicate to the field code whether or not the * operation should continue to completion using the field's * standard logic. <b>It is very important that wizardHook return a * new ReturnVal(true, true) if the wizardHook wishes to simply * specify rescan information while having the field perform its * standard operation.</b> wizardHook() may return new * ReturnVal(true, false) if the wizardHook performs the operation * (or a logically related operation) itself. The same holds true * for the respond() method in GanymediatorWizard subclasses. */ @Override public ReturnVal wizardHook(DBField field, int operation, Object param1, Object param2) { ReturnVal retVal = null; if (field.getID() == NAME) { if (operation == SETVAL) { retVal = handleCreateMailmanList((String) param1); } } return retVal; } /** * <p>This method provides a pre-commit hook that runs after the * user has hit commit but before the system has established write * locks for the commit.</p> * * <p>The intended purpose of this hook is to allow objects that * dynamically maintain hidden label fields to update those fields * from the contents of the object's other fields at commit * time.</p> * * <p>This method runs in a checkpointed context. If this method * fails in any operation, you should return a ReturnVal with a * failure dialog encoded, and the transaction's commit will be * blocked and a dialog explaining the problem will be presented to * the user.</p> * * <p>To be overridden on necessity in DBEditObject subclasses.</p> * * @return A ReturnVal indicating success or failure. May * be simply 'null' to indicate success if no feedback need * be provided. */ @Override public ReturnVal preCommitHook() { switch (getStatus()) { case DROPPING: break; case CREATING: case EDITING: // handle creating the aliases needed for the mailmanlist String name = getLabel(); return handleCreateMailmanList(name); case DELETING: break; } return null; } /** * Handle dealing with Mailman Lists: created all the associated aliases. * Mailman needs 10 total email addresses to be registered. */ public ReturnVal handleCreateMailmanList(String name) { ReturnVal retVal = new ReturnVal(true, true); StringDBField stringfield; stringfield = getStringField(ALIASES); boolean succeed = false; // set a checkpoint so we can verify all the aliases // needed are not currently being used. String checkPointKey = "MailmanListAliases"; DBSession dbSession = getGSession().getDBSession(); dbSession.checkpoint(checkPointKey); try { while (stringfield.size() > 0) { retVal = stringfield.deleteElementLocal(0); if (retVal != null && !retVal.didSucceed()) { return retVal; } } String[] aliases = {name+"-admin", name+"-bounce", name+"-confirm", name+"-join", name+"-leave", name+"-owner", name+"-request", name+"-subscribe", name+"-unsubscribe"}; for (int i = 0; i < aliases.length; i++) { retVal = stringfield.addElementLocal(aliases[i]); if (retVal != null && !retVal.didSucceed()) { return retVal; } } succeed = true; } finally { if (succeed) { dbSession.popCheckpoint(checkPointKey); // tell client to refresh to see the reactivation results retVal = new ReturnVal(true, true); retVal.addRescanField(this.getInvid(), MailmanListSchema.ALIASES); return retVal; } else { if (dbSession.rollback(checkPointKey)) { return retVal; } else { return Ganymede.createErrorDialog(this.getGSession(), "MailmanListCustom: Error", "Ran into a problem during alias creation, and rollback failed"); } } } } }