Question on attr_protected and attr_accessible

View: New views
9 Messages — Rating Filter:   Alert me  

Question on attr_protected and attr_accessible

by Adam Akhtar-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


Currently I have an admin page that I configured that is only accessible
via the following:

On each controller that I do not want people to access, I place..

before_filter :login_required, :authorize

.. which will force them to login and then it will call an authorize
function to check if they are an admin role..

private

def authorize
  unless logged_in? && User.find(current_user).admin?
    redirect_to root_url
  end
end

=======================

This works great for protecting my pages and allowing me to perform many
administrative functions live on the site.  However, one potential issue
that I see is as far as user administration.

I've made it so that I can edit/update users through my administrative
pages and protected those pages so only admins can access them.
However, in order to set whether or not a user is an admin and be able
to update that user, I need to have:

attr_accessible :admin

If I set this to attr_protected :admin

.. I'm unable to access that attribute and won't be able to update my
admins..

So, I'm looking for ways to call an exception but still enforce a
protected status when users go to register and when they edit their
profile.  Obviously I don't want them hacking into their profiles and
giving themselves admin status.  But, at the same time, I want to be
able to manage users through my admin pages..

Any advice, suggestions would be appreciated.

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

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
To post to this group, send email to rubyonrails-talk@...
To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@...
For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en
-~----------~----~----~----~------~----~------~--~---


Re: Question on attr_protected and attr_accessible

by Frederick Cheung-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


On Jul 9, 3:18 pm, "Älphä Blüë" <rails-mailing-l...@...>
wrote:

> This works great for protecting my pages and allowing me to perform many
> administrative functions live on the site.  However, one potential issue
> that I see is as far as user administration.
>
> I've made it so that I can edit/update users through my administrative
> pages and protected those pages so only admins can access them.
> However, in order to set whether or not a user is an admin and be able
> to update that user, I need to have:
>
> attr_accessible :admin
>
> If I set this to attr_protected :admin
>
> .. I'm unable to access that attribute and won't be able to update my
> admins..

Not quite true. it means that you can't do some_user.update_attributes
(:admin => true).

You can however do some_user.admin = true

The attr_accessible/attr_protected mechanism is a bit of a blunt tool.
There has been some discussion about revisiting this for rails 3

Fred

>
> So, I'm looking for ways to call an exception but still enforce a
> protected status when users go to register and when they edit their
> profile.  Obviously I don't want them hacking into their profiles and
> giving themselves admin status.  But, at the same time, I want to be
> able to manage users through my admin pages..
>
> Any advice, suggestions would be appreciated.
>
> Thanks.
> --
> Posted viahttp://www.ruby-forum.com/.
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
To post to this group, send email to rubyonrails-talk@...
To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@...
For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en
-~----------~----~----~----~------~----~------~--~---


Re: Question on attr_protected and attr_accessible

by Adam Akhtar-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


Frederick Cheung wrote:

> On Jul 9, 3:18�pm, "�lph� Bl��" <rails-mailing-l...@...>
> wrote:
>>
>> If I set this to attr_protected :admin
>>
>> .. I'm unable to access that attribute and won't be able to update my
>> admins..
>
> Not quite true. it means that you can't do some_user.update_attributes
> (:admin => true).
>
> You can however do some_user.admin = true
>
> The attr_accessible/attr_protected mechanism is a bit of a blunt tool.
> There has been some discussion about revisiting this for rails 3
>
> Fred

Thanks for the clarification Fred.  So, how would I implement this in my
edit view template?  Or, are you stating it can't be done there but
somewhere else?

<%= f.label :admin? %><br />
<%= f.check_box :admin %>

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

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
To post to this group, send email to rubyonrails-talk@...
To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@...
For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en
-~----------~----~----~----~------~----~------~--~---


Re: Question on attr_protected and attr_accessible

by Felix Schäfer :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message



Am 09.07.2009 um 15:32 schrieb Älphä Blüë:

