pgcrypto 0.2.7 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES.md +68 -0
- data/Gemfile +1 -1
- data/VERSION +1 -1
- data/lib/pgcrypto.rb +3 -2
- data/lib/pgcrypto/column.rb +2 -0
- data/pgcrypto.gemspec +6 -6
- data/spec/lib/pgcrypto_spec.rb +93 -78
- data/spec/spec_helper.rb +3 -6
- metadata +6 -6
- data/CHANGES +0 -59
data/CHANGES.md
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
# CHANGELOG
|
2
|
+
## 0.3.1
|
3
|
+
- Finally solved a large bug with a very simple fix. Looks
|
4
|
+
like we're approaching stability, folks!
|
5
|
+
|
6
|
+
## 0.3.0
|
7
|
+
- Finally solved a large bug with a very simple fix. Looks
|
8
|
+
like we're approaching stability, folks!
|
9
|
+
|
10
|
+
## 0.2.7
|
11
|
+
- So, about that library I arrogantly included? Turns out we
|
12
|
+
should require it in code before expecting anything of it.
|
13
|
+
|
14
|
+
## 0.2.6
|
15
|
+
- We now use the BigSpoon library to hook into reload, because
|
16
|
+
it's SO MUCH MORE AWESOME THAN THE GARBAGE MOST PEOPLE USE.
|
17
|
+
Welp. It's been nice coding with y'all.
|
18
|
+
|
19
|
+
## 0.2.5
|
20
|
+
- PGCrypto now hooks into ActiveRecord::Base#reload in order to
|
21
|
+
reset encrypted column values as expected when calling reload.
|
22
|
+
|
23
|
+
## 0.2.2
|
24
|
+
- Don't try to load columns on new records; should further reduce
|
25
|
+
unnecessary database calls!
|
26
|
+
|
27
|
+
## 0.2.1
|
28
|
+
- Added ActiveModel::Dirty support, so you can now call *_changed?
|
29
|
+
on your models tracking pgcrypto columns.
|
30
|
+
|
31
|
+
## 0.2.0
|
32
|
+
- Overhauled key system. Unfortunately, for performance reasons
|
33
|
+
and due to the insanely hacked nature of PGCrypto, multiple keys
|
34
|
+
are NO LONGER SUPPORTED. I'm working to bring them back, but
|
35
|
+
this was the only solution to get fully performant and functional
|
36
|
+
without any disasters.
|
37
|
+
|
38
|
+
## 0.1.2
|
39
|
+
- Added automatic installation of the pgcrypto extension if'n it
|
40
|
+
doesn't already exist. Helpful, but doesn't fully make the
|
41
|
+
`rake db:test:prepare` cut yet. Still working on that bit...
|
42
|
+
|
43
|
+
## 0.1.1
|
44
|
+
- Rebuilt the WHERE clause stuff to make sure finders AND setters
|
45
|
+
both worked. It's fragile and hackish at this time, but we'll get
|
46
|
+
there, folks!
|
47
|
+
|
48
|
+
## 0.1.0
|
49
|
+
- Overhauled the underpinnings to rely on a separate column. Adds
|
50
|
+
on-demand loading of encrypted attributes from a central table
|
51
|
+
which provides dramatic speed improvements when a record's
|
52
|
+
encrypted attributes aren't needed most of the time.
|
53
|
+
|
54
|
+
## 0.0.4
|
55
|
+
- Compatibility fix between ActiveRecord ## 3.2.1 and ## 3.2.2
|
56
|
+
|
57
|
+
## 0.0.3
|
58
|
+
- Fixed a join bug on SELECT statements
|
59
|
+
|
60
|
+
## 0.0.2
|
61
|
+
- Fixed a number of key-related bugs discovered in testing with our
|
62
|
+
second production app with encrypted columns. Also duck-typed AREL
|
63
|
+
statement types in a few places.
|
64
|
+
|
65
|
+
## 0.0.1
|
66
|
+
- INSERT, SELECT, and UPDATE statements are working. But I wrote this
|
67
|
+
while testing with a production app, and thus haven't written
|
68
|
+
specific tests, so don't get your panties in a twist.
|
data/Gemfile
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3.1
|
data/lib/pgcrypto.rb
CHANGED
@@ -57,6 +57,7 @@ module PGCrypto
|
|
57
57
|
remove_instance_variable("@_pgcrypto_#{column_name}") if defined?(@_pgcrypto_#{column_name})
|
58
58
|
else
|
59
59
|
@_pgcrypto_#{column_name} ||= pgcrypto_columns.select{|column| column.name == "#{column_name}"}.first || pgcrypto_columns.new(:name => "#{column_name}")
|
60
|
+
pgcrypto_columns.push(@_pgcrypto_#{column_name})
|
60
61
|
@_pgcrypto_#{column_name}.value = value
|
61
62
|
end
|
62
63
|
end
|
@@ -91,9 +92,9 @@ module PGCrypto
|
|
91
92
|
pgcrypto_column_finder = pgcrypto_columns
|
92
93
|
if key = PGCrypto.keys[:private]
|
93
94
|
pgcrypto_column_finder = pgcrypto_column_finder.select([
|
94
|
-
%("#{PGCrypto::Column.table_name}"."
|
95
|
+
%w(id owner_id owner_type owner_table).map {|column| %("#{PGCrypto::Column.table_name}"."#{column}")},
|
95
96
|
%[pgp_pub_decrypt("#{PGCrypto::Column.table_name}"."value", pgcrypto_keys.#{key.name}#{", '#{key.password}'" if key.password}) AS "value"]
|
96
|
-
]).joins(%[CROSS JOIN (SELECT #{key.dearmored} AS "#{key.name}") AS pgcrypto_keys])
|
97
|
+
].flatten).joins(%[CROSS JOIN (SELECT #{key.dearmored} AS "#{key.name}") AS pgcrypto_keys])
|
97
98
|
end
|
98
99
|
pgcrypto_column_finder.where(:name => column_name).first
|
99
100
|
rescue ActiveRecord::StatementInvalid => e
|
data/lib/pgcrypto/column.rb
CHANGED
@@ -4,6 +4,8 @@ module PGCrypto
|
|
4
4
|
before_save :set_owner_table
|
5
5
|
belongs_to :owner, :autosave => false, :inverse_of => :pgcrypto_columns, :polymorphic => true
|
6
6
|
|
7
|
+
default_scope select(%w(id owner_id owner_type owner_table))
|
8
|
+
|
7
9
|
protected
|
8
10
|
def set_owner_table
|
9
11
|
self.owner_table = self.owner.class.table_name
|
data/pgcrypto.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "pgcrypto"
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.3.1"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Flip Sasser"]
|
12
|
-
s.date = "2012-08-
|
12
|
+
s.date = "2012-08-14"
|
13
13
|
s.description = "\n PGCrypto is an ActiveRecord::Base extension that allows you to asymmetrically\n encrypt PostgreSQL columns with as little trouble as possible. It's totally\n freaking rad.\n "
|
14
14
|
s.email = "flip@x451.com"
|
15
15
|
s.extra_rdoc_files = [
|
@@ -19,7 +19,7 @@ Gem::Specification.new do |s|
|
|
19
19
|
s.files = [
|
20
20
|
".rspec",
|
21
21
|
".simplecov",
|
22
|
-
"CHANGES",
|
22
|
+
"CHANGES.md",
|
23
23
|
"Gemfile",
|
24
24
|
"Guardfile",
|
25
25
|
"LICENSE",
|
@@ -53,16 +53,16 @@ Gem::Specification.new do |s|
|
|
53
53
|
|
54
54
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
55
55
|
s.add_runtime_dependency(%q<activerecord>, [">= 3.2"])
|
56
|
-
s.add_runtime_dependency(%q<big_spoon>, [">= 0"])
|
56
|
+
s.add_runtime_dependency(%q<big_spoon>, [">= 0.2.0"])
|
57
57
|
s.add_development_dependency(%q<jeweler>, [">= 0"])
|
58
58
|
else
|
59
59
|
s.add_dependency(%q<activerecord>, [">= 3.2"])
|
60
|
-
s.add_dependency(%q<big_spoon>, [">= 0"])
|
60
|
+
s.add_dependency(%q<big_spoon>, [">= 0.2.0"])
|
61
61
|
s.add_dependency(%q<jeweler>, [">= 0"])
|
62
62
|
end
|
63
63
|
else
|
64
64
|
s.add_dependency(%q<activerecord>, [">= 3.2"])
|
65
|
-
s.add_dependency(%q<big_spoon>, [">= 0"])
|
65
|
+
s.add_dependency(%q<big_spoon>, [">= 0.2.0"])
|
66
66
|
s.add_dependency(%q<jeweler>, [">= 0"])
|
67
67
|
end
|
68
68
|
end
|
data/spec/lib/pgcrypto_spec.rb
CHANGED
@@ -4,83 +4,98 @@ describe PGCrypto do
|
|
4
4
|
it "should extend ActiveRecord::Base" do
|
5
5
|
PGCryptoTestModel.should respond_to(:pgcrypto)
|
6
6
|
end
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
7
|
+
|
8
|
+
it "should have readers and writers" do
|
9
|
+
model = PGCryptoTestModel.new
|
10
|
+
model.should respond_to(:test_column)
|
11
|
+
model.should respond_to(:test_column=)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "be settable on create" do
|
15
|
+
model = PGCryptoTestModel.new(:test_column => 'this is a test')
|
16
|
+
model.save!.should be_true
|
17
|
+
end
|
18
|
+
|
19
|
+
it "be settable on update" do
|
20
|
+
model = PGCryptoTestModel.create!
|
21
|
+
model.test_column = 'this is another test'
|
22
|
+
model.save!.should be_true
|
23
|
+
end
|
24
|
+
|
25
|
+
it "be update-able" do
|
26
|
+
model = PGCryptoTestModel.create!(:test_column => 'i am test column')
|
27
|
+
model.update_attributes!(:test_column => 'but now i am a different column, son').should be_true
|
28
|
+
model.test_column.should == 'but now i am a different column, son'
|
29
|
+
end
|
30
|
+
|
31
|
+
it "be retrievable at create" do
|
32
|
+
model = PGCryptoTestModel.create!(:test_column => 'i am test column')
|
33
|
+
model.test_column.should == 'i am test column'
|
34
|
+
end
|
35
|
+
|
36
|
+
it "be retrievable after create" do
|
37
|
+
model = PGCryptoTestModel.create!(:test_column => 'i should return to you')
|
38
|
+
PGCryptoTestModel.find(model.id).test_column.should == 'i should return to you'
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should be retrievable at update" do
|
42
|
+
model = PGCryptoTestModel.create!(:test_column => 'i will update')
|
43
|
+
model.test_column.should == 'i will update'
|
44
|
+
model.update_attributes!(:test_column => 'i updated')
|
45
|
+
model.test_column.should == 'i updated'
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should be retrievable without update" do
|
49
|
+
model = PGCryptoTestModel.create!(:test_column => 'i will update')
|
50
|
+
model.test_column.should == 'i will update'
|
51
|
+
model.test_column = 'i updated'
|
52
|
+
model.test_column.should == 'i updated'
|
53
|
+
end
|
54
|
+
|
55
|
+
it "be searchable" do
|
56
|
+
model = PGCryptoTestModel.create!(:test_column => 'i am findable!')
|
57
|
+
PGCryptoTestModel.where(:test_column => model.test_column).count.should == 1
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should track changes" do
|
61
|
+
model = PGCryptoTestModel.create!(:test_column => 'i am clean')
|
62
|
+
model.test_column = "now i'm not!"
|
63
|
+
model.test_column_changed?.should be_true
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should not be dirty if unchanged" do
|
67
|
+
model = PGCryptoTestModel.create!(:test_column => 'i am clean')
|
68
|
+
model.test_column = 'i am clean'
|
69
|
+
model.test_column_changed?.should_not be_true
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should reload with the class" do
|
73
|
+
model = PGCryptoTestModel.create!(:test_column => 'i am clean')
|
74
|
+
model.test_column = 'i am dirty'
|
75
|
+
model.reload
|
76
|
+
model.test_column.should == 'i am clean'
|
77
|
+
model.test_column_changed?.should_not be_true
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should allow direct setting of values as well" do
|
81
|
+
model = PGCryptoTestModel.create!(:test_column => 'one')
|
82
|
+
model.test_column.should == 'one'
|
83
|
+
model.test_column = 'two'
|
84
|
+
model.save!.should be_true
|
85
|
+
model.select_pgcrypto_column(:test_column).value.should == 'two'
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should delete the column when I set the value to nil" do
|
89
|
+
model = PGCryptoTestModel.create!(:test_column => 'one')
|
90
|
+
model.test_column = nil
|
91
|
+
model.save!
|
92
|
+
model.select_pgcrypto_column(:test_column).should be_nil
|
93
|
+
end
|
94
|
+
|
95
|
+
it "plz work" do
|
96
|
+
model = PGCryptoTestModel.find(PGCryptoTestModel.create!(:test_column => 'one'))
|
97
|
+
model.test_column = 'two'
|
98
|
+
model.save!
|
99
|
+
model.select_pgcrypto_column(:test_column).value.should == 'two'
|
85
100
|
end
|
86
101
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -51,18 +51,15 @@ RSpec.configure do |config|
|
|
51
51
|
end
|
52
52
|
|
53
53
|
config.before :each do
|
54
|
-
|
55
|
-
|
56
|
-
DatabaseCleaner.clean_with :truncation
|
57
|
-
else
|
58
|
-
DatabaseCleaner.strategy = :transaction
|
59
|
-
end
|
54
|
+
DatabaseCleaner.strategy = :transaction
|
55
|
+
DatabaseCleaner.clean_with :transaction
|
60
56
|
DatabaseCleaner.start
|
61
57
|
|
62
58
|
ActiveRecord::Base.establish_connection(database_config)
|
63
59
|
|
64
60
|
class PGCryptoTestModel < ActiveRecord::Base
|
65
61
|
self.table_name = :pgcrypto_test_models
|
62
|
+
pgcrypto :test_column
|
66
63
|
end
|
67
64
|
end
|
68
65
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pgcrypto
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-08-
|
12
|
+
date: 2012-08-14 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activerecord
|
@@ -34,7 +34,7 @@ dependencies:
|
|
34
34
|
requirements:
|
35
35
|
- - ! '>='
|
36
36
|
- !ruby/object:Gem::Version
|
37
|
-
version:
|
37
|
+
version: 0.2.0
|
38
38
|
type: :runtime
|
39
39
|
prerelease: false
|
40
40
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -42,7 +42,7 @@ dependencies:
|
|
42
42
|
requirements:
|
43
43
|
- - ! '>='
|
44
44
|
- !ruby/object:Gem::Version
|
45
|
-
version:
|
45
|
+
version: 0.2.0
|
46
46
|
- !ruby/object:Gem::Dependency
|
47
47
|
name: jeweler
|
48
48
|
requirement: !ruby/object:Gem::Requirement
|
@@ -71,7 +71,7 @@ extra_rdoc_files:
|
|
71
71
|
files:
|
72
72
|
- .rspec
|
73
73
|
- .simplecov
|
74
|
-
- CHANGES
|
74
|
+
- CHANGES.md
|
75
75
|
- Gemfile
|
76
76
|
- Guardfile
|
77
77
|
- LICENSE
|
@@ -108,7 +108,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
108
108
|
version: '0'
|
109
109
|
segments:
|
110
110
|
- 0
|
111
|
-
hash:
|
111
|
+
hash: -1773161376728593818
|
112
112
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
113
113
|
none: false
|
114
114
|
requirements:
|
data/CHANGES
DELETED
@@ -1,59 +0,0 @@
|
|
1
|
-
0.2.7
|
2
|
-
* So, about that library I arrogantly included? Turns out we
|
3
|
-
should require it in code before expecting anything of it.
|
4
|
-
|
5
|
-
0.2.6
|
6
|
-
* We now use the BigSpoon library to hook into reload, because
|
7
|
-
it's SO MUCH MORE AWESOME THAN THE GARBAGE MOST PEOPLE USE.
|
8
|
-
Welp. It's been nice coding with y'all.
|
9
|
-
|
10
|
-
0.2.5
|
11
|
-
* PGCrypto now hooks into ActiveRecord::Base#reload in order to
|
12
|
-
reset encrypted column values as expected when calling reload.
|
13
|
-
|
14
|
-
0.2.2
|
15
|
-
* Don't try to load columns on new records; should further reduce
|
16
|
-
unnecessary database calls!
|
17
|
-
|
18
|
-
0.2.1
|
19
|
-
* Added ActiveModel::Dirty support, so you can now call *_changed?
|
20
|
-
on your models tracking pgcrypto columns.
|
21
|
-
|
22
|
-
0.2.0
|
23
|
-
* Overhauled key system. Unfortunately, for performance reasons
|
24
|
-
and due to the insanely hacked nature of PGCrypto, multiple keys
|
25
|
-
are NO LONGER SUPPORTED. I'm working to bring them back, but
|
26
|
-
this was the only solution to get fully performant and functional
|
27
|
-
without any disasters.
|
28
|
-
|
29
|
-
0.1.2
|
30
|
-
* Added automatic installation of the pgcrypto extension if'n it
|
31
|
-
doesn't already exist. Helpful, but doesn't fully make the
|
32
|
-
`rake db:test:prepare` cut yet. Still working on that bit...
|
33
|
-
|
34
|
-
0.1.1
|
35
|
-
* Rebuilt the WHERE clause stuff to make sure finders AND setters
|
36
|
-
both worked. It's fragile and hackish at this time, but we'll get
|
37
|
-
there, folks!
|
38
|
-
|
39
|
-
0.1.0
|
40
|
-
* Overhauled the underpinnings to rely on a separate column. Adds
|
41
|
-
on-demand loading of encrypted attributes from a central table
|
42
|
-
which provides dramatic speed improvements when a record's
|
43
|
-
encrypted attributes aren't needed most of the time.
|
44
|
-
|
45
|
-
0.0.4
|
46
|
-
* Compatibility fix between ActiveRecord 3.2.1 and 3.2.2
|
47
|
-
|
48
|
-
0.0.3
|
49
|
-
* Fixed a join bug on SELECT statements
|
50
|
-
|
51
|
-
0.0.2
|
52
|
-
* Fixed a number of key-related bugs discovered in testing with our
|
53
|
-
second production app with encrypted columns. Also duck-typed AREL
|
54
|
-
statement types in a few places.
|
55
|
-
|
56
|
-
0.0.1
|
57
|
-
* INSERT, SELECT, and UPDATE statements are working. But I wrote this
|
58
|
-
while testing with a production app, and thus haven't written
|
59
|
-
specific tests, so don't get your panties in a twist.
|