umbrellio-sequel-plugins 0.4.0.112 → 0.4.0.152

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: a60c4a9f3ea7a1e632f44ba475c8523c65eb693e5b92f6d8f36825510af59e8c
4
- data.tar.gz: aba42c9f420d1b042cb37b5410e76a9dc6eadcc2d8d38af1e97a8ae7b10f22a8
3
+ metadata.gz: 7c457e432fd30ccbc7eea5a66e94ce828c179dc25e45f403ee8a7cc78d23d8f1
4
+ data.tar.gz: 3fee2f7af3fedb7ed161964ce6a1bdd4b115b88d8d4faa67bc14f9d0317c74b8
5
5
  SHA512:
6
- metadata.gz: 7ac48cc499a39b5f42fa9eb264ba2afe095a4aa5d367730db5843397f2f97a70ac37a7911a81f0c62bd5d8ba049361b3cb87678b91ed96fb7c3d0074f8787431
7
- data.tar.gz: 8cc13c34e85496374c70b464f624cee2667d40c567c493f6261f9b6f4d60dfc28fb3e9df9fc5369e2bd3a73fdf45d9a4b96d8a0c88a2eed35595bb127b9e5bd8
6
+ metadata.gz: '093103fc7ae3108cc818312319d63ef2229073bfa48453a71d764de9f498bc597b09c5148219c12b930a334824ed6ef828c44b4a814470a90739bf41cca3e12e'
7
+ data.tar.gz: 416ed5d8f41e6d947fc8b82d4752e8caf55dd985f639d8b347b15e3e523fc067c133c14f4d21838c0b3221eb847ba3fe2433907d0349f4b42dfe865545511dee
data/README.md CHANGED
@@ -13,28 +13,30 @@ gem 'umbrellio-sequel-plugins'
13
13
 
14
14
  And then execute:
15
15
 
16
- $ bundle
16
+ $ bundle
17
17
 
18
18
  # Extensions
19
19
 
