attr_password 0.1.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 12f7073d0568e2ee43eec82a4e70aaeca7b37178
4
+ data.tar.gz: b763a893e3545fa58010056bd821d3e4a1cc79a2
5
+ SHA512:
6
+ metadata.gz: d56419de3d7969899236100484b99707fe97e032da24e252257923b1dd928407f0d845d1e4671c0537ea295d032c951458d1fd4cb30079a38ed30841959117aa
7
+ data.tar.gz: 08f5939ed8163a4ea99a021282d0d093a40895eba070c9a42c3ed8a5628dc4a86d57dcd21ab24cfd9cbf33437b10c9ad578ff0f044b0f3a75c9792376abb8cb2
@@ -0,0 +1,20 @@
1
+ # OS Files #
2
+ ############
3
+ .DS_Store
4
+ .Trashes
5
+ ehthumbs.db
6
+ Icon?
7
+ Thumbs.db
8
+
9
+ # Ruby Files #
10
+ ##############
11
+ /Gemfile.lock
12
+ /.bundle/
13
+ /.yardoc
14
+ /_yardoc/
15
+ /coverage/
16
+ /doc/
17
+ /pkg/
18
+ /tmp/
19
+ /spec/reports/
20
+ /vendor/bundle/
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
@@ -0,0 +1,6 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: :spec
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'attr_password/constants'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'attr_password'
8
+ spec.version = AttrPassword::VERSION
9
+ spec.authors = ['Rediweb Hosting']
10
+ spec.email = ['support@rediwebhosting.uk']
11
+
12
+ spec.summary = %q{Password Attribute}
13
+ spec.description = %q{Store passwords securely.}
14
+ spec.homepage = 'https://rubygems.org/gems/attr_password'
15
+ spec.license = 'GPL-3.0'
16
+
17
+ spec.files = `git ls-files -z`.split("\x0")
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.executables = spec.files.grep(%r{^bin/(?!((console|setup)$))}) { |f| File.basename(f) }
20
+ spec.require_paths = ['lib']
21
+
22
+ spec.add_dependency 'activerecord', '~> 4.2'
23
+ spec.add_dependency 'bcrypt', '~> 3.1'
24
+ spec.add_dependency 'unix-crypt', '~> 1.3'
25
+
26
+ spec.add_development_dependency 'rake', '~> 10.0'
27
+ spec.add_development_dependency 'rspec', '~> 3.0'
28
+ spec.add_development_dependency 'bundler', '~> 1.11'
29
+ end
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'attr_password'
5
+
6
+ require 'irb'
7
+
8
+ IRB.start
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
@@ -0,0 +1,81 @@
1
+ # The password attribute module
2
+ #
3
+ module AttrPassword
4
+ class << self
5
+ # Require dependencies
6
+ #
7
+ # Example:
8
+ # >> AttrPassword.require!
9
+ # => nil
10
+ #
11
+ def require!
12
+ require 'bcrypt'
13
+ require 'unix_crypt'
14
+
15
+ require 'attr_password/constants'
16
+ require 'attr_password/adapters'
17
+
18
+ require 'attr_password/bcrypt'
19
+ require 'attr_password/sha512'
20
+ require 'attr_password/sha256'
21
+ require 'attr_password/md5'
22
+ require 'attr_password/des'
23
+ end
24
+ end
25
+
26
+ # Add the password functionality
27
+ #
28
+ # Arguments:
29
+ # algorithm: (Symbol) (Default :bcrypt)
30
+ #
31
+ # Example:
32
+ # >> class Test
33
+ # >> has_password :bcrypt
34
+ # >> end
35
+ #
36
+ def has_password(algorithm = :bcrypt)
37
+ # Get the backend crypt class
38
+ backend = case algorithm
39
+ when :bcrypt
40
+ AttrPassword::BCrypt.new
41
+ when :sha512
42
+ AttrPassword::SHA512.new
43
+ when :sha256
44
+ AttrPassword::SHA256.new
45
+ when :md5
46
+ AttrPassword::MD5.new
47
+ when :des
48
+ AttrPassword::DES.new
49
+ else
50
+ return false
51
+ end
52
+
53
+ define_method("password=") do |password|
54
+ # Get the adapter
55
+ adapter = AttrPassword::Adapters.for(self)
56
+
57
+ # Get the crypted password
58
+ crypted_password = password ? backend.crypt_password(password) : nil
59
+
60
+ # Set the password hash
61
+ adapter.write_attribute(:crypted_password, crypted_password)
62
+ end
63
+
64
+ define_method("valid_password?") do |password|
65
+ # Ensure the password is not nil
66
+ return false if password.nil?
67
+
68
+ # Get the adapter
69
+ adapter = AttrPassword::Adapters.for(self)
70
+
71
+ # Check if the password is valid
72
+ backend.validate_password(password, crypted_password)
73
+ end
74
+
75
+ true
76
+ end
77
+ end
78
+
79
+ # Require dependencies
80
+ #
81
+ AttrPassword.require!
@@ -0,0 +1,60 @@
1
+ module AttrPassword
2
+ # This module contains the adapters
3
+ #
4
+ module Adapters
5
+ class << self
6
+ # Require the adapters
7
+ #
8
+ # Example:
9
+ # >> AttrPassword::Adapters.require!
10
+ # => true
11
+ #
12
+ def require!
13
+ require 'attr_password/adapters/base'
14
+
15
+ # Get the glob for the adapters directory
16
+ adapters_glob = File.expand_path('../adapters/**/*.rb', __FILE__)
17
+
18
+ # Loop over each adapter file
19
+ Dir.glob(adapters_glob).each do |adapter|
20
+ # Require the adapter file
21
+ require(adapter)
22
+ end
23
+ end
24
+
25
+ # Find the best adapter for an object
26
+ #
27
+ # Arguments:
28
+ # object: (Object)
29
+ #
30
+ # Example:
31
+ # >> AttrPassword::Adapters.for(object)
32
+ # => #<AttrPassword::Adapters::Ruby:0x00000000000000>
33
+ #
34
+ def for(object)
35
+ # The list of all adapters
36
+ adapters = [
37
+ AttrPassword::Adapters::ActiveRecord,
38
+ AttrPassword::Adapters::Ruby
39
+ ]
40
+
41
+ # Loop over each adapter
42
+ adapters.each do |klass|
43
+ # Create a new instance of the adapter
44
+ adapter = klass.new(object)
45
+
46
+ # Ensure the adapter is available
47
+ next unless adapter.available?
48
+
49
+ return adapter
50
+ end
51
+
52
+ nil
53
+ end
54
+ end
55
+ end
56
+ end
57
+
58
+ # Require the adapters
59
+ #
60
+ AttrPassword::Adapters.require!
@@ -0,0 +1,63 @@
1
+ module AttrPassword
2
+ module Adapters
3
+ # The ActiveRecord adapter
4
+ #
5
+ class ActiveRecord < Base
6
+ class << self
7
+ # Attempt to inject the AttrPassword class into ActiveRecord::Base
8
+ #
9
+ # Example:
10
+ # >> AttrPassword::Adapters::ActiveRecord.inject!
11
+ # => nil
12
+ #
13
+ def inject!
14
+ # Ensure the ActiveRecord::Base class is defined
15
+ return false unless defined?(::ActiveRecord::Base)
16
+
17
+ # Make the ActiveRecord::Base class extend the AttrPassword class
18
+ ::ActiveRecord::Base.send(:extend, AttrPassword)
19
+
20
+ true
21
+ end
22
+ end
23
+
24
+ # Check if this adapter can be used for the object
25
+ #
26
+ # Example:
27
+ # >> adapter.available?
28
+ # => true
29
+ #
30
+ def available?
31
+ # Ensure the ActiveRecord::Base class is defined
32
+ return false unless defined?(::ActiveRecord::Base)
33
+
34
+ # Check if the object inherits from ActiveRecord::Base
35
+ @object.class.ancestors.include?(::ActiveRecord::Base)
36
+ end
37
+
38
+ # Read an attribute
39
+ #
40
+ # Example:
41
+ # >> adapter.read_attribute(:hello_world)
42
+ # => "Hello, World!"
43
+ #
44
+ def read_attribute(attribute)
45
+ @object.send(:read_attribute, attribute.to_sym)
46
+ end
47
+
48
+ # Write an attribute
49
+ #
50
+ # Example:
51
+ # >> adapter.write_attribute(:hello_world, "Hello, World!")
52
+ # => true
53
+ #
54
+ def write_attribute(attribute, value)
55
+ @object.send(:write_attribute, attribute, value)
56
+ end
57
+ end
58
+ end
59
+ end
60
+
61
+ # Attempt to inject the AttrPassword class into ActiveRecord::Base
62
+ #
63
+ AttrPassword::Adapters::ActiveRecord.inject!
@@ -0,0 +1,57 @@
1
+ module AttrPassword
2
+ module Adapters
3
+ # The base adapter
4
+ #
5
+ class Base
6
+ # The object the adapter relates to
7
+ #
8
+ attr_reader :object
9
+
10
+ # Create a new instance of this adapter
11
+ #
12
+ # Example:
13
+ # >> AttrPassword::Adapters::Base.new(object)
14
+ # => #<AttrPassword::Adapters::Base:0x00000000000000>
15
+ #
16
+ def initialize(object)
17
+ # Ensure the object exists
18
+ unless object
19
+ raise 'The object property cannot be nil.'
20
+ end
21
+
22
+ # Store the object
23
+ @object = object
24
+ end
25
+
26
+ # Check if this adapter can be used for the object
27
+ #
28
+ # Example:
29
+ # >> adapter.available?
30
+ # => true
31
+ #
32
+ def available?
33
+ true
34
+ end
35
+
36
+ # Read an attribute
37
+ #
38
+ # Example:
39
+ # >> adapter.read_attribute(:hello_world)
40
+ # => "Hello, World!"
41
+ #
42
+ def read_attribute(attribute, value)
43
+ nil
44
+ end
45
+
46
+ # Write an attribute
47
+ #
48
+ # Example:
49
+ # >> adapter.write_attribute(:hello_world, "Hello, World!")
50
+ # => true
51
+ #
52
+ def write_attribute(attribute, value)
53
+ false
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,27 @@
1
+ module AttrPassword
2
+ module Adapters
3
+ # The ActiveRecord adapter
4
+ #
5
+ class Ruby < Base
6
+ # Read an attribute
7
+ #
8
+ # Example:
9
+ # >> adapter.read_attribute(:hello_world)
10
+ # => "Hello, World!"
11
+ #
12
+ def read_attribute(attribute)
13
+ @object.instance_variable_get("@#{attribute}")
14
+ end
15
+
16
+ # Write an attribute
17
+ #
18
+ # Example:
19
+ # >> adapter.write_attribute(:hello_world, "Hello, World!")
20
+ # => true
21
+ #
22
+ def write_attribute(attribute, value)
23
+ @object.instance_variable_set("@#{attribute}", value)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,44 @@
1
+ module AttrPassword
2
+ # The BCrypt class
3
+ #
4
+ class BCrypt
5
+ # Crypt the password
6
+ #
7
+ # Arguments:
8
+ # password: (String)
9
+ #
10
+ # Example:
11
+ # >> backend.crypt_password("P@ssw0rd")
12
+ # => "$2a$10$Ou0no1.WrBtZm2rF4Te7getynnENc2wESKZDLyJTmqnSPV1TEXZ8y"
13
+ #
14
+ def crypt_password(password)
15
+ # Get the BCrypt password
16
+ bcrypt = ::BCrypt::Password.create(password)
17
+
18
+ # Get the BCrypt string
19
+ bcrypt.to_s
20
+ end
21
+
22
+ # Check if a password is valid
23
+ #
24
+ # Arguments:
25
+ # password_hash: (String)
26
+ # password: (String)
27
+ #
28
+ # Example:
29
+ # >> backend.crypt_password("P@ssw0rd", "$2a$10$Ou0no1.WrBtZm2rF4Te7getynnENc2wESKZDLyJTmqnSPV1TEXZ8y")
30
+ # => true
31
+ #
32
+ def validate_password(password, password_hash)
33
+ begin
34
+ # Load the BCrypt password hash
35
+ bcrypt = ::BCrypt::Password.new(password_hash)
36
+
37
+ # Check if the password is valid
38
+ bcrypt == password
39
+ rescue => e
40
+ return false
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,3 @@
1
+ module AttrPassword
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,40 @@
1
+ module AttrPassword
2
+ # The DES class
3
+ #
4
+ class DES
5
+ # Crypt the password
6
+ #
7
+ # Arguments:
8
+ # password: (String)
9
+ #
10
+ # Example:
11
+ # >> backend.crypt_password("P@ssw0rd")
12
+ # => "5F9dBJsU0KiKQ"
13
+ #
14
+ def crypt_password(password)
15
+ # Get the DES crypt password
16
+ UnixCrypt::DES.build(password)
17
+ end
18
+
19
+ # Check if a password is valid
20
+ #
21
+ # Arguments:
22
+ # password_hash: (String)
23
+ # password: (String)
24
+ #
25
+ # Example:
26
+ # >> backend.crypt_password("P@ssw0rd", "5F9dBJsU0KiKQ")
27
+ # => true
28
+ #
29
+ def validate_password(password, password_hash)
30
+ # Ensure the password is set
31
+ return false unless password
32
+
33
+ # Ensure the password hash is set
34
+ return false unless password_hash
35
+
36
+ # Check if the password is valid
37
+ UnixCrypt.valid?(password, password_hash)
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,40 @@
1
+ module AttrPassword
2
+ # The MD5 class
3
+ #
4
+ class MD5
5
+ # Crypt the password
6
+ #
7
+ # Arguments:
8
+ # password: (String)
9
+ #
10
+ # Example:
11
+ # >> backend.crypt_password("P@ssw0rd")
12
+ # => "$1$zKiCUMIJ$9w79XD.6T1tQZ3xF2ztcK."
13
+ #
14
+ def crypt_password(password)
15
+ # Get the MD5 crypt password
16
+ UnixCrypt::MD5.build(password)
17
+ end
18
+
19
+ # Check if a password is valid
20
+ #
21
+ # Arguments:
22
+ # password_hash: (String)
23
+ # password: (String)
24
+ #
25
+ # Example:
26
+ # >> backend.crypt_password("P@ssw0rd", "$1$zKiCUMIJ$9w79XD.6T1tQZ3xF2ztcK.")
27
+ # => true
28
+ #
29
+ def validate_password(password, password_hash)
30
+ # Ensure the password is set
31
+ return false unless password
32
+
33
+ # Ensure the password hash is set
34
+ return false unless password_hash
35
+
36
+ # Check if the password is valid
37
+ UnixCrypt.valid?(password, password_hash)
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,40 @@
1
+ module AttrPassword
2
+ # The SHA256 class
3
+ #
4
+ class SHA256
5
+ # Crypt the password
6
+ #
7
+ # Arguments:
8
+ # password: (String)
9
+ #
10
+ # Example:
11
+ # >> backend.crypt_password("P@ssw0rd")
12
+ # => "$5$1zQaVXCHYfnNQALN$BKZbxVPaCnhgigMSLDMlmxSLPZHY1HBOEypeL3ZHfbD"
13
+ #
14
+ def crypt_password(password)
15
+ # Get the SHA256 crypt password
16
+ UnixCrypt::SHA256.build(password)
17
+ end
18
+
19
+ # Check if a password is valid
20
+ #
21
+ # Arguments:
22
+ # password_hash: (String)
23
+ # password: (String)
24
+ #
25
+ # Example:
26
+ # >> backend.crypt_password("P@ssw0rd", "$5$1zQaVXCHYfnNQALN$BKZbxVPaCnhgigMSLDMlmxSLPZHY1HBOEypeL3ZHfbD")
27
+ # => true
28
+ #
29
+ def validate_password(password, password_hash)
30
+ # Ensure the password is set
31
+ return false unless password
32
+
33
+ # Ensure the password hash is set
34
+ return false unless password_hash
35
+
36
+ # Check if the password is valid
37
+ UnixCrypt.valid?(password, password_hash)
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,40 @@
1
+ module AttrPassword
2
+ # The SHA512 class
3
+ #
4
+ class SHA512
5
+ # Crypt the password
6
+ #
7
+ # Arguments:
8
+ # password: (String)
9
+ #
10
+ # Example:
11
+ # >> backend.crypt_password("P@ssw0rd")
12
+ # => "$6$x7NCbuLU4Bdr2SrU$qb.a9XG7AFszgj0qDO66Xce5pFI5eRcGhAyIrmylEuhYHIsyoCk6DKBOKW/eleMSjBuY10kgtS2zvicwLxZj91"
13
+ #
14
+ def crypt_password(password)
15
+ # Get the SHA512 crypt password
16
+ UnixCrypt::SHA512.build(password)
17
+ end
18
+
19
+ # Check if a password is valid
20
+ #
21
+ # Arguments:
22
+ # password_hash: (String)
23
+ # password: (String)
24
+ #
25
+ # Example:
26
+ # >> backend.crypt_password("P@ssw0rd", "$6$x7NCbuLU4Bdr2SrU$qb.a9XG7AFszgj0qDO66Xce5pFI5eRcGhAyIrmylEuhYHIsyoCk6DKBOKW/eleMSjBuY10kgtS2zvicwLxZj91")
27
+ # => true
28
+ #
29
+ def validate_password(password, password_hash)
30
+ # Ensure the password is set
31
+ return false unless password
32
+
33
+ # Ensure the password hash is set
34
+ return false unless password_hash
35
+
36
+ # Check if the password is valid
37
+ UnixCrypt.valid?(password, password_hash)
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,21 @@
1
+ module AttrPassword
2
+ module RSpec
3
+ module Matchers
4
+ module Version
5
+ extend ::RSpec::Matchers::DSL
6
+
7
+ matcher :be_semantic_version do
8
+ match do |string|
9
+ next false if "0.0.0" == string
10
+
11
+ string =~ /^[0-9]+\.[0-9]+\.[0-9]+$/
12
+ end
13
+
14
+ failure_message do |string|
15
+ "%s is not a semantic version" % string
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,16 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+ require 'attr_password'
3
+
4
+ Dir.glob(File.expand_path('../matchers/**/*.rb', __FILE__)).each do |matcher|
5
+ require(matcher)
6
+ end
7
+
8
+ RSpec.configure do |config|
9
+ config.expect_with :rspec do |expectations|
10
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
11
+ end
12
+
13
+ config.mock_with :rspec do |mocks|
14
+ mocks.verify_partial_doubles = true
15
+ end
16
+ end
@@ -0,0 +1,11 @@
1
+ describe AttrPassword do
2
+ describe '::VERSION' do
3
+ include AttrPassword::RSpec::Matchers::Version
4
+
5
+ subject { AttrPassword::VERSION }
6
+
7
+ it 'should be semantic' do
8
+ expect(subject).to be_semantic_version
9
+ end
10
+ end
11
+ end
metadata ADDED
@@ -0,0 +1,152 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: attr_password
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Rediweb Hosting
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-05-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activerecord
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '4.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '4.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bcrypt
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '3.1'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '3.1'
41
+ - !ruby/object:Gem::Dependency
42
+ name: unix-crypt
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '1.3'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '1.3'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: '3.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: '3.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: bundler
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ~>
88
+ - !ruby/object:Gem::Version
89
+ version: '1.11'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ~>
95
+ - !ruby/object:Gem::Version
96
+ version: '1.11'
97
+ description: Store passwords securely.
98
+ email:
99
+ - support@rediwebhosting.uk
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - .gitignore
105
+ - Gemfile
106
+ - Rakefile
107
+ - attr_password.gemspec
108
+ - bin/console
109
+ - bin/setup
110
+ - lib/attr_password.rb
111
+ - lib/attr_password/adapters.rb
112
+ - lib/attr_password/adapters/active_record.rb
113
+ - lib/attr_password/adapters/base.rb
114
+ - lib/attr_password/adapters/ruby.rb
115
+ - lib/attr_password/bcrypt.rb
116
+ - lib/attr_password/constants.rb
117
+ - lib/attr_password/des.rb
118
+ - lib/attr_password/md5.rb
119
+ - lib/attr_password/sha256.rb
120
+ - lib/attr_password/sha512.rb
121
+ - spec/matchers/version.rb
122
+ - spec/spec_helper.rb
123
+ - spec/unit/attr_password_spec.rb
124
+ homepage: https://rubygems.org/gems/attr_password
125
+ licenses:
126
+ - GPL-3.0
127
+ metadata: {}
128
+ post_install_message:
129
+ rdoc_options: []
130
+ require_paths:
131
+ - lib
132
+ required_ruby_version: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - '>='
135
+ - !ruby/object:Gem::Version
136
+ version: '0'
137
+ required_rubygems_version: !ruby/object:Gem::Requirement
138
+ requirements:
139
+ - - '>='
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ requirements: []
143
+ rubyforge_project:
144
+ rubygems_version: 2.5.1
145
+ signing_key:
146
+ specification_version: 4
147
+ summary: Password Attribute
148
+ test_files:
149
+ - spec/matchers/version.rb
150
+ - spec/spec_helper.rb
151
+ - spec/unit/attr_password_spec.rb
152
+ has_rdoc: