All Downloads are FREE. Search and download functionalities are using the official Maven repository.

edu.internet2.middleware.grouper.hooks.examples.GrouperAttributeAssignValueRulesConfigHook Maven / Gradle / Ivy

There is a newer version: 5.13.5
Show newest version
/**
 * Copyright 2014 Internet2
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/**
 * 
 */
package edu.internet2.middleware.grouper.hooks.examples;

import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;

import edu.internet2.middleware.grouper.GrouperSession;
import edu.internet2.middleware.grouper.attr.AttributeDefName;
import edu.internet2.middleware.grouper.attr.assign.AttributeAssign;
import edu.internet2.middleware.grouper.attr.assign.AttributeAssignSave;
import edu.internet2.middleware.grouper.attr.value.AttributeAssignValue;
import edu.internet2.middleware.grouper.exception.GrouperSessionException;
import edu.internet2.middleware.grouper.hooks.AttributeAssignValueHooks;
import edu.internet2.middleware.grouper.hooks.beans.HooksAttributeAssignValueBean;
import edu.internet2.middleware.grouper.hooks.beans.HooksContext;
import edu.internet2.middleware.grouper.hooks.logic.GrouperHookType;
import edu.internet2.middleware.grouper.hooks.logic.GrouperHooksUtils;
import edu.internet2.middleware.grouper.misc.GrouperSessionHandler;
import edu.internet2.middleware.grouper.rules.RuleDefinition;
import edu.internet2.middleware.grouper.rules.RuleEngine;
import edu.internet2.middleware.grouper.rules.RuleSubjectActAs;
import edu.internet2.middleware.grouper.rules.RuleUtils;
import edu.internet2.middleware.grouper.util.GrouperUtil;
import edu.internet2.middleware.subject.Subject;


/**
 * Fire on attribute assign value changes, validate the rules and 
 * set the answer in "valid" T|F attribute value
 * @author mchyzer
 *
 */
public class GrouperAttributeAssignValueRulesConfigHook extends AttributeAssignValueHooks {

  /**
   * 
   */
  public static void clearHook() {
    registered = false;
    registeredSuccess = false;
  }

  /**
   * 
   */
  public GrouperAttributeAssignValueRulesConfigHook() {
    // TODO Auto-generated constructor stub
  }

  /**
   * 
   */
  @Override
  public void attributeAssignValuePostDelete(HooksContext hooksContext,
      HooksAttributeAssignValueBean postDeleteBean) {
    validateRule(postDeleteBean.getAttributeAssignValue(), true);
  }

  /**
   * 
   */
  @Override
  public void attributeAssignValuePostInsert(HooksContext hooksContext,
      HooksAttributeAssignValueBean postInsertBean) {
    
    validateRule(postInsertBean.getAttributeAssignValue(), false);
  }

  /**
   * 
   */
  @Override
  public void attributeAssignValuePostUpdate(HooksContext hooksContext,
      HooksAttributeAssignValueBean postUpdateBean) {
    validateRule(postUpdateBean.getAttributeAssignValue(), false);
  }

  /** thread local to avoid circular references */
  private static ThreadLocal threadLocalInValidateRule = new ThreadLocal();
  