>
> Frederick Cheung wrote:
>> On Jul 9, 3:18�pm, "�lph� Bl��" <rails-mailing-
>> l...@...>
>> wrote:
>>>
>>> If I set this to attr_protected :admin
>>>
>>> .. I'm unable to access that attribute and won't be able to update  
>>> my
>>> admins..
>>
>> Not quite true. it means that you can't do  
>> some_user.update_attributes
>> (:admin => true).
>>
>> You can however do some_user.admin = true
>>
>> The attr_accessible/attr_protected mechanism is a bit of a blunt  
>> tool.
>> There has been some discussion about revisiting this for rails 3
>>
>> Fred
>
> Thanks for the clarification Fred.  So, how would I implement this  
> in my
> edit view template?  Or, are you stating it can't be done there but
> somewhere else?
>
> <%= f.label :admin? %><br />
> <%= f.check_box :admin %>

This won't protect you from someone forgering a request. You should  
check this in the controller, maybe put something like this in the  
update method:
"""
user_to_update.admin = params[:admin] unless !logged_in_user.admin?
"""
(and PLEASE do check this code before relying on it, that's off the  
top of my head). Doing it this way will make sure that no non-admin  
can change the admin status of a user.

Regards,

Felix
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
To post to this group, send email to rubyonrails-talk@...
To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@...
For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en
-~----------~----~----~----~------~----~------~--~---


Re: Question on attr_protected and attr_accessible

by Frederick Cheung-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message




On Jul 9, 3:32 pm, "Älphä Blüë" <rails-mailing-l...@...>
wrote:
> Frederick Cheung wrote:
>
> Thanks for the clarification Fred.  So, how would I implement this in my
> edit view template?  Or, are you stating it can't be done there but
> somewhere else?
>
It's nothing to do with the view template. You need to assign the
relevant attribute by hand in your controller (presumably after
checking that it is allowed).

Fred

> <%= f.label :admin? %><br />
> <%= f.check_box :admin %>
>
> --
> Posted viahttp://www.ruby-forum.com/.
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
To post to this group, send email to rubyonrails-talk@...
To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@...
For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en
-~----------~----~----~----~------~----~------~--~---


Re: Question on attr_protected and attr_accessible

by Adam Akhtar-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message



> It's nothing to do with the view template. You need to assign the
> relevant attribute by hand in your controller (presumably after
> checking that it is allowed).
>
> Fred

Thanks Fred - I understand now.
--
Posted via http://www.ruby-forum.com/.

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
To post to this group, send email to rubyonrails-talk@...
To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@...
For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en
-~----------~----~----~----~------~----~------~--~---


Re: Question on attr_protected and attr_accessible

by Adam Akhtar-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


>
> This won't protect you from someone forgering a request. You should
> check this in the controller, maybe put something like this in the
> update method:
> """
> user_to_update.admin = params[:admin] unless !logged_in_user.admin?
> """
> (and PLEASE do check this code before relying on it, that's off the
> top of my head). Doing it this way will make sure that no non-admin
> can change the admin status of a user.
>
> Regards,
>
> Felix

Thanks Felix,

Yeah I don't want to rely on attr_protected and attr_accessible either.
I would rather code my own pieces and use those as an extra buffer.
Thanks for the input and I'll create a custom check for this and test
thoroughly.
--
Posted via http://www.ruby-forum.com/.

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
To post to this group, send email to rubyonrails-talk@...
To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@...
For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en
-~----------~----~----~----~------~----~------~--~---


Re: Question on attr_protected and attr_accessible

by Adam Akhtar-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


Okay, here's how I did it in complete detail for anyone else that wants
to implement something similar:

First in my users controller I place the following (NEW THINGS):

==========

class UsersController < ApplicationController
  before_filter :login_required, :except => [:new, :create]
  before_filter :authorize, :except => [:user_edit, :update]
..
..
end

==========

Summary:  What this does is forces a login for any action except new and
create because those are what users will register with.  If a user
attempts to go to any other action they will hit the authorize method (I
will show what this does in a minute) except if they are doing user_edit
and update actions.

Now I created a new method called user_edit in the users controller:

