如何限制用户查看他们无法访问的页面?

时间:2014-12-31 17:01:58

标签: ruby-on-rails authorization pundit

我正在学习一门课程,让我创建一个基本的wiki。我对此非常陌生。我需要限制用户只需输入他们想要直接在URL中查看的wiki id(例如:wikis / 5)。应该能够查看维基的唯一人应该是维基所有者,管理员或该维基上的合作者。

我已成功限制索引视图,以便签名用户只能看到他们自己的wiki,公共wiki或他们合作的wiki。

我试图在我的WikiPolicy中实现类似的代码,但它无法正常工作,我似乎无法找到解决方案。我现在的代码只是显示用户登录的wiki。我知道我的逻辑是好的,因为我可以用params [:id]的值代替“5”,它可以正常工作。

wikis_controller.rb

def show
    @wiki = Wiki.find(params[:id])
    authorize @wiki
  end

wiki_policy.rb

def show?
    scope.where(:id => record.id).exists?
    current_wiki = Wiki.find(params[:id])
    collaborations = Collaboration.where(:user_id => user)
    collab_wikis = Wiki.where(id: collaborations.pluck(:wiki_id))
    collab_wikis.include?(current_wiki)
  end

以下是我在wiki_policy.rb中使用的代码,用于返回特定用户有权查看的一组wiki。我相信这是有效的,因为它正在查看所有wiki,而不是依赖于用户试图查看的特定wiki。

class Scope
     attr_reader :user, :scope

     def initialize(user, scope)
       @user = user
       @scope = scope
     end

     def resolve
       wikis = []
       if user.role?(:admin)
         wikis = scope.all # if the user is an admin, show them all the wikis
       elsif user.role?(:premium)
         collaborations = Collaboration.where(:user_id => user)
         collab_wikis = Wiki.where(id: collaborations.pluck(:wiki_id))
         all_wikis = scope.all
         all_wikis.each do |wiki|
           if !wiki.is_private || wiki.user_id == user.id || collab_wikis.include?(wiki)
              wikis << wiki # if the user is premium, only show them public wikis, or that private wikis they created, or private wikis they are a collaborator on
           end
         end
        else # this is the lowly standard user
          collaborations = Collaboration.where(:user_id => user)
          collab_wikis = Wiki.where(id: collaborations.pluck(:wiki_id))
          all_wikis = scope.all
          wikis = []
          all_wikis.each do |wiki|
            if !wiki.is_private? || wiki.user_id == user.id || collab_wikis.include?(wiki)
              wikis << wiki # only show standard users public wikis and private wikis they are a collaborator on
            end
          end
       end
       wikis # return the wikis array we've built up
     end
   end

1 个答案:

答案 0 :(得分:1)

wiki_policy.rb中未提供

params,因为它未在authorize方法中传递。 authorize传递记录(以及找到的Wiki对象)和current_user对象。您可以再次跳过查找当前维基。此外,在此方法和其他操作(update?edit?等)中,您需要返回true或false。因此,您需要根据您的规范确定用户是管理员,协作者还是所有者。

def show?
  record.user_id == user.id or Wiki.where(id: Collaboration.where(:user_id => user.id).pluck(:wiki_id)).include?(record) or user.role?(:admin)
end

这将给你一个真实或错误的回报,并检查你需要授权的所有三个项目。如果你想改变它,你可以使用if / else语句,只需确保return truereturn false所有可能性。