Pregunta

Estoy tratando de conseguir un poco de autenticación / autorización básica con legado / cancán con rieles. En lugar de utilizar funciones como screencast de Ryan B y otros ejemplos en que estoy tratando de hacer algo básico:

1 - Un usuario puede iniciar sesión en
2 - Un usuario sólo puede editar / destruir sus propios artículos (sin papeles, ya sea que estés conectado y puede crear nuevos artículos y editar / destruir su propia o si está desconectado y sólo se puede ver artículos y de inicio de sesión)

Estoy usando legado para la primera parte y que está funcionando bien, pero no puedo obtener la segunda parte de trabajo con CanCan. El la edición y destruir enlaces para los artículos no aparecen cuando está conectado y la dirección URL directa (por ejemplo / artículos / 3 / editar) todavía permite que incluso si el artículo es para otro usuario.

Mi ability.rb es

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

y la vista parcial que enumera los artículos _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>

Con esta configuración, la edición / destruir enlaces en la vista no aparecen a menos que haya un can :manage, :all manta, can :manage, Article aún no funciona. Como he mencionado anteriormente, tampoco es la restricción de las acciones reales como usted es capaz de profunda enlace directo a la edición de un artículo y se lo permite.

No estoy seguro de lo que estoy haciendo mal aquí. Sería muy bueno para conseguir un poco de ayuda.

Gracias de antemano
Jason

¿Fue útil?

Solución

Me las arreglé para resolver mi problema. Cómo reinicio mi entorno (RVM - resintalled las gemas y gemsets - rubí 1.9.2 y 3.0.0 rieles) y ha cambiado una parte del código y todos los problemas que estaba teniendo fui (bucle de redireccionamiento, elementos de la vista no cambiando en función estando conectado en, las acciones del controlador no autorizadas todavía permisibles). He pegado ability.rb, articles_controller.rb y _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

supongo que tiene sentido ahora, pero debido a que sólo actualizar y borrar se supone que son para los artículos del usuario actual, Me dividir los elementos CRUD que es específica.

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

funciona load_and_authorize_resource pero me he puesto específico autorizar! líneas en cada acción del controlador ya que tienen una acción adicional en la parte inferior. Tanto ahora trabajo.

Me ha actualizado la referencia a @ article al artículo para hacer referencia al artículo correspondiente de la lista de _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>

Todo trabajando ahora. Gracias por la ayuda aquí y espero que esto le ayuda a otra persona si se encuentran con este problema.

Otros consejos

Su condición para que coincidan con un ID de usuario no está del todo bien. Debe ser:

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

El atributo que desea comprobar se asigna al valor que desea comprobar en contra.

Además, está comprobando las user.nil? cuando no puede ser cero, puesto que acaba inicializado él. (Probablemente un síntoma de tener un montón de cosas intentado!)

¿Trabaja su captura? Si se quite la lata: administrar: toda la línea será un usuario pueda editar su / su puesto (junto con todos los demás, por supuesto)

?

¿Usted ha intentado cambiar, puede: administrar, artículo,: user_id == usuario

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

nunca he sido capaz de conseguir una carga de autorización a trabajar- aunque sospecho que estaba haciendo algo mal. Para evitar que alguien acceda a la dirección URL directamente, en la acción de editar su artículo, trate de añadir este

 unauthorized! if cannot? :edit, @article
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top