From Zero to launch - Part I
5 05 2008This is the first post in a series of entries that I will use to describe the architecture used in my most recent social networking project. I will discuss the thought processes surrounding each major design decision and explain how the design of the application has helped my team reach the very rough and ambitious deadlines that were placed upon us. This entry will focus on leveraging role-based security and how business rules can easily be written using this approach.
After the information modeling phase of the application was complete, I felt it necessary to focus on the rules that will govern the application’s privacy settings and overall user experience. Given the nature of the application, privacy settings were going to be a large part of every operation that we did so it was important that these rules were clearly defined in a central location. While establishing these rules, we realized that the majority of the rules could be define via roles. Let’s take a look at one rule and observe the evolution as we moved towards a role-based approach.
First iteration:
Some User x may create a Comment for some User y’s profile if at least one of the following is true:
- y is equal to x
- x is a friend of y
Role-based version:
Some User x may create a Comment for some User y’s profile if at least one of the following is true:
- y is in the role ‘Self’
- x is in the role ‘Friend’
This isn’t a huge evolution by any means but it introduces artificial roles that the application must be made aware of. It was time to design a solution that could utilize these artificial roles. The first step was to clearly establish the URL patterns used throughout the application. These URLs represent the very base structure - that is, the URLs that are used underneath any URL rewriting. For the purpose of this article, let’s take a look at a user’s profile page URL:
~/Users/Profile.aspx?UserId=x
For the majority of the projects that I’ve worked on in the past, the validation of these rules would occur by making a call to the business layer in the code behind file of the page. This may work for a variety of cases, but I was beginning to find the restrictions of validating these rules at such a late part in the request lifecycle (e.g. location restriction using roles, role aware controls). To overcome this restriction, we introduced the a series of role-based management HttpModules. Knowing the URL structure, we could rest assured that the “UserId” query string parameter will be present for any User-based viewing action (this was placed in a configuration manager to prevent any potential typos). If the UserId parameter is present, then we can execute a custom stored procedure to retrieve a value that indicates the artificial roles that user belongs to and add the principal user to them.
The code to handle these rules was then pulled into a series of ‘RuleValidator’ classes that were code-based representations of the business rules. The aforementioned rule could be represented in code with the following statement:
/// <summary>
/// Returns a flag indicating the result of rule R102:
///
/// Some User x may create a Comment on some User y's profile if at least one
/// of the following are true:
///
/// <list type="bullet">
/// <item>y is equal to x</item>
/// <item>x is in the role 'Friend'</item>
/// </list>
/// </summary>
/// <param name="pCurrentProfile">The <see cref="UserDetail"/> currently being viewed.</param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"><paramref name="pCurrentProfile"/> was null.</exception>
public static bool IsAuthorizedToCreateComment(UserDetail pCurrentProfile)
{
if (pCurrentProfile == null)
{
throw new ArgumentNullException("pCurrentProfile");
}
IPrincipal _user = HttpContext.Current.User;
return (_user.IsInRole(SiteRoles.Self) || _user.IsInRole(SiteRoles.Friend));
}
After the initial pattern was created for the role-based manager modules (abstracted out into a base role manager class), it was a piece of cake to implement them for the rest of the application modules (e.g. groups, events, photos). That concludes the role-based injection section of the architecture.
Next up: Role-based web controls.
3 Comments