Skip to Content.
Sympa Menu

grouper-dev - hooks update

Subject: Grouper Developers Forum

List archive

hooks update


Chronological Thread 
  • From: Chris Hyzer <>
  • To: "" <>
  • Subject: hooks update
  • Date: Fri, 11 Jul 2008 02:12:08 -0400
  • Accept-language: en-US
  • Acceptlanguage: en-US

Hey,

 

- I mentioned earlier about java Transaction Synchronization to do postCommit hooks.  So I added 29 more hooks (90 total, all tested with 69 unit tests)

                - post commit hooks will make grouper hooks more like signet hooks

                - they also allow for economical notifications (especially if there is a full daily sync, and missing a few here and there doesn’t cause problems)

- I made the asynchronous hooks and postCommit hooks (which could be asynchronous) pass the business objects as clones.  I was nervous that the data might have changed in the meantime.  This also will make grouper more like signet

- We discussed on the call changed to GSH, WS and UI for hooks.  I forgot about graceful veto handling, this could be some decent work depending on if there is an opportunity to add one central veto handling call.  I believe this is the case in WS at least.

- I think we should keep example hooks in the API for people to look at (I have 3 there now, will add more as use cases pop up)

- TomZ gave me a use case for hooks (no new or changed emailAddress attribute of a group can conflict with existing email address of group or subject), and I made an example (untested).  [code below]

 

It does give an example of some complex parts of the API:

                - hook based on insert and update at same time

                - hook based on if an attribute changes (uses dbVersionDifferentFields() )

                - inverse of control on GrouperSession (which I think will be common in hook implementations to execute as GrouperSystem)

                - getting around security on business methods (group.getAttributesDb()).  Note, could also do that with GrouperSystem GrouperSession

 

All this is documented on wiki

 

https://wiki.internet2.edu/confluence/display/GrouperWG/Hooks

 

To do’s:

- finalize how context data works

- set this data from UI / WS / GSH / API / etc

- gracefully handle vetos from UI / WS / GSH

 

Kind regards,

Chris

 

Ps. Hooks list:

Lifecycle.grouperStartup()

Lifecycle.hookInit()

Lifecycle.hibernateInit()

Group.preInsert()

Group.postInsert()

Group.postCommitInsert()

Group.preDelete()

Group.postDelete()

Group.postCommitDelete()

Group.preUpdate()

Group.postUpdate()

Group.postCommitUpdate()

Membership.preAddMember()

Membership.postAddMember()

Membership.postCommitAddMember()

Membership.preRemoveMember()

Membership.postRemoveMember()

Membership.postCommitRemoveMember()

Membership.preInsert()

Membership.postInsert()

Membership.postCommitInsert()

Membership.preDelete()

Membership.postDelete()

Membership.postCommitDelete()

Membership.preUpdate()

Membership.postUpdate()

Membership.postCommitUpdate()

Member.preInsert()

Member.postInsert()

Member.postCommitInsert()

Member.preDelete()

Member.postDelete()

Member.postCommitDelete()

Member.preUpdate()

Member.postUpdate()

Member.postCommitUpdate()

Stem.preInsert()

Stem.postInsert()

Stem.postCommitInsert()

Stem.preDelete()

Stem.postDelete()

Stem.postCommitDelete()

Stem.preUpdate()

Stem.postUpdate()

Stem.postCommitUpdate()

GrouperSession.preInsert()

GrouperSession.postInsert()

GrouperSession.postCommitInsert()

GrouperSession.preDelete()

GrouperSession.postDelete()

GrouperSession.postCommitDelete()

GrouperSession.preUpdate()

GrouperSession.postUpdate()

GrouperSession.postCommitUpdate()

GroupType.preInsert()

GroupType.postInsert()

GroupType.postCommitInsert()

GroupType.preDelete()

GroupType.postDelete()

GroupType.postCommitDelete()

GroupType.preUpdate()

GroupType.postUpdate()

GroupType.postCommitUpdate()

Field.preInsert()

Field.postInsert()

Field.postCommitInsert()

Field.preDelete()

Field.postDelete()

Field.postCommitDelete()

Field.preUpdate()

Field.postUpdate()

Field.postCommitUpdate()

GroupTypeTuple.preInsert()

GroupTypeTuple.postInsert()

GroupTypeTuple.postCommitInsert()

GroupTypeTuple.preDelete()

GroupTypeTuple.postDelete()

GroupTypeTuple.postCommitDelete()

GroupTypeTuple.preUpdate()

GroupTypeTuple.postUpdate()

GroupTypeTuple.postCommitUpdate()

Composite.preInsert()

Composite.postInsert()

Composite.postCommitInsert()

Composite.preDelete()

Composite.postDelete()

Composite.postCommitDelete()

Composite.preUpdate()

Composite.postUpdate()

Composite.postCommitUpdate()

 

Pps. Example code for TomZ use case:

 

http://viewvc.internet2.edu/viewvc.py/grouper/src/grouper/edu/internet2/middleware/grouper/hooks/examples/GroupHooksImplExampleEmail.java?root=I2MI&view=markup

 

/*

 * @author mchyzer

 * $Id: GroupHooksImplExampleEmail.java,v 1.2 2008/07/11 05:47:11 mchyzer Exp $

 */

package edu.internet2.middleware.grouper.hooks.examples;

 

import java.util.Set;

 

import org.apache.commons.lang.StringUtils;

 

