mongoid-encrypted-fields 1.1.0 → 1.2.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.
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