Check if current_user is the owner of a resource and allow edit/delete actions

你。 提交于 2019-12-20 09:38:32

问题


Example:

User A (id=10) has created a photo resource

photo: (id: 1 user_id = 10, url: "http://...")

Now, if User B (id=20) go to this url: /photos/1/edit it can edit photo of user A!!!

Rails+Devise provides something for this by default? It seems it's a very common issue

I just need to allow that any user can edit/delete ONLY resource it has created (where current_user == resource.user)

Using: Rails 4, Devise

Update:

I think CanCan it's something too advanced. I don't need roles or restrict some actions to certain users


回答1:


In your PhotosController:

before_filter :require_permission, only: :edit

def require_permission
  if current_user != Photo.find(params[:id]).user
    redirect_to root_path
    #Or do something else here
  end
end



回答2:


You can make use of Rails' associations and write it like this:

def edit
  @photo = current_user.photos.find(params[:id])

  # ... do everything else
end

This will only find a record when the photo with the supplied ID belongs to the current user. If it doesn't, Rails will raise a ActiveRecord::RecordNotFound exception.

Of course, I'm assuming the current_user method is available and your User model contains the statement has_many :photos.




回答3:


Check this railscasts,

http://railscasts.com/episodes/192-authorization-with-cancan

Complications you will run into,

  1. When you want cancan authorization on User Model that Devise gem is using for authentication

  2. When you want to store your Roles in the Database

  3. When you want to assign Permissions to the Roles as an Admin from the webUI

  4. and more ..

Please comment if you want any of those features, I will be happy to help, because I recently did them with great help from others and its always amazing to pass it on.

A sample Ability for your resources can be like as follows,

class Ability
  include CanCan::Ability

  def initialize(user)

      user ||= User.new # guest users
      send(user.role.name)

        if user.role.blank?
          can :read, User #for guest without roles
        end

  end

  def man
    can :manage, Photo
  end


  def boy
    can :read, Photo
  end

  def kid
    can :read, Article
  end

end



回答4:


I captured the exception from within a before_filter action:

before_action :set_photo, only: [:edit, :update, :destroy]

def set_photo
  @photo = current_user.photos.find(params[:id])

  rescue ActiveRecord::RecordNotFound
    redirect_to(root_url, :notice => 'Record not found')
end

Hope this helps someone. I'm using Rails 4 and Ruby 2.




回答5:


So you are using gem devise.

This gem provides the current_user for the currently logged in user.

In your PhotosController#edit method. I'd do something like below.

def edit
  @photo = Photo.find(params[:id])
  redirect_to root_path, notice: 'Thou Shalt Nought duuu dat :(' unless current_user.id == @photo.user_id
  ...
end

This method is cheaper because you already have 2 objects to compare instead of running a query in the comparison.




回答6:


The simplest would be to to modify routes.rb.

Assign photos to live in the current_user path.

For example,

devise_for :users

resources 'users' do 
  resources 'photos'
end



回答7:


cancan is difficult and complicate i have coding is_onwer method it's very simple, easy

https://gist.github.com/x1wins/0d3f0058270cef37b2d3f25a56a3745d

application controller

 def is_owner user_id
    unless user_id == current_user.id
      render json: nil, status: :forbidden
      return
    end
  end
  def is_owner_object data
    if data.nil? or data.user_id.nil?
      return render status: :not_found
    else
      is_owner data.user_id
    end
  end

your controller

  before_action only: [:edit, :update, :destroy] do
    is_owner_object @article ##your object
  end



回答8:


If CanCan is too advanced, you should loon into checking the id of the accessor in the controller using...

if @user.id == @photo.user_id
  # edit photo details
else
  redirect_to root_path, notice: "You! Shall! Not! Edit!"

...or something like that




回答9:


Write another before_filter in application_controller:

before_filter :has_permission?

has_permission?
controllers=["articles", "photos", "..."]
actions=["edit", "destroy", "..."]
id = params[:id] if (controllers.include?(params[:controller] && actions.include?(params[:action]) end
if id && (current_user.id==(params[:controller][0...1].capitalize!+params[:controller].singularize[1...-1] + ".find(#{id}).user_id").send)
return true
else
redirect_to root_url, :notice=>"no permission for this action"
end

helper_method :has_permission?

And you can use it in views, not to show users link they can't follow.

Some kind of this, of course you need to modify it to suit your needs.



来源:https://stackoverflow.com/questions/17594939/check-if-current-user-is-the-owner-of-a-resource-and-allow-edit-delete-actions

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!