encrypted_attributes 0.0.1
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/MIT-LICENSE +20 -0
- data/README +116 -0
- data/Rakefile +80 -0
- data/init.rb +1 -0
- data/lib/encrypted_attributes/extensions/encryptor.rb +14 -0
- data/lib/encrypted_attributes/extensions/sha_encryptor.rb +28 -0
- data/lib/encrypted_attributes.rb +73 -0
- data/test/app_root/app/models/asymmetric_user.rb +3 -0
- data/test/app_root/app/models/confirmed_sha_user.rb +13 -0
- data/test/app_root/app/models/sha_user.rb +3 -0
- data/test/app_root/app/models/sha_user_with_custom_crypted_attr.rb +3 -0
- data/test/app_root/app/models/sha_user_with_custom_salt.rb +7 -0
- data/test/app_root/app/models/sha_user_with_salt.rb +7 -0
- data/test/app_root/app/models/symmetric_user.rb +3 -0
- data/test/app_root/app/models/user.rb +3 -0
- data/test/app_root/db/migrate/001_create_users.rb +16 -0
- data/test/app_root/test/fixtures/users.yml +8 -0
- data/test/keys/private +9 -0
- data/test/keys/public +4 -0
- data/test/test_helper.rb +10 -0
- data/test/unit/encrypted_attributes_test.rb +130 -0
- data/test/unit/encryptor_test.rb +13 -0
- data/test/unit/sha_encryptor_test.rb +64 -0
- metadata +89 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2006-2007 Aaron Pfeifer & Neil Abraham
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
= encrypted_attributes
|
2
|
+
|
3
|
+
encrypted_attributes adds support for automatically encrypting ActiveRecord
|
4
|
+
attributes.
|
5
|
+
|
6
|
+
== Resources
|
7
|
+
|
8
|
+
API
|
9
|
+
|
10
|
+
* http://api.pluginaweek.org/encrypted_attributes
|
11
|
+
|
12
|
+
Wiki
|
13
|
+
|
14
|
+
* http://wiki.pluginaweek.org/Encrypted_attributes
|
15
|
+
|
16
|
+
Announcement
|
17
|
+
|
18
|
+
* http://www.pluginaweek.org/
|
19
|
+
|
20
|
+
Source
|
21
|
+
|
22
|
+
* http://svn.pluginaweek.org/trunk/plugins/active_record/miscellaneous/encrypted_attributes
|
23
|
+
|
24
|
+
Development
|
25
|
+
|
26
|
+
* http://dev.pluginaweek.org/browser/trunk/plugins/active_record/miscellaneous/encrypted_attributes
|
27
|
+
|
28
|
+
== Description
|
29
|
+
|
30
|
+
Encrypting attributes can be repetitive especially when doing so throughout
|
31
|
+
various models and various projects. encrypted_attributes, in association
|
32
|
+
with the encrypted_strings plugin, helps make encrypting ActiveRecord
|
33
|
+
attributes easier by automating the process.
|
34
|
+
|
35
|
+
The options that #encrypts takes includes all of the encryption options for
|
36
|
+
the specific type of encryptor being used in the encrypted_strings plugin.
|
37
|
+
Therefore, if setting the key for asymmetric encryption, this would be passed
|
38
|
+
into the #encrypts method. Examples of this are shown below.
|
39
|
+
|
40
|
+
=== SHA Encryption
|
41
|
+
|
42
|
+
For SHA encryption, you can either use the default salt, a custom salt, or
|
43
|
+
generate one based on the attributes of the model. If the latter option is
|
44
|
+
being used, a column in the table should be created to store the salt that is
|
45
|
+
generated.
|
46
|
+
|
47
|
+
With the default salt:
|
48
|
+
class User < ActiveRecord::Base
|
49
|
+
encrypts :password
|
50
|
+
end
|
51
|
+
|
52
|
+
With a custom salt:
|
53
|
+
class User < ActiveRecord::Base
|
54
|
+
encrypts :password, :salt => true
|
55
|
+
|
56
|
+
def create_salt
|
57
|
+
"#{login}_salt"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
=== Symmetric Encryption
|
62
|
+
|
63
|
+
With the default key:
|
64
|
+
class User < ActiveRecord::Base
|
65
|
+
encrypts :password, :mode => :symmetric
|
66
|
+
end
|
67
|
+
|
68
|
+
With a custom key:
|
69
|
+
class User < ActiveRecord::Base
|
70
|
+
encrypts :password, :mode => :symmetric, :key => 'custom'
|
71
|
+
end
|
72
|
+
|
73
|
+
=== Asymmetric Encryption
|
74
|
+
|
75
|
+
With default key files:
|
76
|
+
class User < ActiveRecord::Base
|
77
|
+
encrypts :password, :mode => :asymmetric
|
78
|
+
end
|
79
|
+
|
80
|
+
With custom key files:
|
81
|
+
class User < ActiveRecord::Base
|
82
|
+
encrypts :password, :mode => :asymmetric, :public_key_file => '/keys/public', :private_key_file => '/keys/private'
|
83
|
+
end
|
84
|
+
|
85
|
+
=== The crypted attribute
|
86
|
+
|
87
|
+
The attribute which stores the unencrypted value is a "virtual" attribute.
|
88
|
+
This means that there is no column with the same name in the database.
|
89
|
+
Instead, the encrypted value is stored in the crypted attributed. By default,
|
90
|
+
this is assumed to be "crypted_#{attr_name}". Therefore, if you are encrypting
|
91
|
+
the "password" attribute, the encrypted value would be stored in
|
92
|
+
"crypted_password".
|
93
|
+
|
94
|
+
The crypted attribute name can be customized like so:
|
95
|
+
|
96
|
+
class User < ActiveRecord::Base
|
97
|
+
encrypts :password, :crypted_name => 'protected_password'
|
98
|
+
end
|
99
|
+
|
100
|
+
=== Additional information
|
101
|
+
|
102
|
+
For more examples of actual migrations and models that encrypt attributes,
|
103
|
+
see the unit tests. Also, see encrypted_strings for more information about
|
104
|
+
the various options that can be passed in.
|
105
|
+
|
106
|
+
== Testing
|
107
|
+
|
108
|
+
This plugin requires that the plugin_test_helper gem be installed in order to
|
109
|
+
run the unit tests. To install this gem:
|
110
|
+
|
111
|
+
gem install plugin_test_helper
|
112
|
+
|
113
|
+
== Dependencies
|
114
|
+
|
115
|
+
This plugin depends on the presence of the following plugins:
|
116
|
+
# encrypted_strings - http://wiki.pluginaweek.org/Encrypted_strings
|
data/Rakefile
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'rake/testtask'
|
2
|
+
require 'rake/rdoctask'
|
3
|
+
require 'rake/gempackagetask'
|
4
|
+
require 'rake/contrib/sshpublisher'
|
5
|
+
|
6
|
+
PKG_NAME = 'encrypted_attributes'
|
7
|
+
PKG_VERSION = '0.0.1'
|
8
|
+
PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
|
9
|
+
RUBY_FORGE_PROJECT = 'pluginaweek'
|
10
|
+
|
11
|
+
desc 'Default: run unit tests.'
|
12
|
+
task :default => :test
|
13
|
+
|
14
|
+
desc 'Test the encrypted_attributes plugin.'
|
15
|
+
Rake::TestTask.new(:test) do |t|
|
16
|
+
t.libs << 'lib'
|
17
|
+
t.pattern = 'test/**/*_test.rb'
|
18
|
+
t.verbose = true
|
19
|
+
end
|
20
|
+
|
21
|
+
desc 'Generate documentation for the encrypted_attributes plugin.'
|
22
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
23
|
+
rdoc.rdoc_dir = 'rdoc'
|
24
|
+
rdoc.title = 'EncryptedAttributes'
|
25
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
26
|
+
rdoc.rdoc_files.include('README')
|
27
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
28
|
+
end
|
29
|
+
|
30
|
+
spec = Gem::Specification.new do |s|
|
31
|
+
s.name = PKG_NAME
|
32
|
+
s.version = PKG_VERSION
|
33
|
+
s.platform = Gem::Platform::RUBY
|
34
|
+
s.summary = ''
|
35
|
+
|
36
|
+
s.files = FileList['{lib,tasks,test}/**/*'].to_a + %w(init.rb MIT-LICENSE Rakefile README)
|
37
|
+
s.require_path = 'lib'
|
38
|
+
s.autorequire = 'encrypted_attributes'
|
39
|
+
s.has_rdoc = true
|
40
|
+
s.add_dependency 'encrypted_strings', '>= 0.0.1'
|
41
|
+
s.test_files = Dir['test/**/*_test.rb']
|
42
|
+
|
43
|
+
s.author = 'Aaron Pfeifer, Neil Abraham'
|
44
|
+
s.email = 'info@pluginaweek.org'
|
45
|
+
s.homepage = 'http://www.pluginaweek.org'
|
46
|
+
end
|
47
|
+
|
48
|
+
Rake::GemPackageTask.new(spec) do |p|
|
49
|
+
p.gem_spec = spec
|
50
|
+
p.need_tar = true
|
51
|
+
p.need_zip = true
|
52
|
+
end
|
53
|
+
|
54
|
+
desc 'Publish the beta gem'
|
55
|
+
task :pgem => [:package] do
|
56
|
+
Rake::SshFilePublisher.new('pluginaweek@pluginaweek.org', '/home/pluginaweek/gems.pluginaweek.org/gems', 'pkg', "#{PKG_FILE_NAME}.gem").upload
|
57
|
+
end
|
58
|
+
|
59
|
+
desc 'Publish the API documentation'
|
60
|
+
task :pdoc => [:rdoc] do
|
61
|
+
Rake::SshDirPublisher.new('pluginaweek@pluginaweek.org', "/home/pluginaweek/api.pluginaweek.org/#{PKG_NAME}", 'rdoc').upload
|
62
|
+
end
|
63
|
+
|
64
|
+
desc 'Publish the API docs and gem'
|
65
|
+
task :publish => [:pdoc, :release]
|
66
|
+
|
67
|
+
desc 'Publish the release files to RubyForge.'
|
68
|
+
task :release => [:gem, :package] do
|
69
|
+
require 'rubyforge'
|
70
|
+
|
71
|
+
ruby_forge = RubyForge.new
|
72
|
+
ruby_forge.login
|
73
|
+
|
74
|
+
%w( gem tgz zip ).each do |ext|
|
75
|
+
file = "pkg/#{PKG_FILE_NAME}.#{ext}"
|
76
|
+
puts "Releasing #{File.basename(file)}..."
|
77
|
+
|
78
|
+
ruby_forge.add_release(RUBY_FORGE_PROJECT, PKG_NAME, PKG_VERSION, file)
|
79
|
+
end
|
80
|
+
end
|
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'encrypted_attributes'
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module PluginAWeek #:nodoc:
|
2
|
+
module EncryptedAttributes #:nodoc:
|
3
|
+
module Extensions #:nodoc:
|
4
|
+
module Encryptor #:nodoc:
|
5
|
+
def process_options(model, operation, options)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
PluginAWeek::EncryptedStrings::Encryptor.class_eval do
|
13
|
+
extend PluginAWeek::EncryptedAttributes::Extensions::Encryptor
|
14
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module PluginAWeek #:nodoc:
|
2
|
+
module EncryptedAttributes #:nodoc:
|
3
|
+
module Extensions #:nodoc:
|
4
|
+
module ShaEncryptor
|
5
|
+
# Adds support for using a salt that is generated based on the model and
|
6
|
+
# stored in an attribute.
|
7
|
+
def process_options(model, operation, options)
|
8
|
+
if (salt_attr_name = options[:salt]) && (salt_attr_name == true || salt_attr_name.is_a?(Symbol))
|
9
|
+
salt_attr_name = 'salt' if salt_attr_name == true
|
10
|
+
|
11
|
+
if operation == :write
|
12
|
+
salt_value = model.send("create_#{salt_attr_name}").to_s
|
13
|
+
model.send("#{salt_attr_name}=", salt_value)
|
14
|
+
else
|
15
|
+
salt_value = model.send(salt_attr_name)
|
16
|
+
end
|
17
|
+
|
18
|
+
options[:salt] = salt_value
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
PluginAWeek::EncryptedStrings::ShaEncryptor.class_eval do
|
27
|
+
extend PluginAWeek::EncryptedAttributes::Extensions::ShaEncryptor
|
28
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'encrypted_strings'
|
2
|
+
require 'encrypted_attributes/extensions/encryptor'
|
3
|
+
require 'encrypted_attributes/extensions/sha_encryptor'
|
4
|
+
|
5
|
+
module PluginAWeek #:nodoc:
|
6
|
+
module EncryptedAttributes
|
7
|
+
def self.included(base) #:nodoc:
|
8
|
+
base.extend(MacroMethods)
|
9
|
+
end
|
10
|
+
|
11
|
+
module MacroMethods
|
12
|
+
# Encrypts the specified attribute.
|
13
|
+
#
|
14
|
+
# Configuration options:
|
15
|
+
# * <tt>mode</tt> - The mode of encryption to use. Default is sha.
|
16
|
+
# * <tt>crypted_name</tt> - The name of the attribute to store the crypted value in. Default is "crypted_#{attr_name}".
|
17
|
+
#
|
18
|
+
# For additional configuration options, see the individual encryptor class.
|
19
|
+
def encrypts(attr_name, options = {})
|
20
|
+
mode = options.delete(:mode) || :sha
|
21
|
+
encryptor_class = "PluginAWeek::EncryptedStrings::#{mode.to_s.classify}Encryptor".constantize
|
22
|
+
|
23
|
+
options.reverse_merge!(
|
24
|
+
:crypted_name => "crypted_#{attr_name}"
|
25
|
+
)
|
26
|
+
crypted_attr_name = options.delete(:crypted_name)
|
27
|
+
raise ArgumentError, 'Attribute name cannot be same as crypted name' if attr_name == crypted_attr_name
|
28
|
+
|
29
|
+
# Creator accessor for the virtual attribute
|
30
|
+
attr_accessor attr_name
|
31
|
+
|
32
|
+
# Define the reader when reading the crypted value from the db
|
33
|
+
crypted_var_name = "@#{crypted_attr_name}"
|
34
|
+
define_method(crypted_attr_name) do
|
35
|
+
if (value = read_attribute(crypted_attr_name)) && !value.encrypted?
|
36
|
+
encryptor_options = options.dup
|
37
|
+
encryptor_class.process_options(self, :read, encryptor_options)
|
38
|
+
value.encryptor = encryptor_class.new(encryptor_options)
|
39
|
+
end
|
40
|
+
|
41
|
+
value
|
42
|
+
end
|
43
|
+
|
44
|
+
# Set the value immediately before validation takes place
|
45
|
+
before_validation do |model|
|
46
|
+
value = model.send(attr_name)
|
47
|
+
|
48
|
+
if !value.blank?
|
49
|
+
unless value.encrypted?
|
50
|
+
encryptor_options = options.dup
|
51
|
+
encryptor_class.process_options(model, :write, encryptor_options)
|
52
|
+
value = value.encrypt(mode, encryptor_options)
|
53
|
+
end
|
54
|
+
|
55
|
+
model.send("#{crypted_attr_name}=", value)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# After saving, be sure to reset the virtual attribute value. This also
|
60
|
+
# supported resetting the confirmation field if, for example, the plugin
|
61
|
+
# is being used for passwords
|
62
|
+
after_save do |model|
|
63
|
+
model.send("#{attr_name}=", nil)
|
64
|
+
model.send("#{attr_name}_confirmation=", nil) if model.respond_to?("#{attr_name}_confirmation=")
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
ActiveRecord::Base.class_eval do
|
72
|
+
include PluginAWeek::EncryptedAttributes
|
73
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class ConfirmedShaUser < ShaUser
|
2
|
+
with_options(:if => :password_required?) do |klass|
|
3
|
+
validates_presence_of :password,
|
4
|
+
:crypted_password
|
5
|
+
validates_length_of :password,
|
6
|
+
:in => 4..40
|
7
|
+
validates_confirmation_of :password
|
8
|
+
end
|
9
|
+
|
10
|
+
def password_required?
|
11
|
+
crypted_password.blank? || !password.blank?
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class CreateUsers < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :users, :force => true do |t|
|
4
|
+
t.column :protected_password, :string, :limit => 255
|
5
|
+
t.column :crypted_password, :string, :limit => 255
|
6
|
+
t.column :salt, :string, :limit => 50
|
7
|
+
t.column :salt_value, :string, :limit => 50
|
8
|
+
t.column :login, :string, :limit => 50
|
9
|
+
t.column :type, :string, :limit => 20
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.down
|
14
|
+
drop_table :users
|
15
|
+
end
|
16
|
+
end
|
data/test/keys/private
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
-----BEGIN RSA PRIVATE KEY-----
|
2
|
+
MIIBOwIBAAJBAL/xeY6aqFx6z1ThNOwgPgxv3tsonTlCj8VkN3Ikumg6SzBuLxlV
|
3
|
+
i9gFQZ7K9Pv9o/7+xUTYODqBpVhwgLBeu2cCAwEAAQJAHyjFMfg7Yp/xLndMzxRA
|
4
|
+
3mX+yJckRtpeWo31TktWE3syks1r9OrfmxKiStM9kFRubeBHTihZrW92TYkROLxh
|
5
|
+
uQIhAPuftVTJZFDNxeYDKIMIMqwR8KZgtuf25cv4pTxYwPqLAiEAw0gNwDJHBkvo
|
6
|
+
da4402pZNQmBA6qCSf0svDXqoEoaShUCIGBma340Oe6LJ0pb42Vv+pnZtazIWMq9
|
7
|
+
2IQwmn1oM2bJAiEAhgP869mVRIzzi091UCG79tn+4DU0FPLasI+P5VD1mcECIQDb
|
8
|
+
3ndvbPcElVvdJgabxyWJJsNtBBNZYPsuc6NrQyShOw==
|
9
|
+
-----END RSA PRIVATE KEY-----
|
data/test/keys/public
ADDED
data/test/test_helper.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
# Load local repository plugin paths
|
2
|
+
$:.unshift("#{File.dirname(__FILE__)}/../../../../ruby/string/encrypted_strings/lib")
|
3
|
+
|
4
|
+
# Load the plugin testing framework
|
5
|
+
$:.unshift("#{File.dirname(__FILE__)}/../../../../test/plugin_test_helper/lib")
|
6
|
+
require 'rubygems'
|
7
|
+
require 'plugin_test_helper'
|
8
|
+
|
9
|
+
# Run the migrations
|
10
|
+
ActiveRecord::Migrator.migrate("#{RAILS_ROOT}/db/migrate")
|
@@ -0,0 +1,130 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'test_helper'))
|
2
|
+
|
3
|
+
class EncryptedAttributesTest < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
PluginAWeek::EncryptedStrings::AsymmetricEncryptor.default_private_key_file = File.join(File.dirname(__FILE__), '..', 'keys', 'private')
|
6
|
+
PluginAWeek::EncryptedStrings::AsymmetricEncryptor.default_public_key_file = File.join(File.dirname(__FILE__), '..', 'keys', 'public')
|
7
|
+
|
8
|
+
PluginAWeek::EncryptedStrings::SymmetricEncryptor.default_key = 'key'
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_encryption_with_default_options
|
12
|
+
{
|
13
|
+
ShaUser => PluginAWeek::EncryptedStrings::ShaEncryptor,
|
14
|
+
AsymmetricUser => PluginAWeek::EncryptedStrings::AsymmetricEncryptor,
|
15
|
+
SymmetricUser => PluginAWeek::EncryptedStrings::SymmetricEncryptor
|
16
|
+
}.each do |user_class, encryptor_class|
|
17
|
+
user = user_class.new
|
18
|
+
user.login = 'john doe'
|
19
|
+
user.password = 'secret'
|
20
|
+
|
21
|
+
assert user.save
|
22
|
+
assert_not_nil user.crypted_password
|
23
|
+
assert user.crypted_password.encrypted?
|
24
|
+
assert_instance_of encryptor_class, user.crypted_password.encryptor
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_encryption_with_custom_crypted_attribute
|
29
|
+
user = ShaUserWithCustomCryptedAttr.new
|
30
|
+
user.login = 'john doe'
|
31
|
+
user.password = 'secret'
|
32
|
+
|
33
|
+
assert user.save
|
34
|
+
assert_nil user.crypted_password
|
35
|
+
assert_not_nil user.protected_password
|
36
|
+
assert user.protected_password.encrypted?
|
37
|
+
assert_instance_of PluginAWeek::EncryptedStrings::ShaEncryptor, user.protected_password.encryptor
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_should_encrypt_on_invalid_model
|
41
|
+
user = ShaUser.new
|
42
|
+
user.login = nil
|
43
|
+
user.password = 'secret'
|
44
|
+
|
45
|
+
assert !user.save
|
46
|
+
assert_not_nil user.password
|
47
|
+
assert_not_nil user.crypted_password
|
48
|
+
assert user.crypted_password.encrypted?
|
49
|
+
assert_instance_of PluginAWeek::EncryptedStrings::ShaEncryptor, user.crypted_password.encryptor
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_should_not_encrypt_if_attribute_is_blank
|
53
|
+
user = ShaUser.new
|
54
|
+
user.login = 'john doe'
|
55
|
+
user.password = nil
|
56
|
+
user.save
|
57
|
+
assert_nil user.crypted_password
|
58
|
+
|
59
|
+
user.password = ''
|
60
|
+
assert user.save
|
61
|
+
assert_nil user.crypted_password
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_should_not_encrypt_if_already_encrypted
|
65
|
+
encrypted_password = 'secret'.encrypt
|
66
|
+
|
67
|
+
user = ShaUser.new
|
68
|
+
user.login = 'john doe'
|
69
|
+
user.password = encrypted_password
|
70
|
+
|
71
|
+
assert user.save
|
72
|
+
assert_equal encrypted_password, user.crypted_password
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_should_hide_attribute_after_save
|
76
|
+
user = ShaUser.new
|
77
|
+
user.login = 'john doe'
|
78
|
+
user.password = 'secret'
|
79
|
+
|
80
|
+
assert user.save
|
81
|
+
assert_nil user.password
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_should_hide_confirmation_attribute_after_save
|
85
|
+
user = ConfirmedShaUser.new
|
86
|
+
user.login = 'john doe'
|
87
|
+
user.password = 'secret'
|
88
|
+
user.password_confirmation = 'secret'
|
89
|
+
|
90
|
+
assert user.save
|
91
|
+
assert_nil user.password
|
92
|
+
assert_nil user.password_confirmation
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_sha_encryption_with_generated_salt
|
96
|
+
user = ShaUserWithSalt.new
|
97
|
+
user.login = 'john doe'
|
98
|
+
user.password = 'secret'
|
99
|
+
|
100
|
+
assert user.save
|
101
|
+
assert_not_nil user.salt
|
102
|
+
assert_equal 'john doe_salt', user.salt
|
103
|
+
assert_equal 'secret', user.crypted_password
|
104
|
+
end
|
105
|
+
|
106
|
+
def test_sha_encryption_with_custom_generated_salt
|
107
|
+
user = ShaUserWithCustomSalt.new
|
108
|
+
user.login = 'john doe'
|
109
|
+
user.password = 'secret'
|
110
|
+
|
111
|
+
assert user.save
|
112
|
+
assert_not_nil user.salt_value
|
113
|
+
assert_equal 'john doe_salt_value', user.salt_value
|
114
|
+
assert_equal 'secret', user.crypted_password
|
115
|
+
end
|
116
|
+
|
117
|
+
def test_should_return_encrypted_attribute_for_saved_record
|
118
|
+
user = ShaUser.new
|
119
|
+
user.login = 'john doe'
|
120
|
+
user.password = 'secret'
|
121
|
+
|
122
|
+
assert user.save
|
123
|
+
|
124
|
+
user = ShaUser.find(user.id)
|
125
|
+
assert_nil user.password
|
126
|
+
assert_not_nil user.crypted_password
|
127
|
+
assert user.crypted_password.encrypted?
|
128
|
+
assert_instance_of PluginAWeek::EncryptedStrings::ShaEncryptor, user.crypted_password.encryptor
|
129
|
+
end
|
130
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'test_helper'))
|
2
|
+
|
3
|
+
class EncryptorTest < Test::Unit::TestCase
|
4
|
+
def test_should_not_make_any_changes_on_process_options
|
5
|
+
assert PluginAWeek::EncryptedStrings::Encryptor.respond_to?(:process_options)
|
6
|
+
|
7
|
+
options = {:salt => 'test'}
|
8
|
+
expected_options = options.dup
|
9
|
+
PluginAWeek::EncryptedStrings::Encryptor.process_options(User.new, :read, options)
|
10
|
+
|
11
|
+
assert_equal expected_options, options
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'test_helper'))
|
2
|
+
|
3
|
+
class ShaEncryptorTest < Test::Unit::TestCase
|
4
|
+
def test_should_respond_to_process_options
|
5
|
+
assert PluginAWeek::EncryptedStrings::ShaEncryptor.respond_to?(:process_options)
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_process_options_should_not_make_changes_for_salt_string
|
9
|
+
options = {:salt => 'my_salt_value'}
|
10
|
+
expected_options = {:salt => 'my_salt_value'}
|
11
|
+
PluginAWeek::EncryptedStrings::ShaEncryptor.process_options(User.new, :read, options)
|
12
|
+
PluginAWeek::EncryptedStrings::ShaEncryptor.process_options(User.new, :write, options)
|
13
|
+
|
14
|
+
assert_equal expected_options, options
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_process_options_should_use_salt_attribute_for_salt_on_read
|
18
|
+
user = ShaUserWithSalt.new
|
19
|
+
user.login = 'test'
|
20
|
+
user.salt = 'existing_salt'
|
21
|
+
|
22
|
+
options = {:salt => true}
|
23
|
+
expected_options = {:salt => 'existing_salt'}
|
24
|
+
PluginAWeek::EncryptedStrings::ShaEncryptor.process_options(user, :read, options)
|
25
|
+
|
26
|
+
assert_equal expected_options, options
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_process_options_should_generate_new_salt_on_write
|
30
|
+
user = ShaUserWithSalt.new
|
31
|
+
user.login = 'test'
|
32
|
+
user.salt = 'existing_salt'
|
33
|
+
|
34
|
+
options = {:salt => true}
|
35
|
+
expected_options = {:salt => 'test_salt'}
|
36
|
+
PluginAWeek::EncryptedStrings::ShaEncryptor.process_options(user, :write, options)
|
37
|
+
|
38
|
+
assert_equal expected_options, options
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_process_options_should_use_custom_attribute_for_salt_on_read
|
42
|
+
user = ShaUserWithCustomSalt.new
|
43
|
+
user.login = 'test'
|
44
|
+
user.salt_value = 'existing_salt_value'
|
45
|
+
|
46
|
+
options = {:salt => :salt_value}
|
47
|
+
expected_options = {:salt => 'existing_salt_value'}
|
48
|
+
PluginAWeek::EncryptedStrings::ShaEncryptor.process_options(user, :read, options)
|
49
|
+
|
50
|
+
assert_equal expected_options, options
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_process_options_should_generate_new_salt_from_custom_method_on_write
|
54
|
+
user = ShaUserWithCustomSalt.new
|
55
|
+
user.login = 'test'
|
56
|
+
user.salt_value = 'existing_salt_value'
|
57
|
+
|
58
|
+
options = {:salt => :salt_value}
|
59
|
+
expected_options = {:salt => 'test_salt_value'}
|
60
|
+
PluginAWeek::EncryptedStrings::ShaEncryptor.process_options(user, :write, options)
|
61
|
+
|
62
|
+
assert_equal expected_options, options
|
63
|
+
end
|
64
|
+
end
|
metadata
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.9.2
|
3
|
+
specification_version: 1
|
4
|
+
name: encrypted_attributes
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 0.0.1
|
7
|
+
date: 2007-08-05 00:00:00 -04:00
|
8
|
+
summary: ""
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: info@pluginaweek.org
|
12
|
+
homepage: http://www.pluginaweek.org
|
13
|
+
rubyforge_project:
|
14
|
+
description:
|
15
|
+
autorequire: encrypted_attributes
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.0
|
24
|
+
version:
|
25
|
+
platform: ruby
|
26
|
+
signing_key:
|
27
|
+
cert_chain:
|
28
|
+
post_install_message:
|
29
|
+
authors:
|
30
|
+
- Aaron Pfeifer, Neil Abraham
|
31
|
+
files:
|
32
|
+
- lib/encrypted_attributes
|
33
|
+
- lib/encrypted_attributes/extensions
|
34
|
+
- lib/encrypted_attributes/extensions/encryptor.rb
|
35
|
+
- lib/encrypted_attributes/extensions/sha_encryptor.rb
|
36
|
+
- lib/encrypted_attributes.rb
|
37
|
+
- test/app_root
|
38
|
+
- test/app_root/app
|
39
|
+
- test/app_root/app/models
|
40
|
+
- test/app_root/app/models/asymmetric_user.rb
|
41
|
+
- test/app_root/app/models/confirmed_sha_user.rb
|
42
|
+
- test/app_root/app/models/sha_user.rb
|
43
|
+
- test/app_root/app/models/sha_user_with_custom_crypted_attr.rb
|
44
|
+
- test/app_root/app/models/sha_user_with_custom_salt.rb
|
45
|
+
- test/app_root/app/models/sha_user_with_salt.rb
|
46
|
+
- test/app_root/app/models/symmetric_user.rb
|
47
|
+
- test/app_root/app/models/user.rb
|
48
|
+
- test/app_root/db
|
49
|
+
- test/app_root/db/migrate
|
50
|
+
- test/app_root/db/migrate/001_create_users.rb
|
51
|
+
- test/app_root/test
|
52
|
+
- test/app_root/test/fixtures
|
53
|
+
- test/app_root/test/fixtures/users.yml
|
54
|
+
- test/keys
|
55
|
+
- test/keys/private
|
56
|
+
- test/keys/public
|
57
|
+
- test/test_helper.rb
|
58
|
+
- test/unit
|
59
|
+
- test/unit/encrypted_attributes_test.rb
|
60
|
+
- test/unit/encryptor_test.rb
|
61
|
+
- test/unit/sha_encryptor_test.rb
|
62
|
+
- init.rb
|
63
|
+
- MIT-LICENSE
|
64
|
+
- Rakefile
|
65
|
+
- README
|
66
|
+
test_files:
|
67
|
+
- test/unit/encrypted_attributes_test.rb
|
68
|
+
- test/unit/encryptor_test.rb
|
69
|
+
- test/unit/sha_encryptor_test.rb
|
70
|
+
rdoc_options: []
|
71
|
+
|
72
|
+
extra_rdoc_files: []
|
73
|
+
|
74
|
+
executables: []
|
75
|
+
|
76
|
+
extensions: []
|
77
|
+
|
78
|
+
requirements: []
|
79
|
+
|
80
|
+
dependencies:
|
81
|
+
- !ruby/object:Gem::Dependency
|
82
|
+
name: encrypted_strings
|
83
|
+
version_requirement:
|
84
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: 0.0.1
|
89
|
+
version:
|