forked from wasabhi/databasedotcom
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
273 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
require 'databasedotcom/blacklist' | ||
|
||
module Databasedotcom | ||
|
||
# Sometimes you don't want all of the SObjects or SObject fields. One vexing situation is an | ||
# SObject that has a huge number of fields because a query on that object can exceed the | ||
# maximum number of characters allowed in the URL path (8192). This produces a 500 error that | ||
# is quite difficult to understand. The solution is to remove some of the fields from the | ||
# SObject so the query URL is less than the 8192 character limit. | ||
# | ||
# You can effectively hide entire SObjects or individual fields via the whitelist. Create a hash | ||
# with keys 'classes' and/or 'fields' and specify the classes (as an array) and fields (as a hash of | ||
# class / fieldname array pairs) to be excluded. | ||
# | ||
# my_whitelist = {'classes' => ['Account', 'Case'], 'fields' => {'Opportunity' => ['name']}} | ||
# Databasedotcom::Whitelist.whitelist = my_whitelist | ||
class Whitelist | ||
|
||
@whitelist = {'classes' => [], 'fields' => {}} | ||
|
||
# Specify whitelisted class and field names in a hash. The 'class' keypair should contain an array | ||
# of SObject names and the 'fields' keypair should contain a hash of class name & field array keypairs. | ||
# my.whitelist = {'classes' => ['Account', 'Case'], 'fields' => {'Opportunity' => ['field1', 'field2']}} | ||
def self.whitelist=(whitelist_hash) | ||
@whitelist = whitelist_hash || {} | ||
@whitelist['fields'] ||= {} | ||
@whitelist['classes'] ||= [] | ||
end | ||
|
||
# Remove whitelisted fields from the description provided by Salesforce. Once the | ||
# fields are removed, Databasedotcom will not know about them or use them. | ||
def self.filter_description!(description, class_name) | ||
if description && description['fields'] | ||
description['fields'] = description['fields'].select{|f| allow_field?(class_name, f['name'])} | ||
raise Databasedotcom::NoFieldsError.new(class_name) unless description['fields'].length > 0 | ||
end | ||
end | ||
|
||
def self.allow_field?(class_name, field) | ||
allowed_fields = whitelisted_fields(class_name) | ||
allowed_fields.length == 0 || allowed_fields.include?(field) | ||
end | ||
|
||
def self.filter_sobjects(sobjects) | ||
whitelisted_classes.length > 0 ? whitelisted_classes : sobjects | ||
end | ||
|
||
private | ||
|
||
def self.whitelisted_classes | ||
@whitelist['classes'] || [] | ||
end | ||
|
||
def self.whitelisted_fields(class_name) | ||
@whitelist['fields'][class_name] || [] | ||
end | ||
|
||
end | ||
|
||
# Wrap the DESCRIBE_SOBJECT and DESCRIBE_SOBJECTS methods with the whitelist filter so | ||
# we never know about classes and/or fields that are whitelisted. | ||
class Client | ||
def describe_whitelist_sobjects_with_filter | ||
describe_whitelist_sobjects_without_filter.collect do |sobject| | ||
Databasedotcom::Whitelist.filter_description!(sobject['description'], sobject['name']) | ||
sobject | ||
end | ||
end | ||
alias_method :describe_whitelist_sobjects_without_filter, :describe_sobjects | ||
alias_method :describe_sobjects, :describe_whitelist_sobjects_with_filter | ||
|
||
def describe_whitelist_sobject_with_filter(class_name) | ||
description = describe_whitelist_sobject_without_filter(class_name) | ||
Databasedotcom::Whitelist.filter_description!(description, class_name) | ||
description | ||
end | ||
alias_method :describe_whitelist_sobject_without_filter, :describe_sobject | ||
alias_method :describe_sobject, :describe_whitelist_sobject_with_filter | ||
|
||
def list_whitelist_sobjects_with_filter | ||
Databasedotcom::Whitelist.filter_sobjects(list_whitelist_sobjects_without_filter) | ||
end | ||
alias_method :list_whitelist_sobjects_without_filter, :list_sobjects | ||
alias_method :list_sobjects, :list_whitelist_sobjects_with_filter | ||
|
||
end | ||
|
||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
require 'rspec' | ||
require 'spec_helper' | ||
require 'databasedotcom' | ||
require 'databasedotcom/whitelist' | ||
|
||
describe Databasedotcom::Whitelist do | ||
before do | ||
Databasedotcom::Blacklist.instance_variable_set(:@blacklist, {'classes' => [], 'fields' => {}}) | ||
end | ||
|
||
describe '#whitelist=' do | ||
before do | ||
@wl = Databasedotcom::Whitelist | ||
end | ||
it 'should assign classes' do | ||
@wl.whitelist = {'classes' => [1]} | ||
@wl.instance_variable_get(:@whitelist)['classes'].should == [1] | ||
end | ||
it 'should assign fields' do | ||
@wl.whitelist = {'fields' => {'class_name' => [:fields]}} | ||
@wl.instance_variable_get(:@whitelist)['fields'].should == {'class_name' => [:fields]} | ||
end | ||
it 'should initialize classes' do | ||
raw_class = Databasedotcom::Whitelist.dup | ||
raw_class.whitelist = nil | ||
raw_class.instance_variable_get(:@whitelist).keys.should include('classes') | ||
end | ||
it 'should initialize fields' do | ||
raw_class = Databasedotcom::Whitelist.dup | ||
raw_class.whitelist = nil | ||
raw_class.instance_variable_get(:@whitelist).keys.should include('fields') | ||
end | ||
end | ||
|
||
describe '#allow_field?(field)' do | ||
before do | ||
@fake_class_name = 'FakeClassName' | ||
end | ||
it 'should indicate if a field is allowed/included' do | ||
Databasedotcom::Whitelist.whitelist = {'fields' => {@fake_class_name => [:foox]}} | ||
Databasedotcom::Whitelist.allow_field?(@fake_class_name, :foo).should be_false | ||
|
||
Databasedotcom::Whitelist.whitelist = {'fields' => {@fake_class_name => [:foo]}} | ||
Databasedotcom::Whitelist.allow_field?(@fake_class_name, :foo).should be_true | ||
end | ||
it 'should be true if there is no whitelist' do | ||
Databasedotcom::Whitelist.whitelist = nil | ||
Databasedotcom::Whitelist.allow_field?(@fake_class_name, :foo).should be_true | ||
end | ||
it 'should be true if the whitelist is blank' do | ||
Databasedotcom::Whitelist.whitelist = {'fields' => {@fake_class_name => []}} | ||
Databasedotcom::Whitelist.allow_field?(@fake_class_name, :foo).should be_true | ||
end | ||
end | ||
|
||
describe '#filter_sobjects(sobjects)' do | ||
it 'should only include whitelisted sobjects' do | ||
Databasedotcom::Whitelist.whitelist = {'classes' => [:a, :c]} | ||
Databasedotcom::Whitelist.filter_sobjects([:a, :b, :c, :d]).should == [:a, :c] | ||
end | ||
it 'should include all sobjects if there is no whitelist' do | ||
Databasedotcom::Whitelist.whitelist = nil | ||
Databasedotcom::Whitelist.filter_sobjects([:a, :b, :c, :d]).should == [:a, :b, :c, :d] | ||
end | ||
end | ||
|
||
describe '#filter_description!' do | ||
describe 'with a FIELDS keypair' do | ||
before do | ||
@fake_class_name = 'FakeClassName' | ||
@description_hash = {:a => 1, :b => 2, 'fields' => [{'name'=>'one'}, {'name'=>'two'}, {'name'=>'three'}]} | ||
Databasedotcom::Whitelist.stub(:allow_field?).with(@fake_class_name, 'one'){false} | ||
Databasedotcom::Whitelist.stub(:allow_field?).with(@fake_class_name, 'two') {true} | ||
Databasedotcom::Whitelist.stub(:allow_field?).with(@fake_class_name, 'three') {false} | ||
end | ||
it 'should only include allowed fields' do | ||
Databasedotcom::Whitelist.filter_description!(@description_hash, @fake_class_name) | ||
@description_hash['fields'].include?({'name'=>'one'}).should be_false | ||
@description_hash['fields'].include?({'name'=>'three'}).should be_false | ||
end | ||
end | ||
it 'should not change other keypairs' do | ||
description_hash = {:a => 1, :b => 2} | ||
description_hash_clone = description_hash.clone | ||
Databasedotcom::Whitelist.filter_description!(description_hash, @fake_class_name) | ||
description_hash_clone.should == description_hash | ||
end | ||
end | ||
|
||
end | ||
|
||
describe Databasedotcom::Client do | ||
before do | ||
@client = Databasedotcom::Client.new | ||
end | ||
describe '#describe_whitelist_sobjects_with_filter' do | ||
it 'should filter SObjects descriptions using the whitelist' do | ||
@client.should_receive(:describe_whitelist_sobjects_without_filter) { [{'description'=>1, 'name'=>2}] } | ||
Databasedotcom::Whitelist.should_receive(:filter_description!).with(1,2) | ||
@client.describe_sobjects | ||
end | ||
it 'should return the filtered sobjects' do | ||
sobjects = [ {'description'=>1, 'name'=>2} ] | ||
@client.should_receive(:describe_whitelist_sobjects_without_filter) { sobjects } | ||
Databasedotcom::Whitelist.stub(:filter_description!) | ||
@client.describe_sobjects.should == sobjects | ||
end | ||
end | ||
|
||
it 'should filter an SObject description fields using the whitelist' do | ||
description = mock() | ||
class_name = 'fake_class_name' | ||
@client.should_receive(:describe_whitelist_sobject_without_filter).with(class_name) { description } | ||
Databasedotcom::Whitelist.should_receive(:filter_description!).with(description, class_name) | ||
@client.describe_sobject(class_name).should == description | ||
end | ||
|
||
it 'should filter #list_sobjects using the whitelist' do | ||
sobjects = [1,2,3] | ||
filtered_sobjects = [1,2,3] | ||
@client.should_receive(:list_whitelist_sobjects_without_filter) { sobjects } | ||
Databasedotcom::Whitelist.should_receive(:filter_sobjects).once { filtered_sobjects } #.with(:list_sobjects_without_filter) | ||
@client.list_sobjects.should == filtered_sobjects | ||
end | ||
|
||
end |