Как заставить камень авторизации cancan ограничивать пользователей своими данными? - PullRequest
4 голосов
/ 05 декабря 2011

Здравствуйте! Я на самом деле использую авторизацию Ryan 'Bates cancan gem, чтобы пользователи моего приложения могли управлять только данными, которые они создают. Я использую Волшебство gem для обработки аутентификации.

моделей / способностей.рб

class Ability
  include CanCan::Ability

  def initialize(user)
       user ||= User.new # guest user (not logged in)
       if user
        can :manage, Profile, :user_id => user.id
        can :manage, Album, :user_id => user.id
       end

  end
end

Контроллеры / albums_controllers.rb

# -*- encoding : utf-8 -*-
class AlbumsController < ApplicationController

    # Authentification before accessing Albums
    before_filter :require_login, :except => [:not_authenticated]
    load_and_authorize_resource


  def index
    @albums = Album.all

    respond_to do |format|
      format.html # index.html.erb
      format.json { render json: @albums }
    end
  end


  def show
    @album = Client.find(params[:id])
    authorize! :show, @album

    respond_to do |format|
      format.html # show.html.erb
      format.json { render json: @album }
    end
  end


  def new
    @album = Album.new

    respond_to do |format|
      format.html # new.html.erb
      format.json { render json: @album }
    end
  end

  def edit
    @album = Album.find(params[:id])
     authorize! :edit, @album
  end


  def create
    @album = Album.new(params[:album])

    respond_to do |format|
      if @album.save
        format.html { redirect_to @album, notice: 'album was successfully created.' }
        format.json { render json: @album, status: :created, location: @album }
      else
        format.html { render action: "new" }
        format.json { render json: @album.errors, status: :unprocessable_entity }
      end
    end
  end


  def update
    @album = Album.find(params[:id])
     authorize! :update, @album

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


  def destroy
    @album = Album.find(params[:id])
    @album.destroy

    respond_to do |format|
      format.html { redirect_to albums_url }
      format.json { head :ok }
    end
  end
end

Но после этого пользователь все еще может работать с данными другого пользователя. Чего мне не хватает.

Ответы [ 2 ]

5 голосов
/ 10 февраля 2012

load_and_authorize_resource автоматически предоставляет вам @albums (поэтому нет необходимости устанавливать его снова в index. Итак, в следующем:

def index
  @albums = Album.all
   .....# some code
end

@albums снова загружается со всеми альбомами, поэтому показывает их все. Вы можете заменить это следующим:

def index
  @albums = Album.accessible_by(current_ability)
   .....# some code
end

Но даже это не требуется, поскольку load_and_authorize_resource заполняет @albums правильными альбомами для текущего пользователя. Таким образом, будет достаточно следующего:

def index
   .....# some code
end

даст вам тот же результат. Это сила cancan. Также вместо load_and_authorize_resource вы можете использовать authorize_resource или load_resourse отдельно. Подробнее здесь

2 голосов
/ 05 декабря 2011

Согласно документации , я считаю, что вам нужно добавить load_and_authorize_resource или аналогичный классам, которые вы хотите авторизовать, или же добавить метод authorize! для ручной обработки авторизации в действии контроллера..

...