Role based restriction for fields (not views or actions)

I have an application that requires some complex access rules.
Certain fields can only be edited by certain roles. I am using
restful_authentication and role_requirement plugins so I am fine with
restricting an entire controller or specific action based on a role.

I am trying to come up with a solution that would allow me to specify
something as a text field but make it just plain text if the user does
not have edit permissions. Anyone have any ideas on fine grain
access control like this? Can you point me to a project that uses
something like this?




I don't have any leads for you, but I'm very interested in this
myself. I do have one thought: I imagine you could roll your own text
field helper method (and then probably helper methods for the other
form elements). Something like:

require 'active_support/inflector.rb'
module ActionView
  module Helpers
    module FormHelper
      def secured_text_field(object_name, method, options = {})
        current_user.has_role?(options[:required_role]) ?
          "<div id=\"#{object_name}_#{method}
\">#{object_name.instance_eval(method.to_s)}</div>" :
          text_field(object_name, method, options)

# (I added the above to the ApplicationHelper.rb file but not within
the Module namespace... i.e. after it.)

And you'd call it with something like:

<% form_for(@foo) do |f| %>
    <%= f.label :name %><br />
    <%= secured_text_field @foo, :name, :required_role => "admin" %>
<% end %>

If the current_user has the "admin" role, then you'd get:

<form tag...>
  <label for="foo_name">Name</label><br />
    <input id="foo_name" name="foo[name]" size="30" type="text"
value="" />

But if the current_user has any other role, you'd get:

<form tag...>
  <label for="foo_name">Name</label><br />
    <div id="foo_name">Some Name</div>

I'm sure there's a cleaner way, but the above works. I tried doing it
within the FormBuilder constrains (i.e. "f.secured_text_field...") but
I don't understand that code... lots of meta-programming there.

Anyway, I tested the above and it works. Hopefully that gets you


Heh... I'm still learning.

The namespacing was unnecessary. Slap it right in the middle of the
ApplicationHelper module, I.e.:

module ApplicationHelper
  def secured_text_field(object_name, method, options = {})
    options[:required] == "yes" ? content_tag(:div,
"#{object_name.instance_eval(method.to_s)}", :id =>
"#{object_name.class.to_s.underscore}_#{method}") :
text_field(object_name, method, options)

There's probably a cleaner way to get "foo_name" for the ID but the
above works... and is terse and to the point.



i think there is a ruby gem called model_security which provides such
fine grained access control from within the model.
I don't know though if it's mantained and up to date and/or runs
nicely on rails 2.

Hops that helps.


There's also the acl2 plugin from Ezra.

It has a view helper, <% restrict_for "role" do %> which will let you
only show what is part of the code block in the view.

Hope this helps.