ddraper

Aikau Mini Examples - Role Based Rendering

Blog Post created by ddraper on Sep 26, 2014

Introduction

This is one post in a series of short examples of things that can be done using the Aikau framework. The series is not intended to provide complete documentation but simply to show how to solve frequently encountered problems, implement repeating UI patterns, show case how to use existing widgets or how to create new ones.

 

 

Real World Use Case

One of the most frequently asked questions we seem to be getting lately is whether or not we can render a different UI depending upon what groups the logged in user is a member of (also known as “role based rendering”).

 

This can range from simply displaying a warning instead of the page contents if the current user doesn’t have the privileges to be there, right up to fine grained differences between what different users see on the page.

 

 

Example

All widgets can be configured with a set of “renderFilter” rules that determine whether or not the widget is rendered (note: rendered not visible - if the renderFilter does not pass the widget will not be created). The rules are not constrained to just groups, it’s possible to define rules for any property that the widget has access to. However, two key pieces of information are always cascaded through the widget hierarchy and these are “groupMemberships” and “currentItem”.

 

This will be quite a convoluted example (aren’t they all?) but should at least show the options available for configuring renderFilters.

 

 

Pre-Requisites

First of all, log in as the Administrator and create a new group with the identifier “EXAMPLE” (under the covers Alfresco will actually call it “GROUP_EXAMPLE”). Then create two new users and add one (not both) to the group.

 

 

Create Warning Banner

In the JavaScript controller for the page define a warning widget that should be displayed if the logged in user is neither an Administrator or a member of the new example group.

 

 

var warning = {
  name: 'alfresco/header/Warning',
  config: {
    renderFilterMethod: 'ALL',
    renderFilter: [
      {
        target: 'groupMemberships',
        property: 'GROUP_ALFRESCO_ADMINISTRATORS',
        renderOnAbsentProperty: true,
        values: [false]
      },
      {
        target: 'groupMemberships',
        property: 'GROUP_EXAMPLE',
        renderOnAbsentProperty: true,
        values: [false]
      }
    ],
    warnings: [
      {
        message: 'You aren't in right group',
        level: 3
      }
    ]
  }
};


The “renderFilterMethod” defines whether to use AND or OR logic for the rules (e.g. ALL rules must pass in order for the widget to be rendered or ANY one of the rules must pass). There are two rules defined, one for the main Administrators group and one for the our newly created group. The “target” is set to be “groupMemberships” (one of the previously mentioned key attributes) and we also declare set “renderOnAbsentProperty” to be true so that the rule is passed if the group doesn’t appear in the “groupMemberships” object. Finally we set an array of values that the target property must be in order for the rule to be satisfied.

 

Create Menu Bar

Now define a menu bar that will be displayed if the user is an Administrator or a member of the new group.

var menuBar = {
  name: 'alfresco/menus/AlfMenuBar',
  config: {
    renderFilterMethod: 'ANY',
    renderFilter: [
      {
        target: 'groupMemberships',
        property: 'GROUP_ALFRESCO_ADMINISTRATORS',
        values: [true]
      },
      {
        target: 'groupMemberships',
        property: 'GROUP_EXAMPLE',
        values: [true]
      }
    ],
    widgets: []
  }
};

 

This time we are inverting the rules. The “renderFilterMethod” is set to ANY as they user just needs to be a member of one of the groups (although being a member of both groups is also fine). The “renderOnAbsentProperty” attribute is omitted because we want to be sure the user is a member of the group and the target value is switched from false to true.

 

Current Item Data

We’ll now define a custom “currentItem” object for our menu bar:

 

menuBar.config.currentItem = {
  test: {
    value: 'show'
  }
};

 

This data can then be used to determine whether or not to render a couple of menu bar items:

 

var menuBarItems = [
  {
    name: 'alfresco/menus/AlfMenuBarItem',
    config: {
      label: 'Should Appear',
        renderFilter: [
          {
            property: 'test.value',
            values: ['show']
          }
        ]
      }
    },
    {
      name: 'alfresco/menus/AlfMenuBarItem',
      config: {
        label: 'Should NOT appear',
        renderFilter: [
          {
            property: 'test.value',
            values: ['visible']
          }
        ]
      }
    }
];
menuBar.config.widgets = menuBarItems;

 

We’re able to omit the “target” attribute because the default behaviour is to check the “currentItem” object. This also shows how we can use dot-notation to address nested attributes in the “currentItem” object.

 

The first menu bar item should be displayed (because test.value is “show”) but the second should not be rendered (because test.value is not “visible”).

 

Build the Page

Finally let’s combine all the definitions into the JSON model for the page:

 

model.jsonModel = {
  widgets: [
    {
      name: 'alfresco/layout/VerticalWidgets',
      config: {
        widgets: [ warning, menuBar ]
      }
    }
  ]
};

model.jsonModel.groupMemberships = user.properties['alfUserGroups'];

 

The last line is the most important - we need to ensure that the “alfUserGroups” property is retrieved from the current user data (available in the user object since Alfresco 5.0).

 

Example In Action

This is defined in a JavaScript controller for a WebScript mapped to the /renderFilter URL. When deployed to a Share (or any Surf based Aikau application) this can be accessed by the URL: http://localhost:8081/share/page/dp/ws/renderFilter

 

These screen shots show the two states depending upon which user has logged in:

 

AikauEx4_groupfail

 

AIkauEx4_menu_bar_item

 

Download the entire example here.

Download a PDF version of this document here.

Outcomes