passwd 0.2.0 → 0.3.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.
- checksums.yaml +4 -4
- data/.gitignore +10 -17
- data/.travis.yml +3 -11
- data/Gemfile +3 -1
- data/LICENSE +21 -0
- data/README.md +39 -53
- data/Rakefile +6 -6
- data/bin/console +7 -0
- data/bin/setup +8 -0
- data/lib/generators/passwd/install/USAGE +5 -0
- data/lib/generators/passwd/install/install_generator.rb +10 -0
- data/lib/generators/passwd/install/templates/passwd.rb +27 -0
- data/lib/passwd.rb +33 -15
- data/lib/passwd/config.rb +29 -0
- data/lib/passwd/errors.rb +2 -7
- data/lib/passwd/rails/action_controller_ext.rb +77 -0
- data/lib/passwd/rails/active_record_ext.rb +37 -0
- data/lib/passwd/railtie.rb +5 -6
- data/lib/passwd/version.rb +2 -2
- data/passwd.gemspec +13 -14
- metadata +22 -156
- data/.coveralls.yml +0 -1
- data/CHANGELOG.md +0 -35
- data/LICENSE.txt +0 -23
- data/example/.gitignore +0 -16
- data/example/Gemfile +0 -25
- data/example/README.rdoc +0 -28
- data/example/Rakefile +0 -6
- data/example/app/assets/images/.keep +0 -0
- data/example/app/assets/javascripts/application.js +0 -16
- data/example/app/assets/stylesheets/application.css +0 -16
- data/example/app/controllers/application_controller.rb +0 -10
- data/example/app/controllers/concerns/.keep +0 -0
- data/example/app/controllers/profiles_controller.rb +0 -28
- data/example/app/controllers/root_controller.rb +0 -5
- data/example/app/controllers/sessions_controller.rb +0 -29
- data/example/app/helpers/application_helper.rb +0 -2
- data/example/app/mailers/.keep +0 -0
- data/example/app/models/.keep +0 -0
- data/example/app/models/concerns/.keep +0 -0
- data/example/app/models/user.rb +0 -4
- data/example/app/views/layouts/application.html.erb +0 -15
- data/example/app/views/profiles/edit.html.erb +0 -14
- data/example/app/views/profiles/show.html.erb +0 -12
- data/example/app/views/root/index.html.erb +0 -5
- data/example/app/views/sessions/new.html.erb +0 -6
- data/example/bin/bundle +0 -3
- data/example/bin/rails +0 -4
- data/example/bin/rake +0 -4
- data/example/config.ru +0 -4
- data/example/config/application.rb +0 -40
- data/example/config/boot.rb +0 -4
- data/example/config/database.yml +0 -26
- data/example/config/environment.rb +0 -5
- data/example/config/environments/development.rb +0 -37
- data/example/config/environments/production.rb +0 -78
- data/example/config/environments/test.rb +0 -39
- data/example/config/initializers/assets.rb +0 -8
- data/example/config/initializers/backtrace_silencers.rb +0 -7
- data/example/config/initializers/cookies_serializer.rb +0 -3
- data/example/config/initializers/filter_parameter_logging.rb +0 -4
- data/example/config/initializers/inflections.rb +0 -16
- data/example/config/initializers/mime_types.rb +0 -4
- data/example/config/initializers/passwd.rb +0 -41
- data/example/config/initializers/session_store.rb +0 -3
- data/example/config/initializers/wrap_parameters.rb +0 -14
- data/example/config/locales/en.yml +0 -23
- data/example/config/routes.rb +0 -16
- data/example/config/secrets.yml +0 -22
- data/example/db/migrate/20141122165914_create_users.rb +0 -13
- data/example/db/schema.rb +0 -25
- data/example/db/seeds.rb +0 -7
- data/example/lib/assets/.keep +0 -0
- data/example/lib/tasks/.keep +0 -0
- data/example/lib/tasks/user.rake +0 -12
- data/example/log/.keep +0 -0
- data/example/public/404.html +0 -67
- data/example/public/422.html +0 -67
- data/example/public/500.html +0 -66
- data/example/public/favicon.ico +0 -0
- data/example/public/robots.txt +0 -5
- data/example/vendor/assets/javascripts/.keep +0 -0
- data/example/vendor/assets/stylesheets/.keep +0 -0
- data/lib/generators/passwd/config_generator.rb +0 -13
- data/lib/generators/passwd/templates/passwd_config.rb +0 -41
- data/lib/passwd/action_controller_ext.rb +0 -48
- data/lib/passwd/active_record_ext.rb +0 -65
- data/lib/passwd/base.rb +0 -31
- data/lib/passwd/configuration.rb +0 -82
- data/lib/passwd/password.rb +0 -89
- data/lib/passwd/policy.rb +0 -28
- data/lib/passwd/salt.rb +0 -50
- data/spec/passwd/.keep +0 -0
- data/spec/passwd/active_record_ext_spec.rb +0 -80
- data/spec/passwd/base_spec.rb +0 -60
- data/spec/passwd/configuration_spec.rb +0 -50
- data/spec/passwd/password_spec.rb +0 -156
- data/spec/spec_helper.rb +0 -34
- data/spec/support/data_util.rb +0 -11
- data/spec/support/paths.rb +0 -2
data/example/public/favicon.ico
DELETED
File without changes
|
data/example/public/robots.txt
DELETED
File without changes
|
File without changes
|
@@ -1,13 +0,0 @@
|
|
1
|
-
module Passwd
|
2
|
-
module Generators
|
3
|
-
class ConfigGenerator < ::Rails::Generators::Base
|
4
|
-
source_root File.expand_path(File.join(File.dirname(__FILE__), "templates"))
|
5
|
-
|
6
|
-
desc "Create Passwd configuration file"
|
7
|
-
def create_configuration_file
|
8
|
-
template "passwd_config.rb", "config/initializers/passwd.rb"
|
9
|
-
end
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
@@ -1,41 +0,0 @@
|
|
1
|
-
Passwd.configure do |c|
|
2
|
-
# Password settings
|
3
|
-
# The following settings are all default values.
|
4
|
-
|
5
|
-
# Hashing algorithm
|
6
|
-
# Supported algorithm is :md5, :rmd160, :sha1, :sha256, :sha384 and :sha512
|
7
|
-
# c.algorithm = :sha512
|
8
|
-
|
9
|
-
# Random generate password length
|
10
|
-
# c.length = 8
|
11
|
-
|
12
|
-
# Number of hashed by stretching
|
13
|
-
# Not stretching if specified nil.
|
14
|
-
# c.stretching = nil
|
15
|
-
|
16
|
-
# Character type that is used for password
|
17
|
-
# c.lower = true
|
18
|
-
# c.upper = true
|
19
|
-
# c.number = true
|
20
|
-
end
|
21
|
-
|
22
|
-
Passwd.policy_configure do |c|
|
23
|
-
# Minimum password length
|
24
|
-
# c.min_length = 8
|
25
|
-
|
26
|
-
# Character types to force the use
|
27
|
-
# c.require_lower = true
|
28
|
-
# c.require_upper = false
|
29
|
-
# c.require_number = true
|
30
|
-
end
|
31
|
-
|
32
|
-
# Session key for authentication
|
33
|
-
Rails.application.config.passwd.session_key = :user_id
|
34
|
-
|
35
|
-
# Authentication Model Class
|
36
|
-
Rails.application.config.passwd.authenticate_class = :User
|
37
|
-
|
38
|
-
# Redirect path when not signin
|
39
|
-
# E.G. :signin_path # Do not specify ***_url
|
40
|
-
Rails.application.config.passwd.redirect_to = nil
|
41
|
-
|
@@ -1,48 +0,0 @@
|
|
1
|
-
module Passwd
|
2
|
-
module ActionControllerExt
|
3
|
-
extend ActiveSupport::Concern
|
4
|
-
|
5
|
-
included do
|
6
|
-
helper_method :current_user
|
7
|
-
end
|
8
|
-
|
9
|
-
def current_user
|
10
|
-
@current_user ||= auth_class.find_by(id: session[auth_key])
|
11
|
-
end
|
12
|
-
|
13
|
-
def signin!(user)
|
14
|
-
@current_user = user
|
15
|
-
session[auth_key] = user.id
|
16
|
-
end
|
17
|
-
|
18
|
-
def signout!
|
19
|
-
@current_user = session[auth_key] = nil
|
20
|
-
end
|
21
|
-
|
22
|
-
private
|
23
|
-
def auth_key
|
24
|
-
Rails.application.config.passwd.session_key || :user_id
|
25
|
-
end
|
26
|
-
|
27
|
-
def auth_class
|
28
|
-
@_auth_class ||=
|
29
|
-
(Rails.application.config.passwd.authenticate_class || :User).to_s.constantize
|
30
|
-
end
|
31
|
-
|
32
|
-
def _redirect_path
|
33
|
-
_to = Rails.application.config.passwd.redirect_to
|
34
|
-
_to ? Rails.application.routes.url_helpers.send(_to) : nil
|
35
|
-
end
|
36
|
-
|
37
|
-
def require_signin
|
38
|
-
unless current_user
|
39
|
-
if _redirect_path
|
40
|
-
redirect_to _redirect_path
|
41
|
-
else
|
42
|
-
raise UnauthorizedAccess
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
@@ -1,65 +0,0 @@
|
|
1
|
-
module Passwd
|
2
|
-
module ActiveRecordExt
|
3
|
-
def with_authenticate(options = {})
|
4
|
-
_id_key = options.fetch(:id, :email)
|
5
|
-
_salt_key = options.fetch(:salt, :salt)
|
6
|
-
_pass_key = options.fetch(:password, :password)
|
7
|
-
|
8
|
-
_define_passwd(_salt_key, _pass_key)
|
9
|
-
_define_singleton_auth(_id_key)
|
10
|
-
_define_instance_auth
|
11
|
-
_define_set_password(_salt_key, _pass_key)
|
12
|
-
_define_update_password(_salt_key, _pass_key)
|
13
|
-
end
|
14
|
-
|
15
|
-
private
|
16
|
-
def _define_passwd(_salt_key, _pass_key)
|
17
|
-
define_method :passwd do |cache = true|
|
18
|
-
return @_passwd if cache && @_passwd
|
19
|
-
self.reload unless self.new_record?
|
20
|
-
_salt, _pass = self.send(_salt_key), self.send(_pass_key)
|
21
|
-
if _salt.present? && _pass.present?
|
22
|
-
@_passwd = Passwd::Password.from_hash(_pass, _salt)
|
23
|
-
else
|
24
|
-
self.set_password
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def _define_singleton_auth(_id_key)
|
30
|
-
define_singleton_method :authenticate do |_id, _pass|
|
31
|
-
_condition = Array(_id_key).map {|k| "#{k} = :id"}.join(" OR ")
|
32
|
-
_user = self.find_by(_condition, id: _id)
|
33
|
-
_user if _user && _user.passwd.match?(_pass)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
def _define_instance_auth
|
38
|
-
define_method :authenticate do |_pass|
|
39
|
-
self.passwd.match?(_pass)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
def _define_set_password(_salt_key, _pass_key)
|
44
|
-
define_method :set_password do |_pass = nil|
|
45
|
-
_options = _pass ? {plain: _pass} : {}
|
46
|
-
_passwd = Passwd::Password.new(_options)
|
47
|
-
self.send("#{_salt_key}=", _passwd.salt.hash)
|
48
|
-
self.send("#{_pass_key}=", _passwd.hash)
|
49
|
-
self.instance_variable_set(:@_passwd, _passwd)
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
def _define_update_password(_salt_key, _pass_key)
|
54
|
-
define_method :update_password do |_old, _new, _policy = false|
|
55
|
-
raise PolicyNotMatch if _policy && !Passwd.policy_check(_new)
|
56
|
-
if self.passwd.match?(_old)
|
57
|
-
self.set_password(_new)
|
58
|
-
else
|
59
|
-
raise AuthenticationFails
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
data/lib/passwd/base.rb
DELETED
@@ -1,31 +0,0 @@
|
|
1
|
-
module Passwd
|
2
|
-
module Base
|
3
|
-
def random(options = {})
|
4
|
-
c = PwConfig.merge(options)
|
5
|
-
Array.new(c.length){c.letters[rand(c.letters.size)]}.join
|
6
|
-
end
|
7
|
-
|
8
|
-
def digest(plain, _algorithm = nil)
|
9
|
-
_algorithm ||= PwConfig.algorithm
|
10
|
-
|
11
|
-
if PwConfig.stretching
|
12
|
-
_pass = plain
|
13
|
-
PwConfig.stretching.times do
|
14
|
-
_pass = digest_without_stretching(_pass, _algorithm)
|
15
|
-
end
|
16
|
-
else
|
17
|
-
digest_without_stretching(plain, _algorithm)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def digest_without_stretching(plain, _algorithm = nil)
|
22
|
-
algorithm(_algorithm || PwConfig.algorithm).hexdigest(plain)
|
23
|
-
end
|
24
|
-
|
25
|
-
private
|
26
|
-
def algorithm(_algorithm)
|
27
|
-
Digest.const_get(_algorithm.upcase, false)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
data/lib/passwd/configuration.rb
DELETED
@@ -1,82 +0,0 @@
|
|
1
|
-
module Passwd
|
2
|
-
class Configuration
|
3
|
-
KINDS = %i(lower upper number).freeze
|
4
|
-
LETTERS = KINDS.map {|k| "letters_#{k}".to_sym}.freeze
|
5
|
-
|
6
|
-
VALID_OPTIONS = [
|
7
|
-
:algorithm,
|
8
|
-
:length,
|
9
|
-
:policy,
|
10
|
-
:stretching,
|
11
|
-
].concat(KINDS).concat(LETTERS).freeze
|
12
|
-
|
13
|
-
attr_accessor *VALID_OPTIONS
|
14
|
-
|
15
|
-
def initialize
|
16
|
-
reset
|
17
|
-
end
|
18
|
-
|
19
|
-
def configure
|
20
|
-
yield self
|
21
|
-
end
|
22
|
-
|
23
|
-
def merge(params)
|
24
|
-
self.dup.merge!(params)
|
25
|
-
end
|
26
|
-
|
27
|
-
def merge!(params)
|
28
|
-
params.keys.each do |key|
|
29
|
-
self.send("#{key}=", params[key])
|
30
|
-
end
|
31
|
-
self
|
32
|
-
end
|
33
|
-
|
34
|
-
KINDS.each do |kind|
|
35
|
-
define_method "#{kind}_chars" do
|
36
|
-
self.send("letters_#{kind}") || []
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def letters
|
41
|
-
KINDS.detect {|k| self.send(k)} || (raise ConfigError, "letters is empry.")
|
42
|
-
LETTERS.zip(KINDS).map {|l, k|
|
43
|
-
self.send(l) if self.send(k)
|
44
|
-
}.compact.flatten
|
45
|
-
end
|
46
|
-
|
47
|
-
def reset
|
48
|
-
self.algorithm = :sha512
|
49
|
-
self.length = 8
|
50
|
-
self.policy = Policy.new
|
51
|
-
self.stretching = nil
|
52
|
-
self.lower = true
|
53
|
-
self.upper = true
|
54
|
-
self.number = true
|
55
|
-
self.letters_lower = ("a".."z").to_a
|
56
|
-
self.letters_upper = ("A".."Z").to_a
|
57
|
-
self.letters_number = ("0".."9").to_a
|
58
|
-
end
|
59
|
-
|
60
|
-
module Writable
|
61
|
-
def self.extended(base)
|
62
|
-
base.send(:include, Accessible)
|
63
|
-
end
|
64
|
-
|
65
|
-
def configure(options = {}, &block)
|
66
|
-
PwConfig.merge!(options) unless options.empty?
|
67
|
-
PwConfig.configure(&block) if block_given?
|
68
|
-
end
|
69
|
-
|
70
|
-
def policy_configure(&block)
|
71
|
-
PwConfig.policy.configure(&block) if block_given?
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
module Accessible
|
76
|
-
def self.included(base)
|
77
|
-
base.const_set(:PwConfig, Configuration.new)
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
data/lib/passwd/password.rb
DELETED
@@ -1,89 +0,0 @@
|
|
1
|
-
module Passwd
|
2
|
-
class Password
|
3
|
-
include Base
|
4
|
-
|
5
|
-
attr_reader :plain, :hash, :salt
|
6
|
-
|
7
|
-
def initialize(options = {})
|
8
|
-
options = default_options.merge(options)
|
9
|
-
|
10
|
-
if options.has_key?(:hash)
|
11
|
-
raise ArgumentError unless options.has_key?(:salt_hash)
|
12
|
-
@salt = Salt.from_hash(options[:salt_hash], self)
|
13
|
-
@hash = options[:hash]
|
14
|
-
else
|
15
|
-
@salt =
|
16
|
-
case
|
17
|
-
when options.has_key?(:salt_hash)
|
18
|
-
Salt.from_hash(options[:salt_hash], self)
|
19
|
-
when options.has_key?(:salt_plain)
|
20
|
-
Salt.from_plain(options[:salt_plain], self)
|
21
|
-
else
|
22
|
-
Salt.new(password: self)
|
23
|
-
end
|
24
|
-
self.update_plain(options[:plain])
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def update_plain(value)
|
29
|
-
@plain = value
|
30
|
-
rehash
|
31
|
-
end
|
32
|
-
|
33
|
-
def update_hash(value, salt_hash)
|
34
|
-
@plain = nil
|
35
|
-
@hash = value
|
36
|
-
self.salt.update_hash(salt_hash)
|
37
|
-
end
|
38
|
-
|
39
|
-
def rehash
|
40
|
-
raise PasswdError unless self.plain
|
41
|
-
@hash = digest([self.salt.hash, self.plain].join)
|
42
|
-
end
|
43
|
-
|
44
|
-
def match?(value)
|
45
|
-
self.hash == digest([self.salt.hash, value].join)
|
46
|
-
end
|
47
|
-
|
48
|
-
def ==(other)
|
49
|
-
match?(other)
|
50
|
-
end
|
51
|
-
|
52
|
-
def to_s
|
53
|
-
self.plain.to_s
|
54
|
-
end
|
55
|
-
|
56
|
-
def valid?
|
57
|
-
raise PasswdError unless self.plain
|
58
|
-
|
59
|
-
return false if PwConfig.policy.min_length > self.plain.size
|
60
|
-
|
61
|
-
Configuration::KINDS.each do |key|
|
62
|
-
if PwConfig.policy.send("require_#{key}")
|
63
|
-
return false unless include_char?(PwConfig.send("letters_#{key}"))
|
64
|
-
end
|
65
|
-
end
|
66
|
-
true
|
67
|
-
end
|
68
|
-
|
69
|
-
def self.from_plain(value, options = {})
|
70
|
-
new(options.merge(plain: value))
|
71
|
-
end
|
72
|
-
|
73
|
-
def self.from_hash(value, salt_hash)
|
74
|
-
new(hash: value, salt_hash: salt_hash)
|
75
|
-
end
|
76
|
-
|
77
|
-
private
|
78
|
-
def default_options
|
79
|
-
{plain: random}
|
80
|
-
end
|
81
|
-
|
82
|
-
def include_char?(letters)
|
83
|
-
raise PasswdError unless self.plain
|
84
|
-
self.plain.chars.uniq.each {|c| return true if letters.include?(c)}
|
85
|
-
false
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
data/lib/passwd/policy.rb
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
module Passwd
|
2
|
-
class Policy
|
3
|
-
VALID_OPTIONS = [
|
4
|
-
:min_length,
|
5
|
-
:require_lower,
|
6
|
-
:require_upper,
|
7
|
-
:require_number
|
8
|
-
].freeze
|
9
|
-
|
10
|
-
attr_accessor *VALID_OPTIONS
|
11
|
-
|
12
|
-
def initialize
|
13
|
-
reset
|
14
|
-
end
|
15
|
-
|
16
|
-
def configure
|
17
|
-
yield self
|
18
|
-
end
|
19
|
-
|
20
|
-
def reset
|
21
|
-
self.min_length = 8
|
22
|
-
self.require_lower = true
|
23
|
-
self.require_upper = false
|
24
|
-
self.require_number = true
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
data/lib/passwd/salt.rb
DELETED
@@ -1,50 +0,0 @@
|
|
1
|
-
module Passwd
|
2
|
-
class Salt
|
3
|
-
include Base
|
4
|
-
|
5
|
-
attr_reader :plain, :hash
|
6
|
-
|
7
|
-
def initialize(options = {})
|
8
|
-
options = default_options.merge(options)
|
9
|
-
|
10
|
-
@password = options[:password]
|
11
|
-
if options.has_key?(:hash)
|
12
|
-
@plain = nil
|
13
|
-
@hash = options[:hash]
|
14
|
-
else
|
15
|
-
@plain = options[:plain] || (raise ArgumentError)
|
16
|
-
@hash = digest_without_stretching(@plain)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
def update_plain(value)
|
21
|
-
@plain = value
|
22
|
-
@hash = digest_without_stretching(@plain)
|
23
|
-
update_password!
|
24
|
-
end
|
25
|
-
|
26
|
-
def update_hash(value)
|
27
|
-
@plain = nil
|
28
|
-
@hash = value
|
29
|
-
update_password!
|
30
|
-
end
|
31
|
-
|
32
|
-
def self.from_plain(value, password = nil)
|
33
|
-
new(plain: value, password: password)
|
34
|
-
end
|
35
|
-
|
36
|
-
def self.from_hash(value, password = nil)
|
37
|
-
new(hash: value, password: password)
|
38
|
-
end
|
39
|
-
|
40
|
-
private
|
41
|
-
def default_options
|
42
|
-
{plain: Time.now.to_s}
|
43
|
-
end
|
44
|
-
|
45
|
-
def update_password!
|
46
|
-
@password.rehash if @password && @password.plain
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|