unidom-common 1.5 → 1.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1e44a8b8ccece3288519276076c2131e12741b95
4
- data.tar.gz: 9b3ae6a040a4049c4fbfdaf933e6f20fa38a5ff6
3
+ metadata.gz: 1ca73aa2b3b39d5cd33bf7e5a3b6a31605cedfd6
4
+ data.tar.gz: 6b0d9ab155ff7a442e19d754cc1a78417ffbd3d4
5
5
  SHA512:
6
- metadata.gz: 078a2f58cc191dd3bafe0b54ba141314b092f3868d9f9e3a870a4f4f48f9c7ad409ed24110498775e633dbef8387649b3c5d770ee3ce29dac597f31c0b66844b
7
- data.tar.gz: f24e6d3d7a65872cd0910b3aa7c098a1cbb2e1b7d41e84b50f86f0bd15e5dc351920de85eeed7b3b33fdc4895204332503cf33f37d6935d94b5bd0fc4efe782f
6
+ metadata.gz: 5ba36cf153a52b1f321b4a97279fce29b33b7b891652d45c3afe96304491337cb3065ebb81df668e6d3c8cac649fd6020a77dd3e7c874f6fb38d990f901eff4e
7
+ data.tar.gz: c39c2db1e0bad0c883cea0dfafdd5cf84c20050c88414bc8b8966f46ca43fff4d5f96f4491fdf49b41a5d3cc1c2bf9938ae09bdd71833f8cf09678514a940fc6
data/README.md CHANGED
@@ -164,6 +164,126 @@ Person.passport_number_is('E00000000').first==person # true
164
164
 
165
165
 
166
166
 
167
+ ## Secure Column
168
+
169
+ ```ruby
170
+ # db/migrate/YYYYMMDDHHMMSS_create_orderings.rb
171
+ class CreateOrderings < ActiveRecord::Migration[5.0]
172
+
173
+ def change
174
+
175
+ create_table :orderings, id: :uuid do |t|
176
+
177
+ t.string :placer_name, null: false, default: nil, limit: 200
178
+ t.string :taker_name, null: false, default: nil, limit: 200
179
+ t.string :receiver_name, null: false, default: nil, limit: 200
180
+
181
+ t.jsonb :placer
182
+ t.jsonb :taker
183
+ t.jsonb :receiver
184
+
185
+ t.binary :placer_identification_number_exact_signature, null: false, default: nil, limit: 80
186
+ t.binary :placer_mobile_phone_number_exact_signature, null: false, default: nil, limit: 80
187
+ t.binary :taker_identification_number_exact_signature, null: false, default: nil, limit: 80
188
+ t.binary :taker_mobile_phone_number_exact_signature, null: false, default: nil, limit: 80
189
+ t.binary :receiver_identification_number_exact_signature, null: false, default: nil, limit: 80
190
+ t.binary :receiver_mobile_phone_number_exact_signature, null: false, default: nil, limit: 80
191
+
192
+ t.column :state, 'char(1)', null: false, default: 'C'
193
+ t.datetime :opened_at, null: false, default: Time.utc(1970)
194
+ t.datetime :closed_at, null: false, default: Time.utc(3000)
195
+ t.boolean :defunct, null: false, default: false
196
+ t.jsonb :notation, null: false, default: {}
197
+
198
+ t.timestamps
199
+
200
+ end
201
+
202
+ add_index :orderings, :placer_identification_number_exact_signature, name: :index_orderings_on_placer_identification_number
203
+ add_index :orderings, :placer_mobile_phone_number_exact_signature, name: :index_orderings_on_placer_mobile_phone_number
204
+ add_index :orderings, :taker_identification_number_exact_signature, name: :index_orderings_on_taker_identification_number
205
+ add_index :orderings, :taker_mobile_phone_number_exact_signature, name: :index_orderings_on_taker_mobile_phone_number
206
+ add_index :orderings, :receiver_identification_number_exact_signature, name: :index_orderings_on_receiver_identification_number
207
+ add_index :orderings, :receiver_mobile_phone_number_exact_signature, name: :index_orderings_on_receiver_mobile_phone_number
208
+
209
+ end
210
+
211
+ end
212
+
213
+ # app/models/orderings.rb
214
+ class Ordering < ApplicationRecord
215
+
216
+ include Unidom::Common::Concerns::ModelExtension
217
+
218
+ validates :placer_name, presence: true, length: { in: 2..columns_hash['placer_name'].limit }
219
+ validates :taker_name, presence: true, length: { in: 2..columns_hash['taker_name'].limit }
220
+ validates :receiver_name, presence: true, length: { in: 2..columns_hash['receiver_name'].limit }
221
+
222
+ validates :placer_address, presence: true, length: { in: 2..200 }
223
+ validates :taker_address, presence: true, length: { in: 2..200 }
224
+ validates :receiver_address, presence: true, length: { in: 2..200 }
225
+
226
+ validates :placer_identification_number, presence: true, length: { is: 18 }, format: Unidom::Certificate::China::IdentityCard::FORMAT_VALIDATION_REGEX
227
+ validates :taker_identification_number, presence: true, length: { is: 18 }, format: Unidom::Certificate::China::IdentityCard::FORMAT_VALIDATION_REGEX
228
+ validates :receiver_identification_number, presence: true, length: { is: 18 }, format: Unidom::Certificate::China::IdentityCard::FORMAT_VALIDATION_REGEX
229
+
230
+ validates :placer_mobile_phone_number, presence: true, length: { is: 11 }, numericality: { integer_only: true }, format: Unidom::Contact::China::MobilePhoneNumber::FORMAT_VALIDATION_REGEX
231
+ validates :taker_mobile_phone_number, presence: true, length: { is: 11 }, numericality: { integer_only: true }, format: Unidom::Contact::China::MobilePhoneNumber::FORMAT_VALIDATION_REGEX
232
+ validates :receiver_mobile_phone_number, presence: true, length: { is: 11 }, numericality: { integer_only: true }, format: Unidom::Contact::China::MobilePhoneNumber::FORMAT_VALIDATION_REGEX
233
+
234
+ exact_column :placer_identification_number, :placer_mobile_phone_number
235
+ exact_column :taker_identification_number, :taker_mobile_phone_number
236
+ exact_column :receiver_identification_number, :receiver_mobile_phone_number
237
+
238
+ secure_column :placer, fields: [ :placer_name, :placer_address, :placer_identification_number, :placer_mobile_phone_number ]
239
+ secure_column :taker, fields: [ :taker_name, :taker_address, :taker_identification_number, :taker_mobile_phone_number ]
240
+ secure_column :receiver, fields: [ :receiver_name, :receiver_address, :receiver_identification_number, :receiver_mobile_phone_number ]
241
+
242
+ end
243
+
244
+ # in any controller or rails console:
245
+ @placer_name = 'Tim'
246
+ @taker_name = 'Bob'
247
+ @receiver_name = 'Roy'
248
+
249
+ @placer_identification_number = '11022119801231999X'
250
+ @taker_identification_number = '350105199006184567'
251
+ @receiver_identification_number = '532307200001010003'
252
+
253
+ @placer_mobile_phone_number = '13987654321'
254
+ @taker_mobile_phone_number = '18812345678'
255
+ @receiver_mobile_phone_number = '17101020304'
256
+
257
+ @placer_address = 'Beijing'
258
+ @taker_address = 'Jiangsu'
259
+ @receiver_address = 'Guizhou'
260
+
261
+ @ordering = Ordering.new opened_at: Time.now,
262
+ placer_name: @placer_name,
263
+ taker_name: @taker_name,
264
+ receiver_name: @receiver_name,
265
+ placer_address: @placer_address,
266
+ taker_address: @taker_address,
267
+ receiver_address: @receiver_address,
268
+ placer_identification_number: @placer_identification_number,
269
+ taker_identification_number: @taker_identification_number,
270
+ receiver_identification_number: @receiver_identification_number,
271
+ placer_mobile_phone_number: @placer_mobile_phone_number,
272
+ taker_mobile_phone_number: @taker_mobile_phone_number,
273
+ receiver_mobile_phone_number: @receiver_mobile_phone_number
274
+ @ordering.save!
275
+
276
+ ordering_1 = Ordering.placer_identification_number_is(@placer_identification_number).valid_at.alive.first
277
+ ordering_2 = Ordering.taker_identification_number_is(@taker_identification_number).valid_at.alive.first
278
+ ordering_3 = Ordering.receiver_identification_number_is(@receiver_identification_number).valid_at.alive.first
279
+ ordering_4 = Ordering.placer_mobile_phone_number_is(@placer_mobile_phone_number).valid_at.alive.first
280
+ ordering_5 = Ordering.taker_mobile_phone_number_is(@taker_mobile_phone_number).valid_at.alive.first
281
+ ordering_6 = Ordering.receiver_mobile_phone_number_is(@receiver_mobile_phone_number).valid_at.alive.first
282
+ # @ordering should be identical to any of ordering_1, ordering_2, ordering_3, ordering_4, ordering_5, or ordering_6
283
+ ```
284
+
285
+
286
+
167
287
  ## Numeration
168
288
 
169
289
  ```ruby
@@ -0,0 +1,21 @@
1
+ module Unidom::Common::Concerns::ArgumentValidation
2
+
3
+ extend ActiveSupport::Concern
4
+
5
+ included do |includer|
6
+
7
+ def assert_present!(name, value)
8
+ raise ArgumentError.new("The #{name} argument is required.") if value.blank?
9
+ end
10
+
11
+ end
12
+
13
+ module ClassMethods
14
+
15
+ def assert_present!(name, value)
16
+ raise ArgumentError.new("The #{name} argument is required.") if value.blank?
17
+ end
18
+
19
+ end
20
+
21
+ end
@@ -0,0 +1,35 @@
1
+ module Unidom::Common::Concerns::ExactColumn
2
+
3
+ extend ActiveSupport::Concern
4
+
5
+ included do |includer|
6
+
7
+ cattr_accessor :exact_column_names
8
+
9
+ end
10
+
11
+ module ClassMethods
12
+
13
+ def exact_column(*names)
14
+
15
+ exact_column_names = exact_column_names||[]
16
+ exact_column_names += names
17
+
18
+ names.each do |name|
19
+ name = name.to_s
20
+ instance_eval do
21
+ scope :"#{name}_is", ->(value) { where "#{name}_exact_signature" => exact_signature(self, name, value) }
22
+ before_save do send "#{name}_exact_signature=", self.class.exact_signature(self.class, name, send(name)) end
23
+ end
24
+ end
25
+
26
+ end
27
+
28
+ def exact_signature(klass, name, value)
29
+ text = "#{Rails.application.secrets[:secret_key_base]}@#{Rails.root}/#{klass.table_name}##{name}=#{value}"
30
+ "#{Digest::MD5.digest(text)}#{Digest::SHA512.digest(text)}"
31
+ end
32
+
33
+ end
34
+
35
+ end
@@ -2,6 +2,11 @@ module Unidom::Common::Concerns::ModelExtension
2
2
 
3
3
  extend ActiveSupport::Concern
4
4
 
5
+ include Unidom::Common::Concerns::ArgumentValidation
6
+ include Unidom::Common::Concerns::NotationColumn
7
+ include Unidom::Common::Concerns::ExactColumn
8
+ include Unidom::Common::Concerns::SecureColumn
9
+
5
10
  included do |includer|
6
11
 
7
12
  validates :state, presence: true, length: { is: columns_hash['state'].limit }
@@ -17,6 +22,7 @@ module Unidom::Common::Concerns::ModelExtension
17
22
  scope :alive, ->(living: true) { where defunct: !living }
18
23
  scope :dead, ->(defunct: true) { where defunct: defunct }
19
24
 
25
+ =begin
20
26
  scope :notation_column_where, ->(name, operator, value) do
21
27
  operation = :like==operator ? { operator: 'ILIKE', value: "%#{value}%" } : { operator: operator.to_s, value: value }
22
28
  where "#{table_name}.notation -> 'columns' ->> '#{name}' #{operation[:operator]} :value", value: operation[:value]
@@ -25,6 +31,7 @@ module Unidom::Common::Concerns::ModelExtension
25
31
  scope :notation_boolean_column_where, ->(name, value) do
26
32
  where "(#{table_name}.notation -> 'columns' ->> '#{name}')::boolean = :value", value: (value ? true : false)
27
33
  end
34
+ =end
28
35
 
29
36
  if columns_hash['ordinal'].present?&&:integer==columns_hash['ordinal'].type
30
37
  validates :ordinal, presence: true, numericality: { integer_only: true, greater_than: 0 }
@@ -136,9 +143,11 @@ module Unidom::Common::Concerns::ModelExtension
136
143
  end
137
144
  end
138
145
 
146
+ =begin
139
147
  def assert_present!(name, value)
140
148
  raise ArgumentError.new("The #{name} argument is required.") if value.blank?
141
149
  end
150
+ =end
142
151
 
143
152
  end
144
153
 
@@ -147,7 +156,7 @@ module Unidom::Common::Concerns::ModelExtension
147
156
  def to_id(model)
148
157
  model.respond_to?(:id) ? model.id : model
149
158
  end
150
-
159
+ =begin
151
160
  def notation_column(*names)
152
161
  names.each do |name|
153
162
  name = name.to_s
@@ -177,7 +186,9 @@ module Unidom::Common::Concerns::ModelExtension
177
186
  end
178
187
  end
179
188
  end
189
+ =end
180
190
 
191
+ =begin
181
192
  def exact_column(*names)
182
193
  names.each do |name|
183
194
  name = name.to_s
@@ -189,15 +200,20 @@ module Unidom::Common::Concerns::ModelExtension
189
200
  end
190
201
  end
191
202
  end
203
+ =end
192
204
 
205
+ =begin
193
206
  def assert_present!(name, value)
194
207
  raise ArgumentError.new("The #{name} argument is required.") if value.blank?
195
208
  end
209
+ =end
196
210
 
211
+ =begin
197
212
  def exact_signature(klass, name, value)
198
213
  text = "#{Rails.application.secrets[:secret_key_base]}@#{Rails.root}/#{klass.table_name}##{name}=#{value}"
199
214
  "#{Digest::MD5.digest(text)}#{Digest::SHA512.digest(text)}"
200
215
  end
216
+ =end
201
217
 
202
218
  end
203
219
 
@@ -0,0 +1,52 @@
1
+ module Unidom::Common::Concerns::NotationColumn
2
+
3
+ extend ActiveSupport::Concern
4
+
5
+ included do |includer|
6
+
7
+ scope :notation_column_where, ->(name, operator, value) do
8
+ operation = :like==operator ? { operator: 'ILIKE', value: "%#{value}%" } : { operator: operator.to_s, value: value }
9
+ where "#{table_name}.notation -> 'columns' ->> '#{name}' #{operation[:operator]} :value", value: operation[:value]
10
+ end
11
+
12
+ scope :notation_boolean_column_where, ->(name, value) do
13
+ where "(#{table_name}.notation -> 'columns' ->> '#{name}')::boolean = :value", value: (value ? true : false)
14
+ end
15
+
16
+ end
17
+
18
+ module ClassMethods
19
+
20
+ def notation_column(*names)
21
+ names.each do |name|
22
+ name = name.to_s
23
+ instance_eval do
24
+ define_method(name) do
25
+ notation.try(:[], 'columns').try(:[], name)
26
+ end
27
+ define_method("#{name}=") do |value|
28
+ notation['columns'] ||= {}
29
+ notation['columns'][name] = value
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+ def notation_boolean_column(*names)
36
+ names.each do |name|
37
+ name = name.to_s
38
+ instance_eval do
39
+ define_method("#{name}?") do
40
+ notation.try(:[], 'columns').try(:[], name)
41
+ end
42
+ define_method("#{name}=") do |value|
43
+ notation['columns'] ||= {}
44
+ notation['columns'][name] = value
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+ end
51
+
52
+ end
@@ -0,0 +1,58 @@
1
+ module Unidom::Common::Concerns::SecureColumn
2
+
3
+ extend ActiveSupport::Concern
4
+ include Unidom::Common::Concerns::ExactColumn
5
+ include Unidom::Common::Concerns::Aes256Cryptor
6
+
7
+ included do |includer|
8
+
9
+ cattr_accessor :secure_columns
10
+
11
+ end
12
+
13
+ module ClassMethods
14
+
15
+ def secure_column(name, fields: [])
16
+
17
+ name = name.to_s
18
+ secure_columns = secure_columns||{}
19
+ if secure_columns[name].present?
20
+ raise ArgumentError.new("The #{name} column was defined as a secure column already.")
21
+ else
22
+ secure_columns[name] = fields
23
+ end
24
+ fields.each do |field| attr_accessor field.to_sym if columns_hash[field.to_s].blank? end
25
+
26
+ instance_eval do
27
+
28
+ before_save do
29
+ content = { 'nonce' => SecureRandom.hex(8), 'timestamp' => Time.now.to_i }
30
+ secure_columns[name].each do |field| content[field.to_s] = send(field) end
31
+ content = content.sort.to_h.to_json
32
+ aes_key = Digest::SHA512::digest self.class.exact_signature(self.class, name, '')
33
+ encoded = hex_encrypt content, key: aes_key
34
+ json = {
35
+ encoded: encoded,
36
+ signature: Unidom::Common::Numeration.hex(self.class.exact_signature self.class, name, content)
37
+ }
38
+ send "#{name}=", json
39
+ end
40
+
41
+ after_find do
42
+ json = send(name)
43
+ return if json['encoded'].blank?||json['signature'].blank?
44
+ aes_key = Digest::SHA512::digest self.class.exact_signature(self.class, name, '')
45
+ content = decrypt Unidom::Common::Numeration.rev_hex(json['encoded']), key: aes_key
46
+ actual_signature = self.class.exact_signature(self.class, name, content)
47
+ return if Unidom::Common::Numeration.rev_hex(json['signature'])!=actual_signature
48
+ parsed = JSON.parse content
49
+ parsed.each do |key, value| send "#{key}=", value unless [ 'nonce', 'timestamp' ].include? key end
50
+ end
51
+
52
+ end
53
+
54
+ end
55
+
56
+ end
57
+
58
+ end
@@ -1,7 +1,7 @@
1
1
  <!DOCTYPE html>
2
2
  <html>
3
3
  <head>
4
- <title>Common</title>
4
+ <title>Unidom Common</title>
5
5
  <%= stylesheet_link_tag 'unidom/common/application', media: 'all' %>
6
6
  <%= csrf_meta_tags %>
7
7
  </head>
@@ -1,5 +1,5 @@
1
1
  module Unidom
2
2
  module Common
3
- VERSION = '1.5'.freeze
3
+ VERSION = '1.6'.freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: unidom-common
3
3
  version: !ruby/object:Gem::Version
4
- version: '1.5'
4
+ version: '1.6'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Topbit Du
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-10-02 00:00:00.000000000 Z
11
+ date: 2016-10-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -82,8 +82,12 @@ files:
82
82
  - app/controllers/unidom/common/application_controller.rb
83
83
  - app/helpers/unidom/common/application_helper.rb
84
84
  - app/models/unidom/common/concerns/aes256_cryptor.rb
85
+ - app/models/unidom/common/concerns/argument_validation.rb
86
+ - app/models/unidom/common/concerns/exact_column.rb
85
87
  - app/models/unidom/common/concerns/md5_digester.rb
86
88
  - app/models/unidom/common/concerns/model_extension.rb
89
+ - app/models/unidom/common/concerns/notation_column.rb
90
+ - app/models/unidom/common/concerns/secure_column.rb
87
91
  - app/models/unidom/common/concerns/sha1_digester.rb
88
92
  - app/models/unidom/common/concerns/sha256_digester.rb
89
93
  - app/models/unidom/common/concerns/sha2_digester.rb