==========

def user_edit
  @user = User.find(params[:id])
  if logged_in? && User.find(current_user).id == @user.id
    # continue processing
  else
    @user = User.find(current_user.id)
    redirect_to :controller => 'users', :action => 'user_edit', :id =>
@user
  end
end

==========

Summary: What this does is first matches the id up for the page the
person tries to go to.  Let's say for instance someone is trying to hack
your site and they use this new method to look up /users/4/user_edit
(user #4)...

It checks if the user is logged in and if not forces them to.  It then
matches their id with the id they are looking for and if it's not
matched, forces a redirect to the currently logged in user's real
profile path.  So, if the user was user #2, it would force a redirect to
/users/user_edit/2.

Then I changed the way the update action works:

==========

def update
  @user = User.find(params[:id])
  if logged_in? && User.find(current_user).admin?
    if @user.update_attributes(params[:user])

      flash[:notice] = 'Administrative Use : User was successfully
updated.'
      redirect_to(user_path(@user))
    else
      render :action => 'edit'
    end
  else # our user is not an admin so we'll keep him/her that way
    if @user.update_attributes(params[:user].merge({ :admin => "false"
}))
      flash[:notice] = 'Your profile was successfully updated.'
      redirect_to(user_path(@user))
    else
      render :action => 'user_edit'
    end
  end
end

==========

Summary: Now this update action works with both the normal edit and the
new user_edit methods.

It basically checks to see if the currently logged in user is an
administrator.  If that person is, it processes all of the normal update
params, including the admin checkbox.

If the user is not an admin it simply updates the params specified in
the user_edit view template plus it merges another option forcing the
admin value to false.  This makes it so that no one can hack your value
and supply something different.  If the user is not an admin, then their
value should be false.

In the user model I then place the following:

==========

attr_accessible :login, :email, :name, :password,
:password_confirmation, :admin

==========

Summary: .. which allows me to update admin fields with my admin page.

Keep in mind that the admin page or the edit pages that house the
checkbox fields can't be accessed without being logged in and the user
already having admin rights enabled before hand.

In the new user_edit template I have the following:

==========

<%= error_messages_for :user %>

<% form_for @user do |f| -%>
  <p><label for="login">Login</label><br/>

  <p><label for="email">Email</label><br/>
  <%= f.text_field :email %></p>

  <p><label for="password">Password</label><br/>
  <%= f.password_field :password %></p>

  <p><label for="password_confirmation">Confirm Password</label><br/>
  <%= f.password_field :password_confirmation %></p>

  <p><%= submit_tag 'Update' %></p>
<% end %>

==========

Summary: I place my custom authorize method in application_controller.rb
by doing the following at the very bottom of the controller:

==========

private

def authorize
  unless logged_in? && User.find(current_user).admin?
    redirect_to root_url
  end
end

==========

Summary: When you make a call to authorize, if the person is not an
admin, it automatically redirects them back to the root_url of your
site.

Lastly, you need to update a new route in your routes.rb file so that it
can access the new user_edit method in the users controller:

==========

map.resources :users, :member => { :user_edit => :get }

==========

This keeps the controller RESTful but adds a new member method to it.


===================================================

I hope this helps someone in the future.
--
Posted via http://www.ruby-forum.com/.

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
To post to this group, send email to rubyonrails-talk@...
To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@...
For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en
-~----------~----~----~----~------~----~------~--~---


Re: Question on attr_protected and attr_accessible

by Adam Akhtar-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


One correction and one addition:

the before filters should look like this:

before_filter :login_required, :except => [:new, :create]
before_filter :authorize, :except => [:user_edit, :update, :new,
:create]

Otherwise, your new users wouldn't be able to register..

And, to protect your "new user" from being able to hack their form and
add admin=true, you change the following in create method from:

@user = User.new(params[:user])

TO..

@user = User.new(params[:user].merge({ :admin => "false" }))

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

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
To post to this group, send email to rubyonrails-talk@...
To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@...
For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en
-~----------~----~----~----~------~----~------~--~---