Friday 28 October 2011

ADF Automatically disabling and setting read only status on UI components based on fine-grained privileges

I had to automatically apply the view/select type of privilege to implemented ADF pages. The idea was to not have to put EL expression as value to all appropriate components' "disabled" or "read only" properties (hence it should happen 100% automatically). So, my solution for now was to implement a phase listener and within the afterPhase() method execute the following java code:
  // checking whether security privileges are applicable in the sense that
  // - the user is logged in
  // - the security privileges have been loaded for the user.
  if(isLoggedIn() && (null != JSFUtils.getFromSession(SessionKeys.VIEW_ENTITY_PRIVS.getKey()))) {
      // first get a reference to the View Root component
      FacesContext fCtx = phaseEvent.getFacesContext();
      UIViewRoot viewRoot = fCtx.getViewRoot();
      // We have a template component which wraps all our implemented ADF forms     
      UIComponent template = viewRoot.findComponent("p_tmpl");
      if (template != null) {
        // the template knows which Form Bean (backing bean) is tied to the current view/response
        FormBean formBean = (FormBean) template.getAttributes().get("formBean"); 
        if (formBean != null) {
          // The Form Bean knows which logical view is in question.
          String viewName = formBean.getViewNameForPrivilege();         
          if (!FormBean.NO_PRIVS_APPLIED.equals(viewName)) {
            boolean privsExist = PrivilegesUtil.doesViewEntityPrivilegesExist(viewName);
            logger.error("View PRIVS Exist?["+privsExist+"]");           
            // then if no view privileges exist for this view...we disable and set to read only all the components
            if (!privsExist) {
              logger.error("Going to cascade!!");
              this.cascadeDisableAndReadOnly(template.getFacetsAndChildren());
                } // end if (privileges don't exist)
          } // end if NOT default view name
        } // end if (formBean != null)
      } // end if (template != null)
  } // end if (isLoggedIn() && Privileges have been loaded)

For completeness sake I've provided the implementation of the cascadeDisableAndReadOnly() method:
private void cascadeDisableAndReadOnly(final Iterator<UIComponent> children) {
    if(children != null) {
      while (children.hasNext()){
          UIComponent child = children.next();              
          // PLEASE NOTE: One can add some skip conditions based on the nature and instance of the child 
          // FOR EXAMPLE: Skip any OraFormsFaces Form as child
          if (child instanceof Form) {
              logger.error("Detected OraFormsFacesForm...");
              continue;
          }
          cascadeReadOnly(child.getFacetsAndChildren());       
          child.getAttributes().put("readOnly", true);
          child.getAttributes().put("disabled", true);
      } // end while (children.hasNext())
    } // en if (children != null)
}

No comments:

Post a Comment