istox 0.1.97 → 0.1.98

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: 6c5a7f018f60f1cb67728d6cdba0f6a10b5941cd7a9ac00e2957e2fe1041a174
4
- data.tar.gz: 053d1b2aece848ad1f662268a55bb6bf1dddb09ea9d6a0548b76576aa8b0df24
3
+ metadata.gz: b20425ff9b96da28ae9fdf1c6b47c7159df66d16b67d8e2fff99d8ed1d750312
4
+ data.tar.gz: a04b8779b0fa907bb8c58fcba28d26089836c1bfd6b055570d9222e57ebd530c
5
5
  SHA512:
6
- metadata.gz: 112f72f52eb1fd0781c821df36f509ebc6985b115eb6a9e86de2f37166f47ebf143a66af88f43e8615d2af34f8d16bd353fda9815ff78da15bf602c624b90f40
7
- data.tar.gz: 34b293dfe5bc081c1905b32a5856e937869ffaab0845614af000d1acfc2beb9cbf6a0efd51e31331cc496c270b94d567f67f37f728b7b5b6b00359a59fc70666
6
+ metadata.gz: f44c23b065a529e8403bae9317316e34d2c41b91a33356b60cc816c5b25ce04b7096a3c1bbffae58097b4995541622011014f826c5c6c1a2515cf774b4613347
7
+ data.tar.gz: 8838d137671e85a48f18cd4b1d919bdd391f177e66ffcc64f97108dd014134a6d006e74bae944e1f2450b063225c7e71c2e66f5615741aa344d7ec6d705e2c73
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- istox (0.1.91)
4
+ istox (0.1.97)
5
5
  binding_of_caller
6
6
  bunny (>= 2.12.0)
7
7
  graphlient
@@ -26,7 +26,8 @@ module Istox
26
26
  require 'istox/helpers/f_math'
27
27
  require 'istox/helpers/my_open_struct'
28
28
  require 'istox/helpers/common_helper'
29
- require 'istox/helpers/filter'
29
+ require 'istox/helpers/regex_helper'
30
+ require 'istox/helpers/result_handler'
30
31
  require 'istox/models/blockchain_receipt'
31
32
  require 'istox/models/concerns/blockchain_receipt_query'
32
33
  require 'istox/consumers/blockchain_status_handler'
@@ -1,5 +1,18 @@
1
1
  module Istox
2
2
  module CommonHelper
3
+ def self.to_datetime(input)
4
+ return nil if input.blank?
5
+
6
+ begin
7
+ is_numeric = true if Integer input
8
+ rescue StandardError
9
+ false
10
+ end
11
+
12
+ # is unix timestamp
13
+ is_numeric ? Time.at(input.to_i).to_datetime : Time.parse(input)
14
+ end
15
+
3
16
  def self.to_open_struct(model)
4
17
  return nil if model.blank?
5
18
 
@@ -0,0 +1,11 @@
1
+ module Istox
2
+ module RegexHelper
3
+ def self.alphabet_only(input)
4
+ !input.match(/\A[a-zA-Z]*\z/).nil?
5
+ end
6
+
7
+ def self.symbol_only(input)
8
+ !input.match(/\A[^\w\s*]+\z/).nil?
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,131 @@
1
+ module Istox
2
+ module ResultHandler
3
+ ##### main method to be called, suggested to always use this method and not individual method below
4
+ def self.process(query:, meta:, exclude_filter: false, exclude_order: false, exclude_paginate: false)
5
+ query = filter(query: query, meta: meta) unless exclude_filter
6
+ query = order(query: query, meta: meta) unless exclude_order
7
+
8
+ return paginate(query: query, meta: meta) unless exclude_paginate
9
+
10
+ query
11
+ end
12
+
13
+ def self.filter(query:, meta:)
14
+ return query if meta.blank? || meta.filters.blank?
15
+
16
+ meta.filters.each do |filter|
17
+ # chain the query with AND conditions
18
+ if filter.field.present?
19
+ validate_filter(filter)
20
+ query = query.where("#{filter.field} #{transform_compare(filter.type, filter.compare)} ?",
21
+ transform_value(filter.type, filter.value))
22
+ end
23
+
24
+ next if filter.filters.blank?
25
+
26
+ # contains inner filters, chain the query with OR conditions
27
+ columns = []
28
+ values = []
29
+ filter.filters.each do |inner_filter|
30
+ validate_filter(filter)
31
+ columns.push("#{inner_filter.field} #{transform_compare(inner_filter.type, inner_filter.compare)} ?")
32
+ values.push(transform_value(inner_filter.type, inner_filter.value))
33
+ end
34
+
35
+ query = query.where(columns.join(' OR '), *values) unless columns.empty?
36
+ end
37
+
38
+ query
39
+ end
40
+
41
+ def self.order(query:, meta:)
42
+ return query if meta.blank? || meta.sorts.blank?
43
+
44
+ meta.sorts.each do |sort|
45
+ # to prevent sql injection
46
+ # sort.field should contains only alphabet and nothing else
47
+ raise StandardError, 'POSSIBLE_SQL_INJECTION' unless validate_column_name(sort.field)
48
+ # sort.order can only be asc or desc
49
+ raise StandardError, 'POSSIBLE_SQL_INJECTION' unless %w[asc desc].include?(sort.order.downcase)
50
+
51
+ query = query.order("#{sort.field.downcase} #{sort.order.upcase}")
52
+ end
53
+ query
54
+ end
55
+
56
+ def self.paginate(query:, meta:)
57
+ current_page = meta.page
58
+ offset = (current_page - 1) * meta.limit
59
+ total = query.count
60
+ data = query.limit(meta.limit).offset(offset)
61
+
62
+ page_count = (total + meta.limit - 1) / meta.limit
63
+
64
+ OpenStruct.new(
65
+ data: data,
66
+ pagination: OpenStruct.new(
67
+ page: current_page,
68
+ limit: meta.limit,
69
+ previous_page: current_page - 1,
70
+ current_page: current_page,
71
+ next_page: current_page < page_count ? current_page + 1 : 0,
72
+ page_count: page_count,
73
+ total_count: total
74
+ )
75
+ )
76
+ end
77
+
78
+ #######################################
79
+ ######
80
+ ###### private methods
81
+ ######
82
+ ######
83
+ ######
84
+ ##########################################
85
+
86
+ def self.validate_column_name(column)
87
+ # allow underscore
88
+ column = column.gsub('_', '')
89
+
90
+ Istox::RegexHelper.alphabet_only(column)
91
+ end
92
+
93
+ def self.validate_filter(filter)
94
+ # filter.field/column should contains only alphabet and nothing else
95
+ raise StandardError, 'POSSIBLE_SQL_INJECTION' unless validate_column_name(filter.field)
96
+
97
+ # filter.compare should only contains alphabets (eg. IN) or symbols only (eg. >=, =, <=, <>)
98
+ raise StandardError, 'POSSIBLE_SQL_INJECTION' unless validate_compare(filter.compare)
99
+ end
100
+
101
+ def self.transform_compare(type, compare)
102
+ return compare if type.blank?
103
+
104
+ return 'IS' if type.downcase == 'nullable' && ['=', 'is', '=='].include?(compare.downcase)
105
+
106
+ return 'IS NOT' if type.downcase == 'nullable' && ['<>', 'is not', '!='].include?(compare.downcase)
107
+
108
+ compare
109
+ end
110
+
111
+ def self.transform_value(type, value)
112
+ return value if value.blank? || type.blank? || type.downcase == 'string'
113
+
114
+ return 'NULL' if type.downcase == 'nullable' && %w[null true yes].include?(type.downcase)
115
+
116
+ return 'NOT NULL' if type.downcase == 'nullable' && %w[not_null false no].include?(type.downcase)
117
+
118
+ return value.to_i if type.downcase == 'integer'
119
+
120
+ return value.to_f if type.downcase == 'float'
121
+
122
+ return ::Istox::CommonHelper.to_datetime(value) if type.downcase == 'date' || type.downcase == 'datetime'
123
+ end
124
+
125
+ def self.validate_compare(compare)
126
+ Istox::RegexHelper.alphabet_only(compare) || Istox::RegexHelper.symbol_only(compare)
127
+ end
128
+
129
+ private_class_method :validate_compare, :validate_filter, :transform_value, :transform_compare, :validate_column_name
130
+ end
131
+ end
@@ -1,3 +1,3 @@
1
1
  module Istox
2
- VERSION = '0.1.97'.freeze
2
+ VERSION = '0.1.98'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: istox
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.97
4
+ version: 0.1.98
5
5
  platform: ruby
6
6
  authors:
7
7
  - Siong Leng
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-11-27 00:00:00.000000000 Z
11
+ date: 2019-12-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bunny
@@ -294,7 +294,6 @@ files:
294
294
  - lib/istox/helpers/bunny_boot.rb
295
295
  - lib/istox/helpers/common_helper.rb
296
296
  - lib/istox/helpers/f_math.rb
297
- - lib/istox/helpers/filter.rb
298
297
  - lib/istox/helpers/graphql_client.rb
299
298
  - lib/istox/helpers/grpc_client.rb
300
299
  - lib/istox/helpers/gruf_listener_hook.rb
@@ -303,6 +302,8 @@ files:
303
302
  - lib/istox/helpers/order_book_price_time.rb
304
303
  - lib/istox/helpers/order_book_prorate.rb
305
304
  - lib/istox/helpers/publisher.rb
305
+ - lib/istox/helpers/regex_helper.rb
306
+ - lib/istox/helpers/result_handler.rb
306
307
  - lib/istox/helpers/vault.rb
307
308
  - lib/istox/interfaces/chainhub/transaction.rb
308
309
  - lib/istox/models/blockchain_receipt.rb
@@ -1,37 +0,0 @@
1
- module Istox
2
- module Filter
3
- def self.order(query:, filters:)
4
- filters&.sort&.each do |x|
5
- query = query.order("#{x.field.downcase} #{x.order.upcase}")
6
- end
7
- query
8
- end
9
-
10
- def self.paginate(query:, filters:)
11
- current_page = filters.page
12
- offset = (current_page - 1) * filters.limit
13
- total = query.count
14
- data = query.limit(filters.limit).offset(offset)
15
-
16
- page_count = (total + filters.limit - 1) / filters.limit
17
-
18
- {
19
- data: data,
20
- pagination: {
21
- page: current_page,
22
- limit: filters.limit,
23
- previousPage: current_page - 1,
24
- currentPage: current_page,
25
- nextPage: current_page < page_count ? current_page + 1 : 0,
26
- pageCount: page_count,
27
- totalCount: total
28
- }
29
- }
30
- end
31
-
32
- def self.order_and_paginate(query:, filters:)
33
- query = order(query: query, filters: filters)
34
- paginate(query: query, filters: filters)
35
- end
36
- end
37
- end