Avg. Rating 5.0

Problem

You have an application where the permissions needed to access a particular resource require the user to meet several different criteria and one or more of those criteria can be satisfied by multiple values. For example, there may be a report that is only accessible to users who have an administrator role in the application, are members of either the Human Resources or Billing department, and work out of either the North American or European office.

Solution

If the permission requirements for the secured resource can be described in a Boolean statement ("the user must have attribute 1 AND either attribute 2 OR attribute 3 OR attribute 4"), it can then also be represented as a double-delimited list, with one delimiter representing the AND condition and one delimiter representing the OR condition. The relevant attributes from the user's account can then also be represented as a list, and you can use two loops (one nested within the other) to look for the user's attributes within the permission requirements to see if the user meets all of the requirements.

Detailed explanation

The easiest explanation is by example.

User Bob has a user account with an administrative role, is a member of the Billing department, and works in North America.  His permission attributes can be described as "administrator AND Billing AND North America" and represented in a list as "administrator,Billing,North America".

User Sally has a user account with an administrative role, is a member of the PR department, and works in Europe.  Her permission attributes can be described as "administrator AND PR AND Europe" and represented in a list as "administrator,PR,Europe".

The Quarterly Report can only be accessed by users with an administrative role who are members of either the Human Resources or Billing department and work in either the North American or European office.  The security attributes can be described as "administrator AND Human Resources OR Billing AND North America OR Europe" and represented in a list as "administrator|Human Resources,Billing|North America,Europe", with the pipe (|) delimiters denoting the AND conditions and the commas denoting the OR conditions.

To determine if Bob and Sally are permitted to access the Quarterly Report, it becomes simply a matter of counting how many AND conditions there are in the security attributes list, looping through the AND conditions in the security attributes list, and seeing if any of the security attributes within that AND condition can be found in the user's list of permission attributes, and if so incrementing a counter variable.  If at the end of both loops the counter value is equals to the number of AND conditions in the security attributes list, then the user is permitted to access the resource.

Here is code that illustrates that process:

<cfset securityPermList= "administrator|Human Resources,Billing|North America,Europe">
<cfset userAttributeList= "administrator,Billing,North America,whatever else">

<cfset requiredSecurityMatches= ListLen(securityPermList,"|")>
<cfset matchesFound= 0>

<cfloop index="andList" list="#securityPermList#" delimiters="|">
  <!---Loop through the acceptable permission values within the AND condition--->
  <cfloop index="orList" list="#andList#" delimiters=",">
    <cfif ListFind(userAttributeList,orList) GT 0>
       <!---The user has one of the acceptable values, so increment the matchesFound counter--->
       <cfset matchesFound= matchesFound+1>
    </cfif>
  </cfloop>
</cfloop>

<cfif requiredSecurityMatches EQ matchesFound>
  <cfset permitted= "Yes">
<cfelse>
  <cfset permitted= "No">
</cfif>

...using this algorithm, Bob will be permitted to access the Quarterly Report because he meets all three of the AND conditions of the security requirements rule.  Sally however will not be given access to the report, as she only meets two of the three conditions (as a member of the PR department, she fails to meet the middle condition).

One caveat with this recipe: you need to make sure that none of the attribute values you're evaluating (like "North America" or "Billing") contain within their value one of the delimiters you're using in the lists.  If your attribute values are strings (as in this example), you might actually want to avoid using the comma as a delimiter and use a more uncommon character (like ^) instead.  If your attribute values are represented as numeric ids, then this won't be an issue.


+
This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License. Permissions beyond the scope of this license, pertaining to the examples of code included within this work are available at Adobe.

Report abuse

Related recipes