20
- - `CurrencyRates`
21
- - `PGTools`
22
- - `Slave`
23
- - `Synchronize`
24
- - `methods_in_migrations`
25
- - `deferrable_foreign_keys`
20
+ - [`CurrencyRates`](#CurrencyRates)
21
+ - [`PGTools`](#PGTools)
22
+ - [`Slave`](#Slave)
23
+ - [`Synchronize`](#Synchronize)
24
+ - [`Methods in Migrations`](#Methods-in-Migrations)
25
+ - [`Deferrable Foreign Keys`](#Deferrable-Foreign-Keys)
26
26
 
27
27
  # Plugins
28
28
 
29
- - `Duplicate`
30
- - `GetColumnValue`
31
- - `StoreAccessors`
32
- - `Synchronize`
33
- - `Upsert`
34
- - `WithLock`
29
+ - [`AttrEncrypted`](#AttrEncrypted)
30
+ - [`Duplicate`](#Duplicate)
31
+ - [`GetColumnValue`](#GetColumnValue)
32
+ - [`MoneyAccessors`](#MoneyAccessors)
33
+ - [`StoreAccessors`](#StoreAccessors)
34
+ - [`Synchronize`](#Synchronize)
35
+ - [`Upsert`](#Upsert)
36
+ - [`WithLock`](#WithLock)
35
37
 
36
38
  # Tools
37
- - `TimestampMigratorUndoExtension`
39
+ - [`TimestampMigratorUndoExtension`](#TimestampMigratorUndoExtension)
38
40
 
39
41
  ## CurrencyRates
40
42
 
@@ -202,6 +204,39 @@ end
202
204
  # => <Husband @attributes={id:1, wife_id: 1}>
203
205
  ```
204
206
 
207
+ ## AttrEncrypted
208
+
209
+ Enable: `Sequel::Model.plugin :attr_encrypted`
210
+
211
+ Plugin for storing encrypted model attributes.
212
+
213
+ Example:
214
+
215
+ ```ruby
216
+ Sequel.migration do
217
+ change do
218
+ alter_table :orders do
219
+ add_column :encrypted_first_name, :text
220
+ add_column :encrypted_last_name, :text
221
+ add_column :encrypted_secret_data, :text
222
+ end
223
+ end
224
+ end
225
+
226
+ class Order < Sequel::Model
227
+ attr_encrypted :first_name, :last_name, key: Settings.private_key
228
+ attr_encrypted :secret_data, key: Settings.another_private_key
229
+ end
230
+
231
+ Order.create(first_name: "Ivan")
232
+ # => INSERT INTO "orders" ("encrypted_first_name") VALUES ('/sTi9Q==$OTpuMRq5k8R3JayQ$WjSManQGP9UaZ3C40yDjKg==')
233
+
234
+ order = Order.create(first_name: "Ivan", last_name: "Smith",
235
+ secret_data: { "some_key" => "Some Value" })
236
+ order.first_name # => "Ivan"
237
+ order.secret_data # => { "some_key" => "Some Value" }
238
+ ```
239
+
205
240
  ## Duplicate
206
241
 
207
242
  Enable: `Sequel::Model.plugin :duplicate`
@@ -239,14 +274,14 @@ item.get_column_value(:amount) # => 0.5e2
239
274
 
240
275
  ## MoneyAccessors
241
276
 
242
- **Important:** requires `money` gem described above.
277
+ **Important:** requires `money` gem described below.
243
278
 
244
279
  Plugin for using money field keys as model properties.
245
280
 
246
281
  Enable:
247
282
 
248
283
  ```ruby
249
- add_runtime_dependency "money"
284
+ gem "money"
250
285
  Sequel::Model.plugin :money_accessors
251
286
  ````
252
287
 
@@ -301,7 +336,7 @@ Example:
301
336
 
302
337
  ```ruby
303
338
  class User < Sequel::Model
304
- store :data, :first_name
339
+ store :data, :first_name
305
340
  end
306
341
 
307
342
  user = User.create(first_name: "John")
@@ -311,7 +346,7 @@ user.data # => {"first_name": "John"}
311
346
 
312
347
  ## Synchronize
313
348
 
314
- **Important:** requires a `synchronize` extension described above.
349
+ **Important:** requires a `synchronize` extension described below.
315
350
 
316
351
  Same as `DB#synchronize_with`
317
352
 
@@ -353,7 +388,7 @@ Example:
353
388
  ```ruby
354
389
  user = User.first
355
390
  user.with_lock do
356
- user.update(name: "James")
391
+ user.update(name: "James")
357
392
  end
358
393
  ```
359
394
 
@@ -0,0 +1,98 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Creates encrypted attribute storing
4
+ module Sequel::Plugins::AttrEncrypted
5
+ SEPARATOR = "$"
6
+ require "sequel/plugins/attr_encrypted/simple_crypt"
7
+
8
+ module ClassMethods
9
+ # Setup attr encrypted
10
+ #
11
+ # @param attrs [Array<Symbol>] column names
12
+ # @param key [String] 32 bytes key
13
+ # @example
14
+ # Sequel.migration do
15
+ # change do
16
+ # alter_table :orders do
17
+ # add_column :encrypted_first_name, :text
18
+ # add_column :encrypted_last_name, :text
19
+ # add_column :encrypted_secret_data, :text
20
+ # end
21
+ # end
22
+ # end
23
+ #
24
+ # class Order < Sequel::Model
25
+ # attr_encrypted :first_name, :last_name, key: Settings.private_key
26
+ # attr_encrypted :secret_data, key: Settings.another_private_key
27
+ # end
28
+
29
+ # Order.create(first_name: "Ivan")
30
+ # # => INSERT INTO "orders" ("encrypted_first_name")
31
+ # VALUES ('/sTi9Q==$OTpuMRq5k8R3JayQ$WjSManQGP9UaZ3C40yDjKg==')
32
+ #
33
+ # order = Order.create(first_name: "Ivan", last_name: "Smith",
34
+ # secret_data: { "some_key" => "Some Value" })
35
+ # order.first_name # => "Ivan"
36
+ # order.last_name # => "Smith"
37
+ # order.secret_data # => { "some_key" => "Some Value" }
38
+ def attr_encrypted(*attrs, key:)
39
+ include_encrypted_module!
40
+ attrs.each do |attr|
41
+ define_encrypted_setter(attr, key)
42
+ define_encrypted_getter(attr, key)
43
+ @_encrypted_attributes << attr
44
+ end
45
+ end
46
+
47
+ private
48
+
49
+ def define_encrypted_setter(attr, key)
50
+ @_attr_encrypted_module.module_eval do
51
+ define_method("#{attr}=") do |value|
52
+ instance_variable_set("@#{attr}", value)
53
+
54
+ send("encrypted_#{attr}=", SimpleCrypt.encrypt(value.to_json, key))
55
+ end
56
+ end
57
+ end
58
+
59
+ def define_encrypted_getter(attr, key)
60
+ @_attr_encrypted_module.module_eval do
61
+ define_method(attr.to_s) do
62
+ instance_variable_get("@#{attr}") || begin
63
+ decrypted = SimpleCrypt.decrypt(send("encrypted_#{attr}"), key)
64
+
65
+ result = !decrypted.nil? ? JSON.parse(decrypted) : decrypted
66
+ instance_variable_set("@#{attr}", result)
67
+ end
68
+ end
69
+ end
70
+ end
71
+
72
+ def include_encrypted_module!
73
+ return if defined?(@_attr_encrypted_module)
74
+
75
+ @_encrypted_attributes ||= []
76
+ @_attr_encrypted_module = Module.new
77
+ prepend @_attr_encrypted_module
78
+ end
79
+ end
80
+
81
+ module InstanceMethods
82
+ def save(*)
83
+ super.tap { _reset_encrypted_attrs_ivars }
84
+ end
85
+
86
+ def refresh(*)
87
+ super.tap { _reset_encrypted_attrs_ivars }
88
+ end
89
+
90
+ private
91
+
92
+ def _reset_encrypted_attrs_ivars
93
+ self.class.instance_variable_get(:@_encrypted_attributes)&.each do |attr|
94
+ instance_variable_set("@#{attr}", nil)
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sequel::Plugins::AttrEncrypted::SimpleCrypt
4
+ extend self
5
+ require "base64"
6
+
7
+ SEPARATOR = "$"
8
+
9
+ def encrypt(string, key)
10
+ return unless string.is_a?(String) && !string.empty?
11
+
12
+ encryptor = new_cipher(key, &:encrypt)
13
+ iv = encryptor.random_iv
14
+
15
+ encrypted = encryptor.update(string) + encryptor.final
16
+ dump(encrypted, iv, encryptor.auth_tag)
17
+ end
18
+
19
+ def decrypt(string, key)
20
+ encrypted, iv, auth_tag = parse(string) if string.is_a?(String)
21
+ return if [encrypted, iv, auth_tag].any?(&:nil?)
22
+
23
+ decryptor = new_cipher(key, &:decrypt)
24
+ decryptor.iv = iv
25
+ decryptor.auth_tag = auth_tag
26
+
27
+ decryptor.update(encrypted) + decryptor.final
28
+ end
29
+
30
+ private
31
+
32
+ def new_cipher(key)
33
+ result = OpenSSL::Cipher::AES256.new(:gcm)
34
+ yield(result)
35
+ result.key = key
36
+ result
37
+ end
38
+
39
+ def parse(string)
40
+ string.split(SEPARATOR).map { |x| Base64.strict_decode64(x) }
41
+ end
42
+
43
+ def dump(*values)
44
+ [*values].map { |x| Base64.strict_encode64(x) }.join(SEPARATOR)
45
+ end
46
+ end
@@ -22,6 +22,7 @@ Sequel.extension :pg_array_ops
22
22
  Sequel.extension :pg_json_ops
23
23
  Sequel.extension :pg_range_ops
24
24
 
25
+ Sequel::Model.plugin :attr_encrypted
25
26
  Sequel::Model.plugin :duplicate
26
27
  Sequel::Model.plugin :get_column_value
27
28
  Sequel::Model.plugin :money_accessors
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: umbrellio-sequel-plugins
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0.112
4
+ version: 0.4.0.152
5
5
  platform: ruby
6
6
  authors:
7
7
  - nulldef
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-04-07 00:00:00.000000000 Z
11
+ date: 2020-10-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sequel
@@ -190,6 +190,8 @@ files:
190
190
  - lib/sequel/extensions/pg_tools.rb
191
191
  - lib/sequel/extensions/slave.rb
192
192
  - lib/sequel/extensions/synchronize.rb
193
+ - lib/sequel/plugins/attr_encrypted.rb
194
+ - lib/sequel/plugins/attr_encrypted/simple_crypt.rb
193
195
  - lib/sequel/plugins/duplicate.rb
194
196
  - lib/sequel/plugins/get_column_value.rb
195
197
  - lib/sequel/plugins/money_accessors.rb
@@ -224,8 +226,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
224
226
  - !ruby/object:Gem::Version
225
227
  version: '0'
226
228
  requirements: []
227
- rubyforge_project:
228
- rubygems_version: 2.7.7
229
+ rubygems_version: 3.0.8
229
230
  signing_key:
230
231
  specification_version: 4
231
232
  summary: Sequel plugins