Rails 3 Restrict access so that the user can only update their data

This seems like something that should be fairly simple, as it would be necessary a lot. I check if the user is registered correctly, but as soon as the user is registered, they can potentially change other people's accounts. For example: let's say that user with identifier 1 has been registered, and they put / users / 2 / edit as the URL. This will show them 2s user data and allow them to change it. Of course, I can change the editing action in the controller to use something like this ...

def edit @user = User.find(current_user.id) end 

where current_user is set in the controller, so the user is always the person who is logged in. This is normal if you only have a few controllers with multiple actions, but it can be painful if you have a lot of them. There seems to be a way to limit this globally so that the user can update their own data no matter what action or controller they use.

Is there a way to limit the user to their data for all actions?

+6
source share
4 answers

I think your question is really about how to do authorization. In addition, I suspect that you could associate the association name with the name "own_to" with authorization. The association name "own_to" describes how one model relates to another, but it does not imply anything about how the application controls access to any model.

Hishalv is correct that using a controller filter is the right way to manage authorization. This is the correct way to MVC. Give the Rails Guide a good read for you to understand.

You can then consider using an authorization graph such as CanCan, or folding your own Hishalv proposal. CanCan works well in tandem with an authentication stone like Devise. If you really collapse your own, just put the helper method in the ApplicationController and write it in such a way that it works regardless of the model.

+4
source

In your application_controller.rb application, you can try the following:

 class ApplicationController < ActionController::Base before_filter :validate_user private def validate_user() #might need to pass id and current_user if current_user.id == params[:id] # continue to current_user url else flash[:error] = "Please access one of your own pages" redirect_to(:back) end end end 

when placing material in the application controller, it should be available in all controllers, however, if you do not need to confirm that this is the current user (say, maybe the home page), you may need to use skip_before_filter in any specific controller (for a specific action) which he needs, for example, in the page controller, for example

 class PagesController < ApplicationController skip_before_filter :validate_user, :only => [:home, :about] end 

For more information about this link, link to guides for guides on filters . There may be more effective ways to achieve this.

Hope this helps

+8
source

It always seemed strange to me that end users were subject to β€œinternal” Rails, such as /users/2/edit , when all they wanted to do was update their own account.

Therefore, I prefer the method of calling it

 resource :account 

instead

 resources :users 

Then you have paths such as /account , /account/edit , etc., and you only need to process the data for the registered user.

+1
source

If you use cancan then

 def validate_user unless current_user.id == params[:id].to_i raise CanCan::AccessDenied end end 

And in application_controller write

  rescue_from CanCan::AccessDenied do |exception| flash[:error] = "Access denied." redirect_to access_denied_path end 
0
source

Source: https://habr.com/ru/post/896825/


All Articles