2014-12-31 2 views
0

Я беру курс, в котором я создаю базовую вики. Я определенно новичок в этом. Мне нужно ограничить пользователей от простого ввода идентификатора вики, который они хотят просмотреть непосредственно в URL-адресе (пример: wikis/5). Единственные люди, которые должны иметь возможность просматривать wiki, должны быть владельцем вики, администратором или сотрудником в этой вики.Как я могу запретить пользователю просматривать страницу, к которой у них нет доступа?

Я успешно ограничил представление индекса, чтобы пользователь, зарегистрированный в системе, только видел свою собственную вики, общедоступную вики или вики, с которыми они сотрудничают.

Я попытался реализовать аналогичный код в своей WikiPolicy, но он не работает, и я не могу найти решение. Код, который у меня есть, просто покажет вики, если пользователь вошел в систему. Я знаю, что моя логика хороша, потому что я могу подставить значение для 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 вернуть набор вики, что конкретный пользователь авторизован для просмотра. Я считаю, что это работает, потому что он рассматривает все вики, а не зависит от конкретной вики, которую пользователь пытается просмотреть.

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 

ответ

0

params не доступен в wiki_policy.rb, потому что он не передается в методе 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 true или return false по всем возможностям.

+0

Спасибо! Это прекрасно и помогло мне понять, что я пытаюсь сделать лучше. – Tyler