import edu.internet2.middleware.grouper.Group;

import edu.internet2.middleware.grouper.GroupFinder;

import edu.internet2.middleware.grouper.GrouperSession;

import edu.internet2.middleware.grouper.GrouperSessionException;

import edu.internet2.middleware.grouper.GrouperSessionHandler;

import edu.internet2.middleware.grouper.SubjectFinder;

import edu.internet2.middleware.grouper.hooks.GroupHooks;

import edu.internet2.middleware.grouper.hooks.beans.HooksContext;

import edu.internet2.middleware.grouper.hooks.beans.HooksGroupBean;

import edu.internet2.middleware.grouper.hooks.logic.HookVeto;

import edu.internet2.middleware.grouper.util.GrouperUtil;

import edu.internet2.middleware.subject.Subject;

import edu.internet2.middleware.subject.SubjectNotFoundException;

import edu.internet2.middleware.subject.SubjectNotUniqueException;

 

 

/**

 * test implementation of group hooks for test.  checks to make sure group attribute

 * is not in use by another group, subject, or subject id (for email prefix)

 */

public class GroupHooksImplExampleEmail extends GroupHooks {

 

  /**

   * if there is a changed emailAddress, make sure it doesnt already existin another group or subject

   * @see edu.internet2.middleware.grouper.hooks.GroupHooks#groupPreUpdate(edu.internet2.middleware.grouper.hooks.beans.HooksContext, edu.internet2.middleware.grouper.hooks.beans.HooksGroupBean)

   */

  @Override

  public void groupPreUpdate(HooksContext hooksContext, HooksGroupBean preUpdateBean) {

    //if its an update, see if the emailAddress changed

    Group group = preUpdateBean.getGroup();

    if (group.dbVersionDifferentFields().contains(Group.ATTRIBUTE_PREFIX+"emailAddress")) {

      String emailAddress = group.getAttributesDb().get("emailAddress");

      if (!StringUtils.isBlank(emailAddress)) {

        checkEmailAddress(emailAddress);

      }

    }

  }

 

  /**

   * <pre>

   * check a new or changed email address

   * attribute that there is not an existing email address in a subject attribute, or group attribute

   *

   * note: this is example code and is not tested

   * </pre>

   * @param emailAddress is the new email address (changed if update), should not be blank

   */

  static void checkEmailAddress(final String emailAddress) {

 

    try {

      //start session, dont clobber existing session

      GrouperSession grouperSession = GrouperSession.start(SubjectFinder.findRootSubject(), false);

      GrouperSession.callbackGrouperSession(grouperSession, new GrouperSessionHandler() {

 

        public Object callback(GrouperSession grouperSession)

            throws GrouperSessionException {

         

          //first see if there is a group with that attribute

          Set<Group> groups = GroupFinder.findAllByAttribute(grouperSession, "emailAddress", emailAddress);

          if (GrouperUtil.length(groups) > 0) {

            //note, dont show the group who is using it if that is a security problem

            throw new HookVeto("memphis.group.email.attribute.usedByGroup", "The email address: " + emailAddress

                + " is already being used by another group.  Please pick another email address.");

          }

         

          //next see if a subject has that attribute value.  note, this will only work if the subject adapter is

          //conducive to it

          Set<Subject> subjects = SubjectFinder.findAll(emailAddress);

          if (GrouperUtil.length(subjects) > 0) {

            //note, dont show the user who is using it if that is a security problem

            throw new HookVeto("memphis.group.email.attribute.usedBySubjectEmail", "The email address: " + emailAddress

                + " is already being used by another entity.  Please pick another email address.");

          }

         

          //next see if a subject has an identifier with the beginning of the email address.  could also filter by subject type

          String emailPrefix = GrouperUtil.prefixOrSuffix(emailAddress, "@", true);

          boolean foundSubject = false;

          try {

            SubjectFinder.findByIdentifier(emailPrefix);

            foundSubject = true;

          } catch (SubjectNotFoundException snfe) {

 

          } catch (SubjectNotUniqueException snue) {

            //data problem, but also others using the email address

            foundSubject = true;

          }

          if (foundSubject) {

            //note, dont show the user who is using it if that is a security problem

            throw new HookVeto("memphis.group.email.attribute.usedBySubjectEmailPrefix", "The email prefix: " + emailPrefix

                + " is already being used by another entity.  Please pick another email address.");

          }

         

          return null;

        }

       

      });

      GrouperSession.stopQuietly(grouperSession);

    } catch (Exception e) {

      throw new RuntimeException("Problem checking email address: '" + emailAddress + "'", e);

    }

  }

 

  /**

   *

   * @see edu.internet2.middleware.grouper.hooks.GroupHooks#groupPreInsert(edu.internet2.middleware.grouper.hooks.beans.HooksContext, edu.internet2.middleware.grouper.hooks.beans.HooksGroupBean)

   */

  @Override

  public void groupPreInsert(HooksContext hooksContext, HooksGroupBean preInsertBean) {

    //if its an insert, always check the attribute if it is there

    Group group = preInsertBean.getGroup();

    //getAttributesDb goes around permissions, just get the data

    String emailAddress = group.getAttributesDb().get("emailAddress");

    if (!StringUtils.isBlank(emailAddress)) {

      checkEmailAddress(emailAddress);

    }

  }

 

}

 

 

 



  • hooks update, Chris Hyzer, 07/11/2008

Archive powered by MHonArc 2.6.16.

Top of Page