lockbox 2.0.1 → 2.2.0

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: 41d031c1ae819dbf773416fffa04b9fe08abcfe8bd2012dab7a86d9e3046140c
4
- data.tar.gz: 2fa33424258e616693caf343f2b7ca054276619bbf14ce7042a892f743c6f139
3
+ metadata.gz: b3a6c05fd83da2e2fc8474f2daf3b55f27ee61dd8a86ff3264df772816bcf92b
4
+ data.tar.gz: d269773e126958e5288a2fcb48ee228dbcd3918648e02834057c8be04f36ec45
5
5
  SHA512:
6
- metadata.gz: bbc879f38246d0dcbc802beee879895f968d677ae895b6f0c7addebefa2ff7306befdd1406a02b24bbb2bec4f12bfb125f67c11c9280ba5e3e0517d67efb6360
7
- data.tar.gz: 6d1b6474c2e9859b43ee6a44d7eb12aa5c6cb8657ce3b82abed09b13bd66b6912150823f12e67ca2409a99872b152a5527159843980b2668b39a41db445eb6ce
6
+ metadata.gz: f05224cd3e90993ba6a5b7cadfd2bdac839e6590ae3a5702935dc1146b1349ce76d41d3de989f9e10b3510cf420a86936d283968cc343a7eaccfa119a4dff1b6
7
+ data.tar.gz: d185de56bd634a6ba6753d3a1acf91a7f3940edb02ccbcaa89b22839ef4e57e62a5c698074b6cff821bc5869e3b423dee94781fad4a7e0961794982fa2ed1faa
data/CHANGELOG.md CHANGED
@@ -1,3 +1,13 @@
1
+ ## 2.2.0 (2026-04-04)
2
+
3
+ - Dropped support for Active Record < 7.2 and Ruby < 3.3
4
+
5
+ ## 2.1.0 (2025-10-15)
6
+
7
+ - Added warning for `download_chunk` method
8
+ - Fixed error for `download` method with block
9
+ - Dropped support for Active Record < 7.1 and Ruby < 3.2
10
+
1
11
  ## 2.0.1 (2024-12-29)
2
12
 
3
13
  - Added support for Ruby 3.4
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2018-2024 Andrew Kane
3
+ Copyright (c) 2018-2026 Andrew Kane
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -72,7 +72,7 @@ Then follow the instructions below for the data you want to encrypt.
72
72
  Create a migration with:
73
73
 
74
74
  ```ruby
75
- class AddEmailCiphertextToUsers < ActiveRecord::Migration[8.0]
75
+ class AddEmailCiphertextToUsers < ActiveRecord::Migration[8.1]
76
76
  def change
77
77
  add_column :users, :email_ciphertext, :text
78
78
  end
@@ -251,7 +251,7 @@ User.decrypt_email_ciphertext(user.email_ciphertext)
251
251
  Create a migration with:
252
252
 
253
253
  ```ruby
254
- class AddBodyCiphertextToRichTexts < ActiveRecord::Migration[8.0]
254
+ class AddBodyCiphertextToRichTexts < ActiveRecord::Migration[8.1]
255
255
  def change
256
256
  add_column :action_text_rich_texts, :body_ciphertext, :text
257
257
  end
@@ -382,7 +382,7 @@ Encryption is applied to all versions after processing.
382
382
  You can mount the uploader [as normal](https://github.com/carrierwaveuploader/carrierwave#activerecord). With Active Record, this involves creating a migration:
383
383
 
384
384
  ```ruby
385
- class AddLicenseToUsers < ActiveRecord::Migration[8.0]
385
+ class AddLicenseToUsers < ActiveRecord::Migration[8.1]
386
386
  def change
387
387
  add_column :users, :license, :string
388
388
  end
@@ -910,7 +910,7 @@ end
910
910
  You can use `binary` columns for the ciphertext instead of `text` columns.
911
911
 
912
912
  ```ruby
913
- class AddEmailCiphertextToUsers < ActiveRecord::Migration[8.0]
913
+ class AddEmailCiphertextToUsers < ActiveRecord::Migration[8.1]
914
914
  def change
915
915
  add_column :users, :email_ciphertext, :binary
916
916
  end
@@ -961,7 +961,7 @@ end
961
961
  Create a migration with:
962
962
 
963
963
  ```ruby
964
- class MigrateToLockbox < ActiveRecord::Migration[8.0]
964
+ class MigrateToLockbox < ActiveRecord::Migration[8.1]
965
965
  def change
966
966
  add_column :users, :name_ciphertext, :text
967
967
  add_column :users, :email_ciphertext, :text
@@ -994,7 +994,7 @@ end
994
994
  Then remove the previous gem from your Gemfile and drop its columns.
995
995
 
996
996
  ```ruby
997
- class RemovePreviousEncryptedColumns < ActiveRecord::Migration[8.0]
997
+ class RemovePreviousEncryptedColumns < ActiveRecord::Migration[8.1]
998
998
  def change
999
999
  remove_column :users, :encrypted_name, :text
1000
1000
  remove_column :users, :encrypted_name_iv, :text
@@ -80,7 +80,7 @@ module Lockbox
80
80
 
81
81
  module Attachment
82
82
  def download
83
- result = super
83
+ result = super(&nil)
84
84
 
85
85
  options = Utils.encrypted_options(record, name)
86
86
  # only trust the metadata when migrating
@@ -91,24 +91,31 @@ module Lockbox
91
91
  result = Utils.decrypt_result(record, name, options, result)
92
92
  end
93
93
 
94
- result
94
+ if block_given?
95
+ io = StringIO.new(result)
96
+ chunk_size = 5.megabytes
97
+ while (chunk = io.read(chunk_size))
98
+ yield chunk
99
+ end
100
+ else
101
+ result
102
+ end
95
103
  end
96
104
 
97
- def variant(*args)
98
- raise Lockbox::Error, "Variant not supported for encrypted files" if Utils.encrypted_options(record, name)
105
+ def download_chunk(...)
106
+ # TODO raise error in 3.0
107
+ warn "[lockbox] WARNING: download_chunk not supported for encrypted files" if Utils.encrypted_options(record, name)
99
108
  super
100
109
  end
101
110
 
102
- def preview(*args)
103
- raise Lockbox::Error, "Preview not supported for encrypted files" if Utils.encrypted_options(record, name)
111
+ def variant(...)
112
+ raise Lockbox::Error, "Variant not supported for encrypted files" if Utils.encrypted_options(record, name)
104
113
  super
105
114
  end
106
115
 
107
- if ActiveStorage::VERSION::STRING.to_f == 7.1 && ActiveStorage.version >= "7.1.4"
108
- def transform_variants_later
109
- blob.instance_variable_set(:@lockbox_encrypted, true) if Utils.encrypted_options(record, name)
110
- super
111
- end
116
+ def preview(...)
117
+ raise Lockbox::Error, "Preview not supported for encrypted files" if Utils.encrypted_options(record, name)
118
+ super
112
119
  end
113
120
 
114
121
  def open(**options)
@@ -135,12 +142,6 @@ module Lockbox
135
142
  end
136
143
 
137
144
  module Blob
138
- if ActiveStorage::VERSION::STRING.to_f == 7.1 && ActiveStorage.version >= "7.1.4"
139
- def preview_image_needed_before_processing_variants?
140
- !instance_variable_defined?(:@lockbox_encrypted) && super
141
- end
142
- end
143
-
144
145
  private
145
146
 
146
147
  def extract_content_type(io)
data/lib/lockbox/model.rb CHANGED
@@ -259,18 +259,16 @@ module Lockbox
259
259
  result
260
260
  end
261
261
 
262
- if ActiveRecord::VERSION::STRING.to_f >= 7.2
263
- def self.insert(attributes, **options)
264
- super(lockbox_map_record_attributes(attributes), **options)
265
- end
262
+ def self.insert(attributes, **options)
263
+ super(lockbox_map_record_attributes(attributes), **options)
264
+ end
266
265
 
267
- def self.insert!(attributes, **options)
268
- super(lockbox_map_record_attributes(attributes), **options)
269
- end
266
+ def self.insert!(attributes, **options)
267
+ super(lockbox_map_record_attributes(attributes), **options)
268
+ end
270
269
 
271
- def self.upsert(attributes, **options)
272
- super(lockbox_map_record_attributes(attributes, check_readonly: true), **options)
273
- end
270
+ def self.upsert(attributes, **options)
271
+ super(lockbox_map_record_attributes(attributes, check_readonly: true), **options)
274
272
  end
275
273
 
276
274
  def self.insert_all(attributes, **options)
@@ -344,20 +342,9 @@ module Lockbox
344
342
  end
345
343
 
346
344
  # warn on default attributes
347
- if ActiveRecord::VERSION::STRING.to_f >= 7.2
348
- # TODO improve
349
- if pending_attribute_modifications.any? { |v| v.is_a?(ActiveModel::AttributeRegistration::ClassMethods::PendingDefault) && v.name == name.to_s }
350
- warn "[lockbox] WARNING: attributes with `:default` option are not supported. Use `after_initialize` instead."
351
- end
352
- elsif attributes_to_define_after_schema_loads.key?(name.to_s)
353
- opt = attributes_to_define_after_schema_loads[name.to_s][1]
354
-
355
- # not ideal, since NO_DEFAULT_PROVIDED is private
356
- has_default = opt != ActiveRecord::Attributes::ClassMethods.const_get(:NO_DEFAULT_PROVIDED)
357
-
358
- if has_default
359
- warn "[lockbox] WARNING: attributes with `:default` option are not supported. Use `after_initialize` instead."
360
- end
345
+ # TODO improve
346
+ if pending_attribute_modifications.any? { |v| v.is_a?(ActiveModel::AttributeRegistration::ClassMethods::PendingDefault) && v.name == name.to_s }
347
+ warn "[lockbox] WARNING: attributes with `:default` option are not supported. Use `after_initialize` instead."
361
348
  end
362
349
 
363
350
  # preference:
@@ -377,26 +364,15 @@ module Lockbox
377
364
 
378
365
  attribute name, attribute_type
379
366
 
380
- if ActiveRecord::VERSION::STRING.to_f >= 7.1
381
- case options[:type]
382
- when :json
383
- serialize name, coder: JSON
384
- when :hash
385
- serialize name, type: Hash, coder: default_column_serializer || YAML
386
- when :array
387
- serialize name, type: Array, coder: default_column_serializer || YAML
388
- end
389
- else
390
- case options[:type]
391
- when :json
392
- serialize name, JSON
393
- when :hash
394
- serialize name, Hash
395
- when :array
396
- serialize name, Array
397
- end
367
+ case options[:type]
368
+ when :json
369
+ serialize name, coder: JSON
370
+ when :hash
371
+ serialize name, type: Hash, coder: default_column_serializer || YAML
372
+ when :array
373
+ serialize name, type: Array, coder: default_column_serializer || YAML
398
374
  end
399
- elsif ActiveRecord::VERSION::STRING.to_f >= 7.2
375
+ else
400
376
  decorate_attributes([name]) do |attr_name, cast_type|
401
377
  if cast_type.instance_of?(ActiveRecord::Type::Value)
402
378
  original_type = pending_attribute_modifications.find { |v| v.is_a?(ActiveModel::AttributeRegistration::ClassMethods::PendingType) && v.name == original_name.to_s && !v.type.nil? }&.type
@@ -416,27 +392,6 @@ module Lockbox
416
392
  cast_type
417
393
  end
418
394
  end
419
- elsif !attributes_to_define_after_schema_loads.key?(name.to_s)
420
- # when migrating it's best to specify the type directly
421
- # however, we can try to use the original type if its already defined
422
- if attributes_to_define_after_schema_loads.key?(original_name.to_s)
423
- attribute name, attributes_to_define_after_schema_loads[original_name.to_s].first
424
- elsif options[:migrating]
425
- # we use the original attribute for serialization in the encrypt and decrypt methods
426
- # so we can use a generic value here
427
- attribute name, ActiveRecord::Type::Value.new
428
- else
429
- attribute name, :string
430
- end
431
- elsif attributes_to_define_after_schema_loads[name.to_s].first.is_a?(Proc)
432
- # hack for Active Record 6.1+ to set string type after serialize
433
- # otherwise, type gets set to ActiveModel::Type::Value
434
- # which always returns false for changed_in_place?
435
- # earlier versions of Active Record take the previous code path
436
- attribute_type = attributes_to_define_after_schema_loads[name.to_s].first.call(nil)
437
- if attribute_type.is_a?(ActiveRecord::Type::Serialized) && attribute_type.subtype.nil?
438
- attribute name, ActiveRecord::Type::Serialized.new(ActiveRecord::Type::String.new, attribute_type.coder)
439
- end
440
395
  end
441
396
 
442
397
  define_method("#{name}_was") do
@@ -1,3 +1,3 @@
1
1
  module Lockbox
2
- VERSION = "2.0.1"
2
+ VERSION = "2.2.0"
3
3
  end
data/lib/lockbox.rb CHANGED
@@ -98,8 +98,12 @@ end
98
98
  if defined?(ActiveSupport.on_load)
99
99
  ActiveSupport.on_load(:active_record) do
100
100
  ar_version = ActiveRecord::VERSION::STRING.to_f
101
- if ar_version < 7
102
- if ar_version >= 5.2
101
+ if ar_version < 7.2
102
+ if ar_version >= 7.1
103
+ raise Lockbox::Error, "Active Record #{ActiveRecord::VERSION::STRING} requires Lockbox < 2.2"
104
+ elsif ar_version >= 7.0
105
+ raise Lockbox::Error, "Active Record #{ActiveRecord::VERSION::STRING} requires Lockbox < 2.1"
106
+ elsif ar_version >= 5.2
103
107
  raise Lockbox::Error, "Active Record #{ActiveRecord::VERSION::STRING} requires Lockbox < 2"
104
108
  elsif ar_version >= 5
105
109
  raise Lockbox::Error, "Active Record #{ActiveRecord::VERSION::STRING} requires Lockbox < 0.7"
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lockbox
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2024-12-29 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies: []
12
12
  email: andrew@ankane.org
13
13
  executables: []
@@ -48,14 +48,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
48
48
  requirements:
49
49
  - - ">="
50
50
  - !ruby/object:Gem::Version
51
- version: '3.1'
51
+ version: '3.3'
52
52
  required_rubygems_version: !ruby/object:Gem::Requirement
53
53
  requirements:
54
54
  - - ">="
55
55
  - !ruby/object:Gem::Version
56
56
  version: '0'
57
57
  requirements: []
58
- rubygems_version: 3.6.2
58
+ rubygems_version: 4.0.6
59
59
  specification_version: 4
60
60
  summary: Modern encryption for Ruby and Rails
61
61
  test_files: []