示例:
用户 A (id = 10)创建了照片资源
photo: (id: 1 user_id = 10, url: "http://...")
现在,如果用户 B (id = 20)转到此网址:/photos/1/edit
,则可以编辑用户的照片 A !!!
Rails + Devise 默认提供此功能?这似乎是一个非常普遍的问题
我只需要允许任何用户只能编辑/删除它创建的资源(其中current_user == resource.user)
使用: Rails 4,设计
更新:
我认为CanCan太先进了。我不需要角色或限制某些用户的某些操作
答案 0 :(得分:33)
在你的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
答案 1 :(得分:14)
您可以使用Rails的关联并按如下方式编写:
def edit
@photo = current_user.photos.find(params[:id])
# ... do everything else
end
仅当具有提供的ID的照片属于当前用户时,才会找到记录。如果没有,Rails将引发ActiveRecord::RecordNotFound
例外。
当然,我假设current_user
方法可用且您的User
模型包含语句has_many :photos
。
答案 2 :(得分:3)
检查此railscast,
http://railscasts.com/episodes/192-authorization-with-cancan
您将遇到的并发症,
如果您想在Devise gem用于身份验证的用户模型上进行cancan授权
如果要将角色存储在数据库中
如果要从WebUI为管理员分配权限
以及更多..
如果您想要任何这些功能,请发表评论,我将很乐意为您提供帮助,因为我最近在其他人的帮助下完成了这些功能,而且总是令人惊叹地传递它们。
示例资源的能力可以如下所示,
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
答案 3 :(得分:2)
我从before_filter操作中捕获了异常:
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
希望这有助于某人。我正在使用Rails 4和Ruby 2。
答案 4 :(得分:1)
所以你正在使用gem devise
。
此gem为当前登录的用户提供current_user
。
使用PhotosController#edit
方法。我会做类似下面的事情。
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
此方法更便宜,因为您已经有2个对象需要比较,而不是在比较中运行查询。
答案 5 :(得分:1)
最简单的方法是修改routes.rb。
将照片分配到current_user路径中。
例如,
devise_for :users
resources 'users' do
resources 'photos'
end
答案 6 :(得分:1)
康康舞曲既困难又复杂
我有编码is_onwer
方法
非常简单,容易
https://gist.github.com/x1wins/0d3f0058270cef37b2d3f25a56a3745d
应用程序控制器
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
您的控制器
before_action only: [:edit, :update, :destroy] do
is_owner_object @article ##your object
end
答案 7 :(得分:0)
在application_controller中编写另一个before_filter:
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?
您可以在视图中使用它,而不是向用户显示他们无法关注的链接。
某种,当然你需要修改它以满足你的需要。
答案 8 :(得分:0)
如果CanCan过于先进,您应该使用...来检查控制器中访问者的ID ...
if @user.id == @photo.user_id
# edit photo details
else
redirect_to root_path, notice: "You! Shall! Not! Edit!"
......或类似的东西