passwd 0.1.3 → 0.4.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.
Files changed (41) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/ci.yml +28 -0
  3. data/.gitignore +11 -17
  4. data/.rubocop.yml +168 -0
  5. data/.ruby-version +1 -0
  6. data/Gemfile +3 -6
  7. data/LICENSE +21 -0
  8. data/README.md +89 -138
  9. data/Rakefile +5 -6
  10. data/bin/console +7 -0
  11. data/bin/setup +8 -0
  12. data/lib/generators/passwd/install/USAGE +5 -0
  13. data/lib/generators/passwd/install/install_generator.rb +10 -0
  14. data/lib/generators/passwd/install/templates/passwd.rb +21 -0
  15. data/lib/passwd.rb +33 -6
  16. data/lib/passwd/config.rb +27 -0
  17. data/lib/passwd/errors.rb +4 -0
  18. data/lib/passwd/rails/action_controller_ext.rb +78 -0
  19. data/lib/passwd/rails/active_record_ext.rb +35 -0
  20. data/lib/passwd/railtie.rb +18 -0
  21. data/lib/passwd/version.rb +2 -4
  22. data/passwd.gemspec +20 -11
  23. metadata +83 -53
  24. data/.coveralls.yml +0 -1
  25. data/.travis.yml +0 -10
  26. data/LICENSE.txt +0 -22
  27. data/lib/passwd/active_record.rb +0 -58
  28. data/lib/passwd/base.rb +0 -72
  29. data/lib/passwd/configuration/abstract_config.rb +0 -36
  30. data/lib/passwd/configuration/config.rb +0 -23
  31. data/lib/passwd/configuration/policy.rb +0 -46
  32. data/lib/passwd/configuration/tmp_config.rb +0 -18
  33. data/lib/passwd/password.rb +0 -41
  34. data/samples/activerecord/user.rake +0 -28
  35. data/spec/passwd/active_record_spec.rb +0 -142
  36. data/spec/passwd/base_spec.rb +0 -224
  37. data/spec/passwd/configuration/config_spec.rb +0 -242
  38. data/spec/passwd/configuration/policy_spec.rb +0 -133
  39. data/spec/passwd/configuration/tmp_config_spec.rb +0 -257
  40. data/spec/passwd/password_spec.rb +0 -150
  41. data/spec/spec_helper.rb +0 -23
