lockbox 0.6.8 → 1.1.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: 0cc5589dbbfae34908ffdd634798549fa161c7dc79b528f23b8e097a044f3d9d
4
- data.tar.gz: 3eb23c1dfb284abb335e2addfb20fee77b31373b561ab6c0f9afaf28abf8aeb8
3
+ metadata.gz: 860bb7bcddfde22f980e11185c2afae0453e6547064d4538024a16f7652f953d
4
+ data.tar.gz: 5c97a4bcde5621234bf3f832d0c4a2eb7ca2a986541cb203b6370170141fe29b
5
5
  SHA512:
6
- metadata.gz: b0bd8a7ee500cbba73daa2ef0c9c6af07695b53799735f865d5b0e9e907e8ef86904983d5f8cfdff098b554d4cd9d4351133778079bde93a7440bbacf03d0545
7
- data.tar.gz: ea83a9ecb7734e907a03be89e628fc103815b0cc5acc2aec0c21dc0f2d6b7e746f299a489d4a11b14f413a55c4fb06b45d6e23302c853c8b216ad2bca63218d6
6
+ metadata.gz: f1435f9cd4dac0ea8bbee39d787c2a28c73b72a3de260759c27a5bc6c53f2c2fb344f144fa391742f3415baf7a0ea183e683353773c0eb305e145f1084d11918
7
+ data.tar.gz: 7623133737e4e465a3c63a0c5bbec337382fcce37469e9685a77578af02218d82b5988a057d3b9dc1d7c1accc9de84014ec9bf32d5ac1f0bc8d15455a80c392c
data/CHANGELOG.md CHANGED
@@ -1,3 +1,15 @@
1
+ ## 1.1.0 (2022-10-09)
2
+
3
+ - Added support for `insert`, `insert_all`, `insert_all!`, `upsert`, and `upsert_all`
4
+
5
+ ## 1.0.0 (2022-06-11)
6
+
7
+ - Deprecated `encrypts` in favor of `has_encrypted` to avoid conflicting with Active Record encryption
8
+ - Deprecated `lockbox_encrypts` in favor of `has_encrypted`
9
+ - Fixed error with `pluck`
10
+ - Restored warning for attributes with `default` option
11
+ - Dropped support for Active Record < 5.2 and Ruby < 2.6
12
+
1
13
  ## 0.6.8 (2022-01-25)
2
14
 
3
15
  - Fixed issue with `encrypts` loading model schema early
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[6.1]
75
+ class AddEmailCiphertextToUsers < ActiveRecord::Migration[7.0]
76
76
  def change
77
77
  add_column :users, :email_ciphertext, :text
78
78
  end
@@ -83,12 +83,10 @@ Add to your model:
83
83
 
84
84
  ```ruby
85
85
  class User < ApplicationRecord
86
- encrypts :email
86
+ has_encrypted :email
87
87
  end
88
88
  ```
89
89
 
90
- **Note:** With Rails 7, use `lockbox_encrypts` instead of `encrypts`
91
-
92
90
  You can use `email` just like any other attribute.
93
91
 
94
92
  ```ruby
@@ -103,7 +101,7 @@ You can specify multiple fields in single line.
103
101
 
104
102
  ```ruby
105
103
  class User < ApplicationRecord
106
- encrypts :email, :phone, :city
104
+ has_encrypted :email, :phone, :city
107
105
  end
108
106
  ```
109
107
 
@@ -113,17 +111,17 @@ Fields are strings by default. Specify the type of a field with:
113
111
 
114
112
  ```ruby
115
113
  class User < ApplicationRecord
116
- encrypts :born_on, type: :date
117
- encrypts :signed_at, type: :datetime
118
- encrypts :opens_at, type: :time
119
- encrypts :active, type: :boolean
120
- encrypts :salary, type: :integer
121
- encrypts :latitude, type: :float
122
- encrypts :video, type: :binary
123
- encrypts :properties, type: :json
124
- encrypts :settings, type: :hash
125
- encrypts :messages, type: :array
126
- encrypts :ip, type: :inet
114
+ has_encrypted :birthday, type: :date
115
+ has_encrypted :signed_at, type: :datetime
116
+ has_encrypted :opens_at, type: :time
117
+ has_encrypted :active, type: :boolean
118
+ has_encrypted :salary, type: :integer
119
+ has_encrypted :latitude, type: :float
120
+ has_encrypted :video, type: :binary
121
+ has_encrypted :properties, type: :json
122
+ has_encrypted :settings, type: :hash
123
+ has_encrypted :messages, type: :array
124
+ has_encrypted :ip, type: :inet
127
125
  end
128
126
  ```
129
127
 
@@ -137,7 +135,7 @@ class User < ApplicationRecord
137
135
  store :settings, accessors: [:color, :homepage]
138
136
  attribute :configuration, CustomType.new
139
137
 
140
- encrypts :properties, :settings, :configuration
138
+ has_encrypted :properties, :settings, :configuration
141
139
  end
142
140
  ```
143
141
 
@@ -145,7 +143,7 @@ For [StoreModel](https://github.com/DmitryTsepelev/store_model), use:
145
143
 
146
144
  ```ruby
147
145
  class User < ApplicationRecord
148
- encrypts :configuration, type: Configuration.to_type
146
+ has_encrypted :configuration, type: Configuration.to_type
149
147
 
150
148
  after_initialize do
151
149
  self.configuration ||= {}
@@ -176,7 +174,7 @@ Add a new column for the ciphertext, then add to your model:
176
174
 
177
175
  ```ruby
178
176
  class User < ApplicationRecord
179
- encrypts :email, migrating: true
177
+ has_encrypted :email, migrating: true
180
178
  end
181
179
  ```
182
180
 
@@ -190,7 +188,7 @@ Then update the model to the desired state:
190
188
 
191
189
  ```ruby
192
190
  class User < ApplicationRecord
193
- encrypts :email
191
+ has_encrypted :email
194
192
 
195
193
  # remove this line after dropping email column
196
194
  self.ignored_columns = ["email"]
@@ -250,7 +248,7 @@ User.decrypt_email_ciphertext(user.email_ciphertext)
250
248
  Create a migration with:
251
249
 
252
250
  ```ruby
253
- class AddBodyCiphertextToRichTexts < ActiveRecord::Migration[6.1]
251
+ class AddBodyCiphertextToRichTexts < ActiveRecord::Migration[7.0]
254
252
  def change
255
253
  add_column :action_text_rich_texts, :body_ciphertext, :text
256
254
  end
@@ -289,7 +287,7 @@ Add to your model:
289
287
  class User
290
288
  field :email_ciphertext, type: String
291
289
 
292
- encrypts :email
290
+ has_encrypted :email
293
291
  end
294
292
  ```
295
293
 
@@ -381,7 +379,7 @@ Encryption is applied to all versions after processing.
381
379
  You can mount the uploader [as normal](https://github.com/carrierwaveuploader/carrierwave#activerecord). With Active Record, this involves creating a migration:
382
380
 
383
381
  ```ruby
384
- class AddLicenseToUsers < ActiveRecord::Migration[6.1]
382
+ class AddLicenseToUsers < ActiveRecord::Migration[7.0]
385
383
  def change
386
384
  add_column :users, :license, :string
387
385
  end
@@ -574,7 +572,7 @@ Update your model:
574
572
 
575
573
  ```ruby
576
574
  class User < ApplicationRecord
577
- encrypts :email, previous_versions: [{master_key: previous_key}]
575
+ has_encrypted :email, previous_versions: [{master_key: previous_key}]
578
576
  end
579
577
  ```
580
578
 
@@ -710,101 +708,41 @@ Lockbox uses 256-bit keys.
710
708
 
711
709
  ### XSalsa20
712
710
 
713
- You can also use XSalsa20, which uses an extended nonce so you don’t have to worry about nonce collisions. First, [install Libsodium](https://github.com/crypto-rb/rbnacl/wiki/Installing-libsodium). For Homebrew, use:
711
+ You can also use XSalsa20, which uses an extended nonce so you don’t have to worry about nonce collisions. First, [install Libsodium](https://github.com/crypto-rb/rbnacl/wiki/Installing-libsodium). It comes preinstalled on [Heroku](https://devcenter.heroku.com/articles/stack-packages). For Homebrew, use:
714
712
 
715
713
  ```sh
716
714
  brew install libsodium
717
715
  ```
718
716
 
719
- And add to your Gemfile:
717
+ And for Ubuntu, use:
718
+
719
+ ```sh
720
+ sudo apt-get install libsodium23
721
+ ```
722
+
723
+ Then add to your Gemfile:
720
724
 
721
725
  ```ruby
722
726
  gem "rbnacl"
723
727
  ```
724
728
 
725
- Then add to your model:
729
+ And add to your model:
726
730
 
727
731
 
728
732
  ```ruby
729
733
  class User < ApplicationRecord
730
- encrypts :email, algorithm: "xsalsa20"
734
+ has_encrypted :email, algorithm: "xsalsa20"
731
735
  end
732
736
  ```
733
737
 
734
738
  Make it the default with:
735
739
 
736
740
  ```ruby
737
- Lockbox.default_options = {algorithm: "xsalsa20"}
741
+ Lockbox.default_options[:algorithm] = "xsalsa20"
738
742
  ```
739
743
 
740
744
  You can also pass an algorithm to `previous_versions` for key rotation.
741
745
 
742
- #### XSalsa20 Deployment
743
-
744
- ##### Heroku
745
-
746
- Heroku [comes with libsodium](https://devcenter.heroku.com/articles/stack-packages) preinstalled.
747
-
748
- ##### Ubuntu
749
-
750
- For Ubuntu 20.04 and 18.04, use:
751
-
752
- ```sh
753
- sudo apt-get install libsodium23
754
- ```
755
-
756
- For Ubuntu 16.04, use:
757
-
758
- ```sh
759
- sudo apt-get install libsodium18
760
- ```
761
-
762
- ##### GitHub Actions
763
-
764
- For Ubuntu 20.04 and 18.04, use:
765
-
766
- ```yml
767
- - name: Install Libsodium
768
- run: sudo apt-get update && sudo apt-get install libsodium23
769
- ```
770
-
771
- For Ubuntu 16.04, use:
772
-
773
- ```yml
774
- - name: Install Libsodium
775
- run: sudo apt-get update && sudo apt-get install libsodium18
776
- ```
777
-
778
- ##### Travis CI
779
-
780
- On Bionic, add to `.travis.yml`:
781
-
782
- ```yml
783
- addons:
784
- apt:
785
- packages:
786
- - libsodium23
787
- ```
788
-
789
- On Xenial, add to `.travis.yml`:
790
-
791
- ```yml
792
- addons:
793
- apt:
794
- packages:
795
- - libsodium18
796
- ```
797
-
798
- ##### CircleCI
799
-
800
- Add a step to `.circleci/config.yml`:
801
-
802
- ```yml
803
- - run:
804
- name: install Libsodium
805
- command: sudo apt-get install -y libsodium18
806
- ```
807
-
808
746
  ## Hybrid Cryptography
809
747
 
810
748
  [Hybrid cryptography](https://en.wikipedia.org/wiki/Hybrid_cryptosystem) allows servers to encrypt data without being able to decrypt it.
@@ -821,7 +759,7 @@ Store the keys with your other secrets. Then use:
821
759
 
822
760
  ```ruby
823
761
  class User < ApplicationRecord
824
- encrypts :email, algorithm: "hybrid", encryption_key: encryption_key, decryption_key: decryption_key
762
+ has_encrypted :email, algorithm: "hybrid", encryption_key: encryption_key, decryption_key: decryption_key
825
763
  end
826
764
  ```
827
765
 
@@ -851,7 +789,7 @@ To rename a table with encrypted columns/uploaders, use:
851
789
 
852
790
  ```ruby
853
791
  class User < ApplicationRecord
854
- encrypts :email, key_table: "original_table"
792
+ has_encrypted :email, key_table: "original_table"
855
793
  end
856
794
  ```
857
795
 
@@ -859,7 +797,7 @@ To rename an encrypted column itself, use:
859
797
 
860
798
  ```ruby
861
799
  class User < ApplicationRecord
862
- encrypts :email, key_attribute: "original_column"
800
+ has_encrypted :email, key_attribute: "original_column"
863
801
  end
864
802
  ```
865
803
 
@@ -869,7 +807,7 @@ To set a key for an individual field/uploader, use a string:
869
807
 
870
808
  ```ruby
871
809
  class User < ApplicationRecord
872
- encrypts :email, key: ENV["USER_EMAIL_ENCRYPTION_KEY"]
810
+ has_encrypted :email, key: ENV["USER_EMAIL_ENCRYPTION_KEY"]
873
811
  end
874
812
  ```
875
813
 
@@ -877,7 +815,7 @@ Or a proc:
877
815
 
878
816
  ```ruby
879
817
  class User < ApplicationRecord
880
- encrypts :email, key: -> { code }
818
+ has_encrypted :email, key: -> { code }
881
819
  end
882
820
  ```
883
821
 
@@ -887,7 +825,7 @@ To use a different key for each record, use a symbol:
887
825
 
888
826
  ```ruby
889
827
  class User < ApplicationRecord
890
- encrypts :email, key: :some_method
828
+ has_encrypted :email, key: :some_method
891
829
  end
892
830
  ```
893
831
 
@@ -895,7 +833,7 @@ Or a proc:
895
833
 
896
834
  ```ruby
897
835
  class User < ApplicationRecord
898
- encrypts :email, key: -> { some_method }
836
+ has_encrypted :email, key: -> { some_method }
899
837
  end
900
838
  ```
901
839
 
@@ -907,7 +845,7 @@ For Active Record and Mongoid, use:
907
845
 
908
846
  ```ruby
909
847
  class User < ApplicationRecord
910
- encrypts :email, key: :kms_key
848
+ has_encrypted :email, key: :kms_key
911
849
  end
912
850
  ```
913
851
 
@@ -995,7 +933,7 @@ lockbox.decrypt(ciphertext, associated_data: "othercontext") # fails
995
933
  You can use `binary` columns for the ciphertext instead of `text` columns.
996
934
 
997
935
  ```ruby
998
- class AddEmailCiphertextToUsers < ActiveRecord::Migration[6.1]
936
+ class AddEmailCiphertextToUsers < ActiveRecord::Migration[7.0]
999
937
  def change
1000
938
  add_column :users, :email_ciphertext, :binary
1001
939
  end
@@ -1006,7 +944,7 @@ Disable Base64 encoding to save space.
1006
944
 
1007
945
  ```ruby
1008
946
  class User < ApplicationRecord
1009
- encrypts :email, encode: false
947
+ has_encrypted :email, encode: false
1010
948
  end
1011
949
  ```
1012
950
 
@@ -1040,7 +978,7 @@ end
1040
978
  Create a migration with:
1041
979
 
1042
980
  ```ruby
1043
- class MigrateToLockbox < ActiveRecord::Migration[6.1]
981
+ class MigrateToLockbox < ActiveRecord::Migration[7.0]
1044
982
  def change
1045
983
  add_column :users, :name_ciphertext, :text
1046
984
  add_column :users, :email_ciphertext, :text
@@ -1048,11 +986,11 @@ class MigrateToLockbox < ActiveRecord::Migration[6.1]
1048
986
  end
1049
987
  ```
1050
988
 
1051
- And add `encrypts` to your model with the `migrating` option:
989
+ And add `has_encrypted` to your model with the `migrating` option:
1052
990
 
1053
991
  ```ruby
1054
992
  class User < ApplicationRecord
1055
- encrypts :name, :email, migrating: true
993
+ has_encrypted :name, :email, migrating: true
1056
994
  end
1057
995
  ```
1058
996
 
@@ -1066,14 +1004,14 @@ Once all records are migrated, remove the `migrating` option and the previous mo
1066
1004
 
1067
1005
  ```ruby
1068
1006
  class User < ApplicationRecord
1069
- encrypts :name, :email
1007
+ has_encrypted :name, :email
1070
1008
  end
1071
1009
  ```
1072
1010
 
1073
1011
  Then remove the previous gem from your Gemfile and drop its columns.
1074
1012
 
1075
1013
  ```ruby
1076
- class RemovePreviousEncryptedColumns < ActiveRecord::Migration[6.1]
1014
+ class RemovePreviousEncryptedColumns < ActiveRecord::Migration[7.0]
1077
1015
  def change
1078
1016
  remove_column :users, :encrypted_name, :text
1079
1017
  remove_column :users, :encrypted_name_iv, :text
@@ -1085,81 +1023,31 @@ end
1085
1023
 
1086
1024
  ## Upgrading
1087
1025
 
1088
- ### 0.6.0
1026
+ ### 1.0.0
1089
1027
 
1090
- 0.6.0 adds `encrypted: true` to Active Storage metadata for new files. This field is informational, but if you prefer to add it to existing files, use:
1028
+ `encrypts` is now deprecated in favor of `has_encrypted` to avoid conflicting with Active Record encryption.
1091
1029
 
1092
1030
  ```ruby
1093
- User.with_attached_license.find_each do |user|
1094
- next unless user.license.attached?
1095
-
1096
- metadata = user.license.metadata
1097
- unless metadata["encrypted"]
1098
- user.license.blob.update!(metadata: metadata.merge("encrypted" => true))
1099
- end
1031
+ class User < ApplicationRecord
1032
+ has_encrypted :email
1100
1033
  end
1101
1034
  ```
1102
1035
 
1103
- ### 0.3.6
1036
+ ### 0.6.0
1104
1037
 
1105
- 0.3.6 makes content type detection more reliable for Active Storage. You can check and update the content type of existing files with:
1038
+ 0.6.0 adds `encrypted: true` to Active Storage metadata for new files. This field is informational, but if you prefer to add it to existing files, use:
1106
1039
 
1107
1040
  ```ruby
1108
1041
  User.with_attached_license.find_each do |user|
1109
1042
  next unless user.license.attached?
1110
1043
 
1111
- license = user.license
1112
- content_type = Marcel::MimeType.for(license.download, name: license.filename.to_s)
1113
- if content_type != license.content_type
1114
- license.update!(content_type: content_type)
1044
+ metadata = user.license.metadata
1045
+ unless metadata["encrypted"]
1046
+ user.license.blob.update!(metadata: metadata.merge("encrypted" => true))
1115
1047
  end
1116
1048
  end
1117
1049
  ```
1118
1050
 
1119
- ### 0.2.0
1120
-
1121
- 0.2.0 brings a number of improvements. Here are a few to be aware of:
1122
-
1123
- - Added `encrypts` method for database fields
1124
- - Added support for XSalsa20
1125
- - `attached_encrypted` is deprecated in favor of `encrypts_attached`.
1126
-
1127
- #### Optional
1128
-
1129
- To switch to a master key, generate a key:
1130
-
1131
- ```ruby
1132
- Lockbox.generate_key
1133
- ```
1134
-
1135
- And set `ENV["LOCKBOX_MASTER_KEY"]` or `Lockbox.master_key`.
1136
-
1137
- Update your model:
1138
-
1139
- ```ruby
1140
- class User < ApplicationRecord
1141
- encrypts_attached :license, previous_versions: [{key: key}]
1142
- end
1143
- ```
1144
-
1145
- New uploads will be encrypted with the new key.
1146
-
1147
- You can rotate existing records with:
1148
-
1149
- ```ruby
1150
- User.unscoped.find_each do |user|
1151
- user.license.rotate_encryption!
1152
- end
1153
- ```
1154
-
1155
- Once that’s complete, update your model:
1156
-
1157
- ```ruby
1158
- class User < ApplicationRecord
1159
- encrypts_attached :license
1160
- end
1161
- ```
1162
-
1163
1051
  ## History
1164
1052
 
1165
1053
  View the [changelog](https://github.com/ankane/lockbox/blob/master/CHANGELOG.md)
@@ -3,7 +3,12 @@ module Lockbox
3
3
  def pluck(*column_names)
4
4
  return super unless model.respond_to?(:lockbox_attributes)
5
5
 
6
- lockbox_columns = column_names.map.with_index { |c, i| [model.lockbox_attributes[c.to_sym], i] }.select { |la, _i| la && !la[:migrating] }
6
+ lockbox_columns = column_names.map.with_index do |c, i|
7
+ next unless c.respond_to?(:to_sym)
8
+ [model.lockbox_attributes[c.to_sym], i]
9
+ end.select do |la, _i|
10
+ la && !la[:migrating]
11
+ end
7
12
 
8
13
  return super unless lockbox_columns.any?
9
14
 
@@ -106,10 +106,9 @@ module Lockbox
106
106
  end
107
107
 
108
108
  if CarrierWave::VERSION.to_i > 2
109
- raise "CarrierWave version (#{CarrierWave::VERSION}) not supported in this version of Lockbox (#{Lockbox::VERSION})"
109
+ raise Lockbox::Error, "CarrierWave #{CarrierWave::VERSION} not supported in this version of Lockbox"
110
110
  elsif CarrierWave::VERSION.to_i < 1
111
- # TODO raise error in 0.7.0
112
- warn "CarrierWave version (#{CarrierWave::VERSION}) not supported in this version of Lockbox (#{Lockbox::VERSION})"
111
+ raise Lockbox::Error, "CarrierWave #{CarrierWave::VERSION} not supported"
113
112
  end
114
113
 
115
114
  CarrierWave::Uploader::Base.extend(Lockbox::CarrierWaveExtensions)
data/lib/lockbox/model.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  module Lockbox
2
2
  module Model
3
- def lockbox_encrypts(*attributes, **options)
3
+ def has_encrypted(*attributes, **options)
4
4
  # support objects
5
5
  # case options[:type]
6
6
  # when Date
@@ -226,6 +226,52 @@ module Lockbox
226
226
 
227
227
  result
228
228
  end
229
+
230
+ if ActiveRecord::VERSION::MAJOR >= 6
231
+ def self.insert_all(attributes, **options)
232
+ super(lockbox_map_attributes(attributes), **options)
233
+ end
234
+
235
+ def self.insert_all!(attributes, **options)
236
+ super(lockbox_map_attributes(attributes), **options)
237
+ end
238
+
239
+ def self.upsert_all(attributes, **options)
240
+ super(lockbox_map_attributes(attributes, check_readonly: true), **options)
241
+ end
242
+
243
+ # private
244
+ # does not try to handle :returning option for simplicity
245
+ def self.lockbox_map_attributes(records, check_readonly: false)
246
+ return records unless records.is_a?(Array)
247
+
248
+ records.map do |attributes|
249
+ # transform keys like Active Record
250
+ attributes = attributes.transform_keys do |key|
251
+ n = key.to_s
252
+ attribute_aliases[n] || n
253
+ end
254
+
255
+ lockbox_attributes = self.lockbox_attributes.slice(*attributes.keys.map(&:to_sym))
256
+ lockbox_attributes.each do |key, lockbox_attribute|
257
+ attribute = key.to_s
258
+ # check read only
259
+ # users should mark both plaintext and ciphertext columns
260
+ if check_readonly && readonly_attributes.include?(attribute) && !readonly_attributes.include?(lockbox_attribute[:encrypted_attribute].to_s)
261
+ warn "[lockbox] WARNING: Mark attribute as readonly: #{lockbox_attribute[:encrypted_attribute]}"
262
+ end
263
+
264
+ message = attributes[attribute]
265
+ attributes.delete(attribute) unless lockbox_attribute[:migrating]
266
+ encrypted_attribute = lockbox_attribute[:encrypted_attribute]
267
+ ciphertext = send("generate_#{encrypted_attribute}", message)
268
+ attributes[encrypted_attribute] = ciphertext
269
+ end
270
+
271
+ attributes
272
+ end
273
+ end
274
+ end
229
275
  else
230
276
  def reload
231
277
  self.class.lockbox_attributes.each do |_, v|
@@ -241,6 +287,23 @@ module Lockbox
241
287
  @lockbox_attributes[original_name] = options
242
288
 
243
289
  if activerecord
290
+ # warn on default attributes
291
+ if attributes_to_define_after_schema_loads.key?(name.to_s)
292
+ opt = attributes_to_define_after_schema_loads[name.to_s][1]
293
+
294
+ has_default =
295
+ if ActiveRecord::VERSION::MAJOR >= 7
296
+ # not ideal, since NO_DEFAULT_PROVIDED is private
297
+ opt != ActiveRecord::Attributes::ClassMethods.const_get(:NO_DEFAULT_PROVIDED)
298
+ else
299
+ opt.is_a?(Hash) && opt.key?(:default)
300
+ end
301
+
302
+ if has_default
303
+ warn "[lockbox] WARNING: attributes with `:default` option are not supported. Use `after_initialize` instead."
304
+ end
305
+ end
306
+
244
307
  # preference:
245
308
  # 1. type option
246
309
  # 2. existing virtual attribute
@@ -303,11 +366,9 @@ module Lockbox
303
366
  send("restore_#{encrypted_attribute}!")
304
367
  end
305
368
 
306
- if ActiveRecord::VERSION::STRING >= "5.1"
307
- define_method("#{name}_in_database") do
308
- send(name) # writes attribute when not already set
309
- super()
310
- end
369
+ define_method("#{name}_in_database") do
370
+ send(name) # writes attribute when not already set
371
+ super()
311
372
  end
312
373
 
313
374
  define_method("#{name}?") do
@@ -443,7 +504,6 @@ module Lockbox
443
504
  table = activerecord ? table_name : collection_name.to_s
444
505
 
445
506
  unless message.nil?
446
- # TODO use attribute type class in 0.7.0
447
507
  case options[:type]
448
508
  when :boolean
449
509
  message = ActiveRecord::Type::Boolean.new.serialize(message)
@@ -506,7 +566,6 @@ module Lockbox
506
566
  end
507
567
 
508
568
  unless message.nil?
509
- # TODO use attribute type class in 0.7.0
510
569
  case options[:type]
511
570
  when :boolean
512
571
  message = message == "t"
@@ -564,6 +623,11 @@ module Lockbox
564
623
  end
565
624
  end
566
625
 
626
+ def lockbox_encrypts(*attributes, **options)
627
+ ActiveSupport::Deprecation.warn("`#{__callee__}` is deprecated in favor of `has_encrypted`")
628
+ has_encrypted(*attributes, **options)
629
+ end
630
+
567
631
  module Attached
568
632
  def encrypts_attached(*attributes, **options)
569
633
  attributes.each do |name|
@@ -1,3 +1,3 @@
1
1
  module Lockbox
2
- VERSION = "0.6.8"
2
+ VERSION = "1.1.0"
3
3
  end
data/lib/lockbox.rb CHANGED
@@ -16,36 +16,6 @@ require "lockbox/padding"
16
16
  require "lockbox/utils"
17
17
  require "lockbox/version"
18
18
 
19
- # integrations
20
- require "lockbox/carrier_wave_extensions" if defined?(CarrierWave)
21
- require "lockbox/railtie" if defined?(Rails)
22
-
23
- if defined?(ActiveSupport::LogSubscriber)
24
- require "lockbox/log_subscriber"
25
- Lockbox::LogSubscriber.attach_to :lockbox
26
- end
27
-
28
- if defined?(ActiveSupport.on_load)
29
- ActiveSupport.on_load(:active_record) do
30
- # TODO raise error in 0.7.0
31
- if ActiveRecord::VERSION::STRING.to_f < 5.0
32
- warn "Active Record version (#{ActiveRecord::VERSION::STRING}) not supported in this version of Lockbox (#{Lockbox::VERSION})"
33
- end
34
-
35
- extend Lockbox::Model
36
- extend Lockbox::Model::Attached
37
- # alias_method is private in Ruby < 2.5
38
- singleton_class.send(:alias_method, :encrypts, :lockbox_encrypts) if ActiveRecord::VERSION::MAJOR < 7
39
- ActiveRecord::Relation.prepend Lockbox::Calculations
40
- end
41
-
42
- ActiveSupport.on_load(:mongoid) do
43
- Mongoid::Document::ClassMethods.include(Lockbox::Model)
44
- # alias_method is private in Ruby < 2.5
45
- Mongoid::Document::ClassMethods.send(:alias_method, :encrypts, :lockbox_encrypts)
46
- end
47
- end
48
-
49
19
  module Lockbox
50
20
  class Error < StandardError; end
51
21
  class DecryptionError < Error; end
@@ -110,7 +80,39 @@ module Lockbox
110
80
 
111
81
  def self.encrypts_action_text_body(**options)
112
82
  ActiveSupport.on_load(:action_text_rich_text) do
113
- ActionText::RichText.lockbox_encrypts :body, **options
83
+ ActionText::RichText.has_encrypted :body, **options
114
84
  end
115
85
  end
116
86
  end
87
+
88
+ # integrations
89
+ require "lockbox/carrier_wave_extensions" if defined?(CarrierWave)
90
+ require "lockbox/railtie" if defined?(Rails)
91
+
92
+ if defined?(ActiveSupport::LogSubscriber)
93
+ require "lockbox/log_subscriber"
94
+ Lockbox::LogSubscriber.attach_to :lockbox
95
+ end
96
+
97
+ if defined?(ActiveSupport.on_load)
98
+ ActiveSupport.on_load(:active_record) do
99
+ ar_version = ActiveRecord::VERSION::STRING.to_f
100
+ if ar_version < 5.2
101
+ if ar_version >= 5
102
+ raise Lockbox::Error, "Active Record #{ActiveRecord::VERSION::STRING} requires Lockbox < 0.7"
103
+ else
104
+ raise Lockbox::Error, "Active Record #{ActiveRecord::VERSION::STRING} not supported"
105
+ end
106
+ end
107
+
108
+ extend Lockbox::Model
109
+ extend Lockbox::Model::Attached
110
+ singleton_class.alias_method(:encrypts, :lockbox_encrypts) if ActiveRecord::VERSION::MAJOR < 7
111
+ ActiveRecord::Relation.prepend Lockbox::Calculations
112
+ end
113
+
114
+ ActiveSupport.on_load(:mongoid) do
115
+ Mongoid::Document::ClassMethods.include(Lockbox::Model)
116
+ Mongoid::Document::ClassMethods.alias_method(:encrypts, :lockbox_encrypts)
117
+ end
118
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lockbox
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.8
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-01-26 00:00:00.000000000 Z
11
+ date: 2022-10-10 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email: andrew@ankane.org
@@ -51,14 +51,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: '2.4'
54
+ version: '2.6'
55
55
  required_rubygems_version: !ruby/object:Gem::Requirement
56
56
  requirements:
57
57
  - - ">="
58
58
  - !ruby/object:Gem::Version
59
59
  version: '0'
60
60
  requirements: []
61
- rubygems_version: 3.3.3
61
+ rubygems_version: 3.3.7
62
62
  signing_key:
63
63
  specification_version: 4
64
64
  summary: Modern encryption for Ruby and Rails