Канкан не показывает авторизованные элементы просмотра

StackOverflow https://stackoverflow.com/questions/3810977

  •  26-09-2019
  •  | 
  •  

Вопрос

Я пытаюсь получить базовую аутентификацию / авторизацию с разработкой / канкан с рельсами. Вместо того, чтобы использование ролей, таких как скринкаст Ryan B и другие примеры вокруг я пытаюсь сделать что-то базовое:

1 - пользователь может войти в систему
2 - Пользователь может редактировать / уничтожить свои собственные статьи (без ролей, вы либо вошли в систему, и можете создавать новые статьи и редактировать / уничтожить свой собственный или вы выходить из системы, и вы можете увидеть только статьи и вход только в систему)

Я использую разработку для первой части, и это хорошо работает, но я не могу получить вторую часть, работающую с CANCAN. Ссылки для редактирования и уничтожения для статей не появляются, когда вы вошли в систему, и прямой URL (например, / статьи / 3 / редактирование) до сих пор допускают, даже если статья для другого пользователя.

Мой ability.rb является

class Ability
  include CanCan::Ability

  def initialize(user)
    user ||= User.new # guest user

    if user.nil? 
      can :read, :all
    else
#      can :manage, :all #test - with this, all the edit/destroy links appear
       can :manage, Article, :user_id == user
    end
  end
end

articles_controller.rb:

class ArticlesController < ApplicationController

  before_filter :authenticate_user!, :except => [:index, :show] # for Devise
  load_and_authorize_resource


  # GET /articles
  # GET /articles.xml
  def index

    @articles = Article.all

    respond_to do |format|
      format.html # index.html.erb
      format.xml  { render :xml => @articles }
    end
  end

  # GET /articles/1
  # GET /articles/1.xml
  def show
    @article = Article.find(params[:id])

    respond_to do |format|
      format.html # show.html.erb
      format.xml  { render :xml => @article }
    end
  end

  # GET /articles/new
  # GET /articles/new.xml
  def new
    @article = Article.new

    respond_to do |format|
      format.html # new.html.erb
      format.xml  { render :xml => @article }
    end
  end

  # GET /articles/1/edit
  def edit
    @article = Article.find(params[:id])
  end

  # POST /articles
  # POST /articles.xml
  def create
    @article = Article.new(params[:article])
    @article.user = current_user

    respond_to do |format|
      if @article.save
        format.html { redirect_to(articles_path, :notice => 'Article was successfully created.') }
        format.xml  { render :xml => articles_path, :status => :created, :location => articles_path }
      else
        format.html { render :action => "new" }
        format.xml  { render :xml => @article.errors, :status => :unprocessable_entity }
      end
    end
  end

  # PUT /articles/1
  # PUT /articles/1.xml
  def update
    @article = Article.find(params[:id])

    respond_to do |format|
      if @article.update_attributes(params[:article])
        format.html { redirect_to(@article, :notice => 'Article was successfully updated.') }
        format.xml  { head :ok }
      else
        format.html { render :action => "edit" }
        format.xml  { render :xml => @article.errors, :status => :unprocessable_entity }
      end
    end
  end

  # DELETE /articles/1
  # DELETE /articles/1.xml
  def destroy
    @article = Article.find(params[:id])
    @article.destroy

    respond_to do |format|
      format.html { redirect_to(articles_url) }
      format.xml  { head :ok }
    end
  end
end

и вид частичный, который перечисляет статьи _article_list.html.erb:

    <table>
      <tr>
        <th>Title</th>
        <th>Description</th>
        <th>User</th>
        <th></th>
        <th></th>
        <th></th>
      </tr>

    <% @articles.each do |article| %>
      <tr>
        <td><%= article.title %></td>
        <td><%= article.description %></td>
        <td><%= article.user_id %></td>
        <td><%= link_to 'Show', article %></td>
        <% if can? :update, @article %>
            <td><%= link_to 'Edit', edit_article_path(article) %></td>
        <% end %>
        <% if can? :destroy, @article %>
            <td><%= link_to 'Destroy', article, :confirm => 'Are you sure?', :method => :delete %></td>
        <% end%>
      </tr>
    <% end %>
    </table>

С этой настройкой ссылки редактирования / уничтожения в представлении не отображаются, если нет одеяла can :manage, :all, четное can :manage, Article не работает. Как я уже упоминал выше, он также не ограничивает фактические действия, поскольку вы можете глубоко связать прямую связь, чтобы редактировать статью, и это позволяет ему.

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

заранее спасибо
Джейсон

Это было полезно?

Решение

Мне удалось решить мою проблему. Я сбрасываю свою среду (RVM - Resintrated Gems и Gемсет - Ruby 1.9.2 и Rails 3.0.0) и изменил некоторые из кодов, и все проблемы, которые я прошел (перенаправить петлю, просмотр элементов, не меняющихся на основе регистрации В несанкционированном контроллере действий все еще допустимо). Я вставил ability.rb, articles_controller.rb, а также _article_list.html.erb.

