CanSphinx is a Ruby on Rails library which allows you to use CanCan for authorizing resources searched by ThinkingSphinx.
In Rails 3, add this to your Gemfile and run the bundle
command.
gem 'can_sphinx', :git => 'git://github.com/sylogix/can_sphinx.git'
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