我关注此tutorial 我正在尝试仅授权用户如果用户是管理员,他应该能够看到所有帖子和评论,否则普通用户只能看到自己的帖子。我已经读过github页面但是很混乱
[post_controller.rb]
class PostsController < ApplicationController
before_action :authenticate_user!, except: [:index, :show]
def index
@posts = Post.all.order('created_at DESC')
end
def new
@post = Post.new
end
def show
@post = Post.find(params[:id])
end
def create
@post = Post.new(post_params)
@post.user = current_user
if @post.save
redirect_to @post
else
render 'new'
end
end
def edit
@post = Post.find(params[:id])
end
def update
@post = Post.find(params[:id])
if @post.update(params[:post].permit(:title, :body))
redirect_to @post
else
render 'edit'
end
end
def destroy
@post = Post.find(params[:id])
@post.destroy
redirect_to posts_path
end
private
def post_params
params.require(:post).permit(:title, :body)
end
end
[comments_controller]
class CommentsController < ApplicationController
def create
@post = Post.find(params[:post_id])
@comment = @post.comments.create(params[:comment].permit(:name, :body))
@comment.user = current_user
redirect_to post_path(@post)
end
def destroy
@post = Post.find(params[:post_id])
@comment = @post.comments.find(params[:id])
@comment.destroy
redirect_to post_path(@post)
end
end
[ability.rb]
class Ability
include CanCan::Ability
def initialize(user)
unless user
else
case user.roles
when 'admin'
can :manage, Post
can :manage, Comment
when 'user' # 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
end
end
[comment.rb]
class Comment < ActiveRecord::Base
belongs_to :post
end
[post.rb]
class Post < ActiveRecord::Base
has_many :comments, dependent: :destroy
validates :title, presence: true, length: {minimum: 5}
validates :body, presence: true
end
[user.rb]
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
end
[迁移]
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
[移民]
class CreateComments < ActiveRecord::Migration
def change
create_table :comments do |t|
t.string :name
t.text :body
t.references :post, index: true
t.timestamps
end
end
end
[移民]
class CreatePosts < ActiveRecord::Migration
def change
create_table :posts do |t|
t.string :title
t.text :body
t.timestamps
end
end
end
答案 0 :(得分:1)
#app/models/ability.rb
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 #-> cannot read comments
end
end
end
以上是ability
类的外观。您可以将switch/case
替换为if/else
。
-
您错过了evaluation个对象,特别是can?
&amp; 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 %>
答案 1 :(得分:1)
您似乎尚未与user
和post
建立comment
关系,以确定用户是否拥有/创建了评论/帖子
执行命令
rails generate migration AddUserToPost user:belongs_to
rails generate migration AddUserToComment user:belongs_to
bundle exec rake db:migrate
然后添加关联关系:
post.rb
class Post < ActiveRecord::Base
belongs_to :user
# ..
end
comment.rb
class Comment < ActiveRecord::Base
belongs_to :user
# ..
end
user.rb
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
现在,下一步是将登录用户自动关联到新创建的帖子/评论。这是通过控制器完成的:
posts_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
comments_controller.rb
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
现在,此时此刻。每当创建帖子/评论时,登录用户就会自动与其关联(作为所有者)。
最后,我们只需将Ability
类更新为仅授权用户:edit
,:update
,:show
和:destroy
操作,如果{ {1}}(登录用户)。
ability.rb
user_id: current_user
上述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
的最后有用信息:
Ability
这只是一个等于的简写:
can :manage, Post, user_id: user.id
您会注意到can [:show, :edit, :update, :destroy], Post, user_id: user.id
can [:index, :new, :create], Post
,user_id: user.id
和:index
未考虑:new
,因为这些是:create
方法,而不是{{} 1}}方法。更多信息here
如果您想要可读性和可自定义性,您可以选择使用上面较长的一个而不是速记:collection
。
答案 2 :(得分:0)
1)在PostsController中更改此行,删除此条件:[index,show]除外。或者用户可以在未经授权的情况下查看页面。
before_action :authenticate_user!
2)使用此样式更改索引操作和其他操作。使用 - current_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
答案 3 :(得分:0)
你可以用这种方式写你的能力
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
并且只使用能力资源加载帖子的资源,以便它只加载当前用户的帖子(如果不是admin
)class CommentsController < Application
load_and_authorize_resource
def index
@posts = @posts
end
end