Sunday, May 11, 2008

Role-based views using CSS

In multi-role applications, most views are needed to contain almost the same content, but with different actions, varying according to the role of the user. This can be accomplished in most server-side views (like jsp, aspx, erb, ...etc) in a traditional way.

<!--
common content
-->
<% if role1 %>
<!--
role1 actions
-->
<% else if role2 %>
<!--
role2 actions
-->
<% else if role3 %>
<!--
role3 actions
-->

This works just fine. However, It's just so ugly!! Obviously we are embedding runtime logic in the views description. This breaks the concept of separation of concerns. Also, it makes the page fragments hard to cache because the resulting html becomes variant according to role values. The good news is that it can be accomplished in a much more elegant way. Basically, what we could do is, include all possible actions of all roles in the resulting html, relying on simple CSS style rules to show/hide those actions. We assign actions to CSS classes, add simple style rules to show the right actions in the right contexts. As as example, assume possible roles are admin, user, guest. assume the role of current user is known in variable 'role'. we assign the 'body' element an id that varies according to the current user role

< body id= <%=role%> >

Then we add the common content

<!--
common content
-->

Then we add all the possible actions, assigning each action CSS class names that represent the roles where the action should be displayed in.

< a href='.....' class="admin" >
< a href='.....' class="admin user" >
< a href='.....' class="user guest" >
< a href='.....' class="guest" >

The default definition of all those CSS classes are:

.admin, .user, .guest{ display: none }
so they are all hidden by default.
What's left is adding CSS style rules to the view 'head' element to show the right actions in the right context.

< style >
body#admin .admin { display: block }
body#user .user { display: block }
body#guest .guest { display: block }
</ style >

This simply means: show the admin actions if body id is 'admin', show the user actions if body id is 'user' and, show the guest actions if body id is 'guest'.

One more important thing to mention; this scheme introduces (or rather makes easier) a security vulnerability to the application. An opponent, assuming a guest role, can use any client side tool to change the resulting html, to show the hidden admin controls and use them. Obviously, nothing prevents such an attack, even if the proposed scheme was not used. The point is that we're making it easier for him. So, the bottom line is, different roles actions that result from hidden controls must be secured on the server side. Typically, we give everybody the control to DO something, but make sure they are privileged to DO it when they try to.


1 comment:

Amr said...

yea, you are right when the configuration are static.

i.e the admin role will have the same Privileges for ever (not configurable).

7abet a3'ales bas :)