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
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.
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 < AbstractApplicationController
# def initialize
# super
# @guest_perms = [ "posts/summary","posts/show"]
# end
# end
#
include ApplicationHelper
layout "shared/base"
before_filter :authorize
def initialize
@sections ||= %w/Users Groups Roles Permissions/
@pretty_name ||= controller_name
@guest_perms ||= [ "#{@pretty_plural.downcase}/list",
"#{@pretty_plural.downcase}/show"]
@class_object||= Object.const_get(@pretty_name)
@uri_name = @pretty_plural.downcase
@related = @class_object.reflect_on_all_associations.collect{|x|x.name.to_s}
@edit_uri = "#{@pretty_plural.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
#return true
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"]
redirect_to(:controller => "login")
return false
end
unless @session["user"].authorized? required_perm
logger.info("Guest perms are #{@guest_perms.join(';')}")
flash['notice'] = "You are not authorized for #{required_perm}."
redirect_to_path @session["prev_uri"]
return false
end
end
#@session["prev_uri"] = @request.env["REQUEST_URI"]
@session["prev_uri"] = @request.request_uri
return true
end
end
The User model defines authorized?. It determines if the user has the permission string.
class User < ActiveRecord::Base
# 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 = []
groups.each{|g| g.roles.each{|r| r.permissions.each{|p| a<< p.name }}}
a
end
end
————————————————————
If you’re trying to get this to work with the LoginGenerator and the database models as described in AccessControlListExample,
try LoginGeneratorAccessControlList or :
The following changes worked for me (not well tested yet, though):
In the User model, change:
groups.each{|g| g.roles.each{|r| r.permissions.each{|p| a<< p.name }}} to self.roles.each{|r| r.permissions.each{|p| a<< p.name }}In the ACL controller, change:
@pretty_plural to @pretty_name@class_object ||= Object.const_get(@pretty_name) delete it, or comment it out@related = @class_object.reflect_on_all_associations.collect{|x|x.name.to_s} delete it, or comment it outredirect_to(:controller => "login") to redirect_to(:controller => "user", :action => "login")In the controller that’s using the ACL (ie: PostsController), change:
class PostsController < AbstractApplicationController to class PostsController < ACLControllerThis should do it, but I’m sure I’m overlooking some things. Also, it would be good to throw a message in the flash to display on the login screen in case the user needs the priviledges.
——
Feedback:
Should the example PostsController inherit from ACLController?
Should be, this is fixed in the bottom section
The permission_strings method is doing N*M queries where you might be able to do just 1 query using Permission.find_by_sql?
——
eric at snowmoon com
Looking over this it does not seem like “the ruby way”. A few things jump out at me. First off you now have a random controller out there in your web app that does nothing meaningful for the site itself. Secondly how permissions are assigned seems akward as well.
The way I would do something like this is…
Cheers
——
I don’t understand all of what you are suggesting, but my LoginGeneratorACLSystem module does away with the ACLController and a lot of stuff that isn’t needed when using LoginGenerator. -JamesHillyerd
——
Where does Groups come from ? (I just removed it and it works but I’m just wondering if somebody should remove it from this web page since it says it is based on AccessControlListExample, but there is no Groups in this example)
—-
i’m trying to add this ACL but then i got this error message “uninitialized constant Base”.
can anyone help me to fix this up? i think this
might related to the model, but i dunno. tq in advanced!