witness_protection 0.0.1.pre1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5fce464db4f5fed515a73dece789dbc055e83ed1
4
+ data.tar.gz: 78034cd87308c75b8003063b2ca038b9828cfaf2
5
+ SHA512:
6
+ metadata.gz: 2c8e541f429b7cd653a4b36b65f59768e7602f2bc2b6e09679c07ffa7f4da42649332f138f5d0099cc3ea90c393791fce801b0ff99103905bdf3af5b765787fa
7
+ data.tar.gz: 4f497fc5072bde55ba6d47d1dee4c7bcd9161f12170d2600fde7029ab0c1374d6693b78725b93b4a92d4ff28d3719fa95a934cab3fd44fbe0388c2be5de1ef11
data/.gitignore ADDED
@@ -0,0 +1,23 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /test/tmp/
9
+ /test/version_tmp/
10
+ /tmp/
11
+ .dat*
12
+ .repl_history
13
+ build/
14
+ /.yardoc/
15
+ /_yardoc/
16
+ /doc/
17
+ /rdoc/
18
+ /.bundle/
19
+ /lib/bundler/man/
20
+ Gemfile.lock
21
+ .ruby-version
22
+ .ruby-gemset
23
+ .rvmrc
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --warnings
3
+ --require helper
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in witness_protection.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Philip Vieira
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,124 @@
1
+ # Witness Protection
2
+ Rails library that lets you have an encrypted identities for your active record models.
3
+
4
+ ## Setup
5
+
6
+ Add an an encryption salt through your `secrets.yml` or `application.yml` if you're using Figaro.
7
+ As long as you get the encryption salt in to your environment you'll be fine.
8
+
9
+ ```yaml
10
+ development:
11
+ encryption_salt: "$2a$10$pKIdnO.R6xIrnIr5T6k8GO"
12
+ ```
13
+
14
+ You can generate an encryption salt using the bcrypt engine.
15
+
16
+ ```
17
+ require "bcrypt"
18
+ BCrypt::Engine.generate_salt
19
+ # => "$2a$10$pKIdnO.R6xIrnIr5T6k8GO"
20
+ ```
21
+
22
+ Create a model with an attribute you'd like to have encrypted.
23
+
24
+ ```bash
25
+ $ rails generate model Person name:string
26
+ ```
27
+
28
+ Include witness protection in your model and use the protected_identity macro to enable encryption.
29
+
30
+ ```ruby
31
+ require "witness_protection"
32
+
33
+ class Person < ActiveRecord::Base
34
+
35
+ include WitnessProtection
36
+
37
+ protected_identity :name
38
+
39
+ end
40
+ ```
41
+
42
+ ```ruby
43
+ Person.create name: "Philip"
44
+ # => <Person id: 1, name: "$2a$10$8RdONCVhuLKmt0Fu5IxAo.vApyi0LISUJ6XxMNQjwJV...">
45
+
46
+ Person.identify_by_name "Philip"
47
+ # => <Person id: 1, name: "$2a$10$8RdONCVhuLKmt0Fu5IxAo.vApyi0LISUJ6XxMNQjwJV...">
48
+ ```
49
+
50
+ ## Generated values
51
+ You are also able to generate values for the protected identity field. This is useful for things like auth tokens.
52
+
53
+ ```ruby
54
+ class User < ActiveRecord::Base
55
+
56
+ include WitnessProtection
57
+
58
+ protected_identity :auth_token
59
+
60
+ end
61
+ ```
62
+
63
+ ```ruby
64
+ user = User.create
65
+ # => <User id: nil, auth_token: nil>
66
+
67
+ token = user.generate_auth_token { SecureRandom.hex }
68
+ # => cb17f6573c5cb9bc86e90b66d1a441ef
69
+
70
+ user
71
+ # => <User id: nil, auth_token: "$2a$10$8RdONCVhuLKmt0Fu5IxAo.GlU.PXWR4nOeLfv2THxhC...">
72
+
73
+ user.save
74
+ # => true
75
+
76
+ User.identify_by_auth_token(token)
77
+ # => <User id: 1, auth_token: "$2a$10$8RdONCVhuLKmt0Fu5IxAo.GlU.PXWR4nOeLfv2THxhC...">
78
+ ```
79
+
80
+ ## Installation
81
+ Add this line to your application's Gemfile:
82
+
83
+ ```ruby
84
+ gem "witness_protection"
85
+ ```
86
+
87
+ And then execute:
88
+
89
+ ```bash
90
+ $ bundle
91
+ ```
92
+
93
+ Or install it yourself as:
94
+
95
+ ```
96
+ $ gem install witness_protection
97
+ ```
98
+
99
+
100
+ ## Lisence
101
+
102
+ Copyright (c) 2014 Philip Vieira
103
+
104
+ MIT License
105
+
106
+ Permission is hereby granted, free of charge, to any person obtaining
107
+ a copy of this software and associated documentation files (the
108
+ "Software"), to deal in the Software without restriction, including
109
+ without limitation the rights to use, copy, modify, merge, publish,
110
+ distribute, sublicense, and/or sell copies of the Software, and to
111
+ permit persons to whom the Software is furnished to do so, subject to
112
+ the following conditions:
113
+
114
+ The above copyright notice and this permission notice shall be
115
+ included in all copies or substantial portions of the Software.
116
+
117
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
118
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
119
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
120
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
121
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
122
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
123
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
124
+
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,79 @@
1
+ module WitnessProtection
2
+ module RSpec
3
+ module Macros
4
+
5
+ def it_has_been_witness_protected(field, *args, &blk)
6
+
7
+ it { should respond_to("encrypt_#{field}") }
8
+
9
+ context "ClassMethods" do
10
+
11
+ it { expect(described_class).to respond_to("identify_by_#{field}") }
12
+ let(:expected_token) { "super-seCret_url-token" }
13
+
14
+ before(:each) do
15
+ allow(subject).to receive(:__generate_secure_token__).with(field).and_return(expected_token)
16
+ subject.send("encrypt_#{field}")
17
+ subject.save!
18
+ end
19
+
20
+ identify_by_method = "identify_by_#{field}"
21
+ describe ".#{identify_by_method}" do
22
+
23
+ it "returns the record for the corresponding secure token" do
24
+ expect( described_class.send(identify_by_method, expected_token) ).to eq subject
25
+ end
26
+
27
+ context "no records match the secure token" do
28
+
29
+ it "should return nil" do
30
+ described_class.send(identify_by_method, "bad token").should be_nil
31
+ end
32
+
33
+ end
34
+
35
+ end
36
+
37
+ identify_by_bang_method = "identify_by_#{field}!"
38
+ describe ".#{identify_by_bang_method}" do
39
+
40
+ it "returns the record for the corresponding secure token" do
41
+ expect( described_class.send(identify_by_bang_method, expected_token) ).to eq subject
42
+ end
43
+
44
+ context "no records match the secure token" do
45
+
46
+ it "raise active record error" do
47
+ expect { described_class.send(identify_by_bang_method, "bad token") }.to raise_error ActiveRecord::RecordNotFound
48
+ end
49
+
50
+ end
51
+
52
+ end
53
+
54
+ end
55
+
56
+ encrypt_token_method = "encrypt_#{field}"
57
+ describe "##{encrypt_token_method}" do
58
+
59
+ let(:expected_token) { "super-seCret_url-token" }
60
+
61
+ before(:each) { allow(subject).to receive(:__generate_secure_token__).and_return(expected_token) }
62
+
63
+ it "assigns a valid BCrypt hash to password reset token field" do
64
+ expected_value = BCrypt::Engine.hash_secret(expected_token, Figaro.env.encryption_salt!)
65
+ expect(subject).to receive("#{field}=").with(expected_value)
66
+ subject.send(encrypt_token_method)
67
+ end
68
+
69
+ it "returns the token key" do
70
+ expect( subject.send(encrypt_token_method) ).to eq expected_token
71
+ end
72
+
73
+ end
74
+
75
+ end
76
+
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,3 @@
1
+ module WitnessProtection
2
+ VERSION = "0.0.1.pre1"
3
+ end
@@ -0,0 +1,82 @@
1
+ require "active_support/concern"
2
+ require "witness_protection/version"
3
+
4
+ module WitnessProtection
5
+
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ require "bcrypt"
10
+
11
+ class << self
12
+
13
+ def protected_identity(identity_column, *args)
14
+
15
+ define_method "#{identity_column}=" do |value|
16
+ super self.class.__encrypt_protected_token__(value)
17
+ end
18
+
19
+ define_method "encrypt_#{identity_column}" do |&blk|
20
+ self.__encrypt_protected_token__(identity_column, &blk)
21
+ end
22
+
23
+ define_singleton_method "identify_by_#{identity_column}" do |token|
24
+ self.__identify_by_protected_token__(identity_column, token)
25
+ end
26
+
27
+ define_singleton_method "identify_by_#{identity_column}!" do |token|
28
+ self.__identify_by_protected_token__!(identity_column, token)
29
+ end
30
+
31
+ end
32
+
33
+ def __identify_by_protected_token__(column, token)
34
+ send("find_by_#{column}", __encrypt_protected_token__(token))
35
+ end
36
+
37
+ def __identify_by_protected_token__!(column, token)
38
+ record = __identify_by_protected_token__(column, token)
39
+ raise ActiveRecord::RecordNotFound unless record
40
+ return record
41
+ end
42
+
43
+ def __encryption_salt__
44
+ unless salt = ENV["ENCRYPTION_SALT"]
45
+ fail "Can't find `ENCRYPTION_SALT' in environment."
46
+ end
47
+ return salt
48
+ end
49
+
50
+ def __encrypt_protected_token__(token)
51
+ BCrypt::Engine.hash_secret(token, __encryption_salt__)
52
+ end
53
+
54
+ end
55
+
56
+ end
57
+
58
+ def __generate_protected_token__(identity_column, &generator)
59
+ raise ArgumentError unless identity_column
60
+ return instance_eval(&generator) if block_given?
61
+
62
+ generation_method = "generate_#{identity_column}"
63
+ return send(generation_method) if respond_to?(generation_method)
64
+ return SecureRandom.urlsafe_base64
65
+ end
66
+
67
+
68
+ def __encrypt_protected_token__(identity_column, &generator)
69
+ raise ArgumentError unless identity_column
70
+
71
+ token = nil
72
+
73
+ self[identity_column] = loop do
74
+ token = __generate_protected_token__(identity_column, &generator)
75
+ hash = self.class.__encrypt_protected_token__(token)
76
+ break hash unless self.class.exists? identity_column => hash
77
+ end
78
+
79
+ return token
80
+ end
81
+
82
+ end
data/spec/helper.rb ADDED
@@ -0,0 +1,30 @@
1
+ require "witness_protection"
2
+ require "active_record"
3
+
4
+ ActiveRecord::Base.establish_connection adapter: "sqlite3", database: ":memory:"
5
+ load File.dirname(__FILE__) + '/schema.rb'
6
+ require File.dirname(__FILE__) + '/models.rb'
7
+
8
+ RSpec.configure do |config|
9
+
10
+ config.filter_run :focus
11
+ config.run_all_when_everything_filtered = true
12
+
13
+ if config.files_to_run.one?
14
+ config.default_formatter = "doc"
15
+ end
16
+
17
+ config.profile_examples = false
18
+ config.order = :random
19
+ Kernel.srand config.seed
20
+
21
+ config.expect_with :rspec do |expectations|
22
+ expectations.syntax = :expect
23
+ end
24
+
25
+ config.mock_with :rspec do |mocks|
26
+ mocks.syntax = :expect
27
+ mocks.verify_partial_doubles = true
28
+ end
29
+
30
+ end
data/spec/models.rb ADDED
@@ -0,0 +1,16 @@
1
+ class Person < ActiveRecord::Base
2
+
3
+ include WitnessProtection
4
+
5
+ protected_identity :name
6
+
7
+ end
8
+
9
+
10
+ class Access < ActiveRecord::Base
11
+
12
+ include WitnessProtection
13
+
14
+ protected_identity :token
15
+
16
+ end
data/spec/schema.rb ADDED
@@ -0,0 +1,13 @@
1
+ ActiveRecord::Schema.define do
2
+
3
+ self.verbose = false
4
+
5
+ create_table :people, :force => true do |t|
6
+ t.string :name
7
+ end
8
+
9
+ create_table :accesses, :force => true do |t|
10
+ t.string :token
11
+ end
12
+
13
+ end
@@ -0,0 +1,32 @@
1
+ def encryption_salt
2
+ ENV["ENCRYPTION_SALT"] ||= BCrypt::Engine.generate_salt
3
+ end; encryption_salt
4
+
5
+ describe WitnessProtection do
6
+
7
+ describe Person do
8
+
9
+ subject!(:person) { described_class.create name: "Alexander" }
10
+
11
+ it "encrypts & identifies by the name" do
12
+ expect(described_class.identify_by_name("Alexander")).to eq person
13
+ end
14
+
15
+ end
16
+
17
+ describe Access do
18
+
19
+ subject!(:access) { described_class.new }
20
+
21
+ before(:each) do
22
+ access.encrypt_token { "foobar1234" }
23
+ access.save
24
+ end
25
+
26
+ it "encrypts & identifies by a token generated from a proc" do
27
+ expect(described_class.identify_by_token("foobar1234")).to eq access
28
+ end
29
+
30
+ end
31
+
32
+ end
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'witness_protection/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+
8
+ spec.name = "witness_protection"
9
+ spec.version = WitnessProtection::VERSION
10
+ spec.authors = ["Philip Vieira"]
11
+ spec.email = ["philip@vallin.se"]
12
+ spec.summary = "Rails library that lets you have an encrypted identities for your active record models."
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "bcrypt"
22
+ spec.add_dependency "activerecord", "~> 4.0"
23
+ spec.add_dependency "activesupport", "~> 4.0"
24
+
25
+ spec.add_development_dependency "bundler", "~> 1.6"
26
+ spec.add_development_dependency "rake", "~> 10.0"
27
+ spec.add_development_dependency "rspec", "~> 3.0"
28
+ spec.add_development_dependency "sqlite3", "~> 1.3"
29
+
30
+ end
metadata ADDED
@@ -0,0 +1,161 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: witness_protection
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1.pre1
5
+ platform: ruby
6
+ authors:
7
+ - Philip Vieira
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-09-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bcrypt
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activerecord
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '4.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '4.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: activesupport
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '4.0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '4.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.6'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.6'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '10.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '10.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '3.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '3.0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: sqlite3
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '1.3'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '1.3'
111
+ description:
112
+ email:
113
+ - philip@vallin.se
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - ".gitignore"
119
+ - ".rspec"
120
+ - Gemfile
121
+ - LICENSE.txt
122
+ - README.md
123
+ - Rakefile
124
+ - lib/witness_protection.rb
125
+ - lib/witness_protection/rspec/macros.rb
126
+ - lib/witness_protection/version.rb
127
+ - spec/helper.rb
128
+ - spec/models.rb
129
+ - spec/schema.rb
130
+ - spec/witness_protection_spec.rb
131
+ - witness_protection.gemspec
132
+ homepage: ''
133
+ licenses:
134
+ - MIT
135
+ metadata: {}
136
+ post_install_message:
137
+ rdoc_options: []
138
+ require_paths:
139
+ - lib
140
+ required_ruby_version: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ required_rubygems_version: !ruby/object:Gem::Requirement
146
+ requirements:
147
+ - - ">"
148
+ - !ruby/object:Gem::Version
149
+ version: 1.3.1
150
+ requirements: []
151
+ rubyforge_project:
152
+ rubygems_version: 2.2.2
153
+ signing_key:
154
+ specification_version: 4
155
+ summary: Rails library that lets you have an encrypted identities for your active
156
+ record models.
157
+ test_files:
158
+ - spec/helper.rb
159
+ - spec/models.rb
160
+ - spec/schema.rb
161
+ - spec/witness_protection_spec.rb