  /**
   * validate this rule
   * @param attributeAssignValue
   * @param isDelete 
   */
  public void validateRule(final AttributeAssignValue attributeAssignValue, final boolean isDelete) {

    Subject runningSubject = GrouperSession.staticGrouperSession().getSubject();
    
    RuleSubjectActAs.actAsThreadLocalAssign(runningSubject);
    
    //see if deleting the parent attribute assignment, if so, then allow it (still refresh rules cache)
    
    try {
      
      //do this as admin
      GrouperSession.internal_callbackRootGrouperSession(new GrouperSessionHandler() {
  
        /**
         * 
         */
        public Object callback(GrouperSession grouperSession)
            throws GrouperSessionException {
          //if deleting the attribute rule type, then dont worry about validations...
          Set attributeAssignDeletes = AttributeAssign.attributeAssignDeletes();
  
          AttributeDefName ruleAttributeDefName = RuleUtils.ruleAttributeDefName();
          if (ruleAttributeDefName != null) {
  
            for (AttributeAssign attributeAssign : GrouperUtil.nonNull(attributeAssignDeletes)) {
              if (StringUtils.equals(ruleAttributeDefName.getId(), attributeAssign.getAttributeDefNameId())) {
                //this means we are deleting a rule type, so dont worry about validating stuff
                return null;
              }
            }
          }
          
          //if we are importing, then dont validate
          if (AttributeAssignSave.inSaveThreadlocal()) {
            //there are issues with constraint violations here...
            return null;
          }
          
          //we want to avoid circular references
          Boolean inValidateAlready = threadLocalInValidateRule.get();
          if (inValidateAlready == null) {
            inValidateAlready = false;
          }
          
          //no need to validate if already in validate, dont want a circular reference
          if (inValidateAlready) {
            return null;
          }
          
          threadLocalInValidateRule.set(true);
          
          try {
          
            //see if this is a rule attribute
            AttributeAssign attributeAssign = attributeAssignValue.getAttributeAssign();
            
            AttributeDefName attributeDefName = attributeAssign.getAttributeDefName();
            if (!StringUtils.equals(RuleUtils.ruleAttrAttributeDef().getId(), 
                attributeDefName.getAttributeDefId())) {
              return null;
            }
            
            //we want the rules to refresh since something changed
            RuleEngine.clearRuleEngineCache();
                  
            //this is a rule attribute, lets validate
            RuleDefinition ruleDefinition = new RuleDefinition(attributeAssign.getOwnerAttributeAssignId());
        
            String validReason = ruleDefinition.validate();
            
            
            if (StringUtils.isBlank(validReason)) {
              validReason = "T";
              ruleDefinition.setValidInAttributes(true);
            } else {
              validReason = "INVALID: " + validReason;
              ruleDefinition.setValidInAttributes(false);
            }
            
            //now, we need to assign the valid attribute if not there already
            AttributeAssign typeAttributeAssign = attributeAssign.getOwnerAttributeAssign();
            
            if (isDelete && !StringUtils.equals("T", validReason)) {
              //you are allowed to delete the valid attribute (so you can remove the whole thing..)
              //note, the valid attribute will need to be deleted last... will this be a problem on cascade?
              //if this isnt the valid attribute itself, if it is, it will be deleted by whatever fired the hook
              if (!StringUtils.equals(RuleUtils.ruleValidName(), attributeDefName.getName())) {
                //delete the valid attribute...
                typeAttributeAssign.getAttributeDelegate().removeAttribute(RuleUtils.ruleValidAttributeDefName());
              }        
            } else {
  
              typeAttributeAssign.getAttributeValueDelegate().assignValue(RuleUtils.ruleValidName(), validReason);
              
            }      
  
            
            
          } finally {
            threadLocalInValidateRule.set(false);
          }
          return null;
        }
        
      });
    } finally {
      RuleSubjectActAs.actAsThreadLocalClear();
    }
  }
  
  /**
   * only register once
   */
  private static boolean registered = false;

  /** if the hook was registered and being used */
  private static boolean registeredSuccess = false;
  
  /**
   * register this hook
   * @param tryAgainIfNotBefore 
   */
  public static void registerHookIfNecessary(boolean tryAgainIfNotBefore) {
    
    if (registered && !tryAgainIfNotBefore) {
      return;
    }
    
    //if trying again, but already registered, fine
    if (tryAgainIfNotBefore && registeredSuccess) {
      return;
    }

      
    registeredSuccess = true;
    LOG.debug("Registering hooks GrouperAttributeAssignValueRulesConfigHook");
    //register this hooks
    GrouperHooksUtils.addHookManual(GrouperHookType.ATTRIBUTE_ASSIGN_VALUE.getPropertyFileKey(), 
        GrouperAttributeAssignValueRulesConfigHook.class);
    
    registered = true;

  }

  /**
   * logger 
   */
  private static final Log LOG = GrouperUtil.getLog(GrouperAttributeAssignValueRulesConfigHook.class);

  
  /**
   * @return the threadLocalInValidateRule
   */
  public static ThreadLocal getThreadLocalInValidateRule() {
    return threadLocalInValidateRule;
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy