lockbox 0.2.3 → 0.2.4
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 +4 -4
- data/CHANGELOG.md +8 -0
- data/README.md +58 -15
- data/lib/lockbox.rb +55 -16
- data/lib/lockbox/active_storage_extensions.rb +25 -37
- data/lib/lockbox/carrier_wave_extensions.rb +2 -6
- data/lib/lockbox/io.rb +5 -0
- data/lib/lockbox/model.rb +58 -12
- data/lib/lockbox/railtie.rb +3 -0
- data/lib/lockbox/utils.rb +32 -0
- data/lib/lockbox/version.rb +1 -1
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d4bf60bca21cbcbf37397b2431401a56191b2a8a2b311ddd12bbe8f94d43a259
|
4
|
+
data.tar.gz: '09969a1e9c7904fe69e017dd6aa8a0d5e1a50573fc5937994ad2c0eab63f499b'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5b513fb92e0074f10a5044acbcd9a06bba8f90af473cdc52ae7d981e5432e77afedca887372246afbbb16df7c72cc099ad12a59312e909ef36203c9678b2d987
|
7
|
+
data.tar.gz: 1ab527b1cad1a112b1ce43a3e2745faff13289dfa9dabcd15d7e0ca856cfec801b41112faa09ca312dd57537f3ac5a32d5882fb369d2bb0e262f8bd2bd20d8b4
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
## 0.2.4
|
2
|
+
|
3
|
+
- Added support for Mongoid
|
4
|
+
- Added `encrypt_io` and `decrypt_io` methods
|
5
|
+
- Made it easier to rotate algorithms with master key
|
6
|
+
- Fixed error with migrate and default scope
|
7
|
+
- Fixed encryption with Active Storage 6 and `record.create!`
|
8
|
+
|
1
9
|
## 0.2.3
|
2
10
|
|
3
11
|
- Added time type
|
data/README.md
CHANGED
@@ -46,6 +46,8 @@ Alternatively, you can use a [key management service](#key-management) to manage
|
|
46
46
|
|
47
47
|
## Database Fields
|
48
48
|
|
49
|
+
### Active Record
|
50
|
+
|
49
51
|
Create a migration with:
|
50
52
|
|
51
53
|
```ruby
|
@@ -72,7 +74,7 @@ User.create!(email: "hi@example.org")
|
|
72
74
|
|
73
75
|
If you need to query encrypted fields, check out [Blind Index](https://github.com/ankane/blind_index).
|
74
76
|
|
75
|
-
|
77
|
+
#### Types
|
76
78
|
|
77
79
|
Specify the type of a field with:
|
78
80
|
|
@@ -101,10 +103,30 @@ class User < ApplicationRecord
|
|
101
103
|
end
|
102
104
|
```
|
103
105
|
|
104
|
-
|
106
|
+
#### Validations
|
105
107
|
|
106
108
|
Validations work as expected with the exception of uniqueness. Uniqueness validations require a [blind index](https://github.com/ankane/blind_index).
|
107
109
|
|
110
|
+
### Mongoid
|
111
|
+
|
112
|
+
Add to your model:
|
113
|
+
|
114
|
+
```ruby
|
115
|
+
class User
|
116
|
+
field :email_ciphertext, type: String
|
117
|
+
|
118
|
+
encrypts :email
|
119
|
+
end
|
120
|
+
```
|
121
|
+
|
122
|
+
You can use `email` just like any other attribute.
|
123
|
+
|
124
|
+
```ruby
|
125
|
+
User.create!(email: "hi@example.org")
|
126
|
+
```
|
127
|
+
|
128
|
+
If you need to query encrypted fields, check out [Blind Index](https://github.com/ankane/blind_index).
|
129
|
+
|
108
130
|
## Files
|
109
131
|
|
110
132
|
### Active Storage
|
@@ -140,37 +162,58 @@ def license
|
|
140
162
|
end
|
141
163
|
```
|
142
164
|
|
143
|
-
|
165
|
+
### CarrierWave
|
166
|
+
|
167
|
+
Add to your uploader:
|
168
|
+
|
169
|
+
```ruby
|
170
|
+
class LicenseUploader < CarrierWave::Uploader::Base
|
171
|
+
encrypt
|
172
|
+
end
|
173
|
+
```
|
174
|
+
|
175
|
+
Encryption is applied to all versions after processing.
|
176
|
+
|
177
|
+
To serve encrypted files, use a controller action.
|
144
178
|
|
145
179
|
```ruby
|
146
|
-
|
180
|
+
def license
|
181
|
+
send_data @user.license.read, type: @user.license.content_type
|
182
|
+
end
|
147
183
|
```
|
148
184
|
|
149
|
-
|
185
|
+
### Shrine
|
186
|
+
|
187
|
+
Create a box
|
150
188
|
|
151
189
|
```ruby
|
152
|
-
|
153
|
-
user.attach(params[:avatar])
|
154
|
-
user.save!
|
190
|
+
box = Lockbox.new(key: key)
|
155
191
|
```
|
156
192
|
|
157
|
-
|
193
|
+
Encrypt files before passing them to Shrine
|
158
194
|
|
159
|
-
|
195
|
+
```ruby
|
196
|
+
LicenseUploader.upload(box.encrypt_io(file), :store)
|
197
|
+
```
|
198
|
+
|
199
|
+
And decrypt them after reading
|
160
200
|
|
161
201
|
```ruby
|
162
|
-
|
163
|
-
encrypt
|
164
|
-
end
|
202
|
+
box.decrypt(uploaded_file.read)
|
165
203
|
```
|
166
204
|
|
167
|
-
|
205
|
+
For models, encrypt with:
|
206
|
+
|
207
|
+
```ruby
|
208
|
+
license = params.require(:user).fetch(:license)
|
209
|
+
@user.license = box.encrypt_io(license)
|
210
|
+
```
|
168
211
|
|
169
212
|
To serve encrypted files, use a controller action.
|
170
213
|
|
171
214
|
```ruby
|
172
215
|
def license
|
173
|
-
send_data @user.license.read, type: @user.license.
|
216
|
+
send_data box.decrypt(@user.license.read), type: @user.license.mime_type
|
174
217
|
end
|
175
218
|
```
|
176
219
|
|
data/lib/lockbox.rb
CHANGED
@@ -6,6 +6,8 @@ require "securerandom"
|
|
6
6
|
require "lockbox/box"
|
7
7
|
require "lockbox/encryptor"
|
8
8
|
require "lockbox/key_generator"
|
9
|
+
require "lockbox/io"
|
10
|
+
require "lockbox/model"
|
9
11
|
require "lockbox/utils"
|
10
12
|
require "lockbox/version"
|
11
13
|
|
@@ -15,9 +17,12 @@ require "lockbox/railtie" if defined?(Rails)
|
|
15
17
|
|
16
18
|
if defined?(ActiveSupport)
|
17
19
|
ActiveSupport.on_load(:active_record) do
|
18
|
-
require "lockbox/model"
|
19
20
|
extend Lockbox::Model
|
20
21
|
end
|
22
|
+
|
23
|
+
ActiveSupport.on_load(:mongoid) do
|
24
|
+
Mongoid::Document::ClassMethods.include(Lockbox::Model)
|
25
|
+
end
|
21
26
|
end
|
22
27
|
|
23
28
|
class Lockbox
|
@@ -49,35 +54,47 @@ class Lockbox
|
|
49
54
|
attributes = fields.map { |_, v| v[:encrypted_attribute] }
|
50
55
|
attributes += blind_indexes.map { |_, v| v[:bidx_attribute] }
|
51
56
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
57
|
+
if defined?(ActiveRecord::Base) && model.is_a?(ActiveRecord::Base)
|
58
|
+
attributes.each_with_index do |attribute, i|
|
59
|
+
relation =
|
60
|
+
if i == 0
|
61
|
+
relation.where(attribute => nil)
|
62
|
+
else
|
63
|
+
relation.or(model.unscoped.where(attribute => nil))
|
64
|
+
end
|
65
|
+
end
|
59
66
|
end
|
60
67
|
end
|
61
68
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
record.send("#{v[:attribute]}=", record.send(k)) if restart || !record.send(v[:encrypted_attribute])
|
69
|
+
if relation.respond_to?(:find_each)
|
70
|
+
relation.find_each do |record|
|
71
|
+
migrate_record(record, fields: fields, blind_indexes: blind_indexes, restart: restart)
|
66
72
|
end
|
67
|
-
|
68
|
-
|
73
|
+
else
|
74
|
+
relation.all.each do |record|
|
75
|
+
migrate_record(record, fields: fields, blind_indexes: blind_indexes, restart: restart)
|
69
76
|
end
|
70
|
-
record.save(validate: false) if record.changed?
|
71
77
|
end
|
72
78
|
end
|
73
79
|
|
80
|
+
# private
|
81
|
+
def self.migrate_record(record, fields:, blind_indexes:, restart:)
|
82
|
+
fields.each do |k, v|
|
83
|
+
record.send("#{v[:attribute]}=", record.send(k)) if restart || !record.send(v[:encrypted_attribute])
|
84
|
+
end
|
85
|
+
blind_indexes.each do |k, v|
|
86
|
+
record.send("compute_#{k}_bidx") if restart || !record.send(v[:bidx_attribute])
|
87
|
+
end
|
88
|
+
record.save(validate: false) if record.changed?
|
89
|
+
end
|
90
|
+
|
74
91
|
def initialize(**options)
|
75
92
|
options = self.class.default_options.merge(options)
|
76
93
|
previous_versions = options.delete(:previous_versions)
|
77
94
|
|
78
95
|
@boxes =
|
79
96
|
[Box.new(options)] +
|
80
|
-
Array(previous_versions).map { |v| Box.new(v) }
|
97
|
+
Array(previous_versions).map { |v| Box.new({key: options[:key]}.merge(v)) }
|
81
98
|
end
|
82
99
|
|
83
100
|
def encrypt(message, **options)
|
@@ -112,6 +129,18 @@ class Lockbox
|
|
112
129
|
end
|
113
130
|
end
|
114
131
|
|
132
|
+
def encrypt_io(io, **options)
|
133
|
+
new_io = Lockbox::IO.new(encrypt(io.read, **options))
|
134
|
+
copy_metadata(io, new_io)
|
135
|
+
new_io
|
136
|
+
end
|
137
|
+
|
138
|
+
def decrypt_io(io, **options)
|
139
|
+
new_io = Lockbox::IO.new(decrypt(io.read, **options))
|
140
|
+
copy_metadata(io, new_io)
|
141
|
+
new_io
|
142
|
+
end
|
143
|
+
|
115
144
|
def self.generate_key
|
116
145
|
SecureRandom.hex(32)
|
117
146
|
end
|
@@ -199,4 +228,14 @@ class Lockbox
|
|
199
228
|
raise TypeError, "can't convert #{name} to string" unless str.respond_to?(:to_str)
|
200
229
|
str.to_str
|
201
230
|
end
|
231
|
+
|
232
|
+
def copy_metadata(source, target)
|
233
|
+
target.original_filename =
|
234
|
+
if source.respond_to?(:original_filename)
|
235
|
+
source.original_filename
|
236
|
+
elsif source.respond_to?(:path)
|
237
|
+
File.basename(source.path)
|
238
|
+
end
|
239
|
+
target.content_type = source.content_type if source.respond_to?(:content_type)
|
240
|
+
end
|
202
241
|
end
|
@@ -10,35 +10,11 @@ class Lockbox
|
|
10
10
|
def encrypted?
|
11
11
|
# could use record_type directly
|
12
12
|
# but record should already be loaded most of the time
|
13
|
-
|
13
|
+
Utils.encrypted?(record, name)
|
14
14
|
end
|
15
15
|
|
16
16
|
def encrypt_attachable(attachable)
|
17
|
-
|
18
|
-
box = Utils.build_box(record, options, record.class.table_name, name)
|
19
|
-
|
20
|
-
case attachable
|
21
|
-
when ActiveStorage::Blob
|
22
|
-
raise NotImplementedError, "Not supported"
|
23
|
-
when ActionDispatch::Http::UploadedFile, Rack::Test::UploadedFile
|
24
|
-
attachable = {
|
25
|
-
io: StringIO.new(box.encrypt(attachable.read)),
|
26
|
-
filename: attachable.original_filename,
|
27
|
-
content_type: attachable.content_type
|
28
|
-
}
|
29
|
-
when Hash
|
30
|
-
attachable = {
|
31
|
-
io: StringIO.new(box.encrypt(attachable[:io].read)),
|
32
|
-
filename: attachable[:filename],
|
33
|
-
content_type: attachable[:content_type]
|
34
|
-
}
|
35
|
-
when String
|
36
|
-
raise NotImplementedError, "Not supported"
|
37
|
-
else
|
38
|
-
nil
|
39
|
-
end
|
40
|
-
|
41
|
-
attachable
|
17
|
+
Utils.encrypt_attachable(record, name, attachable)
|
42
18
|
end
|
43
19
|
|
44
20
|
def rebuild_attachable(attachment)
|
@@ -51,9 +27,11 @@ class Lockbox
|
|
51
27
|
end
|
52
28
|
|
53
29
|
module AttachedOne
|
54
|
-
|
55
|
-
|
56
|
-
|
30
|
+
if ActiveStorage::VERSION::MAJOR < 6
|
31
|
+
def attach(attachable)
|
32
|
+
attachable = encrypt_attachable(attachable) if encrypted?
|
33
|
+
super(attachable)
|
34
|
+
end
|
57
35
|
end
|
58
36
|
|
59
37
|
def rotate_encryption!
|
@@ -66,15 +44,17 @@ class Lockbox
|
|
66
44
|
end
|
67
45
|
|
68
46
|
module AttachedMany
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
attachables
|
73
|
-
|
74
|
-
|
75
|
-
|
47
|
+
if ActiveStorage::VERSION::MAJOR < 6
|
48
|
+
def attach(*attachables)
|
49
|
+
if encrypted?
|
50
|
+
attachables =
|
51
|
+
attachables.flatten.collect do |attachable|
|
52
|
+
encrypt_attachable(attachable)
|
53
|
+
end
|
54
|
+
end
|
76
55
|
|
77
|
-
|
56
|
+
super(attachables)
|
57
|
+
end
|
78
58
|
end
|
79
59
|
|
80
60
|
def rotate_encryption!
|
@@ -99,6 +79,14 @@ class Lockbox
|
|
99
79
|
end
|
100
80
|
end
|
101
81
|
|
82
|
+
module CreateOne
|
83
|
+
def initialize(name, record, attachable)
|
84
|
+
# this won't encrypt existing blobs
|
85
|
+
attachable = Lockbox::Utils.encrypt_attachable(record, name, attachable) if Lockbox::Utils.encrypted?(record, name) && !attachable.is_a?(ActiveStorage::Blob)
|
86
|
+
super(name, record, attachable)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
102
90
|
module Attachment
|
103
91
|
extend ActiveSupport::Concern
|
104
92
|
|
@@ -1,15 +1,11 @@
|
|
1
1
|
class Lockbox
|
2
2
|
module CarrierWaveExtensions
|
3
|
-
class FileIO < StringIO
|
4
|
-
attr_accessor :original_filename
|
5
|
-
end
|
6
|
-
|
7
3
|
def encrypt(**options)
|
8
4
|
class_eval do
|
9
5
|
before :cache, :encrypt
|
10
6
|
|
11
7
|
def encrypt(file)
|
12
|
-
@file = CarrierWave::SanitizedFile.new(
|
8
|
+
@file = CarrierWave::SanitizedFile.new(lockbox.encrypt_io(file))
|
13
9
|
end
|
14
10
|
|
15
11
|
def read
|
@@ -22,7 +18,7 @@ class Lockbox
|
|
22
18
|
end
|
23
19
|
|
24
20
|
def rotate_encryption!
|
25
|
-
io =
|
21
|
+
io = Lockbox::IO.new(read)
|
26
22
|
io.original_filename = file.filename
|
27
23
|
previous_value = enable_processing
|
28
24
|
begin
|
data/lib/lockbox/io.rb
ADDED
data/lib/lockbox/model.rb
CHANGED
@@ -107,7 +107,7 @@ class Lockbox
|
|
107
107
|
def serializable_hash(options = nil)
|
108
108
|
options = options.try(:dup) || {}
|
109
109
|
options[:except] = Array(options[:except])
|
110
|
-
options[:except] += self.class.lockbox_attributes.values.
|
110
|
+
options[:except] += self.class.lockbox_attributes.values.flat_map { |v| [v[:attribute], v[:encrypted_attribute]] }
|
111
111
|
super(options)
|
112
112
|
end
|
113
113
|
|
@@ -127,9 +127,21 @@ class Lockbox
|
|
127
127
|
self.class.lockbox_attributes.each do |_, lockbox_attribute|
|
128
128
|
attribute = lockbox_attribute[:attribute]
|
129
129
|
|
130
|
-
if changes.include?(attribute)
|
131
|
-
|
130
|
+
if changes.include?(attribute)
|
131
|
+
type = (self.class.try(:attribute_types) || {})[attribute]
|
132
|
+
if type && type.is_a?(ActiveRecord::Type::Serialized)
|
133
|
+
send("#{attribute}=", send(attribute))
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
if defined?(Mongoid::Document) && included_modules.include?(Mongoid::Document)
|
140
|
+
def reload
|
141
|
+
self.class.lockbox_attributes.each do |_, v|
|
142
|
+
instance_variable_set("@#{v[:attribute]}", nil)
|
132
143
|
end
|
144
|
+
super
|
133
145
|
end
|
134
146
|
end
|
135
147
|
end
|
@@ -137,7 +149,36 @@ class Lockbox
|
|
137
149
|
serialize name, JSON if options[:type] == :json
|
138
150
|
serialize name, Hash if options[:type] == :hash
|
139
151
|
|
140
|
-
attribute
|
152
|
+
if respond_to?(:attribute)
|
153
|
+
attribute name, attribute_type
|
154
|
+
else
|
155
|
+
m = Module.new do
|
156
|
+
define_method("#{name}=") do |val|
|
157
|
+
prev_val = instance_variable_get("@#{name}")
|
158
|
+
|
159
|
+
unless val == prev_val
|
160
|
+
# custom attribute_will_change! method
|
161
|
+
unless changed_attributes.key?(name.to_s)
|
162
|
+
changed_attributes[name.to_s] = prev_val.__deep_copy__
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
instance_variable_set("@#{name}", val)
|
167
|
+
end
|
168
|
+
|
169
|
+
define_method(name) do
|
170
|
+
instance_variable_get("@#{name}")
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
include m
|
175
|
+
|
176
|
+
alias_method "#{name}_changed?", "#{encrypted_attribute}_changed?"
|
177
|
+
|
178
|
+
define_method "#{name}_was" do
|
179
|
+
attribute_was(name.to_s)
|
180
|
+
end
|
181
|
+
end
|
141
182
|
|
142
183
|
define_method("#{name}=") do |message|
|
143
184
|
original_message = message
|
@@ -174,8 +215,8 @@ class Lockbox
|
|
174
215
|
# do nothing
|
175
216
|
# encrypt will convert to binary
|
176
217
|
else
|
177
|
-
type = self.class.attribute_types[name.to_s]
|
178
|
-
if type.is_a?(ActiveRecord::Type::Serialized)
|
218
|
+
type = (self.class.try(:attribute_types) || {})[name.to_s]
|
219
|
+
if type && type.is_a?(ActiveRecord::Type::Serialized)
|
179
220
|
message = type.serialize(message)
|
180
221
|
end
|
181
222
|
end
|
@@ -195,6 +236,7 @@ class Lockbox
|
|
195
236
|
else
|
196
237
|
self.class.send(class_method_name, message, context: self)
|
197
238
|
end
|
239
|
+
|
198
240
|
send("#{encrypted_attribute}=", ciphertext)
|
199
241
|
|
200
242
|
super(original_message)
|
@@ -210,7 +252,8 @@ class Lockbox
|
|
210
252
|
ciphertext
|
211
253
|
else
|
212
254
|
ciphertext = Base64.decode64(ciphertext) if encode
|
213
|
-
|
255
|
+
table = self.class.respond_to?(:table_name) ? self.class.table_name : self.class.collection_name.to_s
|
256
|
+
Lockbox::Utils.build_box(self, options, table, encrypted_attribute).decrypt(ciphertext)
|
214
257
|
end
|
215
258
|
|
216
259
|
unless message.nil?
|
@@ -233,8 +276,8 @@ class Lockbox
|
|
233
276
|
# do nothing
|
234
277
|
# decrypt returns binary string
|
235
278
|
else
|
236
|
-
type = self.class.attribute_types[name.to_s]
|
237
|
-
if type.is_a?(ActiveRecord::Type::Serialized)
|
279
|
+
type = (self.class.try(:attribute_types) || {})[name.to_s]
|
280
|
+
if type && type.is_a?(ActiveRecord::Type::Serialized)
|
238
281
|
message = type.deserialize(message)
|
239
282
|
else
|
240
283
|
# default to string if not serialized
|
@@ -244,13 +287,15 @@ class Lockbox
|
|
244
287
|
end
|
245
288
|
|
246
289
|
# set previous attribute on first decrypt
|
247
|
-
@attributes[name.to_s].instance_variable_set("@value_before_type_cast", message)
|
290
|
+
@attributes[name.to_s].instance_variable_set("@value_before_type_cast", message) if @attributes[name.to_s]
|
248
291
|
|
249
292
|
# cache
|
250
293
|
if respond_to?(:_write_attribute, true)
|
251
294
|
_write_attribute(name, message)
|
252
|
-
|
295
|
+
elsif respond_to?(:raw_write_attribute)
|
253
296
|
raw_write_attribute(name, message)
|
297
|
+
else
|
298
|
+
instance_variable_set("@#{name}", message)
|
254
299
|
end
|
255
300
|
end
|
256
301
|
|
@@ -259,7 +304,8 @@ class Lockbox
|
|
259
304
|
|
260
305
|
# for fixtures
|
261
306
|
define_singleton_method class_method_name do |message, **opts|
|
262
|
-
|
307
|
+
table = respond_to?(:table_name) ? table_name : collection_name.to_s
|
308
|
+
ciphertext = Lockbox::Utils.build_box(opts[:context], options, table, encrypted_attribute).encrypt(message)
|
263
309
|
ciphertext = Base64.strict_encode64(ciphertext) if encode
|
264
310
|
ciphertext
|
265
311
|
end
|
data/lib/lockbox/railtie.rb
CHANGED
@@ -6,6 +6,9 @@ class Lockbox
|
|
6
6
|
if defined?(ActiveStorage)
|
7
7
|
require "lockbox/active_storage_extensions"
|
8
8
|
ActiveStorage::Attached.prepend(Lockbox::ActiveStorageExtensions::Attached)
|
9
|
+
if ActiveStorage::VERSION::MAJOR >= 6
|
10
|
+
ActiveStorage::Attached::Changes::CreateOne.prepend(Lockbox::ActiveStorageExtensions::CreateOne)
|
11
|
+
end
|
9
12
|
ActiveStorage::Attached::One.prepend(Lockbox::ActiveStorageExtensions::AttachedOne)
|
10
13
|
ActiveStorage::Attached::Many.prepend(Lockbox::ActiveStorageExtensions::AttachedMany)
|
11
14
|
end
|
data/lib/lockbox/utils.rb
CHANGED
@@ -27,5 +27,37 @@ class Lockbox
|
|
27
27
|
end
|
28
28
|
key
|
29
29
|
end
|
30
|
+
|
31
|
+
def self.encrypted?(record, name)
|
32
|
+
!encrypted_options(record, name).nil?
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.encrypt_attachable(record, name, attachable)
|
36
|
+
options = encrypted_options(record, name)
|
37
|
+
box = build_box(record, options, record.class.table_name, name)
|
38
|
+
|
39
|
+
case attachable
|
40
|
+
when ActiveStorage::Blob
|
41
|
+
raise NotImplementedError, "Not supported"
|
42
|
+
when ActionDispatch::Http::UploadedFile, Rack::Test::UploadedFile
|
43
|
+
attachable = {
|
44
|
+
io: StringIO.new(box.encrypt(attachable.read)),
|
45
|
+
filename: attachable.original_filename,
|
46
|
+
content_type: attachable.content_type
|
47
|
+
}
|
48
|
+
when Hash
|
49
|
+
attachable = {
|
50
|
+
io: StringIO.new(box.encrypt(attachable[:io].read)),
|
51
|
+
filename: attachable[:filename],
|
52
|
+
content_type: attachable[:content_type]
|
53
|
+
}
|
54
|
+
when String
|
55
|
+
raise NotImplementedError, "Not supported"
|
56
|
+
else
|
57
|
+
nil
|
58
|
+
end
|
59
|
+
|
60
|
+
attachable
|
61
|
+
end
|
30
62
|
end
|
31
63
|
end
|
data/lib/lockbox/version.rb
CHANGED
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.2.
|
4
|
+
version: 0.2.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Kane
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-08-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -164,6 +164,20 @@ dependencies:
|
|
164
164
|
- - ">="
|
165
165
|
- !ruby/object:Gem::Version
|
166
166
|
version: '0'
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: mongoid
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - ">="
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
type: :development
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - ">="
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0'
|
167
181
|
description:
|
168
182
|
email: andrew@chartkick.com
|
169
183
|
executables: []
|
@@ -179,6 +193,7 @@ files:
|
|
179
193
|
- lib/lockbox/box.rb
|
180
194
|
- lib/lockbox/carrier_wave_extensions.rb
|
181
195
|
- lib/lockbox/encryptor.rb
|
196
|
+
- lib/lockbox/io.rb
|
182
197
|
- lib/lockbox/key_generator.rb
|
183
198
|
- lib/lockbox/model.rb
|
184
199
|
- lib/lockbox/railtie.rb
|