Skip to content

Commit

Permalink
Bugfix: make Sanitizy work for multiple configs
Browse files Browse the repository at this point in the history
Sanitizy wasn't behaving appropriately when assigning different
allowable tags/attributes options on different columns. It does now.
  • Loading branch information
GIT_AUTHOR_NAME authored and GIT_AUTHOR_NAME committed Jan 28, 2009
1 parent d401fd3 commit db39cbb
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 20 deletions.
57 changes: 45 additions & 12 deletions lib/sanitizy.rb
@@ -1,32 +1,65 @@
module Sanitizy module Sanitizy
class Sanitizer < HTML::WhiteListSanitizer
attr_reader :columns
def initialize(*columns)
@columns = columns
end
[:attributes,:tags].each do |acc|
class_eval <<-CODE
alias default_allowed_#{acc} allowed_#{acc}
def allowed_#{acc}
@allowed_#{acc} ||= default_allowed_#{acc}.dup
end
def allowed_#{acc}=(#{acc})
@allowed_#{acc} = Set.new(#{acc})
end
CODE
end
end

def self.included(base) def self.included(base)
base.extend(ClassMethods) base.extend(ClassMethods)
base.before_save :sanitize_declared_columns base.before_save :sanitize_declared_columns
base.class_inheritable_array :sanitizy_columns base.class_inheritable_accessor :sanitizy_columns
base.sanitizy_columns = {}
end end


module ClassMethods module ClassMethods
def cleanse_columns(*columns, &block) def cleanse_columns(*columns, &block)
self.sanitizy_columns = columns columns.each do |column|
sanitizy_columns.each do |column| name = sanitizer_attr_name_for(column)
class_inheritable_accessor sanitizer_attr_name_for(column) class_eval <<-CODE
send("#{self.sanitizer_attr_name_for(column)}=", HTML::WhiteListSanitizer.new) def #{name}
yield sanitizer_for(column) self.class.sanitizy_columns["#{column}"]
end
def #{name}=(sanitizer)
self.class.sanitizy_columns["#{column}"] = sanitizer
end
CODE
end end

sanitizer = Sanitizy::Sanitizer.new *columns
yield sanitizer
columns.each do |column|
self.sanitizy_columns[column.to_s] = sanitizer
end
sanitizer
end end
alias cleanse_column cleanse_columns


def sanitizer_attr_name_for(column) def sanitizer_attr_name_for(column)
"#{column}_sanitizer" "#{column}_sanitizer"
end end

def sanitizer_for(column)
send(sanitizer_attr_name_for(column))
end
end end


def sanitize_declared_columns def sanitize_declared_columns
self.class.sanitizy_columns.each do |column, options| self.class.sanitizy_columns.each do |column, sanitizer|
self.send("#{column}=", self.class.sanitizer_for(column).sanitize(self.send(column))) options = {
:tags => sanitizer.allowed_tags.to_a,
:attributes => sanitizer.allowed_attributes.to_a
}
sanitized = sanitizer.sanitize(self.send(column), options)
self.send("#{column}=", sanitized)
end end
end end
end end
Expand Down
77 changes: 69 additions & 8 deletions spec/lib/sanitizy_spec.rb
@@ -1,34 +1,34 @@
require File.dirname(__FILE__) + '/../spec_helper' require File.dirname(__FILE__) + '/../spec_helper'


# dummy class on which to test, just uses users table to avoisserrors # dummy class on which to test, just uses users table to avoisserrors
class TestSanitizy < ActiveRecord::Base class SingularSanitizy < ActiveRecord::Base
include Sanitizy include Sanitizy
set_table_name "news_items" set_table_name "news_items"
cleanse_columns(:video_embed) do |sanitizer| cleanse_columns(:video_embed) do |sanitizer|
sanitizer.allowed_tags.replace(%w(object param embed a img)) sanitizer.allowed_tags = %w(object param embed a img)
sanitizer.allowed_attributes.replace(%w(width height name src value allowFullScreen type href allowScriptAccess style wmode pluginspage classid codebase data quality)) sanitizer.allowed_attributes = %w(width height name src value allowFullScreen type href allowScriptAccess style wmode pluginspage classid codebase data quality)
end end
end end


describe "Sanitizy library" do describe "Sanitizy library" do
before do before do
@sanitized = TestSanitizy.new @sanitized = SingularSanitizy.new
end end


describe "#cleanse_columns" do describe "#cleanse_columns" do
it "should set a class attribute called 'video_embed_sanitizer'" do it "should set a class attribute called 'video_embed_sanitizer'" do
TestSanitizy.should respond_to(:video_embed_sanitizer) @sanitized.should respond_to(:video_embed_sanitizer)
end end


it "should create an instance of a sanitizer" do it "should create an instance of a sanitizer" do
@sanitized.sanitize_declared_columns @sanitized.sanitize_declared_columns
TestSanitizy.video_embed_sanitizer.should be_an_instance_of(HTML::WhiteListSanitizer) @sanitized.video_embed_sanitizer.should be_an_instance_of(Sanitizy::Sanitizer)
end end


it "should set the allowed attributes on the sanitizer" do it "should set the allowed attributes on the sanitizer" do
@sanitized.sanitize_declared_columns @sanitized.sanitize_declared_columns
TestSanitizy.video_embed_sanitizer.allowed_attributes.should_not be_empty @sanitized.video_embed_sanitizer.allowed_attributes.should_not be_empty
TestSanitizy.video_embed_sanitizer.allowed_attributes.should be_a_kind_of(Set) @sanitized.video_embed_sanitizer.allowed_attributes.should be_a_kind_of(Set)
end end


describe "sanitizing the contents of the field" do describe "sanitizing the contents of the field" do
Expand Down Expand Up @@ -77,3 +77,64 @@ class TestSanitizy < ActiveRecord::Base


end end


class MultipleSanitizy < ActiveRecord::Base
include Sanitizy
set_table_name 'news_items'
cleanse_column(:short_description) do |s|
s.allowed_tags = %w(baz quuz)
end
cleanse_column(:video_embed) do |s|
s.allowed_tags = %w(foo bar)
end
end

describe "Multiple sanitizers on a model" do
before do
@sanitized = MultipleSanitizy.new
end

it "should have two columns stored in self.class.sanitizy_columns" do
MultipleSanitizy.sanitizy_columns.size.should == 2
end

describe "short description" do
it "should only allow baz and quuz tags" do
@sanitized.short_description_sanitizer.allowed_tags.should == ['baz', 'quuz'].to_set
end
end
describe "video embed" do
it "should only allow foo and bar tags" do
@sanitized.video_embed_sanitizer.allowed_tags.should == ['foo', 'bar'].to_set
end

it "should be a new instance of a sanitizer" do
@sanitized.video_embed_sanitizer.should_not == @sanitized.short_description_sanitizer
end
end
end

class SetSanitizy < ActiveRecord::Base
include Sanitizy
set_table_name 'news_items'
cleanse_column(:short_description) do |s|
s.allowed_tags.delete('div')
end
cleanse_column(:video_embed) do |s|
s.allowed_tags.replace(['object'])
end
end

describe "when using Set operations" do
before do
@sanitized = SetSanitizy.new
end

it "should allow deleting tags" do
@sanitized.short_description_sanitizer.allowed_tags.should_not include('div')
end

it "should allow replacing tags" do
@sanitized.video_embed_sanitizer.allowed_tags.should == ['object'].to_set
end
end

0 comments on commit db39cbb

Please sign in to comment.