سؤال

أحاول الحصول على بعض المصادقة/التفويض الأساسي مع Pintise/Cancan مع القضبان. بدلاً من استخدام أدوار مثل شاشة Ryan B والأمثلة الأخرى حولها أحاول القيام بشيء أساسي:

1 - يمكن للمستخدم تسجيل الدخول
2 - لا يمكن للمستخدم سوى تحرير/تدمير مقالاته الخاصة (بدون أدوار ، إما قمت بتسجيل الدخول ويمكنك إنشاء مقالات جديدة وتحرير/تدميرك أو يمكنك تسجيلها فقط ويمكنك رؤية المقالات وتسجيل الدخول فقط)

أنا أستخدم ابتكار للجزء الأول وهذا يعمل بشكل جيد ولكن لا يمكنني الحصول على الجزء الثاني مع كانان. لا تظهر روابط التحرير وتدمير المقالات عندما تقوم بتسجيل الدخول وما زال عنوان 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 - Resintalled الأحجار الكريمة والأحجار الكريمة - Ruby 1.9.2 و Rails 3.0.0) وغيرت بعض الكود وجميع المشكلات التي كنت قد ذهبت بعيدًا (Redirect Loop ، عرض عناصر لا تتغير بناءً على تسجيل الدخول في ، لا تزال إجراءات وحدة تحكم غير مصرح بها يمكن السماح بها). لقد لصق 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: إدارة ، مقالة ،: user_id == المستخدم إلى

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

لم أتمكن مطلقًا من التحميل لتوضيح العمل- على الرغم من أنني أظن أنني كنت أفعل شيئًا خاطئًا. لمنع شخص ما من الوصول إلى عنوان URL مباشرة ، في إجراء تحرير مقالتك ، حاول إضافة هذا

 unauthorized! if cannot? :edit, @article
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top