During this weekend I have made a new version of the Permission Manager. There are several changes and the new version will only be available for the Visual Studio 2005 October CTP, it will not work for the Beta 1. Some of the changes are:
1) Permissions are now added to the configuration file. It will make it easier to deploy an application that uses the Permission Manager.
2) There are new methods for updating and removing permissions from users and roles.
3) It’s now possible to give a user or role a specific permission without setting the permission on a source (object).
4) The CreatePermission method is removed, instead there is a Permissions method and a Groups property added to the PermissionProvider. Those members will return the permissions added to the configuration file.
The following is a simple demonstration of how you can use the Permission Manager.
When you use the Permission Manager you first have to specify the permissions that should be used. This is done by adding the <permissions> element to the <permissionManager> section in the configuration file:
<configSections>
<section name="permissionManager" type="Nsquared2.Web.Configuration.PermissionManagerSection, Nsquared2.Web, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</configSections>
<permissionManager enabled="true">
<permissions>
<group>
<permission name="Read" description=""/>
<permission name="Write" description=""/>
<permission name="Modify" description=""/>
</group>
<group name="News">
<permission name="Read" description="Allows to read news"/>
<permission name="Write" description="Allow to create news"/>
</group>
</permissions>
</permissionManager>
Permissions are grouped into groups by using the <group> element. By using the <group> element, you can specify the permissions that will only be available for a specific kind of object. In the code above there are two groups, one global and a News group. With the global group you can grant a user or role a global permission (permissions that belongs to the user and not to an specific object), for example, user John Doe should have Read permission:
PermissionManager.SetPermissionForUser("John Doe", "Read");
You don’t need to set this permission to a source. The source will instead be the application. So if you should check if a user has the “Read” permission you can use the HasUserPermission method:
if (PermissionManager.HasUserPermission("John Doe", "Read"))
Response.Write("User has permission to read..");
You can’t use the global permissions for a source that belongs to another group. Every source (object) belongs to a specific group. The reason why, is because you should not have the possibility to specify other permissions than the ones allowed to be set for an object. For example if you have a News object, you maybe only want to use a Read and Write permission, nothing else. So if you have given a user or a role the Read permission globally you can’t check if the user has the Read permission for an object that belongs to another group:
if (PermissionManager.HasUserPermission("John Doe","News","MyNews","Read"))
Response.Write("User has permission to read..");
The code above will return false. If you have given the user the Read permission for a specific source, you can then check if a user has the permission to read the source:
PermissionManager.SetPermissionForUser("John Doe", "News", "MyNews", "Read");
if (PermissionManager.HasUserPermission("John Doe","News","MyNews","Read"))
Response.Write("User has permission to read..");
In the code above the “News” is the name if the group that are specified in the configuration file, it’s the group where the “MyNews” source belongs to:
<group name="News">
<permission name="Read" description="Allows to read news"/>
<permission name="Write" description="Allow to create news"/>
</group>
Note: If you try to grant a user or s role permission that does not belong to the “News” group, an exception will be thrown.
Every object you can set permissions for must belong to a group and have a unique identifier. Instead of passing the name of the group and a unique identifier to the SetPermissionForUser method etc, you can create an object that you pass as an argument. To create a custom object you have to implement the IAccessObject interface.
public interface IAccessObject
{
string SourceGroup
{
get;
set;
}
string SourceId
{
get;
set;
}
}
The SourceGroup property returns the name of the group the object belongs to and the SourceId the unique identifier that will unique identify the instance of the object. The following is a News object that uses the IAccessObject interface:
public class News : IAccessObject
{
private string _group = “News”;
private int _id;
public string SourceGroup
{
get { return this._group; }
set { throw new NotSupportedException(); }
}
public string SourceId
{
get { return this._id.ToString(); }
set { throw new NotSupportedException() };
}
public int Id
{
get { return this._id; }
set { this._id = value; }
}
...
}
The SourceId in the code above will return a string that will represents the unique id of News object.
The following example will give the role “Everyone” permission to modify the News object:
News news = new News();
news.ID = 10;
PermissionManager.SetPermissionForRole("Everyone", news, "Write");
To check if the role “Everyone” has been granted the “Write” permission for the News object you use the HasRolePermission method:
if (PermissionManager.HasRolePermission("Everyone", news, "Write"))
Response.Write("Everyone has the permission to modify the news");
Note: You can only set permission for a role if the .Net 2.0 Roles feature is used, if not an exception will be thrown.
When you use the HasUserPermission, the method will first check if the roles a user belong to have the specified permission. If one of the roles a user belongs to have the specified permission, the method will return true, but only if the user don’t have the permission denied. The following example have granted the “Everyone” the permission to read the News object, assume that the user “John Doe” belongs to the “Everyone” role, the example will also check if “John Doe” has the permission to read the news object:
PermissionManager.SetPermissionForRole("Everyone", news, "Read");
//This method will return true
if (PermissionManager.HasUserPermission("John Doe", news, "Read"))
Response.Write(“John Doe can read the news”);
You can also allow or deny permission for a user or role. Denied permission has the highest priority, so even if you have allowed a specific permission for a user, but one of its roles has the same permission set to deny, the user will not have the permission allowed.
If you have any questions or if there are methods that you wanted to be added to the Permission manager, please let me know. You can find the latest version of the Permission Manager on the Permission Manager workspace.