Skip to content
This repository
Fetching contributors…

Cannot retrieve contributors at this time

file 211 lines (171 sloc) 8.293 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
if ENV["MODEL_ADAPTER"] == "mongoid"
  require "spec_helper"

  class MongoidCategory
    include Mongoid::Document

    references_many :mongoid_projects
  end

  class MongoidProject
    include Mongoid::Document

    referenced_in :mongoid_category
  end

  Mongoid.configure do |config|
    config.master = Mongo::Connection.new('127.0.0.1', 27017).db("cancan_mongoid_spec")
  end

  describe CanCan::ModelAdapters::MongoidAdapter do
    context "Mongoid defined" do
      before(:each) do
        @ability = Object.new
        @ability.extend(CanCan::Ability)
      end

      after(:each) do
        Mongoid.master.collections.select do |collection|
          collection.name !~ /system/
        end.each(&:drop)
      end

      it "should be for only Mongoid classes" do
        CanCan::ModelAdapters::MongoidAdapter.should_not be_for_class(Object)
        CanCan::ModelAdapters::MongoidAdapter.should be_for_class(MongoidProject)
        CanCan::ModelAdapters::AbstractAdapter.adapter_class(MongoidProject).should == CanCan::ModelAdapters::MongoidAdapter
      end

      it "should compare properties on mongoid documents with the conditions hash" do
        model = MongoidProject.new
        @ability.can :read, MongoidProject, :id => model.id
        @ability.should be_able_to(:read, model)
      end

      it "should be able to read hashes when field is array" do
        one_to_three = MongoidProject.create(:numbers => ['one', 'two', 'three'])
        two_to_five = MongoidProject.create(:numbers => ['two', 'three', 'four', 'five'])

        @ability.can :foo, MongoidProject, :numbers => 'one'
        @ability.should be_able_to(:foo, one_to_three)
        @ability.should_not be_able_to(:foo, two_to_five)
      end

      it "should return [] when no ability is defined so no records are found" do
        MongoidProject.create(:title => 'Sir')
        MongoidProject.create(:title => 'Lord')
        MongoidProject.create(:title => 'Dude')

        MongoidProject.accessible_by(@ability, :read).entries.should == []
      end

      it "should return the correct records based on the defined ability" do
        @ability.can :read, MongoidProject, :title => "Sir"
        sir = MongoidProject.create(:title => 'Sir')
        lord = MongoidProject.create(:title => 'Lord')
        dude = MongoidProject.create(:title => 'Dude')

        MongoidProject.accessible_by(@ability, :read).entries.should == [sir]
      end

      it "should be able to mix empty conditions and hashes" do
        @ability.can :read, MongoidProject
        @ability.can :read, MongoidProject, :title => 'Sir'
        sir = MongoidProject.create(:title => 'Sir')
        lord = MongoidProject.create(:title => 'Lord')

        MongoidProject.accessible_by(@ability, :read).count.should == 2
      end

      it "should return everything when the defined ability is manage all" do
        @ability.can :manage, :all
        sir = MongoidProject.create(:title => 'Sir')
        lord = MongoidProject.create(:title => 'Lord')
        dude = MongoidProject.create(:title => 'Dude')

        MongoidProject.accessible_by(@ability, :read).entries.should == [sir, lord, dude]
      end

      it "should allow a scope for conditions" do
        @ability.can :read, MongoidProject, MongoidProject.where(:title => 'Sir')
        sir = MongoidProject.create(:title => 'Sir')
        lord = MongoidProject.create(:title => 'Lord')
        dude = MongoidProject.create(:title => 'Dude')

        MongoidProject.accessible_by(@ability, :read).entries.should == [sir]
      end

      describe "Mongoid::Criteria where clause Symbol extensions using MongoDB expressions" do
        it "should handle :field.in" do
          obj = MongoidProject.create(:title => 'Sir')
          @ability.can :read, MongoidProject, :title.in => ["Sir", "Madam"]
          @ability.can?(:read, obj).should == true
          MongoidProject.accessible_by(@ability, :read).should == [obj]

          obj2 = MongoidProject.create(:title => 'Lord')
          @ability.can?(:read, obj2).should == false
        end

        describe "activates only when there are Criteria in the hash" do
          it "Calls where on the model class when there are criteria" do
            obj = MongoidProject.create(:title => 'Bird')
            @conditions = {:title.nin => ["Fork", "Spoon"]}

            @ability.can :read, MongoidProject, @conditions
            @ability.should be_able_to(:read, obj)
          end
          it "Calls the base version if there are no mongoid criteria" do
            obj = MongoidProject.new(:title => 'Bird')
            @conditions = {:id => obj.id}
            @ability.can :read, MongoidProject, @conditions
            @ability.should be_able_to(:read, obj)
          end
        end

        it "should handle :field.nin" do
          obj = MongoidProject.create(:title => 'Sir')
          @ability.can :read, MongoidProject, :title.nin => ["Lord", "Madam"]
          @ability.can?(:read, obj).should == true
          MongoidProject.accessible_by(@ability, :read).should == [obj]

          obj2 = MongoidProject.create(:title => 'Lord')
          @ability.can?(:read, obj2).should == false
        end

        it "should handle :field.size" do
          obj = MongoidProject.create(:titles => ['Palatin', 'Margrave'])
          @ability.can :read, MongoidProject, :titles.size => 2
          @ability.can?(:read, obj).should == true
          MongoidProject.accessible_by(@ability, :read).should == [obj]

          obj2 = MongoidProject.create(:titles => ['Palatin', 'Margrave', 'Marquis'])
          @ability.can?(:read, obj2).should == false
        end

        it "should handle :field.exists" do
          obj = MongoidProject.create(:titles => ['Palatin', 'Margrave'])
          @ability.can :read, MongoidProject, :titles.exists => true
          @ability.can?(:read, obj).should == true
          MongoidProject.accessible_by(@ability, :read).should == [obj]

          obj2 = MongoidProject.create
          @ability.can?(:read, obj2).should == false
        end

        it "should handle :field.gt" do
          obj = MongoidProject.create(:age => 50)
          @ability.can :read, MongoidProject, :age.gt => 45
          @ability.can?(:read, obj).should == true
          MongoidProject.accessible_by(@ability, :read).should == [obj]

          obj2 = MongoidProject.create(:age => 40)
          @ability.can?(:read, obj2).should == false
        end

        it "should handle instance not saved to database" do
          obj = MongoidProject.new(:title => 'Sir')
          @ability.can :read, MongoidProject, :title.in => ["Sir", "Madam"]
          @ability.can?(:read, obj).should == true

          # accessible_by only returns saved records
          MongoidProject.accessible_by(@ability, :read).entries.should == []

          obj2 = MongoidProject.new(:title => 'Lord')
          @ability.can?(:read, obj2).should == false
        end
      end

      it "should call where with matching ability conditions" do
        obj = MongoidProject.create(:foo => {:bar => 1})
        @ability.can :read, MongoidProject, :foo => {:bar => 1}
        MongoidProject.accessible_by(@ability, :read).entries.first.should == obj
      end
      
      it "should exclude from the result if set to cannot" do
        obj = MongoidProject.create(:bar => 1)
        obj2 = MongoidProject.create(:bar => 2)
        @ability.can :read, MongoidProject
        @ability.cannot :read, MongoidProject, :bar => 2
        MongoidProject.accessible_by(@ability, :read).entries.should == [obj]
      end

      it "should combine the rules" do
        obj = MongoidProject.create(:bar => 1)
        obj2 = MongoidProject.create(:bar => 2)
        obj3 = MongoidProject.create(:bar => 3)
        @ability.can :read, MongoidProject, :bar => 1
        @ability.can :read, MongoidProject, :bar => 2
        MongoidProject.accessible_by(@ability, :read).entries.should =~ [obj, obj2]
      end
      
      it "should not allow to fetch records when ability with just block present" do
        @ability.can :read, MongoidProject do
          false
        end
        lambda {
          MongoidProject.accessible_by(@ability)
        }.should raise_error(CanCan::Error)
      end
    end
  end
end
Something went wrong with that request. Please try again.