ability.rb:

class Ability
  include CanCan::Ability

  def initialize(user)
    if user
      can :create, Article
      can :read, :all
      can :update, Article, :user_id => user.id
      can :delete, Article, :user_id => user.id
    else
      can :read, :all
    end
  end
end

Я думаю, что это имеет смысл сейчас, но потому что только обновление и удаление должны были быть для текущих средств пользователя, я разбил элементы Crud, чтобы быть конкретными.

articles_controller.rb

class ArticlesController < ApplicationController

  before_filter :authenticate_user!, :except => [:index, :show]
#  load_and_authorize_resource # RESTful automated CanCam authorization - excludes non RESTful

  # GET /articles
  # GET /articles.xml
  def index
    @articles = Article.all
    authorize! :read, @articles


    respond_to do |format|
      format.html # index.html.erb
      format.xml  { render :xml => @articles }
    end
  end

  # GET /articles/1
  # GET /articles/1.xml
  def show
    @article = Article.find(params[:id])
    authorize! :read, @article

    respond_to do |format|
      format.html # show.html.erb
      format.xml  { render :xml => @article }
    end
  end

  # GET /articles/new
  # GET /articles/new.xml
  def new
    @article = Article.new
    authorize! :create, @article

    respond_to do |format|
      format.html # new.html.erb
      format.xml  { render :xml => @article }
    end
  end

  # GET /articles/1/edit
  def edit
    @article = Article.find(params[:id])
    authorize! :update, @article
  end

  # POST /articles
  # POST /articles.xml
  def create
    @article = Article.new(params[:article])
    @article.user = current_user
    authorize! :create, @article

    respond_to do |format|
      if @article.save
        format.html { redirect_to(articles_path, :notice => 'Article was successfully created.') }
        format.xml  { render :xml => articles_path, :status => :created, :location => articles_path }
      else
        format.html { render :action => "new" }
        format.xml  { render :xml => @article.errors, :status => :unprocessable_entity }
      end
    end
  end

  # PUT /articles/1
  # PUT /articles/1.xml
  def update
    @article = Article.find(params[:id])
    authorize! :update, @article

    respond_to do |format|
      if @article.update_attributes(params[:article])
        format.html { redirect_to(@article, :notice => 'Article was successfully updated.') }
        format.xml  { head :ok }
      else
        format.html { render :action => "edit" }
        format.xml  { render :xml => @article.errors, :status => :unprocessable_entity }
      end
    end
  end

  # DELETE /articles/1
  # DELETE /articles/1.xml
  def destroy
    @article = Article.find(params[:id])
    @article.destroy
    authorize! :delete, @article

    respond_to do |format|
      format.html { redirect_to(articles_url) }
      format.xml  { head :ok }
    end
  end

  def by
    @user = User.find(params[:id])
    @articles = @user.articles
    authorize! :read, @articles
  end
end

load_and_authorize_resource Работает, но я положил конкретную авторизую! Линии в каждом действии контроллера, так как у меня есть дополнительные действия внизу. Оба сейчас работают.

Я обновил ссылку на @Article к статье, чтобы ссылаться на текущую статью в списке в _article_list.html.rb:

<table>
  <tr>
    <th>Title</th>
    <th>Description</th>
    <th>User</th>
    <th></th>
    <th></th>
    <th></th>
  </tr>

<% @articles.each do |article| %>
  <tr>
    <td><%= article.title %></td>
    <td><%= article.description %></td>
    <td><%= article.user_id %></td>
    <td><%= link_to 'Show', article %></td>
    <% if can? :update, article %>
        <td><%= link_to 'Edit', edit_article_path(article) %></td>
    <% end %>
    <% if can? :delete, article %>
        <td><%= link_to 'Destroy', article, :confirm => 'Are you sure?', :method => :delete %></td>
    <% end %>
  </tr>
<% end %>
</table>

Все работает сейчас. Спасибо за помощь здесь и, надеюсь, это поможет кому-то еще, если они столкнутся с этой проблемой.

Другие советы

Ваше условие соответствия идентификатора пользователя не совсем правильно. Так должно быть:

can :manage, Article, :user_id => user.id

Атрибут, который вы хотите проверить, сопоставлен на значение, на котором вы хотите проверить.

Кроме того, вы проверяете на user.nil? Когда он не может быть ноль, потому что вы только что инициализировали. (Вероятно, симптом пробовал много вещей!)

Ваша работаешь? Если вы беспокоить CAN: Manage: All Line будет возможность редактировать свой пост (вместе со всеми остальными)?

Вы пытались меняться, можно: Управление, статья: user_id == пользователь на

can :manage, Article do |article|
 article.try(:user) == user

Я никогда не смог нагружать разрешение на работу - хотя я подозреваю, что я делаю что-то не так. Чтобы предотвратить доступ к кому-либо доступа к URL-адресам, в редактировании вашей статьи, попробуйте добавить это

 unauthorized! if cannot? :edit, @article
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top