Permission Pattern

Most application code revolves around doing things – reading and writing data primarily. But a large portion is dedicated to the sole task of checking if you can do things. This is generally referred to as “business rules”. The logic of these rules is often subject to rapid change at request of the client, and it can get very complex. This makes it a prime nest for bugs, or worse yet, features masquerading as bugs.

In the real world, you might mentally check dozens of questions before you do something, and then other people might check as well. Lets say you want to go to a trendy new night club. A preliminary set of permission checks might include:

  1. Do you have money for the cover?
  2. Are you old enough?
  3. Are you carrying an ID?
  4. Are you dressed according to the dress code?
  5. Are you carrying any drugs, weapons or other forbidden items?

Now the establishement might have additional checks:

  1. Is the club letting in patrons at this time?
  2. Is the club filled to capacity?
  3. Are you on the guest list or with someone on the guest list?

Additional rules might supersede other rules:

  1. Are you a VIP? If so, you don’t need to pay the cover or get an ID check. Also you will be in a VIP room so you may enter even if the club is filled to capacity.

So as you can see, the process of checking if you can enter the club is much more complex than the action of walking through the door. The same is true of application logic. In fact, the explicit nature of coding would apply additional questions that you wouldn’t reasonably ask in the real world:

  1. Do you exist?
  2. Does the club exist?
  3. Are you a human?
  4. Are you alive?
  5. Have you already entered the club?

If there are multiple entrances to the club, you might have to relay these rules to several people, make sure they are notified if the rules change, make sure they stay in sync as global conditions change (like max capacity), and be sure they are enforcing the rules vigorously.

Suddenly a seemingly simple check has become a complex beast with a high probability of failure.

I developed the Permission Pattern primarily to encapsulate and organize rules, to increase code readability and continuity, as well as to improve security and data integrity.

Can You Dig It?

For every business action, create a method that answers whether that action is permitted.

In code speak, if you have a class with a method called DoSomething(), write a method called CanDoSomething() which returns true or false. Keep these methods paired so the pattern can be easily replicated.

No matter how complex the permission check gets, you can write it once and forget about it. From a readability perspective, the calling code practically reads like English. It’s that simple!

 vb.net |  copy code |? 
1
2
If Thing.CanDoSomething() Then Thing.DoSomething()
3

The key is to create both functions at the same time even if the permission check initially always returns true.

Tell Me Why

But what if you can’t do something? You’re normally going to want a reason why not, so you can decide how to proceed.

So now our permission function will return two values: a boolean and a string. To accomplish this, I’m going to pass in an optional reference string and modify it internally. In our generic example, let’s imagine the Thing class has a property called SomeRequiredData:

 vb.net |  copy code |? 
1
2
Public Function CanDoSomething(Optional ByRef ReasonWhyNot As String = "") As Boolean
3
            If Me.SomeRequiredData is Nothing Then
4
                ReasonWhyNot = "No Data was received."
5
                Return False
6
            End If
7
            Return True
8
        End Function
9

Notice the parameter is ByRef and not ByVal. It is critical that the parameter is a pointer to the original string and not a copy. By default in nearly all languages, strings are copied and not referenced when they are passed into methods.

Let’s also assume that our calling code has a Message function that displays a message to the user.

 vb.net |  copy code |? 
1
2
 
3
Dim ReasonWhyNot = ""
4
If Thing.CanDoSomething(ReasonWhyNot) Then 
5
   Thing.DoSomething()
6
   Message("Something was done.")
7
Else
8
   Message("Something was not done. " & ReasonWhyNot)
9

Now maybe this isn’t sitting well with you. It’s a bit unconventional and you might be wondering why it’s necessary to pass in an empty string rather than just making the string a return value. Or why not return a status code that references the messages somewhere else. Let’s examine those two options and see.

Alternate 1: Just return the string response

First off, a function with a prefix of Can or Is should return a boolean. So let’s also change the name to be more specific.

 vb.net |  copy code |? 
1
2
Public Function GetReasonYouCanNotDoSomething() As String
3
            If Me.SomeRequiredData is Nothing Then
4
                Return "No Data was received."
5
            End If
6
            Return ""
7
        End Function
8

 vb.net |  copy code |? 
1
2
Dim ReasonWhyNot as String = Thing.GetReasonYouCanNotDoSomething()
3
If Not String.IsNullOrEmpty(ReasonWhyNot) Then 
4
   Thing.DoSomething()
5
   Message("Something was done.")
6
Else
7
   Message("Something was not done. " & ReasonWhyNot)
