Click here to Skip to main content
Click here to Skip to main content

Creating a DotNetNuke Module with Custom Permissions

, 9 Jan 2009 CPOL
Rate this:
Please Sign up or sign in to vote.
Tutorial on how to add custom permissions to a module's settings.

Introduction

Welcome, keen DNN module developer, to this walkthrough. Here I'll describe, step by step, how to add custom permissions to a DNN module. This tutorial may change in future, as new information emerges; to keep informed of new developments, subscribe to the RSS feed of my blog.

First things first. Here are the assumptions I'm making in this walkthrough:

  1. You know about basic module structure, the DAL, and the module starter kit.
  2. You're using Visual Studio or Visual Studio Express with the module templates installed.
  3. You know about C# and ASP.NET.

These are, of course, not obligatory. Your life will be a lot easier if these assumptions apply, though.

Are you sitting comfortably? Then, we'll begin...

Step 1: Creating a Dummy Module

The easy bit. You should have done this before, so I'll keep it short. Go to your DNN project in Visual Web Developer, right-click on the top node, and select "Add New Item". Select "DotNetNuke Dynamic Module" and the language of your choice (this walkthrough will use C#). Enter 'PermissionTest' as the module name. Rename the folders as per instructions, don't forget to amend the web.config file, and hit Ctrl-F5 to start your development installation of DNN. Go to Host->Module Definitions, scroll to the bottom of the page, click on "Import Module Definition", select the manifest of the module you just created, and hit "Import Manifest".

Your module should appear in the list of installed modules, but there's a little bug to take care of. Click on the pencil icon next to 'PermissionTest' to bring up the module properties page. If you have some sort of prefix in the module name and folder name text boxes (CreativeCats.PermissionTest, in my case), delete the prefix so that only 'PermissionTest' remains. Next, go to Host->SQL, copy and paste the contents of the file "01.00.00.SqlDataProvider" which was created for you in the DesktopModules/MODULENAME folder. Make sure the "Run as Script" checkbox is ticked, and click "Execute".

If I just lost you, you may want to go back to Michael Washington's tutorial series, which gives detailed instructions on how to create a simple module.

Now, go to any page on your site and install the module, just to see that the code so far is OK. Click on "Settings" to take a look at the default settings page. You'll see the standard permissions that apply to all modules, "View Module" and "Edit Module". That's what we're going to change.

According to Vicenç Masanas' blog entry, there is no automated way of creating custom module permissions during module installation, so he suggests using the IUpgradeable interface to accomplish this. Yes, the blog is from 2006, but so far, I haven't found any information to the contrary, so that's the method I'm using. (I have seen a suggestion for creating the permissions during the page_load event, but I can't help wondering if that is truly wise... However, if you know anything I don't, please give me a shout.)

Purely for development purposes, we're going to cheat by putting a button on our view control and wiring the button_click event handler to add the permissions. That's just to give you the opportunity to step through what's happening in the debugger and to allow testing without continually uninstalling and reinstalling the module. So, add a button at the bottom of your ViewPermissionTest.ascx (or whatever yours is called), double-click it to add the event handler in the code-behind file, and add the following lines:

PermissionTestController cntrl = new PermissionTestController();
cntrl.UpgradeModule("01.00.00");

Step 2: Implementing the IUpgradeable Interface

First, of course, we need to declare our controller class as implementing the IUpgradeable interface. The class declaration should look something like this:

public class PermissionTestController : ISearchable, IPortable, IUpgradeable

To implement the IUpgradeable interface, we need to implement the following method in the module's controller class:

string UpgradeModule(string Version)

(The controller class has been created for you in the App_Code directory. I called my module PermissionTest, so in my case, the controller is 'Visual Studio 2008\WebSites\DNN484\App_Code\PermissionTestController.cs'.)

The standard way of doing this seems to be by checking the module version and calling whatever you want to happen during the upgrade. In our case, creating the custom permissions via a private method, InitModulePermissions(). First off, you'll need to include the following namespaces in the controller class:

using DotNetNuke.Security.Permissions;
using DotNetNuke.Entities.Modules;
using DotNetNuke.Entities.Modules.Definitions 
using System.Collections;

Next, you need to implement the IUpgradeable functionality:

public string UpgradeModule(string Version) 
{ 
   if (Version == "01.00.00") 
   { 
      // Install module permissions 
      InitModulePermissions(); 
   } 
   return Version; 
}

