umbrellio-sequel-plugins 0.4.0.114 → 0.4.0.164

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: d8c7ff5ac5ebea27eafa18c31cd1d662265d4f482ef5918cadf94d0aa4f08f7f
4
- data.tar.gz: 3fa003eb8fa8c4f8fe5b0f5bb5bc43305a14248f02eeece91013329dfe7be17d
3
+ metadata.gz: 6bd4394bf53fcf0c95a1c67b2268c5def71d15f2a64fec6e30cb70fcb281caed
4
+ data.tar.gz: 57178f6c6365073e28bb3787f6253a774c6b134d6cd4a84656725e2d6400d373
5
5
  SHA512:
6
- metadata.gz: 0b252fd339fa0b4fc0c48861ae344b199cec544b81ad1b39524fc3a787e7a92ddcd7f8bf7160f5b97255ee99cdf08a1c9887872c2d4b28a0878adec9f3de41a6
7
- data.tar.gz: 077edb4f06abb73764d73eaab2ef3ee5a9bad1897e5faf9e7b1c892b775ff487b8d3273a74613aad4822336a180f59bd38aa83f50a7e10330007f386ffd8f534
6
+ metadata.gz: f34fda6b627aed0be50ae0a3fa6bc3978d7186f8477748870ff1871868ddbca2c0175b6bd4a7471b617406b28c0efee4ace1096d94795e40e402d7e0b2d0a1e9
7
+ data.tar.gz: b440a1b8b808c71b8c52fee03d0ead284dbbdf963cf3391fba385392703db6744b0aad41268e298430641709270f1f595edcabc63e3184ad0ec0d157beb8cecd
@@ -1,6 +1,7 @@
1
1
  language: ruby
2
2
 
3
3
  os: linux
4
+
4
5
  dist: xenial
5
6
 
6
7
  jobs:
@@ -43,10 +44,6 @@ install: bundle install --jobs=3 --retry=3 --path=${BUNDLE_PATH:-vendor/bundle}
43
44
  before_script:
44
45
  - psql -c 'create database sequel_plugins;' -U postgres
45
46
 
46
- script:
47
- - bundle exec rspec
48
- - bundle exec rubocop
49
-
50
47
  deploy:
51
48
  provider: rubygems
52
49
  api_key:
@@ -8,78 +8,81 @@ PATH
8
8
  GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
- activesupport (6.0.2.2)
11
+ activesupport (6.0.3.4)
12
12
  concurrent-ruby (~> 1.0, >= 1.0.2)
13
13
  i18n (>= 0.7, < 2)
14
14
  minitest (~> 5.1)
15
15
  tzinfo (~> 1.1)
16
- zeitwerk (~> 2.2)
17
- ast (2.4.0)
18
- coderay (1.1.2)
19
- concurrent-ruby (1.1.6)
16
+ zeitwerk (~> 2.2, >= 2.2.2)
17
+ ast (2.4.1)
18
+ coderay (1.1.3)
19
+ concurrent-ruby (1.1.7)
20
20
  coveralls (0.8.23)
21
21
  json (>= 1.8, < 3)
22
22
  simplecov (~> 0.16.1)
23
23
  term-ansicolor (~> 1.3)
24
24
  thor (>= 0.19.4, < 2.0)
25
25
  tins (~> 1.6)
26
- diff-lcs (1.3)
26
+ diff-lcs (1.4.4)
27
27
  docile (1.3.2)
28
- i18n (1.8.2)
28
+ i18n (1.8.5)
29
29
  concurrent-ruby (~> 1.0)
30
- jaro_winkler (1.5.4)
31
- json (2.3.0)
30
+ json (2.3.1)
32
31
  method_source (1.0.0)
33
- minitest (5.14.0)
34
- money (6.13.7)
32
+ minitest (5.14.2)
33
+ money (6.13.8)
35
34
  i18n (>= 0.6.4, <= 2)
36
- parallel (1.19.1)
37
- parser (2.7.1.0)
38
- ast (~> 2.4.0)
35
+ parallel (1.20.1)
36
+ parser (2.7.2.0)
37
+ ast (~> 2.4.1)
39
38
  pg (1.2.3)
40
- pry (0.13.0)
39
+ pry (0.13.1)
41
40
  coderay (~> 1.1)
42
41
  method_source (~> 1.0)
43
- rack (2.2.2)
42
+ rack (2.2.3)
44
43
  rainbow (3.0.0)
45
44
  rake (13.0.1)
45
+ regexp_parser (2.0.0)
46
46
  rexml (3.2.4)
47
- rspec (3.9.0)
48
- rspec-core (~> 3.9.0)
49
- rspec-expectations (~> 3.9.0)
50
- rspec-mocks (~> 3.9.0)
51
- rspec-core (3.9.1)
52
- rspec-support (~> 3.9.1)
53
- rspec-expectations (3.9.1)
47
+ rspec (3.10.0)
48
+ rspec-core (~> 3.10.0)
49
+ rspec-expectations (~> 3.10.0)
50
+ rspec-mocks (~> 3.10.0)
51
+ rspec-core (3.10.0)
52
+ rspec-support (~> 3.10.0)
53
+ rspec-expectations (3.10.0)
54
54
  diff-lcs (>= 1.2.0, < 2.0)
55
- rspec-support (~> 3.9.0)
56
- rspec-mocks (3.9.1)
55
+ rspec-support (~> 3.10.0)
56
+ rspec-mocks (3.10.0)
57
57
  diff-lcs (>= 1.2.0, < 2.0)
58
- rspec-support (~> 3.9.0)
59
- rspec-support (3.9.2)
60
- rubocop (0.81.0)
61
- jaro_winkler (~> 1.5.1)
58
+ rspec-support (~> 3.10.0)
59
+ rspec-support (3.10.0)
60
+ rubocop (0.90.0)
62
61
  parallel (~> 1.10)
63
- parser (>= 2.7.0.1)
62
+ parser (>= 2.7.1.1)
64
63
  rainbow (>= 2.2.2, < 4.0)
64
+ regexp_parser (>= 1.7)
65
65
  rexml
66
+ rubocop-ast (>= 0.3.0, < 1.0)
66
67
  ruby-progressbar (~> 1.7)
67
68
  unicode-display_width (>= 1.4.0, < 2.0)
68
- rubocop-config-umbrellio (0.81.0.78)
69
- rubocop (= 0.81.0)
70
- rubocop-performance (= 1.5.2)
71
- rubocop-rails (= 2.5.0)
72
- rubocop-rspec (= 1.38.1)
73
- rubocop-performance (1.5.2)
74
- rubocop (>= 0.71.0)
75
- rubocop-rails (2.5.0)
76
- activesupport
69
+ rubocop-ast (0.8.0)
70
+ parser (>= 2.7.1.5)
71
+ rubocop-config-umbrellio (0.90.0.93)
72
+ rubocop (= 0.90.0)
73
+ rubocop-performance (= 1.7.1)
74
+ rubocop-rails (= 2.7.0)
75
+ rubocop-rspec (= 1.42.0)
76
+ rubocop-performance (1.7.1)
77
+ rubocop (>= 0.82.0)
78
+ rubocop-rails (2.7.0)
79
+ activesupport (>= 4.2.0)
77
80
  rack (>= 1.1)
78
- rubocop (>= 0.72.0)
79
- rubocop-rspec (1.38.1)
80
- rubocop (>= 0.68.1)
81
+ rubocop (>= 0.87.0)
82
+ rubocop-rspec (1.42.0)
83
+ rubocop (>= 0.87.0)
81
84
  ruby-progressbar (1.10.1)
82
- sequel (5.31.0)
85
+ sequel (5.39.0)
83
86
  simplecov (0.16.1)
84
87
  docile (~> 1.1)
85
88
  json (>= 1.8, < 3)
@@ -91,12 +94,12 @@ GEM
91
94
  tins (~> 1.0)
