From zero to launch - Part II: Role-based Security and Web Controls

12 05 2008

This is the second post in a series of entries that I am using to describe the architecture used in my most recent social networking project. While some of the architecture is omitted from these discussions, I would like to share some of the tricks that my team used to decrease development time and meet the rough and ambitious deadlines that were placed upon us. This entry will continue the discussion on role-based security but it will focus on creating role-based web controls.

First, I will discuss the design of the commonly used controls. The layout of the application consistently made use of a Cascading Style Sheet (CSS) class named “module”. This was essentially a tabbed container with varying content that was used consistently throughout our mockups. The other variation of this style was a similar construct without the tabs. This spawned two controls that became the basis of the site:

  • LayoutModule
  • TablessModule

These controls use a template container approach to ensure that the proper classes are used but allow for complete customization of the inner content. The following is an example using the TablessModule:

<rr:TablessModule ID="contactModule" runat="server">
	<HeaderTemplate>
		<h2>
			Company Information</h2>
		<hr />
	</HeaderTemplate>
	<ContentTemplate>
		<p>Content here</p>
	</ContentTemplate>
</rr:TablessModule>

After creating the skeleton structure of the majority of our pages, we began to observe a pattern: we were showing/hiding controls based on roles that the principal user belonged to. This then spawned a series of controls which utilized the notion of “AllowedRoles” and “DeniedRoles” which then controlled their visibility.

Consider the following helper method:

/// <summary>
/// Parses the specifed <see cref="System.String"/> values into a comma separated
/// list of values.
/// </summary>
/// <param name="values"></param>
/// <returns></returns>
public static string GetCommaSeparatedString(params string[] values)
{
	if (values == null || values.Length == 0)
	{
		return String.Empty;
	}

	StringBuilder retVal = new StringBuilder();
	int last = values.Length - 1;
	for (int i = 0; i < values.Length; ++i)
	{
		retVal.Append(values[i]);
		if (i != last)
		{
			retVal.Append(",");
		}
	}
	return retVal.ToString();
}

Given a TablessModule “userInfoModule”, consider the following example:

userInfoModule.AllowedRoles = SiteUtil.GetCommaSeparatedString(SiteRoles.User);
userInfoModule.DeniedRoles= SiteUtil.GetCommaSeparatedString(SiteRoles.Friend);

This is especially helpful for profile links that are useful for other users viewing your profile. We don’t want to display links like “Send a Message” when you’re looking at yourself. The example above grants Users in the Role ‘User’ to view the module and explicitly denies access to Users in the Role ‘Self’. A simple translation would be:

Given some TablessModule containing information for some User x, some User y may view that TablessModule if that User y is in the Role ‘User’ and that User y is not that User x.

Once again, this was another step towards readability and simplicity for business-rule implementation. Stating the allowed and denied roles in code is easily understandable, in my opinion. This concludes the role-based web control section of this discussion.

Next up: Reusable user controls

kick it on DotNetKicks.com


One Response to “From zero to launch - Part II: Role-based Security and Web Controls”

  1. From Zero to launch - Part I | Joshua Arnold Says:

    [...] From zero to launch - Part II: Role-based Security and Web Controls [...]

Leave a Reply