Topic: Design Review: Business Object Permissions in my Models
Greetings forum! The design I describe below for custom object permissions is working well for me in development. I have not yet taken this to production. I am posting this design for public review and commentary. Is there a more efficient way to implement a dynamic roles/rights model? Please tear it apart. What am I doing wrong?
Kudos to Bruce Perens for his ModelSecurity gem.
Happy Friday!
- Taylor
-----------------------------------
A. Overview
My new collaboration application requires a roles/rights system that goes beyond what is described in "Rails Recipies", Fowler. Rather than having a global, fixed caste system of moderators or admins, my access rights are very 'per object' and subject to business rules.
I implemented my permissions business rules down at my Model layer as ModelSecurity User.current aware can_user_do_this? boolean instance methods. I then use these methods with my current working object (@project.can_user_do_this?) in the view rhtml to restrict visibility of widgets and in the controller layer to prevent posts of information.
I hope to, as a separate phase, implement full on ModelSecurity, but haven't though that out fully yet.
B. Requirements
My Business Rules / Permissions Requirements:
1. Project Owners can view and modify all parts of their own projects.
2. Project Team Members can view and modify some parts of their team projects.
3. Registered Visitor can see most parts of all projects.
4. Anonymous can see parts of all projects.
5. Nobody can modify a project if the Owner hasn't paid his subscription fee.
6. A Project Owner may also be a Project Team Member on other Projects.
C. Implementation Examples
Model Permissions implementation:
class Project < ActiveRecord::Base
belongs_to :user # owner relationship, do not confuse with User.current.
def user_can_read_core?
# ModelSecurity convention - means user logged in. Must have an account to read core.
true if User.current
false
end
def user_can_post_core?
# Only the owner can post core information, and only if he's paid.
true if User.current && User.current.id == user_id && project_is_paid_for?
false
end
end
;
Controller Permissions usage:
class ProjectController < ApplicationController
before_filter :require_login, :only => [ :post_core ]
def post_core
@project = Project.find_by_id(@params['id'])
raise "Permissions Exception" if @project.user_can_post_core?
# Do magic to store parameters to object.
...
end
end
;
View permissions usage:
<% if @project.user_can_read_core? %>
Project ID: <%= @project.id %>, Name: <%= @project.name %>
<% end %><% if @project.user_can_post_core? %>
Modify the core information below: ...
<% end %>
;
Last edited by brockman (2006-08-25 11:10:36)