corny-sql_filter 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 [Julian K., Can Filip S.]
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,53 @@
1
+ = sql_filter
2
+
3
+ sql_filter helps you to build sql-conditions from parameters
4
+ and avoids sql injections.
5
+
6
+
7
+
8
+
9
+ == INSTALL:
10
+
11
+ coming soon
12
+
13
+ == EXAMPLE:
14
+
15
+ === Options for attributes
16
+
17
+ * value => fixed value or array of allowed values
18
+ * operator => fixed operator or list of allowed operators [default: =]
19
+ * default_operator => operator or first element of operator
20
+ * ignore_blank => Boolean [default: true]
21
+ * escape => Boolean [default: true]
22
+
23
+ === Simple
24
+ MyFilter < SqlFilter
25
+ attributes :foo
26
+ end
27
+
28
+ filter = MyFilter.new(:foo => 'bar')
29
+ filter.to_a == ["1 AND (`foo` = ?)",'bar']
30
+
31
+ === With default
32
+ MyFilter < SqlFilter
33
+ attributes :name, :default => 'any', :operator => :like
34
+ end
35
+
36
+ filter = MyFilter.new(:foo => 'bar')
37
+ filter.to_a == ["1 AND (`foo` LIKE ?)",'%bar%']
38
+
39
+ === Custom method
40
+ MyFilter < SqlFilter
41
+ attributes :name
42
+
43
+ def name_to_sql
44
+ ["foreign_id IN (SELECT id FROM foreigns WHERE name LIKE ?)",name]
45
+ end
46
+
47
+ end
48
+
49
+ filter = MyFilter.new(:foo => 'bar')
50
+ filter.to_a == ["1 AND `foreign_id` IN (SELECT id FROM foreigns WHERE name LIKE ?))","bar"]
51
+
52
+
53
+ Copyright (c) 2009 Julian K., released under the MIT license
data/init.rb ADDED
@@ -0,0 +1,2 @@
1
+ # Include hook code here
2
+ require File.join(File.dirname(__FILE__), "/lib/sql_filter")
@@ -0,0 +1,152 @@
1
+ # SqlFilter
2
+
3
+
4
+ module SqlFilterAttributes
5
+
6
+ def self.included(base)
7
+ base.extend(ClassMethods)
8
+ end
9
+
10
+ module ClassMethods
11
+
12
+ def inherited(subclass)
13
+ subclass.instance_variable_set('@attributes', instance_variable_get('@attributes').clone)
14
+ end
15
+
16
+ # returns the configuration hash
17
+ def attributes
18
+ @attributes
19
+ end
20
+
21
+ end
22
+ end
23
+
24
+
25
+ class SqlFilter
26
+
27
+ include SqlFilterAttributes
28
+
29
+ @attributes = {}
30
+
31
+ def self.attribute(*args)
32
+ options = args.delete_at(args.size-1) if args.last.is_a?(Hash)
33
+ options ||= {}
34
+
35
+ #puts "#############################"
36
+ #puts self
37
+ #puts "#############################"
38
+
39
+ for attr in args
40
+
41
+
42
+ class_method_lines = []
43
+
44
+ options[:escape] ||= true
45
+ options[:ignore_blank] ||= true
46
+
47
+ value = options[:value]
48
+ operator = options[:operator] || "="
49
+
50
+ if operator.is_a?(Array)
51
+ attr_accessor "operator_for_#{attr}"
52
+ class_method_lines << "def operator_for_#{attr}"
53
+ class_method_lines << " options = self.class.attributes[:#{attr}]"
54
+ class_method_lines << " @operator_for_#{attr} ||= options[:default_operator]"
55
+ if options[:ignore_blank]
56
+ class_method_lines << " return nil if @operator_for_#{attr}.to_s.empty?"
57
+ end
58
+ class_method_lines << " raise 'unknown operator '+@operator_for_#{attr}+' for #{attr}' unless options[:operator].include?(@operator_for_#{attr})"
59
+ class_method_lines << " @operator_for_#{attr}"
60
+ class_method_lines << "end"
61
+
62
+ else
63
+ class_method_lines << "def operator_for_#{attr}"
64
+ class_method_lines << " '#{operator.to_s.upcase}'"
65
+ class_method_lines << "end"
66
+ end
67
+
68
+ class_method_lines << "def #{attr}_to_sql"
69
+ class_method_lines << "return nil unless operator_for_#{attr}"
70
+
71
+ # wenn kein statischer Wert vorgegeben ist
72
+ unless options[:value].is_a?(String)
73
+ attr_accessor attr
74
+ # leere Werte bei Wunsch ignorieren
75
+ if options[:ignore_blank]
76
+ class_method_lines << "return nil if @#{attr}.to_s.empty?"
77
+ end
78
+ end
79
+
80
+
81
+ right_sql = nil
82
+ if value
83
+ if value.is_a?(Array)
84
+ # eingabe überprüfen
85
+ class_method_lines << "raise 'xxx' unless self.class.attributes[:#{attr}][:value].include?(#{attr})"
86
+ right_sql = attr.to_s
87
+ else
88
+ # vorgabe einsetzen
89
+ right_sql = value.inspect
90
+ end
91
+ else
92
+ if operator==:like
93
+ right_sql = "'%'+#{attr}+'%'"
94
+ else
95
+ # nur methode aufrufen
96
+ right_sql = attr.to_s
97
+ end
98
+ end
99
+
100
+ field = options[:field] ? options[:field] : attr
101
+ field = field.to_s.split(".").collect{|c| "`"+c+"`"}.join "."
102
+ if options[:escape] == false
103
+ class_method_lines << " '#{field} ' + operator_for_#{attr} + " + right_sql
104
+ else
105
+ class_method_lines << " ['#{field} ' + operator_for_#{attr} + ' ?', " + right_sql + ']'
106
+ end
107
+
108
+ class_method_lines << "end"
109
+
110
+ @attributes[attr] = options
111
+
112
+
113
+ #puts class_method_lines.join "\n"
114
+ class_eval class_method_lines.join "\n"
115
+
116
+ operator = options[:operators]
117
+
118
+ end
119
+ end
120
+
121
+ def initialize(vars=nil)
122
+ # set default values
123
+ for attr,options in self.class.attributes
124
+ instance_variable_set '@'+attr.to_s, options[:default]
125
+ end
126
+
127
+ if vars
128
+ # send input values to setter methods
129
+ for key,val in vars
130
+ send "#{key}=", val
131
+ end
132
+ end
133
+ end
134
+
135
+ # Build the whole conditions array
136
+ def to_a
137
+ sql = ["1"]
138
+
139
+ for key, options in self.class.attributes
140
+ val = instance_variable_get("@#{key}") || options[:default]
141
+ res = send "#{key}_to_sql"
142
+ if res.is_a?(Array)
143
+ sql[0] << " AND (#{res.shift})"
144
+ sql = sql + res
145
+ elsif res # nicht nil
146
+ sql[0] << " AND (#{res})"
147
+ end
148
+ end
149
+
150
+ sql
151
+ end
152
+ end
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{sql_filter}
5
+ s.version = "0.0.1"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Corny", "Averell"]
9
+ s.date = %q{2009-02-04}
10
+ s.description = %q{sql_filter helps you to build sql-conditions from parameters and avoids sql injections.}
11
+ s.email = %q{mail@digineo.de}
12
+ s.files = %w(
13
+ MIT-LICENSE
14
+ README.rdoc
15
+ init.rb
16
+ sql_filter.gemspec
17
+ lib/sql_filter.rb
18
+ test/sql_filter_test.rb
19
+ )
20
+ s.has_rdoc = true
21
+ s.homepage = %q{http://github.com/corny/sql_filter/tree/master}
22
+ s.rdoc_options = ["--inline-source", "--charset=UTF-8"]
23
+ s.require_paths = ["lib"]
24
+ s.rubygems_version = %q{1.3.0}
25
+ s.summary = %q{sql_filter helps you to build sql-conditions from parameters and avoids sql injections.}
26
+ end
@@ -0,0 +1,133 @@
1
+ require 'test/unit'
2
+ require File.join(File.dirname(__FILE__), "../init")
3
+
4
+ class SqlFilterTest < Test::Unit::TestCase
5
+
6
+ # erwartet: nichts
7
+ class EmptyFilter < SqlFilter
8
+ end
9
+
10
+ # erwartet:
11
+ # * name
12
+ class NameFilter < SqlFilter
13
+ attribute :name, :field=>'certificate.issuer'
14
+ end
15
+
16
+ # erwartet:
17
+ # * name
18
+ class NameLikeFilter < SqlFilter
19
+ attribute :name, :operator => :like
20
+ end
21
+
22
+ # erwartet:
23
+ # * state
24
+ class OptionsFilter < SqlFilter
25
+ attribute :state, :value => %w(new open closed)
26
+ end
27
+
28
+ # erwartet:
29
+ # * operator_for_issued_at
30
+ class OperatorFilter < SqlFilter
31
+ attribute :issued_at, :operator => %w(< >), :value => "NOW()", :escape => false, :default_operator=>"<"
32
+ end
33
+
34
+ # erwartet:
35
+ # * updated_at
36
+ # * operator_for_updated_at
37
+ class OperatorValueFilter < SqlFilter
38
+ attribute :issued_at, :operator => %w(< = >)
39
+ end
40
+
41
+ # empty filter
42
+ def test_empty_filter
43
+ filter = EmptyFilter.new
44
+ # darf nicht auf :name reagieren
45
+ assert !filter.respond_to?(:name)
46
+
47
+ # Conditions muss leer sein
48
+ assert_equal ["1"], filter.to_a
49
+ end
50
+
51
+ def test_assertion
52
+ value = 'foo bar'
53
+
54
+ filter = NameFilter.new
55
+ assert_nil filter.name
56
+
57
+ filter.name = value
58
+ assert_equal value, filter.name
59
+
60
+ filter = NameFilter.new :name => value
61
+ assert_equal value, filter.name
62
+ end
63
+
64
+ def test_name_filter
65
+ text = 'hello world'
66
+ filter = NameFilter.new(:name => text)
67
+
68
+ # sollte auf :name reagieren
69
+ assert_respond_to filter, :name
70
+
71
+ assert_equal ["1 AND (`certificate`.`issuer` = ?)",text], filter.to_a
72
+
73
+ text = 'Test'
74
+ filter.name = text
75
+ assert_equal ["1 AND (`certificate`.`issuer` = ?)",text], filter.to_a
76
+ end
77
+
78
+ def test_name_like_filter
79
+ filter = EmptyFilter.new
80
+
81
+ text = 'hello world'
82
+ filter = NameLikeFilter.new(:name => text)
83
+
84
+ assert_equal ["1 AND (`name` LIKE ?)","%#{text}%"], filter.to_a
85
+ end
86
+
87
+ def test_options_filter
88
+ filter = OptionsFilter.new
89
+
90
+ # leerer wert
91
+ assert_equal ["1"], filter.to_a
92
+
93
+ filter = OptionsFilter.new(:state => 'closed')
94
+ assert_equal ["1 AND (`state` = ?)", "closed"], filter.to_a
95
+
96
+ assert_raises RuntimeError do
97
+ filter = OptionsFilter.new(:state => 'sldjfh sdkjfh oiz3 4 zr')
98
+ assert_equal ["1 AND (`state` = ?)", "sldjfh sdkjfh oiz3 4 zr"], filter.to_a
99
+ end
100
+ end
101
+
102
+ def test_operator_filter
103
+
104
+ # leerer wert
105
+ filter = OperatorFilter.new
106
+ assert_equal ["1 AND (`issued_at` < ?)", "NOW()"], filter.to_a
107
+
108
+ # Gültiger Wert
109
+ filter = OperatorFilter.new(:operator_for_issued_at=>">")
110
+ assert_equal ["1 AND (`issued_at` > ?)", "NOW()"], filter.to_a
111
+
112
+ # Ungültiger Wert
113
+ assert_raises RuntimeError do
114
+ filter = OperatorFilter.new(:operator_for_issued_at=>"sddlkh234097f ")
115
+ assert_equal ["1 AND (`issued_at` < ?)", "sddlkh234097f"], filter.to_a
116
+ end
117
+ end
118
+
119
+ def test_operator_value_filter
120
+ filter = OptionsFilter.new
121
+
122
+ # leerer wert
123
+ assert_equal ["1"], filter.to_a
124
+
125
+ filter = OperatorValueFilter.new(:issued_at => "NOW()", :operator_for_issued_at=>">")
126
+ assert_equal ["1 AND (`issued_at` > ?)", "NOW()"], filter.to_a
127
+
128
+ assert_raises RuntimeError do
129
+ filter = OperatorValueFilter.new(:issued_at => "NOW()", :operator_for_issued_at=>"sdfsklödf")
130
+ assert_equal ["1 AND (`issued_at` sdfsklödf ?)", "NOW()"], filter.to_a
131
+ end
132
+ end
133
+ end
metadata ADDED
@@ -0,0 +1,60 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: corny-sql_filter
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Corny
8
+ - Averell
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2009-02-04 00:00:00 -08:00
14
+ default_executable:
15
+ dependencies: []
16
+
17
+ description: sql_filter helps you to build sql-conditions from parameters and avoids sql injections.
18
+ email: mail@digineo.de
19
+ executables: []
20
+
21
+ extensions: []
22
+
23
+ extra_rdoc_files: []
24
+
25
+ files:
26
+ - MIT-LICENSE
27
+ - README.rdoc
28
+ - init.rb
29
+ - sql_filter.gemspec
30
+ - lib/sql_filter.rb
31
+ - test/sql_filter_test.rb
32
+ has_rdoc: true
33
+ homepage: http://github.com/corny/sql_filter/tree/master
34
+ post_install_message:
35
+ rdoc_options:
36
+ - --inline-source
37
+ - --charset=UTF-8
38
+ require_paths:
39
+ - lib
40
+ required_ruby_version: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: "0"
45
+ version:
46
+ required_rubygems_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: "0"
51
+ version:
52
+ requirements: []
53
+
54
+ rubyforge_project:
55
+ rubygems_version: 1.2.0
56
+ signing_key:
57
+ specification_version: 2
58
+ summary: sql_filter helps you to build sql-conditions from parameters and avoids sql injections.
59
+ test_files: []
60
+