<commit_before>require 'spec_helper'

class User < ActiveRecord::Base; end

class Article < ActiveRecord::Base
  include Heimdallr::Model

  belongs_to :owner, :class_name => 'User'

  restrict do |user, record|
    if user.admin?
      # Administrator or owner can do everything
      scope :fetch
      scope :delete
      can [:view, :create, :update]
    else
      # Other users can view only their own or non-classified articles...
      scope :fetch,  -> { where('owner_id = ? or secrecy_level < ?', user.id, 5) }
      scope :delete, -> { where('owner_id = ?', user.id) }

      # ... and see all fields except the actual security level
      # (through owners can see everything)...
      if record.try(:owner) == user
        can    :view
      else
        can    :view
        cannot :view, [:secrecy_level]
      end

      # ... and can create them with certain restrictions.
      can :create, %w(content)
      can [:create, :update], {
        owner:         user,
        secrecy_level: { inclusion: { in: 0..4 } }
      }
    end
  end
end

describe Heimdallr::Proxy do
  before(:all) do
    @john = User.create! :admin => false
    Article.create! :owner_id => @john.id, :content => 'test', :secrecy_level => 10
    Article.create! :owner_id => @john.id, :content => 'test', :secrecy_level => 3
  end

  before(:each) do
    @admin  = User.new :admin => true
    @looser = User.new :admin => false
  end

  it "should apply restrictions" do
    proxy = Article.restrict(@admin)
    proxy.should be_a_kind_of Heimdallr::Proxy::Collection

    proxy = Article.restrict(@looser)
    proxy.should be_a_kind_of Heimdallr::Proxy::Collection
  end

  it "should handle fetch scope" do
    Article.restrict(@admin).all.count.should == 2
    Article.restrict(@looser).all.count.should == 1
    Article.restrict(@john).all.count.should == 2
  end

  it "should handle destroy scope" do
    article = Article.create! :owner_id => @john.id, :content => 'test', :secrecy_level => 0
    expect { article.restrict(@looser).destroy }.should raise_error
    expect { article.restrict(@john).destroy }.should_not raise_error

    article = Article.create! :owner_id => @john.id, :content => 'test', :secrecy_level => 0
    expect { article.restrict(@admin).destroy }.should raise_error
  end
end<commit_msg>Complete proxy spec<commit_after>require 'spec_helper'

class User < ActiveRecord::Base; end

class Article < ActiveRecord::Base
  include Heimdallr::Model

  belongs_to :owner, :class_name => 'User'

  restrict do |user, record|
    if user.admin?
      # Administrator or owner can do everything
      scope :fetch
      scope :delete
      can [:view, :create, :update]
    else
      # Other users can view only their own or non-classified articles...
      scope :fetch,  -> { where('owner_id = ? or secrecy_level < ?', user.id, 5) }
      scope :delete, -> { where('owner_id = ?', user.id) }

      # ... and see all fields except the actual security level
      # (through owners can see everything)...
      if record.try(:owner) == user
        can    :view
      else
        can    :view
        cannot :view, [:secrecy_level]
      end

      # ... and can create them with certain restrictions.
      can :create, %w(content)
      can [:create, :update], {
        owner:         user,
        secrecy_level: { inclusion: { in: 0..4 } }
      }
    end
  end
end

describe Heimdallr::Proxy do
  before(:all) do
    @john = User.create! :admin => false
    Article.create! :owner_id => @john.id, :content => 'test', :secrecy_level => 10
    Article.create! :owner_id => @john.id, :content => 'test', :secrecy_level => 3
  end

  before(:each) do
    @admin  = User.new :admin => true
    @looser = User.new :admin => false
  end

  it "should apply restrictions" do
    proxy = Article.restrict(@admin)
    proxy.should be_a_kind_of Heimdallr::Proxy::Collection

    proxy = Article.restrict(@looser)
    proxy.should be_a_kind_of Heimdallr::Proxy::Collection
  end

  it "should handle fetch scope" do
    Article.restrict(@admin).all.count.should == 2
    Article.restrict(@looser).all.count.should == 1
    Article.restrict(@john).all.count.should == 2
  end

  it "should handle destroy scope" do
    article = Article.create! :owner_id => @john.id, :content => 'test', :secrecy_level => 0
    expect { article.restrict(@looser).destroy }.should raise_error
    expect { article.restrict(@john).destroy }.should_not raise_error

    article = Article.create! :owner_id => @john.id, :content => 'test', :secrecy_level => 0
    expect { article.restrict(@admin).destroy }.should_not raise_error
  end

  it "should handle list of fields to view" do
    article = Article.create! :owner_id => @john.id, :content => 'test', :secrecy_level => 0
    expect { article.restrict(@looser).secrecy_level }.should raise_error
    expect { article.restrict(@admin).secrecy_level }.should_not raise_error
    expect { article.restrict(@john).secrecy_level }.should raise_error
    article.restrict(@looser).content.should == 'test'
  end

  it "should handle entities creation" do
    expect { Article.restrict(@looser).create! :content => 'test', :secrecy_level => 10 }.should raise_error

    article = Article.restrict(@john).create! :content => 'test', :secrecy_level => 3
    article.owner.should == @john
  end
  it "should handle entities creation" do
    expect { Article.restrict(@looser).create! :content => 'test', :secrecy_level => 10 }.should raise_error

    article = Article.restrict(@john).create! :content => 'test', :secrecy_level => 3
    article.owner.should == @john
  end

  it "should handle entities update" do
    article = Article.create! :owner_id => @john.id, :content => 'test', :secrecy_level => 10
    expect {
      article.restrict(@john).attributes = {:secrecy_level => 8}
    }.should raise_error
    expect {
      article.restrict(@looser).attributes = {:secrecy_level => 3}
    }.should raise_error
    expect {
      article.restrict(@john).attributes = {:secrecy_level => 10}
    }.should_not raise_error
  end
end
{'fraction_non_alphanumeric': 0.13087193011373002, 'fraction_numerical': 0.005768913795945278, 'mean_word_length': 3.0917060013486175, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 56, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6770597', 'n_tokens_mistral': 1983, 'n_tokens_neox': 1891, 'n_words': 524}