8

See how awkward that is to read? In conversation, there is a two part dialog of asking if you can, then asking why not. You wouldn’t simply ask someone to provide a reason you can’t do something, then interpret their silence as permission! This brings me to a key point:

The more closely code resembles natural language, the easier it is to read, understand, and spot bugs

Alternate 2: Return a status code

Again, we’ll change the name to match the new purpose.

 vb.net |  copy code |? 
1
2
Public Function GetDoSomethingStatus() As Integer
3
            If Me.SomeRequiredData is Nothing Then
4
                Return Status.NoData // 2
5
            End If
6
            Return Status.CanDoSomething  // 1
7
        End Function
8

 vb.net |  copy code |? 
1
2
Dim Status as Integer = Thing.GetDoSomethingStatus()
3
If Status = Status.CanDoSomething Then 
4
   Thing.DoSomething()
5
   Message("Something was done.")
6
Else
7
   Message("Something was not done. " & Thing.GetStatusDescription(Status))
8

So in this case, the readability of the If statement is better than the previous example. The main drawback about this approach is that the calling code now has to be more knowledgeable of the class it calls. It has to know about status codes, what they mean, and how to convert them to a text response. A true or false response as to whether you can do something is about as clear as it gets. And there is another advantage to passing in a reference string.

Chaining

With even a small application, you’re rarely interacting with a single object that makes all the decisions. You generally have a web of interconnected objects that all communicate with each other. If you replicate the Permission pattern in several classes, the permission functions can call each other and pass the same reference string along.

Let’s assume there’s a global CurrentUser object with some permission rules. And let’s also assume that Thing contains modifies two child objects in DoSomething()

 vb.net |  copy code |? 
01
02
Public Function CanDoSomething(Optional ByRef ReasonWhyNot As String = "") As Boolean
03
            If Not CurrentUser.CanModifyThing(ReasonWhyNot)
04
                Return False
05
            End If
06
            If Not Me.ChildObject.CanBeModified(ReasonWhyNot) Then
07
                Return False
08
            End If
09
            Return Me.AnotherChildObject.CanBeModified(ReasonWhyNot)
10
        End Function
11

What’s nice is that even as your logic grows more complex, the calling code stays the same. The ReasonWhyNot string can get passed around to different objects and update accordingly. Conversely, the status code approach would have needed to grow to accommodate the various codes, and each class would be required to know more about the other classes.

Internal Enforcement

What if you don’t check if you can do something before you do it? In the night club scenario, you could get away with it, or get thrown out on your head. Either way, it’s a bad idea and likely to cause trouble.

Even though you will probably write your calling code and your class interface at the same time, defensive programming dictates you should write your class with the assumption that the calling code will misuse it. Here’s how to add some security to DoSomething()

 vb.net |  copy code |? 
1
2
public sub DoSomething()
3
  Dim ReasonWhyNot = ""
4
  If Not CanDoSomething(ReasonWhyNot) Then 
5
    throw Exception("Thing.CanDoSomething = false " & ReasonWhyNot)
6
  End If
7
 //execute code here
8
end sub
9

Now you’ve added an extra layer of security, you’ve possibly prevented some data corruption, and you have a user friendly error message in your exception.

The cost is that now the CanDoSomething check is being called twice. There might be cases where that check is resource intensive, testing dozens of other classes and you don’t want the performance hit of redundant calls. Now you could store the results of CanDoSomething() internally the first time and just return it the second time, but this is risky if you are checking external factors that are subject to change.

Try Something

One way around this is to modify the calling code. Rather than calling CanDoSomething() followed by DoSomething(), you could simply wrap DoSomething() in a Try/Catch block and use the exception message as your response.

 vb.net |  copy code |? 
1
2
Try
3
   Thing.DoSomething()
4
   Message("Something was done.")
5
Catch ex
6
   Message("Something was not done. " & ex.Message)
7
End
8

This approach should be used very judiciously because it will catch all exceptions including any cases you might have missed in CanDoSomething(). This could have the unwanted effect of preventing deeper exceptions that would stop code execution, as well as possibly exposing exception messages that are either not user friendly or leak secure application information if you choose to display the exception message to the user.

User Interface

It’s a much better user experience to prevent an action before it’s ever attempted. Using the Permission Pattern, we can easily toggle a button and display the reason why not as the title of a disabled button. The caveat is that the Thing object must exist and have all necessary data required to make the check at the time the page is displayed. So it works better for role and status checks than input validation, which is kind of a separate process than the privilege check.

 ASP |  copy code |? 
