views:

241

answers:

4

Hey all, I need some advice on this...

We have certain permissions setup in the database for certain levels of control a user can have over the application. Disabled, ReadOnly and Edit.

My question is: Are there more generic/better ways to handle permissions applied to a form element on the page than writing a security method/check per page to enable/disable/hide/show proper controls depending on the permissions allowed?

Anyone have any experience handling this in different ways?

Edit:

I just thought about the possibility of adding constants for each layer that needs security and then adding an IsAuthorized function in the user class that would accept a constant from the form that the control is on, and return boolean to enable/disable controls, this would really reduce the amount of places I'd have to hit when/if I ever need to modify the security for all forms.

Cheers!

+1  A: 
This project is a little more simple than the depth you're getting into. Really we have the three roles a user can have, per page on the site. It's that I want to see what other options are available for assigning those permissions dynamically/generically to all form fields. Thanks for the answer.
thismat
+2  A: 

You may want to check how django handles forms and validates them. Forms are handled like models, they have their own class, so their field list, validation rules and display logic is no more scattered throughout the view, the controller and the helper. With such a structure, it's pretty clear where the hidden/readonly/editable logic belong.

It seems that such a feature is not yet implemented in rails. It's not only a time-saver, it keeps your code clean and structured. You could start by creating a base class for forms, where validation is separated from the controller.

vincent
+2  A: 

Sorry for going slightly off-topic here, but learn from my mistake:

I had a simple web app one time that I was developing and I thought that I'd setup 3 levels of security: limited read-only (public), read-limited write (user), read-write (admin). The users table had a level of security in it and everything worked fine... until I needed finer control over security levels as the project grew. It all started with a user that needed more than user control in one area of the program but not full admin control.

What I should have done was setup an expandable system with finer control even though I didn't need it at first. This would have saved me sooo much time.

BoltBait
Not your fault as a programmer, I'd say, you did the right thing : the cheapest solution for the problem. You can't be blamed for incomplete requirements - but since it seems no one but you gathered these requirements, all you can regret is not insisting enough when interviewing your users ;-)
vincent
In this case, the stakeholder was my wife. It was a simple database for her web site. When a wife is involved, we all know where the blame falls... ;)
BoltBait
Good point. Luckily we've setup just about control level permissions and some even really do dig into the control level. I ended up just adding a security method to the pages I needed it on. Painful yes, but I was on a limited budget of time. Thanks for the comment!
thismat
A: 

To work properly, I have found that access levels should be in this increasing order: NONE, VIEW, REQUIRED, EDIT.

Note that REQUIRED is NOT the top level as you may think it would be since EDIT (both populate & de-populate permission) is a greater privilege than REQUIRED (populate-only permission).

The enum would look like this:

/** NO permissions.
 *     Presentation: "hidden"
 *     Database: "no access"
 */
NONE(0),

/** VIEW permissions.
 *     Presentation: "read-only"
 *     Database: "read access"
 */
VIEW(1),

/** VIEW and POPULATE permissions.
 *     Presentation: "required/highlighted"
 *     Database: "non-null"
 */
REQUIRED(2),

/** VIEW, POPULATE, and DEPOPULATE permissions.
 *     Presentation: "editable"
 *     Database: "nullable"
 */
EDIT(3);

From the bottom layer (database constraints), create a map of fields-to-access. This map then gets updated (further restrained) at the next layer up (business rules + user permissions). Finally, the top layer (presentation rules) can then further restrain the map again if desired.

Important: The map must be wrapped so that it only allows access to be decreased with any subsequent update. Updates which attempt to increase access should just be ignored without triggering any error. This is because it should act like a voting system on what the access should look like. In essence, the subsequent layering of access levels as mentioned above can happen in any order since it will result in an access-level low-water-mark for each field once all layers have voted.

Ramifications:

1) The presentation layer CAN hide a field (set access to NONE) for a database-specified read-only (VIEW) field.

2) The presentation layer CANNOT display a field when the business rules say that the user does not have at least VIEW access.

3) The presentation layer CANNOT move a field's access up to "editable" (nullable) if the database says it's only "required" (non-nullable).

Note: The presentation layer should be made (custom display tags) to render the fields by reading the access map without the need for any "if" statements.

The same access map that is used for setting up the display can also be using during the submit validations. A generic validator can be written to read any form and its access map to ensure that all the rules have been followed.

(Also see thread: http://stackoverflow.com/questions/368904/best-practices-for-controlling-access-to-form-fields/1743719#1743719)

Julian Bromwich