Skip to content

Commit af727a4

Browse files
committed
Move column validation to method execution to prevent migration issues, discussed in #1
1 parent 68aeed8 commit af727a4

File tree

2 files changed

+28
-9
lines changed

2 files changed

+28
-9
lines changed

lib/kms_rails/active_record.rb

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,13 @@ def kms_attr(field, key_id:, retain: false, msgpack: false, context_key: nil, co
1414
include InstanceMethods
1515

1616
real_field = "#{field}_enc"
17-
raise RuntimeError, "Field '#{real_field}' must exist to store encrypted data" unless self.column_names.include?(real_field)
18-
raise RuntimeError, "Field '#{field}' must not be a real column, '#{real_field}' is the real column" if self.column_names.include?(field)
17+
raise RuntimeError, "Field '#{field}' must not be a real column, '#{real_field}' is the real column" if self.column_names.include?(field.to_s)
1918

2019
enc = Core.new(key_id: key_id, msgpack: msgpack, context_key: context_key, context_value: context_value)
2120

2221
define_method "#{field}=" do |data|
22+
raise RuntimeError, "Field '#{real_field}' must exist to store encrypted data" unless self.class.column_names.include?(real_field)
23+
2324
if data.blank? # Just set to nil if nil
2425
clear_retained(field)
2526
self[real_field] = nil
@@ -34,10 +35,13 @@ def kms_attr(field, key_id:, retain: false, msgpack: false, context_key: nil, co
3435
end
3536

3637
define_method "#{real_field}" do
38+
raise RuntimeError, "Field '#{real_field}' must exist to retrieve encrypted data" unless self.class.column_names.include?(real_field)
3739
Core.to64( get_hash(field) )
3840
end
3941

4042
define_method "#{field}" do
43+
raise RuntimeError, "Field '#{real_field}' must exist to retrieve decrypted data" unless self.class.column_names.include?(real_field)
44+
4145
hash = get_hash(field)
4246
return nil unless hash
4347

spec/kms_rails/active_record_spec.rb

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@
5050

5151
context '::kms_attr' do
5252
let(:model) { NormalModelNoRetain }
53-
subject { model.kms_attr :the_secret, key_id: 'a' }
5453

5554
it 'defines the_secret fields' do
5655
expect(model.instance_methods).to include(
@@ -59,29 +58,45 @@
5958
end
6059

6160
context '_enc field doens\'t exist' do
62-
let (:model) { NoEncModel }
63-
6461
with_model :NoEncModel do
6562
table do |t|
6663
t.string :secret_name
6764
end
6865
end
6966

70-
it 'throws an exception' do
71-
expect { subject }.to raise_error(RuntimeError)
67+
let(:model) { NoEncModel }
68+
69+
before do
70+
model.kms_attr :the_secret, key_id: 'a'
71+
end
72+
73+
subject { model.new }
74+
75+
it 'throws an exception on retrieve' do
76+
expect { subject.the_secret }.to raise_error(RuntimeError)
77+
end
78+
79+
it 'throws an exception on set' do
80+
expect { subject.the_secret = 'foo' }.to raise_error(RuntimeError)
81+
end
82+
83+
it 'throws an exception on real retrieve' do
84+
expect { subject.the_secret_enc }.to raise_error(RuntimeError)
7285
end
7386
end
7487

7588
context 'real field exists' do
76-
let (:model) { RealFieldModel }
77-
7889
with_model :RealFieldModel do
7990
table do |t|
8091
t.string :secret_name
8192
t.binary :the_secret
93+
t.binary :the_borker
8294
end
8395
end
8496

97+
let (:model) { RealFieldModel }
98+
subject { model.kms_attr :the_secret, key_id: 'a' }
99+
85100
it 'throws an exception' do
86101
expect { subject }.to raise_error(RuntimeError)
87102
end

0 commit comments

Comments
 (0)