data/.coveralls.yml DELETED
@@ -1 +0,0 @@
1
- repo_token: 106V5oEIwXeOfqT35UWifTnifi5sEO2QP
data/.travis.yml DELETED
@@ -1,10 +0,0 @@
1
- language: ruby
2
- rvm:
3
- - 1.9.3
4
- - 2.0.0
5
- gemfile:
6
- - Gemfile
7
- script: bundle exec rake spec
8
- notifications:
9
- mails:
10
- - i2bskn@gmail.com
data/LICENSE.txt DELETED
@@ -1,22 +0,0 @@
1
- Copyright (c) 2013 i2bskn
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.
@@ -1,58 +0,0 @@
1
- # coding: utf-8
2
-
3
- module Passwd
4
- module ActiveRecord
5
- module ClassMethods
6
- def define_column(options={})
7
- id_name = options.fetch(:id, :email)
8
- salt_name = options.fetch(:salt, :salt)
9
- password_name = options.fetch(:password, :password)
10
-
11
- define_singleton_auth(id_name, salt_name, password_name)
12
- define_instance_auth(id_name, salt_name, password_name)
13
- define_set_password(id_name, salt_name, password_name)
14
- define_update_password(salt_name, password_name)
15
- end
16
-
17
- private
18
- def define_singleton_auth(id_name, salt_name, password_name)
19
- define_singleton_method :authenticate do |id, pass|
20
- user = self.where(id_name => id).first
21
- user if user && Passwd.auth(pass, user.send(salt_name), user.send(password_name))
22
- end
23
- end
24
-
25
- def define_instance_auth(id_name, salt_name, password_name)
26
- define_method :authenticate do |pass|
27
- Passwd.auth(pass, self.send(salt_name), self.send(password_name))
28
- end
29
- end
30
-
31
- def define_set_password(id_name, salt_name, password_name)
32
- define_method :set_password do |pass=nil|
33
- password = pass || Passwd.create
34
- salt = self.send(salt_name) || Passwd.hashing("#{self.send(id_name)}#{Time.now.to_s}")
35
- self.send("#{salt_name.to_s}=", salt)
36
- self.send("#{password_name.to_s}=", Passwd.hashing("#{salt}#{password}"))
37
- password
38
- end
39
- end
40
-
41
- def define_update_password(salt_name, password_name)
42
- define_method :update_password do |old_pass, new_pass|
43
- if Passwd.auth(old_pass, self.send(salt_name), self.send(password_name))
44
- set_password(new_pass)
45
- else
46
- false
47
- end
48
- end
49
- end
50
- end
51
-
52
- class << self
53
- def included(base)
54
- base.extend ClassMethods
55
- end
56
- end
57
- end
58
- end
data/lib/passwd/base.rb DELETED
@@ -1,72 +0,0 @@
1
- # coding: utf-8
2
-
3
- require "singleton"
4
- require "passwd/configuration/config"
5
- require "passwd/configuration/tmp_config"
6
- require "passwd/configuration/policy"
7
-
8
- module Passwd
9
- @config = Config.instance
10
- @policy = Policy.instance
11
-
12
- module Base
13
- def create(options={})
14
- if options.empty?
15
- config = @config
16
- else
17
- config = TmpConfig.new(@config, options)
18
- end
19
- Array.new(config.length){config.letters[rand(config.letters.size)]}.join
20
- end
21
-
22
- def auth(password_text, salt_hash, password_hash)
23
- enc_pass = Passwd.hashing("#{salt_hash}#{password_text}")
24
- password_hash == enc_pass
25
- end
26
-
27
- def hashing(plain)
28
- Digest::SHA1.hexdigest plain
29
- end
30
-
31
- def confirm_check(password, confirm, with_policy=false)
32
- return false if password != confirm
33
- return true unless with_policy
34
- Passwd.policy_check(password)
35
- end
36
-
37
- def configure(options={}, &block)
38
- if block_given?
39
- @config.configure &block
40
- else
41
- if options.empty?
42
- @config
43
- else
44
- @config.merge options
45
- end
46
- end
47
- end
48
- alias :config :configure
49
-
50
- def policy_configure(&block)
51
- if block_given?
52
- @policy.configure &block
53
- else
54
- @policy
55
- end
56
- end
57
-
58
- def policy_check(password)
59
- @policy.valid?(password, @config)
60
- end
61
-
62
- def reset_config
63
- @config.reset
64
- end
65
-
66
- def reset_policy
67
- @policy.reset
68
- end
69
- end
70
-
71
- extend Base
72
- end
@@ -1,36 +0,0 @@
1
- # coding: utf-8
2
-
3
- module Passwd
4
- class AbstractConfig
5
- VALID_OPTIONS_KEYS = [
6
- :length,
7
- :lower,
8
- :upper,
9
- :number,
10
- :letters_lower,
11
- :letters_upper,
12
- :letters_number
13
- ].freeze
14
-
15
- attr_accessor *VALID_OPTIONS_KEYS
16
-
17
- def configure
18
- yield self
19
- end
20
-
21
- def merge(configs)
22
- configs.keys.each do |k|
23
- send("#{k}=", configs[k])
24
- end
25
- end
26
-
27
- def letters
28
- chars = []
29
- chars.concat(self.letters_lower) if self.lower
30
- chars.concat(self.letters_upper) if self.upper
31
- chars.concat(self.letters_number) if self.number
32
- raise "letters is empty" if chars.empty?
33
- chars
34
- end
35
- end
36
- end
@@ -1,23 +0,0 @@
1
- # coding: utf-8
2
-
3
- require "passwd/configuration/abstract_config"
4
-
5
- module Passwd
6
- class Config < AbstractConfig
7
- include Singleton
8
-
9
- def initialize
10
- reset
11
- end
12
-
13
- def reset
14
- self.length = 8
15
- self.lower = true
16
- self.upper = true
17
- self.number = true
18
- self.letters_lower = ("a".."z").to_a
19
- self.letters_upper = ("A".."Z").to_a
20
- self.letters_number = ("0".."9").to_a
21
- end
22
- end
23
- end
@@ -1,46 +0,0 @@
1
- # coding: utf-8
2
-
3
- module Passwd
4
- class Policy
5
- include Singleton
6
-
7
- VALID_OPTIONS_KEYS = [
8
- :min_length,
9
- :require_lower,
10
- :require_upper,
11
- :require_number
12
- ].freeze
13
-
14
- attr_accessor *VALID_OPTIONS_KEYS
15
-
16
- def initialize
17
- reset
18
- end
19
-
20
- def configure
21
- yield self
22
- end
23
-
24
- def valid?(password, config)
25
- return false if self.min_length > password.size
26
- return false if self.require_lower && !include_char?(config.letters_lower, password)
27
- return false if self.require_upper && !include_char?(config.letters_upper, password)
28
- return false if self.require_number && !include_char?(config.letters_number, password)
29
- true
30
- end
31
-
32
- def include_char?(letters, strings)
33
- strings.each_char do |c|
34
- return true if letters.include? c
35
- end
36
- false
37
- end
38
-
39
- def reset
40
- self.min_length = 8
41
- self.require_lower = true
42
- self.require_upper = false
43
- self.require_number = true
44
- end
45
- end
46
- end
@@ -1,18 +0,0 @@
1
- # coding: utf-8
2
-
3
- require "passwd/configuration/abstract_config"
4
-
5
- module Passwd
6
- class TmpConfig < AbstractConfig
7
- def initialize(config, options)
8
- config.instance_variables.each do |v|
9
- key = v.to_s.sub(/^@/, "").to_sym
10
- if options.has_key? key
11
- instance_variable_set v, options[key]
12
- else
13
- instance_variable_set v, config.instance_variable_get(v)
14
- end
15
- end
16
- end
17
- end
18
- end
@@ -1,41 +0,0 @@
1
- # coding: utf-8
2
-
3
- module Passwd
4
- class Password
5
- attr_reader :text, :hash, :salt_text, :salt_hash
6
-
7
- def initialize(options={})
8
- @text = options.fetch(:password, Passwd.create)
9
- @salt_text = options.fetch(:salt_text, Time.now.to_s)
10
- @salt_hash = Passwd.hashing(@salt_text)
11
- @hash = Passwd.hashing("#{@salt_hash}#{@text}")
12
- end
13
-
14
- def text=(password)
15
- @hash = Passwd.hashing("#{@salt_hash}#{password}")
16
- @text = password
17
- end
18
-
19
- def hash=(password_hash)
20
- @text = nil
21
- @hash = password_hash
22
- end
23
-
24
- def salt_text=(salt_text)
25
- @salt_hash = Passwd.hashing(salt_text)
26
- @hash = Passwd.hashing("#{@salt_hash}#{@text}")
27
- @salt_text = salt_text
28
- end
29
-
30
- def salt_hash=(salt_hash)
31
- @salt_text = nil
32
- @hash = Passwd.hashing("#{salt_hash}#{@text}")
33
- @salt_hash = salt_hash
34
- end
35
-
36
- def ==(password)
37
- enc_pass = Passwd.hashing("#{@salt_hash}#{password}")
38
- @hash == enc_pass
39
- end
40
- end
41
- end
@@ -1,28 +0,0 @@
1
- namespace :user do
2
- # E.G. rake name="Taro Suzuki" email=taro@example.com password=secret user:create
3
- desc "create user (specify env of name and email and password)"
4
- task :create => :environment do
5
- raise ArgumentError, "email is required" if ENV["email"].nil?
6
- raise ArgumentError, "name is required" if ENV["name"].nil?
7
-
8
- raise "must be a unique email" if User.exists?(email: ENV["email"])
9
-
10
- user = User.new(name: ENV["name"], email: ENV["email"])
11
-
12
- password = user.set_password(ENV["password"])
13
- user.save!
14
- puts "Creating a user was successful.\nPassword: #{password}"
15
- end
16
-
17
- # E.G. rake email=taro@example.com password=secret user:password_update
18
- desc "update password (specify env of email and password)"
19
- task :password_update => :environment do
20
- raise ArgumentError, "email is required" if ENV["email"].nil?
21
- raise "must specify the email that exists" unless User.exists?(email: ENV["email"])
22
-
23
- user = User.find_by(email: ENV["email"])
24
- password = user.set_password(ENV["password"])
25
- user.save!
26
- puts "Password update was successful.\nPassword: #{password}"
27
- end
28
- end
@@ -1,142 +0,0 @@
1
- # coding: utf-8
2
-
3
- require "spec_helper"
4
-
5
- describe Passwd::ActiveRecord do
6
- class User
7
- include Passwd::ActiveRecord
8
- define_column
9
- end
10
-
11
- let(:salt) {Digest::SHA1.hexdigest("salt")}
12
- let(:password_text) {"secret"}
13
- let(:password_hash) {Digest::SHA1.hexdigest("#{salt}#{password_text}")}
14
-
15
- describe ".included" do
16
- it "define singleton methods" do
17
- expect(User.respond_to? :define_column).to be_true
18
- end
19
- end
20
-
21
- describe "extend methods" do
22
- describe ".define_column" do
23
- let(:user) {User.new}
24
-
25
- it "define singleton methods" do
26
- expect(User.respond_to? :authenticate).to be_true
27
- end
28
-
29
- it "define authenticate method" do
30
- expect(user.respond_to? :authenticate).to be_true
31
- end
32
-
33
- it "define set_password method" do
34
- expect(user.respond_to? :set_password).to be_true
35
- end
36
-
37
- it "define update_password" do
38
- expect(user.respond_to? :update_password).to be_true
39
- end
40
- end
41
- end
42
-
43
- describe "defined methods from define_column" do
44
- describe ".authenticate" do
45
- let!(:record) {
46
- record = double("record mock")
47
- record.stub(:salt).and_return(salt)
48
- record.stub(:password).and_return(password_hash)
49
- response = [record]
50
- User.stub(:where).and_return(response)
51
- record
52
- }
53
-
54
- it "user should be returned if authentication is successful" do
55
- User.should_receive(:where)
56
- expect(User.authenticate("valid_id", password_text)).to eq(record)
57
- end
58
-
59
- it "should return nil if authentication failed" do
60
- User.should_receive(:where)
61
- expect(User.authenticate("valid_id", "invalid_secret")).to be_nil
62
- end
63
-
64
- it "should return nil if user not found" do
65
- User.should_receive(:where).with(:email => "invalid_id").and_return([])
66
- expect(User.authenticate("invalid_id", password_text)).to be_nil
67
- end
68
- end
69
-
70
- describe "#authenticate" do
71
- let!(:user) {
72
- user = User.new
73
- user.stub(:salt).and_return(salt)
74
- user.stub(:password).and_return(password_hash)
75
- user
76
- }
77
-
78
- it "should return true if authentication is successful" do
79
- expect(user.authenticate(password_text)).to be_true
80
- end
81
-
82
- it "should return false if authentication failed" do
83
- expect(user.authenticate("invalid_pass")).to be_false
84
- end
85
- end
86
-
87
- describe "#set_password" do
88
- let!(:user) {
89
- user = User.new
90
- user.stub(:salt).and_return(salt)
91
- user
92
- }
93
-
94
- it "should return set password" do
95
- user.should_receive(:salt=).with(salt)
96
- user.should_receive(:password=).with(Passwd.hashing("#{salt}#{password_text}"))
97
- expect(user.set_password(password_text)).to eq(password_text)
98
- end
99
-
100
- it "should set random password if not specified" do
101
- user.should_receive(:salt=).with(salt)
102
- random_password = Passwd.create
103
- Passwd.should_receive(:create).and_return(random_password)
104
- user.should_receive(:password=).with(Passwd.hashing("#{salt}#{random_password}"))
105
- user.set_password
106
- end
107
-
108
- it "should set salt if salt is nil" do
109
- mail_addr = "foo@example.com"
110
- time_now = Time.now
111
- salt2 = Passwd.hashing("#{mail_addr}#{time_now.to_s}")
112
- Time.stub(:now).and_return(time_now)
113
- user.stub(:email).and_return(mail_addr)
114
- user.should_receive(:salt).and_return(nil)
115
- user.should_receive(:salt=).with(salt2)
116
- user.should_receive(:password=).with(Passwd.hashing("#{salt2}#{password_text}"))
117
- user.set_password(password_text)
118
- end
119
- end
120
-
121
- describe "#update_password" do
122
- let!(:user) {
123
- user = User.new
124
- user.stub(:salt).and_return(salt)
125
- user.stub(:password).and_return(password_hash)
126
- user
127
- }
128
-
129
- it "should return update password" do
130
- pass = "new_password"
131
- user.should_receive(:set_password).with(pass).and_return(pass)
132
- expect(user.update_password(password_text, pass)).to eq(pass)
133
- end
134
-
135
- it "should return false if authentication failed" do
136
- Passwd.should_receive(:auth).and_return(false)
137
- user.should_not_receive(:set_password)
138
- user.update_password("invalid_password", "new_password")
139
- end
140
- end
141
- end
142
- end