mongoid-encrypted-fields 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -2,7 +2,9 @@
2
2
  *.rbc
3
3
  .bundle
4
4
  .config
5
+ .sw?
5
6
  .yardoc
7
+ .*.sw?
6
8
  Gemfile.lock
7
9
  InstalledFiles
8
10
  _yardoc
@@ -17,4 +19,4 @@ test/version_tmp
17
19
  tmp
18
20
 
19
21
  #Ignore IDEA directory
20
- /.idea
22
+ /.idea
data/CHANGLOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Revision history
2
2
 
3
+ ## 1.2 - Add EncryptedHash
4
+
5
+ * Accepted [pull request](https://github.com/KoanHealth/mongoid-encrypted-fields/pull/4) from ashirazi to add support for encrypted hashes
6
+
3
7
  ## 1.1 - Breaking changes - PLEASE READ
4
8
 
5
9
  ### encrypted-strings gem
data/README.md CHANGED
@@ -51,6 +51,12 @@ Queries encrypt data before searching the database, so equality matches work aut
51
51
 
52
52
  ## Known Limitations
53
53
  * Single cipher for all encrypted fields
54
+ * Currently can encrypt these [Mongoid types](http://mongoid.org/en/mongoid/docs/documents.html#fields)
55
+ * Date
56
+ * DateTime
57
+ * Hash
58
+ * String
59
+ * Time
54
60
 
55
61
  ## Copyright
56
62
  (c) 2012 Koan Health. See LICENSE.txt for further details.
data/Rakefile CHANGED
@@ -1 +1,8 @@
1
1
  require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new do |task|
5
+ task.rspec_opts = ["-c", "-f progress", "-r ./spec/spec_helper.rb"]
6
+ task.pattern = 'spec/**/*_spec.rb'
7
+ end
8
+
@@ -1,7 +1,7 @@
1
1
  require 'gibberish/aes'
2
2
 
3
- # Gibberish uses a unique salt for every encryption, but we need the same text to return the same ciphertext
4
- # so Searching for encrypted field will work
3
+ # Gibberish uses a unique salt for every encryption, but we need the same text
4
+ # to return the same ciphertext so Searching for encrypted field will work
5
5
  class GibberishCipher < Gibberish::AES
6
6
 
7
7
  SALT = "OU812FTW" # TODO: If you use this example class, make a unique 8-byte salt for your project
@@ -11,9 +11,9 @@ class GibberishCipher < Gibberish::AES
11
11
  @salt = options[:salt] || SALT
12
12
  end
13
13
 
14
- def generate_salt
14
+ def generate_salt(supplied_salt)
15
15
  return @salt if @salt
16
16
  super
17
17
  end
18
18
 
19
- end
19
+ end
@@ -1,6 +1,7 @@
1
1
  require 'mongoid-encrypted-fields/version'
2
2
  require 'mongoid-encrypted-fields/logging'
3
3
  require 'mongoid-encrypted-fields/fields/encrypted_field'
4
+ require 'mongoid-encrypted-fields/fields/encrypted_hash'
4
5
  require 'mongoid-encrypted-fields/fields/encrypted_string'
5
6
  require 'mongoid-encrypted-fields/fields/encrypted_date'
6
7
  require 'mongoid-encrypted-fields/fields/encrypted_date_time'
@@ -15,4 +16,4 @@ module Mongoid
15
16
  end
16
17
 
17
18
  end
18
- end
19
+ end
@@ -1,4 +1,5 @@
1
- require "base64"
1
+ require 'active_support/concern'
2
+ require 'base64'
2
3
 
3
4
  module Mongoid
4
5
  module EncryptedField
@@ -6,10 +7,10 @@ module Mongoid
6
7
 
7
8
  def encrypted
8
9
  if frozen?
9
- @encrypted ||= self.class.encrypt(to_s)
10
+ @encrypted ||= self.class.encrypt(raw_value)
10
11
  else
11
12
  # We are mutable - need to encrypt whenever asked
12
- self.class.encrypt(to_s)
13
+ self.class.encrypt(raw_value)
13
14
  end
14
15
  end
15
16
 
@@ -18,6 +19,11 @@ module Mongoid
18
19
  encrypted
19
20
  end
20
21
 
22
+ # Provide string to be encrypted and stored in Mongo DB
23
+ def raw_value
24
+ to_s
25
+ end
26
+
21
27
  module ClassMethods
22
28
 
23
29
  # Get the object as it was stored in the database, and instantiate this custom class from it.
@@ -72,4 +78,4 @@ module Mongoid
72
78
  end
73
79
 
74
80
  end
75
- end
81
+ end
@@ -0,0 +1,48 @@
1
+ # encoding: utf-8
2
+ #
3
+ # Used to store an encrypted hash in Mongo
4
+ #
5
+ # Usage:
6
+ # field :address, type: Mongoid::EncryptedHash
7
+ #
8
+ # Set with an unencrypted hash
9
+ # p = Person.new()
10
+ # p.address = {street: "123 Main St", city: "Springdale", state: "MD"}
11
+ #
12
+ # Get returns the unencrypted hash
13
+ # puts p.address -> {:street=>"123 Main St", :city=>"Springdale", :state=>"MD"}
14
+ #
15
+ # Use the encrypted property to see the encrypted value
16
+ # puts p.address.encrypted -> '....'
17
+ require 'yaml'
18
+
19
+ module Mongoid
20
+ class EncryptedHash < ::Hash
21
+ include Mongoid::EncryptedField
22
+
23
+ # Return value to be encrypted
24
+ def raw_value
25
+ to_yaml
26
+ end
27
+
28
+ class << self
29
+
30
+ # converts from a plain Hash to an EncryptedHash
31
+ def from_hash(h)
32
+ self[h.to_hash]
33
+ end
34
+
35
+ # Takes an object representation (Hash or string) and converts it to an
36
+ # EncryptedHash.
37
+ def convert(object)
38
+ case object
39
+ when Hash
40
+ from_hash(object)
41
+ else
42
+ from_hash(::YAML.load(object))
43
+ end
44
+ end
45
+
46
+ end
47
+ end
48
+ end
@@ -1,3 +1,5 @@
1
+ require 'logger'
2
+
1
3
  module Mongoid
2
4
  module EncryptedFields
3
5
  # Contains behavior for logging.
@@ -1,5 +1,5 @@
1
1
  module Mongoid
2
2
  module EncryptedFields
3
- VERSION = "1.1.0"
3
+ VERSION = '1.2.0'
4
4
  end
5
5
  end
@@ -17,10 +17,10 @@ Gem::Specification.new do |gem|
17
17
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
18
  gem.require_paths = ["lib"]
19
19
 
20
- gem.add_dependency "rake"
21
20
  gem.add_dependency "mongoid", "~> 3"
22
21
 
22
+ gem.add_development_dependency "rake"
23
23
  gem.add_development_dependency "rspec"
24
- gem.add_development_dependency "gibberish", "~> 1.2"
24
+ gem.add_development_dependency "gibberish", "~> 1.2.2"
25
25
  gem.add_development_dependency "encrypted_strings", "~> 0.3"
26
26
  end
@@ -0,0 +1,69 @@
1
+ require 'spec_helper'
2
+
3
+ module Mongoid
4
+ describe EncryptedHash do
5
+
6
+ before(:all) do
7
+ Mongoid::EncryptedFields.cipher = GibberishCipher.new('my test password')
8
+ end
9
+
10
+ subject { Mongoid::EncryptedHash }
11
+ let(:raw) { {street: "123 Main St", city: "Springdale", state: "MD"} }
12
+ let(:encrypted) { Mongoid::EncryptedHash.mongoize({street: "123 Main St", city: "Springdale", state: "MD"}) }
13
+
14
+ it "returns the same hash" do
15
+ subject.from_hash(raw).should eq(raw)
16
+ end
17
+
18
+ it "should encrypt the hash" do
19
+ subject.from_hash(raw).encrypted.should eq(encrypted)
20
+ end
21
+
22
+ it "nil should fail" do
23
+ -> { subject.from_hash(nil) }.should raise_error()
24
+ end
25
+
26
+ describe "demongoize" do
27
+
28
+ it "nil should return nil" do
29
+ subject.demongoize(nil).should be_nil
30
+ end
31
+
32
+ it "blank string should return blank string" do
33
+ subject.demongoize('').should eq('')
34
+ end
35
+
36
+ it "invalid hash should fail" do
37
+ -> { subject.demongoize('not a hash') }.should raise_error
38
+ end
39
+
40
+ it "encrypted hash should return unencrypted hash" do
41
+ decrypted = subject.demongoize(encrypted)
42
+ decrypted.is_a?(subject).should be_true
43
+ decrypted.should eq(raw)
44
+ end
45
+
46
+ end
47
+
48
+ describe "mongoize" do
49
+
50
+ it "encrypted hash should return encrypted" do
51
+ subject.mongoize(subject.from_hash(raw)).should eq(encrypted)
52
+ end
53
+
54
+ it "encrypted hash should return itself" do
55
+ subject.mongoize(encrypted).should eq(encrypted)
56
+ end
57
+
58
+ it "nil should return nil" do
59
+ subject.mongoize(nil).should eq(nil)
60
+ end
61
+
62
+ it "valid hash should return encrypted" do
63
+ subject.mongoize(raw).should eq(encrypted)
64
+ end
65
+
66
+ end
67
+
68
+ end
69
+ end
@@ -10,7 +10,9 @@ describe 'Single model' do
10
10
  let (:ssn_encrypted) { Mongoid::EncryptedString.mongoize(ssn) }
11
11
  let (:birth_date) { 20.years.ago.to_date }
12
12
  let (:birth_date_encrypted) { Mongoid::EncryptedDate.mongoize(birth_date) }
13
- let (:person) { Person.new(name: 'John Doe', ssn: ssn, birth_date: birth_date) }
13
+ let (:address) { {street: '123 Main St', city: 'Anytown', state: 'TX' } }
14
+ let (:address_encrypted) { Mongoid::EncryptedHash.mongoize(address) }
15
+ let (:person) { Person.new(name: 'John Doe', ssn: ssn, birth_date: birth_date, address: address) }
14
16
 
15
17
  it "model stores encrypted ssn" do
16
18
  person.attributes['ssn'].should eq(ssn_encrypted)
@@ -20,6 +22,10 @@ describe 'Single model' do
20
22
  person.attributes['birth_date'].should eq(birth_date_encrypted)
21
23
  end
22
24
 
25
+ it "model stores encrypted address" do
26
+ person.attributes['address'].should eq(address_encrypted)
27
+ end
28
+
23
29
  it "ssn getter returns raw value" do
24
30
  person.ssn.should eq(ssn)
25
31
  end
@@ -28,6 +34,10 @@ describe 'Single model' do
28
34
  person.birth_date.should eq(birth_date)
29
35
  end
30
36
 
37
+ it "address getter returns raw value" do
38
+ person.address.should eq(address)
39
+ end
40
+
31
41
  describe "after save" do
32
42
 
33
43
  before(:each) do
@@ -44,6 +54,10 @@ describe 'Single model' do
44
54
  @persisted.attributes['birth_date'].should eq(birth_date_encrypted)
45
55
  end
46
56
 
57
+ it "encrypted address is persisted" do
58
+ @persisted.attributes['address'].should eq(address_encrypted)
59
+ end
60
+
47
61
  it "encrypted ssn getter returns raw value" do
48
62
  @persisted.ssn.should eq(ssn)
49
63
  end
@@ -52,6 +66,10 @@ describe 'Single model' do
52
66
  @persisted.birth_date.should eq(birth_date)
53
67
  end
54
68
 
69
+ it "encrypted address getter returns raw value" do
70
+ @persisted.address.should eq(address)
71
+ end
72
+
55
73
  end
56
74
 
57
75
  describe "find model by encrypted field" do
@@ -4,5 +4,6 @@ class Person
4
4
  field :name, type: String
5
5
  field :ssn, type: Mongoid::EncryptedString
6
6
  field :birth_date, type: Mongoid::EncryptedDate
7
+ field :address, type: Mongoid::EncryptedHash
7
8
 
8
9
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongoid-encrypted-fields
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,40 +9,40 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-02-03 00:00:00.000000000 Z
12
+ date: 2013-03-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
- name: rake
15
+ name: mongoid
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
- - - ! '>='
19
+ - - ~>
20
20
  - !ruby/object:Gem::Version
21
- version: '0'
21
+ version: '3'
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
25
  none: false
26
26
  requirements:
27
- - - ! '>='
27
+ - - ~>
28
28
  - !ruby/object:Gem::Version
29
- version: '0'
29
+ version: '3'
30
30
  - !ruby/object:Gem::Dependency
31
- name: mongoid
31
+ name: rake
32
32
  requirement: !ruby/object:Gem::Requirement
33
33
  none: false
34
34
  requirements:
35
- - - ~>
35
+ - - ! '>='
36
36
  - !ruby/object:Gem::Version
37
- version: '3'
38
- type: :runtime
37
+ version: '0'
38
+ type: :development
39
39
  prerelease: false
40
40
  version_requirements: !ruby/object:Gem::Requirement
41
41
  none: false
42
42
  requirements:
43
- - - ~>
43
+ - - ! '>='
44
44
  - !ruby/object:Gem::Version
45
- version: '3'
45
+ version: '0'
46
46
  - !ruby/object:Gem::Dependency
47
47
  name: rspec
48
48
  requirement: !ruby/object:Gem::Requirement
@@ -66,7 +66,7 @@ dependencies:
66
66
  requirements:
67
67
  - - ~>
68
68
  - !ruby/object:Gem::Version
69
- version: '1.2'
69
+ version: 1.2.2
70
70
  type: :development
71
71
  prerelease: false
72
72
  version_requirements: !ruby/object:Gem::Requirement
@@ -74,7 +74,7 @@ dependencies:
74
74
  requirements:
75
75
  - - ~>
76
76
  - !ruby/object:Gem::Version
77
- version: '1.2'
77
+ version: 1.2.2
78
78
  - !ruby/object:Gem::Dependency
79
79
  name: encrypted_strings
80
80
  requirement: !ruby/object:Gem::Requirement
@@ -113,6 +113,7 @@ files:
113
113
  - lib/mongoid-encrypted-fields/fields/encrypted_date.rb
114
114
  - lib/mongoid-encrypted-fields/fields/encrypted_date_time.rb
115
115
  - lib/mongoid-encrypted-fields/fields/encrypted_field.rb
116
+ - lib/mongoid-encrypted-fields/fields/encrypted_hash.rb
116
117
  - lib/mongoid-encrypted-fields/fields/encrypted_string.rb
117
118
  - lib/mongoid-encrypted-fields/fields/encrypted_time.rb
118
119
  - lib/mongoid-encrypted-fields/logging.rb
@@ -122,6 +123,7 @@ files:
122
123
  - spec/mongoid-encrypted-fields/fields/encrypted_date_spec.rb
123
124
  - spec/mongoid-encrypted-fields/fields/encrypted_datetime_spec.rb
124
125
  - spec/mongoid-encrypted-fields/fields/encrypted_field_spec.rb
126
+ - spec/mongoid-encrypted-fields/fields/encrypted_hash_spec.rb
125
127
  - spec/mongoid-encrypted-fields/fields/encrypted_string_spec.rb
126
128
  - spec/mongoid-encrypted-fields/fields/encrypted_time_spec.rb
127
129
  - spec/mongoid-encrypted-fields/fields/model_spec.rb
@@ -141,7 +143,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
141
143
  version: '0'
142
144
  segments:
143
145
  - 0
144
- hash: -323082810856718661
146
+ hash: -3259061833501052041
145
147
  required_rubygems_version: !ruby/object:Gem::Requirement
146
148
  none: false
147
149
  requirements:
@@ -150,7 +152,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
150
152
  version: '0'
151
153
  segments:
152
154
  - 0
153
- hash: -323082810856718661
155
+ hash: -3259061833501052041
154
156
  requirements: []
155
157
  rubyforge_project:
156
158
  rubygems_version: 1.8.25
@@ -162,6 +164,7 @@ test_files:
162
164
  - spec/mongoid-encrypted-fields/fields/encrypted_date_spec.rb
163
165
  - spec/mongoid-encrypted-fields/fields/encrypted_datetime_spec.rb
164
166
  - spec/mongoid-encrypted-fields/fields/encrypted_field_spec.rb
167
+ - spec/mongoid-encrypted-fields/fields/encrypted_hash_spec.rb
165
168
  - spec/mongoid-encrypted-fields/fields/encrypted_string_spec.rb
166
169
  - spec/mongoid-encrypted-fields/fields/encrypted_time_spec.rb
167
170
  - spec/mongoid-encrypted-fields/fields/model_spec.rb