1
2
<% Dim ReasonWhyNot = ""
3
  If Thing.CanDoSomething(ReasonWhyNot) Then %>
4
     <button title="Click to do something" onClick="Thing.DoSomething()" />
5
  <% Else %>
6
     <button disabled title="<%= ReasonWhyNot %>" />
7
  <% End If %>
8

With all these features in place, you are now checking privileges with the same logic and displaying the same messages in the user interface, the calling code, and within the class itself. It’s easy to read and keeps the logic hidden away where it belongs.

Multiple Permission Denial Message at Once

It’s often better for the user if you can give all the reasons an action is denied at once. Imagine once again that there are several reasons you can’t enter our trendy night club.

  1. You don’t adhere to the dress code (input validation)
  2. The night club is full except for VIP’s (business rule)
  3. You are not a VIP (role-based access)

Now you would be pretty upset if you were only given the first reason, went home, changed your clothes, came back, waited in line, then got the second reason! You would much prefer to get all the information at once, so you could make a more informed decision and not waste time. In this case you could modify the pattern to pass either a list or dictionary object instead of a string. You would also need to rewrite the permission functions to not return early if a reason is discovered. This has to be handled on a case by case basis depending on your specific needs.

Real World Example

I was working on a file uploader when I truly evaluated and solidified this pattern. File uploading in general requires checks against missing data, file size, valid name, valid extension, and for extra security, valid mime type. With the file size requirement, I wanted to provide a custom response with the size of your file and the max size.

 vb.net |  copy code |? 
01
02
Public Function CanUploadFile(Optional ByRef ReasonWhyNot As String = "") As Boolean
03
 
04
            If MFileData Is Nothing Then
05
                ReasonWhyNot = "No File Data was received."
06
                Return False
07
            End If
08
 
09
            Dim fileSize = FileData.Length
10
 
11
            If fileSize > MAX_FILE_BYTE_SIZE Then
12
                Dim fileMegs = Math.Round(fileSize / 1000000, 2)
13
                Dim maxMegs = Math.Round(MAX_FILE_BYTE_SIZE / 1000000, 2)
14
                ReasonWhyNot = String.Format("The file size is {0} MB and exceeds the max size of {1} MB.", fileSize, maxMegs)
15
                Return False
16
            End If
17
 
18
            If Not ExtensionIsValid Then
19
                ReasonWhyNot = String.Format("{0} is not a valid file type. Only the following file types are accepted: {1}", Extension, String.Join(",", BusUserFile.VALID_EXTENSIONS))
20
                Return False
21
            End If
22
 
23
 
24
            Return True
25
        End Function
26
 
27
 
28

Summary

The main objective of this pattern is to simplify complex rules. All too often I’ve seen permission checks begin at the beginning of a post action, and continue to grow into monstrosities as rules get more complex. These monstrosities then replicate with new pages. If you simply get into the habit of creating a CanDo() function right above your Do() function, you will keep permission checks simple, keep your classes loosely coupled and your business logic modular and flexible. Simple code also means less bugs, and in this case that means greater security as well. That’s all for now. Happy coding and I’ll see you in the VIP section.

This entry was posted in asp.net, object oriented programming, The Good. Bookmark the permalink.

3 Responses to Permission Pattern

  1. Willy Connor says:

    I love the readablility of this code. If I inherited a code base written using this pattern I think it would be a breeze to get up to speed on the business logic. This would also make unit tests easy to write, maintain and read.

  2. Jesse Voogt says:

    I too appreciate the pattern’s readability, and it’s a good case for the use of “ByRef” arguments. The only thing that bothers me is that the “ReasonWhyNot” is a string rather than an Enum error code — I don’t like my business logic generating the text that the end-user might see. Then again, with an error code the business logic wouldn’t be able to return specific information as to why it failed.

    For most applications, I’d probably stick with returning an Enum, which has a attribute for each enum value (and of course I have a handy extension method for getting that attribute for any enum by calling MyEnum.Description). That way you can have a code and a message all in one — the View might use the code instead of the enum if the Description attribute doesn’t quite work so well in whatever context the message is seen.

    To be able to return more detailed reasons-why-not, I might just use two separate ByRef params: ByRef ReasonWhyNotCode As SomeKindOfEnum, Optional ByRef ReasonWhyNotMessage As String = Nothing

  3. Jesse Voogt says:

    In my last comment, second paragraph first sentence, I meant to write “which has a Description attribute” — I’m guessing the less than and greater than signs kept that from making it…

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>