92
95
  thor (1.0.1)
93
96
  thread_safe (0.3.6)
94
- tins (1.24.1)
97
+ tins (1.26.0)
95
98
  sync
96
- tzinfo (1.2.7)
99
+ tzinfo (1.2.8)
97
100
  thread_safe (~> 0.1)
98
101
  unicode-display_width (1.7.0)
99
- zeitwerk (2.3.0)
102
+ zeitwerk (2.4.2)
100
103
 
101
104
  PLATFORMS
102
105
  ruby
data/README.md CHANGED
@@ -13,29 +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
- - `MoneyAccessors`
32
- - `StoreAccessors`
33
- - `Synchronize`
34
- - `Upsert`
35
- - `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)
36
37
 
37
38
  # Tools
38
- - `TimestampMigratorUndoExtension`
39
+ - [`TimestampMigratorUndoExtension`](#TimestampMigratorUndoExtension)
39
40
 
40
41
  ## CurrencyRates
41
42
 
@@ -203,6 +204,39 @@ end
203
204
  # => <Husband @attributes={id:1, wife_id: 1}>
204
205
  ```
205
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
+
206
240
  ## Duplicate
207
241
 
208
242
  Enable: `Sequel::Model.plugin :duplicate`
@@ -302,7 +336,7 @@ Example:
302
336
 
303
337
  ```ruby
304
338
  class User < Sequel::Model
305
- store :data, :first_name
339
+ store :data, :first_name
306
340
  end
307
341
 
308
342
  user = User.create(first_name: "John")
@@ -354,7 +388,7 @@ Example:
354
388
  ```ruby
355
389
  user = User.first
356
390
  user.with_lock do
357
- user.update(name: "James")
391
+ user.update(name: "James")
358
392
  end
359
393
  ```
360
394
 
data/Rakefile CHANGED
@@ -2,7 +2,9 @@
2
2
 
3
3
  require "bundler/gem_tasks"
4
4
  require "rspec/core/rake_task"
5
+ require "rubocop/rake_task"
5
6
 
6
7
  RSpec::Core::RakeTask.new(:spec)
8
+ RuboCop::RakeTask.new(:lint)
7
9
 
8
- task default: :spec
10
+ task default: %i[lint spec]
@@ -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.new("aes-256-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
+ Array(values).map { |x| Base64.strict_encode64(x) }.join(SEPARATOR)
45
+ end
46
+ end
@@ -8,10 +8,10 @@ module Sequel
8
8
  # Rollback a migration
9
9
  def undo(version)
10
10
  path = files.find { |file| migration_version_from_file(get_filename(file)) == version }
11
- raise "Migration #{version} does not exist in the filesystem" unless path
11
+ error!("Migration #{version} does not exist in the filesystem") unless path
12
12
 
13
13
  filename = get_filename(path)
14
- raise "Migration #{version} is not applied" unless applied_migrations.include?(filename)
14
+ error!("Migration #{version} is not applied") unless applied_migrations.include?(filename)
15
15
 
16
16
  migration = get_migration(path)
17
17
 
@@ -41,7 +41,7 @@ module Sequel
41
41
  end
42
42
  end
43
43
 
44
- Sequel::TimestampMigrator.prepend TimestampMigratorLogger
44
+ Sequel::TimestampMigrator.prepend(TimestampMigratorLogger)
45
45
 
46
46
  private
47
47
 
@@ -57,6 +57,10 @@ module Sequel
57
57
  def get_filename(path)
58
58
  File.basename(path).downcase
59
59
  end
60
+
61
+ def error!(message)
62
+ raise Sequel::Migrator::Error, message
63
+ end
60
64
  end
61
65
  end
62
66
  # rubocop:enable Layout/ClassStructure
@@ -1,3 +1,3 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "umbrellio_sequel_plugins.rb"
3
+ require_relative "umbrellio_sequel_plugins"
@@ -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.114
4
+ version: 0.4.0.164
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-10 00:00:00.000000000 Z
11
+ date: 2020-12-02 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