At the risk of appearing overly verbose, I want to present the topic of DotNetNuke permissions by working from the database level all the way up through the data providers, controllers, and info classes. One of the benefits of using layers of abstraction is that it allows programmers like you and me to work with frameworks without having to know what the cogs inside are doing. However, I find that if you're going to be using the classes in the DotNetNuke framework, then you really must know what is going on behind the scenes. Since there is very little documentation at this time, the only way to learn how to work with the framework is to dig deep. So let's do it.
The Common Patterns
If you haven't picked up on it by now, just about everything within the DotNetNuke framework follows the same few patterns. The tables in the database have associated stored procedures (sprocs) that are used for CRUD (create, read, update, delete) operations. Inside the data provider classes there are methods for CRUD operations that call the sprocs in the database. For each genera of framework functionality there exists controller classes that interact with the data provider in order to provide strongly-typed classes that encapsulate the information from the database. In one way or another, the controller classes have the data from the database "hydrated" into the info classes that you end up accessing in your code (i.e. UserInfo, PermissionInfo, ModuleInfo...). The controller also "un-hydrates" the data from the info classes when in order to send the information back to the data provider. This is how the permissions system works in the DotNetNuke framework.
In The Database
For this portion of the article I will assume that you are using MSSQL and the SqlDataProvider. For those of you who are using some other database, you are freaks! Get with the show! But really, your job will be so much less painful if you use MSSQL with .Net. I say this coming from several years of developing .Net against FoxPro, so trust me on this. But I digress.
The DNN database contains several tables that are pertinent to our discussion. First we have the Permission table. This table holds the different types of permission that you can give to a user or a role. For example "View", "Edit", and "Full Access" are three of the permissions in this table. The PermissionCode column is a string of text that identifies what part of the system or what module the permission is used by. The built-in permissions for the framework begin with the text "SYSTEM_". If your code needs to give custom permissions to its entities, then you could use this table in order to define those permissions. You just need to create your own PermissionCode string as well as set the ModuleDefID column to the ID of the definition for your module. My guess is that there are facilities in the DNN module definition system to register this information for you. Also in the Permission table there is a PermissionKey table. This column, along with PermissionCode in essence establish a compound key for the record to be referenced with.
The other tables that we are interested in are the FolderPermission, ModulePermission, and TabPermission tables. These guys hold granular permission settings for you, you guessed it, folders, module instances, and pages, respectively. Records in these tables will contain the ID of a user or a role, along with the ID of a folder, module instance, or a tab. Records in these tables also have a foreign key to the Permission table so to specify what type of permission you are giving the user or role.
Sprocs
As I stated before, the DotNetNuke framework utilizes stored procedures in its SqlDataProvider to do all its CRUD operations in the database. There are too many to list here, but suffice it to say there is a stored procedure for just about every method defined in the DotNetNuke abstract data provider class (DotNetNuke.Data.DataProvider). Inside the SqlDataProvider, the SqlHelper class is used to execute these sprocs. So if you ever wonder where the SQL code is, the sprocs are where you need to look.
The Info Classes
In order to provide strongly-typed entities to work with, the DNN framework has classes that hold the information from a single record in the database. The FolderPermission, ModulePermission, and TabPermission classes in the DotNetNuke.Security.Permissions namespace are used to encapsulate records from the FolderPermission, ModulePermission, and TabPermission tables, respectively. These classes typically have a public property for each column of their respective table in the database.
The Controller Classes
When you work with permission, you don't have to interact with the data provider directly. You instead use an instance of a controller class. The FolderPermissionController, ModulePermissionController, and TabPermissionController classes in the DotNetNuke.Security.Permissions namespace contain methods that will perform most of the common CRUD operations on the FolderPermission, ModulePermission, and TabPermission tables. When you need to retrieve information from one of the tables in the database you call a Get method on one of these controller, and you will receive an Info object, or a collection of Info objects back. When you want to create or update records in one of the tables in the database you call an Add or Update method on one of these controllers, and pass it a populated instance of one the associated Info classes. This pattern keeps your code clean, and abstracts all of the data access to its own layer.
On To The Good Stuff - Examples
Here is an example of how you can add a new ModulePermission for either a user or a role.
ModulePermissionExample1CS.ascx:
<%@ Control Language="C#" AutoEventWireup="true" CodeFile="ModulePermissionExample1CS.ascx.cs"
Inherits="ModulePermissionExample1CS" %>
<asp:DropDownList ID="ModulesDropDownList" runat="server" Width="300px">
</asp:DropDownList>
<br />
<asp:DropDownList ID="UsersDropDownList" runat="server" Width="300px">
</asp:DropDownList>
<br />
<asp:DropDownList ID="RolesDropDownList" runat="server" Width="300px">
</asp:DropDownList>
<br />
<asp:DropDownList ID="PermissionsDropDownList" runat="server" Width="300px">
</asp:DropDownList>
<br />
<asp:Button ID="Button1" runat="server" Text="Add Permission"
onclick="Button1_Click" />
ModulePermissionExample1CS.ascx.cs:
using System;
using DotNetNuke.Entities.Modules;
using DotNetNuke.Security.Permissions;
using DotNetNuke.Entities.Users;
using DotNetNuke.Security.Roles;
public partial class ModulePermissionExample1CS : PortalModuleBase
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
// populate Modules drop-down lists
ModuleController moduleController
= new ModuleController();
// get ArrayList of ModuleInfo
ModulesDropDownList.DataSource
= moduleController.GetAllTabsModules(PortalId, false);
ModulesDropDownList.DataTextField = "ModuleTitle";
ModulesDropDownList.DataValueField = "ModuleID";
ModulesDropDownList.DataBind();
ModulesDropDownList.Items.Insert(0, "- Select Module Instance -");
// populate Users drop-down lists
// get ArrayList of UserInfo
UsersDropDownList.DataSource
= UserController.GetUsers(PortalId, false);
UsersDropDownList.DataTextField = "Username";
UsersDropDownList.DataValueField = "UserID";
UsersDropDownList.DataBind();
UsersDropDownList.Items.Insert(0, "- Select User -");
// populate Roles drop-down list
RoleController roleController
= new RoleController();
// get ArrayList of RoleInfo
RolesDropDownList.DataSource = roleController.GetRoles();
RolesDropDownList.DataTextField = "RoleName";
RolesDropDownList.DataValueField = "RoleID";
RolesDropDownList.DataBind();
RolesDropDownList.Items.Insert(0, "- Select Role -");
// populate Permissions drop-down list
PermissionController permissionController
= new PermissionController();
PermissionsDropDownList.DataSource
= permissionController.GetPermissionByCodeAndKey("SYSTEM_MODULE_DEFINITION", "");
PermissionsDropDownList.DataTextField = "PermissionName";
PermissionsDropDownList.DataValueField = "PermissionID";
PermissionsDropDownList.DataBind();
PermissionsDropDownList.Items.Insert(0, "- Select Permission -");
}
}
protected void Button1_Click(object sender, EventArgs e)
{
// create instance of ModulePermissionController
// to do all the work for us
ModulePermissionController modPermissionController
= new ModulePermissionController();
// create instance of ModulePermissionInfo to
// hold our permission information
ModulePermissionInfo modPermInfo
= new ModulePermissionInfo();
// i'm not sure if AllowAccess is actually used
// but the framework seems to set this to true
// when it adds ModuleInfo instances to the DB
modPermInfo.AllowAccess = true;
// set id of the permission that was selected
modPermInfo.PermissionID
= int.Parse(PermissionsDropDownList.SelectedValue);
// set id of the Module, not the TabModule
// ... i know, this is confusing
modPermInfo.ModuleID = int.Parse(ModulesDropDownList.SelectedValue);
if (UsersDropDownList.SelectedIndex > 0)
{
// set id of user
modPermInfo.UserID = int.Parse(UsersDropDownList.SelectedValue);
// save the ModulePermissionInfo to the db
modPermissionController.AddModulePermission(modPermInfo);
}
else if (RolesDropDownList.SelectedIndex > 0)
{
// set id of role
modPermInfo.RoleID = int.Parse(RolesDropDownList.SelectedValue);
// save the ModulePermissionInfo to the db
modPermissionController.AddModulePermission(modPermInfo);
}
// set drop-down indexes back to 0
ModulesDropDownList.SelectedIndex = 0;
UsersDropDownList.SelectedIndex = 0;
RolesDropDownList.SelectedIndex = 0;
PermissionsDropDownList.SelectedIndex = 0;
}
}