OK, explanations about the InitModulePermissions method:

In order to add permissions, we need a PermissionController.

private void InitModulePermissions()
{
    PermissionController permCtl = new PermissionController();
}

To add a permission, we need to call the PermissionController's AddPermission method, which takes a PermissionInfo object as an argument. So now, we have:

private void InitModulePermissions() 
{ 
   PermissionController permCtl = new PermissionController(); 
   try 
   { 
      PermissionInfo pi = new PermissionInfo(); 
      permCtl.AddPermission(pi); 
   }
   catch{}
}

Of course, an empty PermissionInfo object is no use to anybody. At this point, it's worth taking a little detour to look at the Permission table in DNN:

Permission Table

This is the information we need to provide. The Permission Code identifies which module settings will be affected. This code can also be used to retrieve permissions later (you'll see...). The Permission Key is, well, a key value, and the Permission Name is what will be displayed on the settings page. These three values are defined by you, like so:

private void InitModulePermissions() 
{ 
   PermissionController permCtl = new PermissionController(); 
   try 
   { 
      PermissionInfo pi = new PermissionInfo(); 
      pi.PermissionCode = "PERMISSIONTEST";
      pi.PermissionKey = "PERMISSION1";
      pi.PermissionName = "A custom permission"; 
      permCtl.AddPermission(pi); 
   }
   catch{}
}

The ModuleDefID is a little trickier. Each module's ModuleDefID is stored in a ModuleDefinitionInfo object. This can be retrieved through the GetModuleDefinitionByName() method of the ModuleDefinitionController. However...

GetModuleDefinitionByName() needs, apart from the module name, the DesktopModuleID, which is stored in a DesktopModuleInfo object. And, that can be accessed through yet another controller, the DesktopModuleController. Which leaves us with the following code:

private void InitModulePermissions()
{ 
   PermissionController permCtl = new PermissionController(); 
   DesktopModuleController desktopMod = new DesktopModuleController(); 
   DesktopModuleInfo desktopInfo = 
     desktopMod.GetDesktopModuleByModuleName("PermissionTest"); 
   ModuleDefinitionController modDef = new ModuleDefinitionController(); 
   ModuleDefinitionInfo modDefInfo = 
     modDef.GetModuleDefinitionByName(desktopInfo.DesktopModuleID, 
     "PermissionTest"); 
   try 
   { 
      PermissionInfo pi = new PermissionInfo(); 
      pi.ModuleDefID = modDefInfo.ModuleDefID; 
      pi.PermissionCode = "PERMISSIONTEST";
      pi.PermissionKey = "PERMISSION1";
      pi.PermissionName = "A custom permission"; 
      permCtl.AddPermission(pi); 
   }
   catch{}
}

Phew.

Note: GetModuleDefinitionByName() takes two arguments: the Desktop Module ID and the Friendly Name of the view control in question. So, if your module has a friendly name that differs from the module name, or if you are developing a module with multiple definitions, make sure that you use the appropriate name...

But, that's it (for now). Set a breakpoint at the beginning of this new method, run up your DNN site in debug mode, click on the button on your new module, and see what your handiwork does. If you look at the Permission table when this method has finished, you should see your new entry, and looking at the settings for your module, you should have a new column of checkboxes...

Step 3: Encapsulating the Permissions

The code so far uses a number of magic strings - generally considered as practical as a chocolate wok. A much better solution is to encapsulate the security functionality in a special class. So, in the App_Code directory, create a new class, ModuleSecurity, with the strings you need declared as constants:

public class ModuleSecurity 
{ 
   // Constants 
   public const string PERMISSIONCODE = "PERMISSIONTEST"; 
   public const string PERMISSION1 = "PERMISSION1"; 
}

Now, you can change your try() block to use these constants:

try 
{ 
   PermissionInfo pi = new PermissionInfo(); 
   pi.ModuleDefID = modDefInfo.ModuleDefID; 
   pi.PermissionCode = ModuleSecurity.PERMISSIONCODE; 
   pi.PermissionKey = ModuleSecurity.PERMISSION1; 
   pi.PermissionName = "A custom permission"; 
   permCtl.AddPermission(pi); 
}

Step 4: Implementing Permission-based Functionality

OK, putting the custom permissions into the module settings page is all very well, but without a way of actually checking the permissions, for whatever nefarious purpose you have in mind, it's a moot point. So, let's add a little extra functionality to our module - a secret message (woooo...). Just add a Label to your view control, set some text, and change the Visibility to False.

<asp:label id=Label1 Visible="False" Text="My Secret Message" runat="server"></asp:label>

Next, we need to modify the ModuleSecurity class to give us a way of retrieving the permissions. We can get the permissions for each individual module through a ModulePermissionController, but...

The ModulePermissionController's HasModulePermission() method needs a ModulePermissionCollection, which can be retrieved through the ModuleInfo class, which each module inherits, similar to its ModuleID. So, if we want to check a module's permissions, we need to pass its ModuleInfo into the constructor of our ModuleSecurity class. We also need a private member for each permission, and a way of retrieving it. That makes the complete ModuleSecurity class:

public class ModuleSecurity 
{ 
   // Constants 
   public const string PERMISSIONCODE = "PERMISSIONTEST"; 
   public const string PERMISSION1 = "PERMISSION1"; 

   // private variables 
   private bool _permission1; 

   public ModuleSecurity(ModuleInfo moduleInfo) 
   { 
      ModulePermissionCollection permCollection = moduleInfo.ModulePermissions; 
      _permission1 = 
        ModulePermissionController.HasModulePermission(permCollection, PERMISSION1); 
   } 

   public bool HasPermission1 
   { 
      get { return _permission1; } 
   } 
}

Say, we want to display the new Label based on permissions. That means adding the following lines to the Page_Load event of the view control:

ModuleSecurity ms = new ModuleSecurity(this.ModuleConfiguration); 
Label1.Visible = ms.HasPermission1;

And, that's all there is to it. Add a few test modules to a page, give different permissions to different user groups, and see how the label visibility changes based on each module's permissions...

Epilogue: The Belt Upon the Braces

It you take a look at some of the standard DNN modules that use custom permissions (such as the User Defined Table), you'll see that existing permissions are retrieved and checked before adding new ones. Now, when I tried adding redundant permissions by clicking the button several times, nothing untoward happened, i.e., the permissions table did not suddenly sprout multiple entries for each permission. However, if you want to be on the safe side, it's worth putting this little check in place - it's not as if it's hugely complicated. I'll give you the entire source code; the change is straightforward, and I'm sure you'll figure it out...

private void InitModulePermissions() 
{ 
   PermissionController permCtl = new PermissionController(); 
   DesktopModuleController desktopMod = new DesktopModuleController(); 
   DesktopModuleInfo desktopInfo = 
     desktopMod.GetDesktopModuleByModuleName("PermissionTest"); 
   ModuleDefinitionController modDef = new ModuleDefinitionController(); 
   ModuleDefinitionInfo modDefInfo = 
     modDef.GetModuleDefinitionByName(desktopInfo.DesktopModuleID, 
     "PermissionTest"); 
   ArrayList arr = 
     permCtl.GetPermissionByCodeAndKey(ModuleSecurity.PERMISSIONCODE, "");
   bool bPermission1=false;
   foreach (PermissionInfo p in arr) 
   { 
      if ((p.PermissionKey == ModuleSecurity.PERMISSION1)&&
          (p.ModuleDefID == modDefInfo.ModuleDefID)) 
         bPermission1 = true; 
   }
   try 
   { 
      PermissionInfo pi = new PermissionInfo(); 
      pi.ModuleDefID = modDefInfo.ModuleDefID; 
      if(!bPermission1)
      { 
         pi.PermissionCode = ModuleSecurity.PERMISSIONCODE; 
         pi.PermissionKey = ModuleSecurity.PERMISSION1; 
         pi.PermissionName = "A custom permission"; 
         permCtl.AddPermission(pi); 
      }
   }
   catch{}
}

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Frauke
Web Developer Creative Cats
United Kingdom United Kingdom
No Biography provided

Comments and Discussions

 
QuestionYou can use manifest file to add custom permission now Pinmemberm2land21-Oct-12 5:40 
AnswerRe: You can use manifest file to add custom permission now Pinmemberremesqny14-Jul-13 4:48 
GeneralBreakpoints PinmemberMel Shellam17-Jan-09 8:09 
GeneralRe: Breakpoints PinmemberFrauke17-Jan-09 12:52 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.1411023.1 | Last Updated 9 Jan 2009
Article Copyright 2009 by Frauke
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid