Auto-populate authorization rights

I have implemented the Role-Right authorization recipe in Rails Recipes
(recipe 32), which works fine, but I’d like to auto-populate the Rights
table with all the actions in my system … since the system is rather
large. Doing it manually, from a administrative interface or the
console, is going to be annoying … and it would have to be updated
every time I change the number of actions …

I attempted to write a migration to find all my controllers, load each
one, and call “Controller.public_methods - Controller.hidden_actions” to
give me the actions defined in that controller, but for a controller
with one action, it definitely doesn’t give me just one action back …
check this out :stuck_out_tongue:

irb:001:0> Admin::HomeController.public_methods -
Admin::HomeController.hidden_actions
=> [“cattr_writer”, “prepend_before_filter”,
“reset_inheritable_attributes”, “const_defined?”, “skip_filter”,
“depend_on_without_deprecation”, “cattr_accessor”, “included_modules”,
“attr_internal_writer”, “parent”, “const_missing”, “before_filter”,
“inherited_with_action_controller”, “prepend_before_invocation”,
“helper_method”, “attr_internal_accessor”, “before_filters”,
“web_client_api”, “class_variables”, “class_inheritable_reader”,
“include?”, “append_after_filter”, “model”, “verify”, “helper_attr”,
“name”, “attr_internal”, “depend_on”, “access_control”, “after_filters”,
“cache_sweeper”, “class_inheritable_writer”, “ancestors”,
“attr_internal_naming_format”, “reloadable?”, “yaml_tag_read_class”,
“require_web_service_api”, “included_actions”,
“attr_internal_naming_format=”, “register_protocol”,
“class_inheritable_array_writer”, “prepend_after_filter”,
“append_after_invocation”, “service”, “method_defined?”,
“deprecated_method_warning”, “excluded_actions”, “deprecate”,
“class_inheritable_hash_writer”, “after_filter”,
“public_method_defined?”, “dependencies_on”, “prepend_after_invocation”,
“yaml_tag_subclasses?”, “delegate”, “class_inheritable_option”,
“remove_subclasses”, “web_service_api_with_require”,
“uses_component_template_root”, “find_filter”, “view_class”,
“superclass”, “class_inheritable_accessor”, “silence”, “<=>”,
“append_around_filter”, “caches_page”, “web_service_api”,
“private_method_defined?”, “<”, “deprecation_horizon”, “benchmark”,
“>=”, “>”, “<=”, “web_service_api_without_require”, “allocate”,
“class_inheritable_array”, “hidden_actions”,
“protected_method_defined?”, “model_with_deprecation”,
“before_invocation_interceptors”, “filter_excluded_from_action?”,
“public_class_method”, “parents”, “action_methods”, “subclasses”,
“session_store”, “class_inheritable_hash”, “hide_action”,
“add_web_service_api_callback”, “model_without_deprecation”,
“after_invocation_interceptors”, “session_store=”, “instance_methods”,
“uses_component_template_root_with_deprecation”, “private_class_method”,
“included_in_classes”, “view_root”, “inherited”,
“cached_session_options”, “inheritable_attributes”,
“prepend_around_filter”, “filter_parameter_logging”,
“service_with_deprecation”, “included_intercepted_methods”,
“public_instance_methods”,
“uses_component_template_root_without_deprecation”, “module_eval”,
“as_load_path”, “remove_class”, “observer”, “new”,
“session_options_for”, “autoload”, “in_place_edit_for_model”,
“around_filter”, “caches_action”, “web_service”,
“service_without_deprecation”, “excluded_intercepted_methods”,
“protected_instance_methods”, “auto_complete_for”, “class_eval”,
“alias_method_chain”, “yaml_as”, “scaffold”, “js_list_for”,
“write_inheritable_attribute”, “fragment_cache_store=”,
“skip_before_filter”, “observer_with_deprecation”, “layout”,
“private_instance_methods”, “rails_original_const_missing”,
“append_before_filter”, “autoload?”, “mattr_reader”, “js_generate_code”,
“write_inheritable_array”, “observer_without_deprecation”, “constants”,
“instance_method”, “process_with_exception”, “append_before_invocation”,
“has_web_service?”, “method_added”, “mattr_writer”, “layout_conditions”,
“web_services”, “dependencies_on_with_deprecation”, “const_get”,
“in_place_edit_for”, “web_service_scaffold”, “cattr_reader”,
“yaml_tag_class_name”, “helper”, “mattr_accessor”,
“read_inheritable_attribute”, “skip_after_filter”,
“add_web_service_definition_callback”,
“dependencies_on_without_deprecation”, “const_set”, “alias_attribute”,
“session_options”, “add_template_helper”, “attr_internal_reader”,
“write_inheritable_hash”, “default_layout”, “exempt_from_layout”,
“depend_on_with_deprecation”]

Now these are definitely not the actions my controller is capable of
responding to … is there any way to find out exactly what actions a
controller responds to?. Any ideas? If this is the wrong approach, any
suggestions on another? Anything obvious I’m missing?

~Jimmy

Any ideas? If this is the wrong approach, any
suggestions on another? Anything obvious I’m missing?

~Jimmy

Ok, I came up with a semi-suitable solution. Since I’m not turning this
on yet, I stuck this in my ApplicationController to store rights as the
system handles actions:

before_filter :store_right

def store_right
Right.find_or_create_by_name_and_controller_and_action(controller_name

  • " - " + action_name, controller_path, action_name)
    end

Of course, not perfect … since my migrations don’t capture this data
… and it doesn’t ensure that all actions are represented. So, I’m
looking for a solution better than this :slight_smile:

~Jimmy

James Schementi wrote:


Posted via http://www.ruby-forum.com/.

The user_engine has a rake task that basically does this.

However… I have found that unless you really expect that the roles
and permissions will be changing a lot, that the database approach to
this is 1) slower, because of the extra queries required, 2) a royal
PITA, precisely because it is so sensitive to the database setup.

I’d consider hard wiring in the roles and authorization. This is
faster and it’s easy to see at a glance through the source code, which
roles should be able to access which actions.

_Kevin

This will give you the difference between a controller and its parent:
Admin::HomeController.public_instance_methods -
HomeController.public_instance_methods

BUT (there has to be one), if the parent controller has a method of the
same name it will not be listed - so the array may be incomplete…

James Schementi wrote:

I have implemented the Role-Right authorization recipe in Rails Recipes
(recipe 32), which works fine, but I’d like to auto-populate the Rights
table with all the actions in my system … since the system is rather…

I have a piece of code that does exactly that at the end of this
article…

http://blog.wolfman.com/articles/2006/05/20/role-based-authentication-admin-page


Jim M., http://blog.wolfman.com

hello,
you can use a rake task to pre-populate your database from fixture
files. There are a few reference tables in my system that rarely
change (but are too large to hardcode…be careful of that route; it
can also be very brittle), so this works really well for me.
http://pastie.caboo.se/34809

Adam

Jimmy,
The public_methods method will give you everything in the inheritance
chain. If you want to look at just the methods defined for the current
class, you could explicitly remove every method that is in the parent
class, presumably ApplicationController.

You might also want to look at my Authorization plugin:
http://www.writertopia.com/developers/authorization

The plugin allows class-level permits in a fashion similar to
before_filter.
-Bill