/can_sphinx

CanSphinx allows you to use CanCan for authorizing resources searched by ThinkingSphinx

Primary LanguageRubyMIT LicenseMIT

CanSphinx

CanSphinx is a Ruby on Rails library which allows you to use CanCan for authorizing resources searched by ThinkingSphinx.

Installation

In Rails 3, add this to your Gemfile and run the bundle command.

gem 'can_sphinx', :git => 'git://github.com/sylogix/can_sphinx.git'

Getting Started

CanSphinx uses sphinx attributes in order to check authorization. So the first thing we need to do is to make sure that all attributes needed are indexed. In this example, we are authorized to see all our coworkers (= people with the same company_id as us) and all our friends (= people with a friendship association with us)

class Person < ActiveRecord::Base

  define_index do
    indexes first_name
    indexes last_name

    has company_id
    has friendships(:person_id), :as => :friends

  end

  belongs_to :company
  has_many :friendships
  has_many :friends, :through => :friendships    

end

class Friendship < ActiveRecord::Base
  belongs_to :person
  belongs_to :friend, :class_name => 'Person', :foreign_key => 'friend_id'
end

Then we need to update our ability.rb so we can add a condition in a langage Sphinx can understand :

can :read, Person, Person.include(:friendships).where(['company_id = ? OR friendships.user_id = ?', user.company_id, user.id]) do |p|
  p.company_id == user.company_id or p.friendships.where(:user_id => user.id).empty?
end

Simply becomes :

can :read, Person, Person.include(:friendships).where(['company_id = ? OR friendships.user_id = ?', user.company_id, user.id]), "company_id = #{user.company_id} OR IN(friends,#{user.id})" do |p|
  p.company_id == user.company_id or p.friendships.where(:user_id => user.id).empty?
end

You can find the complete syntax of Sphinx select here. In a future release, CanSphinx might directly use CanCan conditions when it’s a Hash. We will need to it manually for complex conditions. Now we simply have to pass our abilities to the ThinkingSphinx search. In our People controller we might have something like this :

def index
  @people = Person.search params[:search], :authorize_with => current_ability
end