Have you ever needed to implement functionality into a SPFx web part based off the current user’s permissions to a site, list or item. Luckily you aren’t the first and there are many examples out there to show you how to do this and even functions within PnP JS to make it easier.

This past month I had to do it for the first time and decided to use the EffectiveBasePermissions endpoint since I could easily check to see if the user has both the AddListItems and EditListItems permssions. it was pretty straight-forward and easy to implement, however I didn’t really know how or why it worked and I couldn’t find a blog post that dived deep enough and explained it all. Thus, I set off to try and understand it and document it along the way.

The Code

Before we begin let me set the stage with the code that I will be referencing. You can use PnP JS to implement this functionality and I took the hasPermissions function from their library but to illustrate it all clearly I extracted the code and wrote it all out in a linear fashion.

javascript
// PermissionKind Enum, will discuss later on in the post.
import { PermissionKind } from "../../common/models/PermissionKind";
/**
* Function that gets the current user's based permissions and checks to see if they have the AddListItems role.
*/
private async getListPermissions(): Promise<void> {
const effectivePermissions = await this.getListPermissions(
this.properties.siteUrl,
this.properties.eventListId
);
this.canAdd = this.hasPermissions(
effectivePermissions,
PermissionKind.AddListItems
);
}
/**
* Function that makes the REST call to SharePoint
*/
private getListPermissions(webUrl: string, listId: string): Promise<any> {
return new Promise<any>((resolve, reject) => {
let endpoint = Text.format(
"{0}/_api/web/lists(guid'{1}')/EffectiveBasePermissions",
webUrl,
listId
);
this.spHttpClient
.get(endpoint, SPHttpClient.configurations.v1)
.then((response: SPHttpClientResponse) => {
if (response.ok) {
resolve(response.json());
} else {
reject(response);
}
})
.catch((error) => {
reject(error);
});
});
}
/**
* Function that checks to see if the user has a specific permission. This is where the magic happens.
*/
private hasPermissions(value: any, perm: PermissionKind): boolean {
if (!perm) {
return true;
}
if (perm === PermissionKind.FullMask) {
return (value.High & 32767) === 32767 && value.Low === 65535;
}
perm = perm - 1;
let num = 1;
if (perm >= 0 && perm < 32) {
num = num << perm;
return 0 !== (value.Low & num);
} else if (perm >= 32 && perm < 64) {
num = num << (perm - 32);
return 0 !== (value.High & num);
}
return false;
}

Part 1: The Endpoint

Whenever I am trying to understand how code works I start off with the Endpoint the code is calling so I can see the data that is coming back. The EffectiveBasePermission endpoint returns a SP.BasePermission object with 2 properties, type Int.64, High and Low.

xml
<d:EffectiveBasePermissions xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:georss="http://www.georss.org/georss" xmlns:gml="http://www.opengis.net/gml" m:type="SP.BasePermissions">
<d:High m:type="Edm.Int64">2147483647</d:High>
<d:Low m:type="Edm.Int64">4294967295</d:Low>
</d:EffectiveBasePermissions>

Google searches prior had spoiled the reveal of this mystery for me but I still had no clue as to how SharePoint takes this numbers and derives permissions off of it nor did I understand why, to me it would have been much easier to store an key/value pair of the permissions.

Part 2: Dive into the Code

Now that I knew the data I went back to the code to try and figure out what was going on. We get the SP.BasePermission object back from SharePoint and pass that along with the permission right, PermissionKind.AddListItems, to our hasPermission function. The first 2 checks are to make sure a permission right was passed on and the second is to see if the permission right is full mask. The full mask permission simply means that they have all the permission #GodMode.

The next piece of code creates a binary representation of an integer using Bitwise operators. Before we go to deep into that we need to talk about the PermissionKind enum.

The PermissionKind enum is what allows us to write PermissionKind.AddListItems and have it resolve to the correct integer, in this case 2. You can find the enum in the PnP JS library or you can explore the Microsoft.SharePointOnline.CSOM on fuget.org to see the enum. The number that corresponds with the permission right is the position, in a 32 bit binary string, where a 1 will appear. That is why in the function we subtract 1 from the permission right value so that we can shift the 1 in the num variable to the left by that many spaces. If the integer (minus 1) is above 32 then that permission right is considered high and we subtract 32 from it since the first 32 spots will always be 0 and that can be seen on line 62 in the else if condition.

The rest of the code has to do with Bitwise Operators and we use these to convert the integers into binary and compare the binary numbers to see if a user has a specific permissions right. The << (zero fill left shift) bitwise operator shifts a number to the left x amount and fills the remaining slots with 0s. The single & (AND) bitwise operator compares 2 binary strings to see if the 1s match up. For more information on Bitwise Operators click here, it helped me understand what was happening and how it all worked.

Part 3: Running through the Code

Let’s use the AddListitems permission right to test our code and see if the user has permissions. If we check the enum it resolves to the number 2. Now we need to subtract 1 and put it through our IF condition. It is less than 32 so we are going to be testing against the Low permission number and do not need to subtract 32 before performing our zero fill left shift. After performing the shift the num variable holds the value of 2.

debugging the hasPermission methoddebugging the hasPermission method

We then compare it with the AND bitwise operator to see if there is a 1 in the second position of the Low number. If there is then it will return 1 if there isn’t it will return 0. We then run this against our test to see if it is not equal to 0 and return the outcome of that check. When we run this part of the code we find out there is a 1 in the second position of the Low number so the user has the AddListItems permission right.

canAdd equals truecanAdd equals true

Conclusion

SharePoint uses integers to store which permission rights a user has to a given site, web, list or item. When converted to binary each 1 in the string acts as a flag or indicator that says this user has this permission. Based on where the 1 appears in the 32 character binary string determines a different permission right. If a 1 appears in the second position it means that the user has the ability to add items, if it appears in the third they have the ability to edit items so on and so forth. We can use the PermissionKind enum and Bitwise operators to perform these checks and see what permissions a user has to integrate it into our solutions.

I hope this post helps you better understand these functions and how it all works behind the scenes so that when you use them you can speak to how they work. If you have any questions drop a comment below.

AaaS - Anthony as a Service