Ruby on rails Rails与cancan的授权
我正在关注这一点 我试图授权用户只有当用户是管理员,他应该能够看到所有的帖子和评论,否则普通用户只能看到自己的帖子。我读过github页面,但相当混乱Ruby on rails Rails与cancan的授权,ruby-on-rails,cancan,Ruby On Rails,Cancan,我正在关注这一点 我试图授权用户只有当用户是管理员,他应该能够看到所有的帖子和评论,否则普通用户只能看到自己的帖子。我读过github页面,但相当混乱 [post_controller.rb] [评论.rb] class注释
[post_controller.rb]
[评论.rb]
class注释
[post.rb]
class Post < ActiveRecord::Base
has_many :comments, dependent: :destroy
validates :title, presence: true, length: {minimum: 5}
validates :body, presence: true
end
class Post
[user.rb]
class用户
[迁移]
class DeviseCreateUsers < ActiveRecord::Migration
def change
create_table(:users) do |t|
## Database authenticatable
t.string :email, null: false, default: ""
t.string :encrypted_password, null: false, default: ""
## Recoverable
t.string :reset_password_token
t.datetime :reset_password_sent_at
## Rememberable
t.datetime :remember_created_at
## Trackable
t.integer :sign_in_count, default: 0, null: false
t.datetime :current_sign_in_at
t.datetime :last_sign_in_at
t.string :current_sign_in_ip
t.string :last_sign_in_ip
t.timestamps
end
add_index :users, :email, unique: true
add_index :users, :reset_password_token, unique: true
end
end
classdeveliecCreateUsers
[迁移]
class CreateComments
[迁移]
class CreatePosts
以上是能力
类的外观。您可以将替换为if/else
--
您缺少对象的权限,特别是使用can?
和authorize
方法:
#app/controllers/comments_controller.rb
class CommentsController < ApplicationController
def create
@post = Post.find params[:post_id]
@comment = @post.comments.new comment_params
@comment.save if authorize! :create, @comment
redirect_to @post
end
def destroy
@post = Post.find params[:post_id]
@comment = @post.comments.find params[:id]
@comment.destroy if authorize! :destroy, @comment
redirect_to @post
end
private
def comment_params
params.require(:comment).permit(:name, :body)
end
end
#app/controllers/posts_controller.rb
class PostsController < ApplicationController
def show
@post = Post.find params[:id]
end
end
#app/views/posts/show.html.erb
<%= @post.title %>
<%= render @post.comments if can? :read, @post.comments %>
#app/controllers/comments_controller.rb
类CommentsController
1)在PostsController中更改此行,删除此条件:除了[索引,显示]。或者用户可以在未经授权的情况下查看页面
before_action :authenticate_user!
2) 使用此样式更改索引操作和其他操作。使用-当前用户
def index
if current_user.has_role? :admin
@posts = Post.all.order('created_at DESC')
else
@posts = current_user.posts.order('created_at DESC')
end
end
您似乎还没有与
post
和comment
的user
关系,您需要在其中确定用户是否拥有/创建了评论/帖子
运行:
然后添加关联关系:
post.rb
class Post < ActiveRecord::Base
belongs_to :user
# ..
end
现在,下一步是将登录用户与新创建的帖子/评论自动关联。通过控制器完成此操作:
posts\u controller.rb
class PostsController < ApplicationController
authorize_resource
# ..
def create
@post = Post.new(post_params)
@post.user = current_user # I assume you have a variable current_user, or if you are using Devise current_user is already accessible
if @post.save
redirect_to @post
else
render :new
end
end
end
class CommentsController < Application
authorize_resource
# ..
def create
@post = Post.find(params[:post_id])
@comment = @post.comments.build(params[:comment].permit(:name, :body))
#puts "hhhhhhhhhh#{@comment}"
@comment.user = current_user # I assume you have a variable current_user, or if you are using Devise current_user is already accessible
@comment.save
redirect_to post_path(@post)
end
end
仅提供上述功能的最后有用信息:
can:manage,Post,user\u-id:user.id
这只是一个简写,等于:
can [:show, :edit, :update, :destroy], Post, user_id: user.id
can [:index, :new, :create], Post
您会注意到,:index
、:new
和:create
没有考虑用户id:user.id
,因为它们是:collection
方法,而不是:member
方法。更多信息
- 如果您想要可读性和可定制性,您可以选择使用上面的较长版本,而不是速记
:manage
你可以用这种方式书写你的能力
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user (not logged in)
case user.role
when "admin"
can :manage, :all
else
can :read, Post, :user_id => user.id
end
end
end
并且只需使用能力资源加载post的资源,以便它只加载当前用户的post(如果不是admin)
class CommentsController < Application
load_and_authorize_resource
def index
@posts = @posts
end
end
class-commentscoontroller
我需要一个用户登录,并且可以看到其唯一的帖子和评论。。。。但是管理员可以让每个人都发布comments@aniket,我假设您的Post和Comment模型都有一个名为user\u id
的属性(或者您可以说是一个“列”),在您的Post
和Comment
模型中都有一个属于:user
。如果您没有这些,则需要先添加它们,因为这是您需要检查用户是否拥有帖子或评论的标识符。@aniket,我更新了答案,将用户分配到正在创建的帖子或评论。所以你知道是谁创造了它们。此用户将在您的能力中进行检查。rb
只有在用户创建它们时才被授权。当然,这将更有帮助。但是如果您已经有了Post和Comment.thx的user\u id
列,您就不必这样做了。这是我的最后一个问题,因为我是rails@Comment.user=current\u user的新手……那么这里的“user”是什么意思呢???它是我的用户表中的列名还是模型名,还是一些预定义的函数???
before_action :authenticate_user!
def index
if current_user.has_role? :admin
@posts = Post.all.order('created_at DESC')
else
@posts = current_user.posts.order('created_at DESC')
end
end
rails generate migration AddUserToPost user:belongs_to
rails generate migration AddUserToComment user:belongs_to
bundle exec rake db:migrate
class Post < ActiveRecord::Base
belongs_to :user
# ..
end
class Comment < ActiveRecord::Base
belongs_to :user
# ..
end
class User < ActiveRecord::Base
has_many :posts
has_many :comments
# ..
end
# rails console
post = Post.find(1)
post_owner = post.user
comment = Comment.find(1)
comment_owner = comment.user
user = User.find(1)
user_comments = user.comments
user_posts = user.posts
class PostsController < ApplicationController
authorize_resource
# ..
def create
@post = Post.new(post_params)
@post.user = current_user # I assume you have a variable current_user, or if you are using Devise current_user is already accessible
if @post.save
redirect_to @post
else
render :new
end
end
end
class CommentsController < Application
authorize_resource
# ..
def create
@post = Post.find(params[:post_id])
@comment = @post.comments.build(params[:comment].permit(:name, :body))
#puts "hhhhhhhhhh#{@comment}"
@comment.user = current_user # I assume you have a variable current_user, or if you are using Devise current_user is already accessible
@comment.save
redirect_to post_path(@post)
end
end
class Ability
include CanCan::Ability
def initialize(user)
# if not logged in (Guest)
unless user
# cant do anything unless you add more `can` here
# else if logged in
else
case user.role
when 'admin'
can :manage, Post
can :manage, Comment
when 'normal' # or whatever role you assigned to a normal logged in user
can :manage, Post, user_id: user.id
can :manage, Comment, user_id: user.id
# If you don't have a role name for a normal user, then use the else condition like Rich Peck's answer. Uncomment the following instead, and then comment the `when 'normal' block of code just above
# else
# can :manage, Post, user_id: user.id
# can :manage, Comment, user_id: user.id
end
end
end
end
can [:show, :edit, :update, :destroy], Post, user_id: user.id
can [:index, :new, :create], Post
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user (not logged in)
case user.role
when "admin"
can :manage, :all
else
can :read, Post, :user_id => user.id
end
end
end
class CommentsController < Application
load_and_authorize_resource
def index
@posts = @posts
end
end