Domanda

Sto cercando di ottenere un'autenticazione/autorizzazione di base con devise/cancan con Rails.Invece di utilizzare ruoli come lo screencast di Ryan B e altri esempi in giro, sto cercando di fare qualcosa di semplice:

1 - Un utente può accedere
2 - Un utente può solo modificare/distruggere i propri articoli (nessun ruolo, o hai effettuato l'accesso e puoi creare nuovi articoli e modificare/distruggere i tuoi oppure sei disconnesso e puoi solo vedere gli articoli ed effettuare l'accesso)

Sto usando devise per la prima parte e funziona bene, ma non riesco a far funzionare la seconda parte con CanCan.I link di modifica e distruzione degli articoli non vengono visualizzati quando hai effettuato l'accesso e l'URL diretto (ad es./articles/3/edit) consente comunque anche se l'articolo è per un altro utente.

Mio 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

e la vista parziale che elenca gli articoli _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 questa configurazione, i collegamenti di modifica/distruzione nella vista non vengono visualizzati a meno che non sia presente una coperta can :manage, :all, Anche can :manage, Article non funziona.Come ho già detto in precedenza, inoltre, non limita le azioni effettive poiché puoi collegarti direttamente alla modifica di un articolo e ciò lo consente.

Non sono sicuro di cosa sto facendo di sbagliato qui.Sarebbe fantastico ricevere aiuto.

grazie in anticipo
Giasone

È stato utile?

Soluzione

Sono riuscito a risolvere il mio problema.Ho ripristinato il mio ambiente (rvm - ho resinato le gemme e i set di gemme - ruby ​​1.9.2 e rails 3.0.0) e ho modificato parte del codice e tutti i problemi che avevo sono scomparsi (loop di reindirizzamento, visualizzazione degli elementi che non cambiavano in base alla registrazione in, azioni del titolare non autorizzate sono ancora consentite).Ho incollato ability.rb, articles_controller.rb, E _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

Immagino che ora abbia senso, ma poiché solo l'aggiornamento e l'eliminazione avrebbero dovuto riguardare gli articoli dell'utente corrente, ho suddiviso gli elementi CRUD per essere specifici.

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 funziona ma ho messo l'autorizzazione specifica!linee in ogni azione del controller poiché ho un'azione extra in basso.Entrambi ora funzionano.

Ho aggiornato il riferimento a @article in article per fare riferimento all'articolo corrente nell'elenco in _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>

Tutto funziona adesso.Grazie per l'aiuto qui e spero che questo possa aiutare qualcun altro se dovesse riscontrare questo problema.

Altri suggerimenti

La vostra condizione per corrispondenza un ID utente non è giusto. Dovrebbe essere:

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

L'attributo che si desidera controllare è mappato il valore che si desidera controllare contro.

Inoltre, si sta verificando per user.nil? quando non può essere pari a zero, perché hai appena inizializzato esso. (Probabilmente un sintomo di avere un sacco di cose provato!)

Il vostro lavoro trucco? Se si rimuove il commento dalla lattina: gestire: tutto linea sarà un utente in grado di modificare la sua / il suo posto (insieme di tutti gli altri, naturalmente)

?

Hai provato cambiando, in grado di: gestire, articolo,: user_id == all'utente di

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

non sono mai stato in grado di ottenere un carico di autorizzare al lavoro-anche se ho il sospetto che stavo facendo qualcosa di sbagliato. Per impedire a qualcuno di accedere al URL direttamente, in azione di modifica del tuo articolo, prova ad aggiungere questo

 unauthorized! if cannot? :edit, @article
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top