json2sql 1.0.11 → 1.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b734e672123b35d6b3878a30bf9629821915140e3240eba21cd8e853ac414911
4
- data.tar.gz: 819e7767505a2154f0071a46ffee6640d30954e7bae623f308cb185791f2f1f3
3
+ metadata.gz: 3a1ea5e0f95c4a548b1bb9360e2adb5a4b5356992016d76b4babc16acb0d85c9
4
+ data.tar.gz: '01873a86ae29993fd7b5e9902506b074333294207fa8ef6b4b8d122272bad4b6'
5
5
  SHA512:
6
- metadata.gz: 8a0743bbb6f1e26aacf1cdf62e0e81ce19992a79b0c748225a3d563a810ef4d8278b59d068fe28ee8707bb55080130d27538dc6711a2782dc392762aefd92a32
7
- data.tar.gz: 90cb0a70a7443c7bd6b3f4c6f12d02298d6e6c906d399cebc02c1edf1c566dc5eef470790d7f9213ef88b266a3b11f39f53fd74eaaa1ca1f37ef8daa015331d8
6
+ metadata.gz: 01d567792598296fbeaa37e25a215a33a911fabcf8c847818a3f6c1dba59c9a9ef792ccd387f4728bbf2616a3135ff6a6246a637376e9b3940414c8127160ce6
7
+ data.tar.gz: 0263df1d2046c256341c926b9dfece8bdedc9722e603153df64c7175884acf76bd66fe24f9de360177dcb97639444c6b32539d2eaec52cc91761d229ba426f23
@@ -6,7 +6,9 @@ module Json2sql
6
6
  # mode: :allow (default) — only tables listed in `tables:` are accessible.
7
7
  # Tables absent from `tables:` are blocked entirely.
8
8
  # Empty `tables:` = no restriction.
9
- # :deny — all tables pass; only listed columns are stripped.
9
+ # :deny — all tables pass. After column filtering, tables
10
+ # with no remaining accessible columns are removed.
11
+ # Same rule applies to children and parents.
10
12
  # tables: Per-table configuration Hash (recursive):
11
13
  # { table_name => { columns: [...],
12
14
  # children: { child_table => { columns: [...], ... } },
@@ -25,7 +27,7 @@ module Json2sql
25
27
  # user-supplied values — primary IDOR guard.
26
28
  #
27
29
  # Usage:
28
- # policy = Json2sql::InputPolicy.new(
30
+ # policy = Json2sql::QueryPolicy.new(
29
31
  # mode: :allow,
30
32
  # tables: {
31
33
  # orders: {
@@ -39,7 +41,7 @@ module Json2sql
39
41
  # safe_input = policy.apply(raw_params)
40
42
  # sql = Json2sql::SelectRunner.build(safe_input)
41
43
 
42
- class InputPolicy
44
+ class QueryPolicy
43
45
 
44
46
  def initialize(mode: :allow, tables: {})
45
47
 
@@ -54,73 +56,79 @@ module Json2sql
54
56
  def apply(input)
55
57
 
56
58
  input = Json2sql.normalize(input)
59
+
60
+ filter_tables(input, @tables)
57
61
 
58
- input = filter_tables(input)
62
+ input.each { |table, params| sanitize_table(params, @tables[table]) }
59
63
 
60
- input.each { |table, params| sanitize_table(params, @tables[table] || {}) }
64
+ input.reject! { |_, params| empty_columns?(params) }
61
65
 
62
66
  input
63
67
  end
64
68
 
65
69
  private
66
70
 
67
- def filter_tables(input)
68
-
69
- return input if @mode == :deny || @tables.empty?
70
-
71
- input.select { |table, _| @tables.key?(table) }
72
- end
73
-
74
71
  def sanitize_table(params, config)
75
72
 
76
73
  return unless params.is_a?(Hash)
77
74
 
75
+ return unless config.is_a?(Hash)
76
+
78
77
  filter_columns(params, config)
79
78
 
80
79
  inject_where(params, config)
81
80
 
82
81
  %w[children parents].each do |relation|
83
82
 
84
- if @mode == :deny
83
+ filter_relations(params, config, relation)
85
84
 
86
- next unless params[relation].is_a?(Hash)
85
+ next unless params[relation].is_a?(Hash)
87
86
 
