Ruby on Rails
LoginGeneratorAccessControlList

This example is based on ACLController.

It uses AccessControlListExample database model and assumes you used the LoginGenerator.

It adds Roles such that

Users <-> Roles <-> Permissions

A User’s permissions are added to their session when they authenticate. Permissions are of the form {controller}/{method}. For example:

posts/add
posts/edit
posts/index   #use this if you want to protect "url/posts"

The Controller supports ‘guest perms’ which do not require any permissions. Other methods require the user to have the permission string before the action is performed. If the user is unauthorized, they are returned to the requesting page.

Any other method will require the user to have that permission. Permissions are kept as part of their session. Any changes made to the User’s permissions will not take effect until they login again. The filters added to this controller will be run for all controllers in the application. Likewise all the methods added be available for all controllers.

acl_controller.rb:


require ‘action_controller’
require ‘application_helper’
require ‘user’

class ACLController < ActionController::Base
# This is a secured controller from which others should derive. They are a limited set
# of methods which are callable by anyone. They are defined in the @guest_perms array.
# By default, #list and #show are unsecured.
# Example:
# class PostsController < ACLController
# def initialize
# super
# @guest_perms = [ “posts/summary”,“posts/show”
# end
# end
#
include ApplicationHelper

layout “shared/base” before_filter :authorize def initialize @sections ||= %w/Users Roles Permissions/ @pretty_name ||= controller_name guest_perms ||= [ "#{pretty_name.downcase}/list", “#{@pretty_name.downcase}/show” @uri_name = @pretty_name.downcase edit_uri = "#{pretty_name.downcase}/edit" end def list end def show end def new end def edit end def update end def destroy end def create end protected # Authorizes the user for an action. # This works in conjunction with the LoginController. # The LoginController loads the User object. def authorize required_perm = “s/s” % [ @params“controller”, @params“action” ] unless @guest_perms.include? required_perm unless @session[:user] flash‘error’ = “Request not permitted unless logged in.” @session[:return_to] = @session“prev_uri” #ensure you change “user” to your login controller name redirect_to(:controller => “user”, :action => "login") return false end unless @session[:user].authorized? required_perm flash‘notice’ = “You are not authorized for #{required_perm}.” redirect_to_path @session“prev_uri”.to_s return false end end @session“prev_uri” = @request.request_uri return true end

end

The User model defines authorized?. It determines if the user has the permission string.

user.rb: (add the new methods under self.authenticate)


# Return true/false if User is authorized for resource.
def authorized?(resource)
return permission_strings.include? resource
end
# Load permission strings
def permission_strings
a = []
self.roles.each{|r| r.permissions.each{|p| a<< p.name }}
a
end


In the controller that’s using the ACL (ie: \PostsController), change:


If you want to automatically populate a table (e.g. Permissions) with a list of all controller/actions defined in your app, see DiscoveringControllersAndActions

——
I’m curious to know why this was done by inheritance instead of as a module. It seems to me that a module would do the job, and a module could be packaged for reuse more easily.

——
I think it was just modified just enough from the original ACLController to barely function… I’ve refactored it into a module called ACLSystem, which can be found here: LoginGeneratorACLSystem. I would recommend people use it instead of this ACLController. -JamesHillyerd