88
- relation_configs = config[relation].is_a?(Hash) ? config[relation] : {}
87
+ tables = config[relation].is_a?(Hash) ? config[relation] : {}
89
88
 
90
- params[relation].each { |child_table, child_params| sanitize_table(child_params, relation_configs[child_table] || {}) }
89
+ params[relation].each { |table, params| sanitize_table(params, tables[table]) }
91
90
 
92
- params[relation].reject! { |_, child_params| child_params.is_a?(Hash) && child_params["columns"].is_a?(Array) && child_params["columns"].empty? }
91
+ params[relation].reject! { |_, params| empty_columns?(params) }
93
92
 
94
- else
93
+ end
94
+ end
95
95
 
96
- filter_relations(params, config, relation)
96
+ def empty_columns?(params)
97
97
 
98
- next unless params[relation].is_a?(Hash)
98
+ params.is_a?(Hash) && params["columns"].is_a?(Array) && params["columns"].empty?
99
+ end
99
100
 
100
- relation_configs = config[relation].is_a?(Hash) ? config[relation] : {}
101
+ def filter_tables(params, config)
101
102
 
102
- params[relation].each { |child_table, child_params| sanitize_table(child_params, relation_configs[child_table] || {}) }
103
+ return if @mode == :deny
103
104
 
104
- end
105
- end
106
- end
105
+ return unless params.is_a?(Hash)
106
+
107
+ tables = config.is_a?(Hash) ? config : {}
107
108
 
109
+ return if tables.empty?
110
+
111
+ params.select! { |table, _| tables.key?(table) }
112
+ end
113
+
108
114
  # Filters children/parents relations in :allow mode.
109
- # Only relations present as keys in config[relation_key] pass through.
110
- # If config[relation_key] is absent or not a Hash, relations are untouched.
111
- # In :deny mode, pruning is handled in sanitize_table after column filtering.
115
+ # Only relations present as keys in config[relation] pass through.
116
+ # If config[relation] is absent or not a Hash, relations are untouched.
117
+ # No-op in :deny mode.
118
+
119
+ def filter_relations(params, config, relation)
112
120
 
113
- def filter_relations(params, config, relation_key)
121
+ return if @mode == :deny
114
122
 
115
- relations = params[relation_key]
123
+ param_tables = params[relation]
116
124
 
117
- return unless relations.is_a?(Hash)
125
+ return unless param_tables.is_a?(Hash)
118
126
 
119
- relation_config = config[relation_key]
127
+ config_tables = config[relation]
120
128
 
121
- return unless relation_config.is_a?(Hash)
129
+ return unless config_tables.is_a?(Hash)
122
130
 
123
- params[relation_key] = relations.select { |t, _| relation_config.key?(t) }
131
+ params[relation] = param_tables.select { |table, _| config_tables.key?(table) }
124
132
  end
125
133
 
126
134
  # Filters "columns" using mode (:allow or :deny).
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Json2sql
4
- VERSION = "1.0.11"
4
+ VERSION = "1.0.12"
5
5
  end
data/lib/json2sql.rb CHANGED
@@ -10,7 +10,7 @@ require_relative "json2sql/update_model"
10
10
  require_relative "json2sql/update_runner"
11
11
  require_relative "json2sql/delete_model"
12
12
  require_relative "json2sql/delete_runner"
13
- require_relative "json2sql/input_policy"
13
+ require_relative "json2sql/query_policy"
14
14
 
15
15
  # Json2sql — SQL builder that generates MySQL/MariaDB query strings from
16
16
  # plain Ruby Hashes (or parsed JSON).
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: json2sql
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.11
4
+ version: 1.0.12
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tiago da Silva
@@ -49,9 +49,9 @@ files:
49
49
  - lib/json2sql.rb
50
50
  - lib/json2sql/delete_model.rb
51
51
  - lib/json2sql/delete_runner.rb
52
- - lib/json2sql/input_policy.rb
53
52
  - lib/json2sql/insert_model.rb
54
53
  - lib/json2sql/insert_runner.rb
54
+ - lib/json2sql/query_policy.rb
55
55
  - lib/json2sql/sanitizer.rb
56
56
  - lib/json2sql/select_model.rb
57
57
  - lib/json2sql/select_runner.rb