devise_challenge_questionable 2.0.0 → 3.3.2
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 +7 -7
- data/.gitignore +1 -0
- data/README.md +12 -8
- data/app/controllers/devise/challenge_questions_controller.rb +39 -32
- data/app/views/devise/challenge_questions/edit.html.erb +7 -22
- data/devise_challenge_questionable.gemspec +3 -3
- data/lib/devise_challenge_questionable/controllers/helpers.rb +2 -2
- data/lib/devise_challenge_questionable/mailer.rb +2 -2
- data/lib/devise_challenge_questionable/model.rb +16 -13
- data/lib/devise_challenge_questionable/version.rb +1 -1
- data/lib/generators/devise_challenge_questionable/templates/challenge_question_model.rb +11 -7
- metadata +59 -50
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
---
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: a77778f0523bd02065afa11b69367b3430cbb92a5359b8b8817d2723efabba4e
|
|
4
|
+
data.tar.gz: 6e91e372d2199dffaed5ade3eddf2d0a3e43eae70f0ba1ffe807915cafc217cb
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 24febe5a3b8ae5ff545e5f9a9498f3e0d6bad1e93e1176877e9436c5bc4326d37435c54296f31bf8f820a04fef3b306b8d23ef80d45caa37cda77548b4786542
|
|
7
|
+
data.tar.gz: 3ac583e0d4c08d5f3ab00f973a88a7b801649201444a386ae496d2b68c39ecb4dff32c526f23f2ba1b375e563bd5048816a5656537a42cb13821421b943b4876
|
data/.gitignore
CHANGED
data/README.md
CHANGED
|
@@ -26,9 +26,9 @@ Once that's done, run:
|
|
|
26
26
|
In order to add challenge questions to a model, run the command:
|
|
27
27
|
|
|
28
28
|
bundle exec rails g devise_challenge_questionable MODEL
|
|
29
|
-
|
|
29
|
+
|
|
30
30
|
bundle exec rails g devise_challenge_questionable:install
|
|
31
|
-
|
|
31
|
+
|
|
32
32
|
bundle exec rails g devise_challenge_questionable:views users
|
|
33
33
|
|
|
34
34
|
Where MODEL is your model name (e.g. User or Admin). This generator will add `:challenge_questionable` to your model
|
|
@@ -45,9 +45,9 @@ To manually enable challenge questions for the User model, you should add the fo
|
|
|
45
45
|
```ruby
|
|
46
46
|
has_many :user_challenge_questions, :validate => true, :inverse_of => :user
|
|
47
47
|
accepts_nested_attributes_for :user_challenge_questions, :allow_destroy => true
|
|
48
|
-
|
|
48
|
+
|
|
49
49
|
devise :challenge_questionable
|
|
50
|
-
|
|
50
|
+
|
|
51
51
|
attr_accessible :user_challenge_questions_attributes
|
|
52
52
|
```
|
|
53
53
|
|
|
@@ -68,9 +68,13 @@ You also need to add the `user_challenge_question.rb` Model.
|
|
|
68
68
|
before_save :digest_challenge_answer
|
|
69
69
|
|
|
70
70
|
def digest_challenge_answer
|
|
71
|
-
|
|
71
|
+
if ENV['PASSWORD_PEPPER']
|
|
72
|
+
write_attribute(:challenge_answer, ::BCrypt::Password.create(self.challenge_answer.downcase + ENV['PASSWORD_PEPPER'], :cost => Devise.stretches)) unless self.challenge_answer.nil?
|
|
73
|
+
else
|
|
74
|
+
write_attribute(:challenge_answer, ::BCrypt::Password.create(self.challenge_answer.downcase, :cost => Devise.stretches)) unless self.challenge_answer.nil?
|
|
75
|
+
end
|
|
72
76
|
end
|
|
73
|
-
|
|
77
|
+
|
|
74
78
|
private
|
|
75
79
|
def challenge_question_uniqueness
|
|
76
80
|
if self.challenge_question.present? && self.user.user_challenge_questions.select{|q| q.challenge_question == self.challenge_question}.count > 1
|
|
@@ -83,7 +87,7 @@ You also need to add the `user_challenge_question.rb` Model.
|
|
|
83
87
|
errors.add(:challenge_answer, 'can only be used once')
|
|
84
88
|
end
|
|
85
89
|
end
|
|
86
|
-
|
|
90
|
+
|
|
87
91
|
def challenge_answer_repeating
|
|
88
92
|
if self.challenge_answer.present? && self.challenge_answer =~ /(.)\1{2,}/
|
|
89
93
|
errors.add(:challenge_answer, 'can not have more then two repeating characters in a row')
|
|
@@ -132,7 +136,7 @@ By default challenge questions are enabled for each user, you can change it with
|
|
|
132
136
|
def login_challenge_questions?(request)
|
|
133
137
|
request.ip != '127.0.0.1'
|
|
134
138
|
end
|
|
135
|
-
|
|
139
|
+
|
|
136
140
|
def set_challenge_questions?(request)
|
|
137
141
|
request.ip != '127.0.0.1'
|
|
138
142
|
end
|
|
@@ -1,43 +1,43 @@
|
|
|
1
1
|
class Devise::ChallengeQuestionsController < DeviseController
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
prepend_before_action :require_no_authentication, :only => [ :new, :create, :edit, :update, :max_challenge_question_attempts_reached ]
|
|
4
|
+
prepend_before_action :authenticate_scope!, :only => [:show, :authenticate, :manage, :forgot]
|
|
5
|
+
before_action :prepare_and_validate, :handle_challenge_questions, :only => [:show, :authenticate]
|
|
6
|
+
|
|
7
7
|
# GET /resource/challenge_question/new
|
|
8
8
|
def new
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
self.resource = resource_class.new
|
|
10
|
+
render :new
|
|
11
11
|
end
|
|
12
|
-
|
|
12
|
+
|
|
13
13
|
# POST /resource/challenge_question
|
|
14
14
|
def create
|
|
15
15
|
self.resource = resource_class.send_reset_challenge_questions_instructions(params[resource_name])
|
|
16
16
|
if resource.errors.empty?
|
|
17
17
|
set_flash_message :notice, :send_instructions
|
|
18
|
-
redirect_to
|
|
18
|
+
redirect_to home_path
|
|
19
19
|
else
|
|
20
|
-
|
|
20
|
+
render :new
|
|
21
21
|
end
|
|
22
22
|
end
|
|
23
|
-
|
|
23
|
+
|
|
24
24
|
# GET /resource/challenge_question/edit?reset_challenge_questions_token=abcdef
|
|
25
25
|
def edit
|
|
26
26
|
self.resource = resource_class.new
|
|
27
27
|
resource.reset_challenge_questions_token = params[:reset_challenge_questions_token]
|
|
28
28
|
Devise.number_of_challenge_questions_stored.times { resource.send("#{resource_name}_challenge_questions").build }
|
|
29
|
-
|
|
29
|
+
render :edit
|
|
30
30
|
end
|
|
31
|
-
|
|
31
|
+
|
|
32
32
|
# PUT /resource/challenge_question
|
|
33
33
|
def update
|
|
34
34
|
self.resource = resource_class.reset_challenge_questions_by_token(params[resource_name])
|
|
35
35
|
|
|
36
36
|
if resource.errors.empty?
|
|
37
37
|
set_flash_message :notice, :updated_challenge_questions
|
|
38
|
-
|
|
38
|
+
sign_in_and_redirect(resource)
|
|
39
39
|
else
|
|
40
|
-
|
|
40
|
+
render :edit
|
|
41
41
|
end
|
|
42
42
|
end
|
|
43
43
|
|
|
@@ -45,11 +45,11 @@ class Devise::ChallengeQuestionsController < DeviseController
|
|
|
45
45
|
def show
|
|
46
46
|
@challenge_questions = resource.send("#{resource_name}_challenge_questions").sample(params[:limit].try(:to_i) || Devise.number_of_challenge_questions_asked)
|
|
47
47
|
respond_to do |format|
|
|
48
|
-
format.html {
|
|
48
|
+
format.html { render :show }
|
|
49
49
|
format.json { render :json => @challenge_questions.as_json(:only => [:id, :challenge_question]) }
|
|
50
50
|
end
|
|
51
51
|
end
|
|
52
|
-
|
|
52
|
+
|
|
53
53
|
def authenticate
|
|
54
54
|
build_challenge_questions
|
|
55
55
|
if @challenge_questions.present? && challenge_questions_authenticated?
|
|
@@ -61,21 +61,21 @@ class Devise::ChallengeQuestionsController < DeviseController
|
|
|
61
61
|
else
|
|
62
62
|
failed_attempts
|
|
63
63
|
end
|
|
64
|
-
end
|
|
64
|
+
end
|
|
65
65
|
end
|
|
66
|
-
|
|
66
|
+
|
|
67
67
|
# Build token and redirect
|
|
68
68
|
def manage
|
|
69
69
|
resource.set_reset_challenge_questions_token
|
|
70
70
|
sign_out(resource)
|
|
71
|
-
redirect_to
|
|
71
|
+
redirect_to edit_user_challenge_question_path(resource, :reset_challenge_questions_token => resource.reset_challenge_questions_token)
|
|
72
72
|
end
|
|
73
|
-
|
|
73
|
+
|
|
74
74
|
def forgot
|
|
75
75
|
sign_out(resource)
|
|
76
|
-
redirect_to
|
|
76
|
+
redirect_to new_user_challenge_question_path(resource_name)
|
|
77
77
|
end
|
|
78
|
-
|
|
78
|
+
|
|
79
79
|
def max_challenge_question_attempts_reached
|
|
80
80
|
end
|
|
81
81
|
|
|
@@ -90,21 +90,28 @@ class Devise::ChallengeQuestionsController < DeviseController
|
|
|
90
90
|
@limit = resource.class.max_challenge_question_attempts
|
|
91
91
|
if resource.max_challenge_question_attempts?
|
|
92
92
|
sign_out(resource)
|
|
93
|
-
|
|
93
|
+
render :max_challenge_question_attempts_reached and return
|
|
94
94
|
end
|
|
95
95
|
end
|
|
96
|
-
|
|
96
|
+
|
|
97
97
|
def challenge_questions_authenticated?
|
|
98
|
-
@challenge_questions.all?
|
|
98
|
+
@challenge_questions.all? do |question|
|
|
99
|
+
@user_hash = ::BCrypt::Password.new(question[:answer])
|
|
100
|
+
if ENV['PASSWORD_PEPPER']
|
|
101
|
+
@user_hash.is_password?(question[:challenge_answer].try(:downcase) + ENV['PASSWORD_PEPPER'])
|
|
102
|
+
else
|
|
103
|
+
@user_hash.is_password?(question[:challenge_answer].try(:downcase))
|
|
104
|
+
end
|
|
105
|
+
end
|
|
99
106
|
end
|
|
100
|
-
|
|
107
|
+
|
|
101
108
|
def build_challenge_questions
|
|
102
109
|
respond_to do |format|
|
|
103
110
|
format.html { @challenge_questions = (params[:challenge_questions] || []).map{|cq, params| params.merge(:answer => resource.send("#{resource_name}_challenge_questions").find(params[:id]).challenge_answer)} }
|
|
104
111
|
format.json { @challenge_questions = (params[:challenge_questions] || []).map{|cq| cq.merge(:answer => resource.send("#{resource_name}_challenge_questions").find(cq[:id]).challenge_answer)} }
|
|
105
112
|
end
|
|
106
113
|
end
|
|
107
|
-
|
|
114
|
+
|
|
108
115
|
def challenge_questions_authenticated
|
|
109
116
|
respond_to do |format|
|
|
110
117
|
format.html do
|
|
@@ -115,25 +122,25 @@ class Devise::ChallengeQuestionsController < DeviseController
|
|
|
115
122
|
end
|
|
116
123
|
resource.update_attribute(:challenge_question_failed_attempts, 0)
|
|
117
124
|
end
|
|
118
|
-
|
|
125
|
+
|
|
119
126
|
def set_failed_attempt
|
|
120
127
|
resource.challenge_question_failed_attempts += 1
|
|
121
128
|
resource.save
|
|
122
129
|
end
|
|
123
|
-
|
|
130
|
+
|
|
124
131
|
def max_failed_attempts
|
|
125
132
|
resource.max_challenge_question_lock_account
|
|
126
133
|
sign_out(resource)
|
|
127
134
|
respond_to do |format|
|
|
128
|
-
format.html {
|
|
135
|
+
format.html { render :max_challenge_question_attempts_reached and return }
|
|
129
136
|
format.json { render :json => {:max_attempts_reached => true, :errors => I18n.t(:"#{resource_name}.#{:max_attempts_reached}", :resource_name => resource_name, :scope => [:devise, controller_name.to_sym], :default => :attempt_failed)} }
|
|
130
137
|
end
|
|
131
138
|
end
|
|
132
|
-
|
|
139
|
+
|
|
133
140
|
def failed_attempts
|
|
134
141
|
respond_to do |format|
|
|
135
142
|
format.html { redirect_to send("#{resource_name}_challenge_question_path" ) }
|
|
136
143
|
format.json { render :json => {:errors => I18n.t(:"#{resource_name}.#{:attempt_failed}", :resource_name => resource_name, :scope => [:devise, controller_name.to_sym], :default => :attempt_failed)} }
|
|
137
144
|
end
|
|
138
145
|
end
|
|
139
|
-
end
|
|
146
|
+
end
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
<%= devise_error_messages! %>
|
|
8
8
|
<%= f.hidden_field :id %>
|
|
9
9
|
<%= f.hidden_field :reset_challenge_questions_token %>
|
|
10
|
-
|
|
10
|
+
|
|
11
11
|
<%= f.fields_for :"#{resource_name}_challenge_questions", resource.send("#{resource_name}_challenge_questions") do |cq| %>
|
|
12
12
|
<% if cq.object.new_record? %>
|
|
13
13
|
<p>
|
|
@@ -40,25 +40,10 @@
|
|
|
40
40
|
|
|
41
41
|
<script type="text/javascript" language="javascript">
|
|
42
42
|
if (window.jQuery) {
|
|
43
|
-
|
|
44
|
-
$
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
otherSelects.find('option:contains('+ $(this).val() +')').attr('disabled', 'disabled');
|
|
49
|
-
if (prevVal) {
|
|
50
|
-
otherSelects.find('option:contains('+ prevVal +')').removeAttr('disabled');
|
|
51
|
-
}
|
|
52
|
-
$this.data("prev", $this.val());
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
$("select").each(function () {
|
|
56
|
-
var $this = $(this);
|
|
57
|
-
var prevVal = $this.data("prev");
|
|
58
|
-
var otherSelects = $("select").not(this);
|
|
59
|
-
otherSelects.find('option:contains('+ $(this).val() +')').attr('disabled', 'disabled');
|
|
60
|
-
$this.data("prev", $this.val());
|
|
61
|
-
});
|
|
62
|
-
});
|
|
43
|
+
$('select').on('change', function(e) {
|
|
44
|
+
var $this = $(this);
|
|
45
|
+
var otherSelects = $("select").not(this);
|
|
46
|
+
otherSelects.find('option:contains('+ $(this).val() +')').attr('disabled','disabled')
|
|
47
|
+
})
|
|
63
48
|
}
|
|
64
|
-
</script>
|
|
49
|
+
</script>
|
|
@@ -12,7 +12,7 @@ Gem::Specification.new do |s|
|
|
|
12
12
|
s.description = <<-EOF
|
|
13
13
|
### Features ###
|
|
14
14
|
* configure max challenge question attempts
|
|
15
|
-
* per user level control if
|
|
15
|
+
* per user level control if they really need challenge questions
|
|
16
16
|
EOF
|
|
17
17
|
|
|
18
18
|
s.rubyforge_project = "devise_challenge_questionable"
|
|
@@ -22,8 +22,8 @@ Gem::Specification.new do |s|
|
|
|
22
22
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
|
23
23
|
s.require_paths = ["lib"]
|
|
24
24
|
|
|
25
|
-
s.add_runtime_dependency 'rails', '>=
|
|
26
|
-
s.add_runtime_dependency 'devise', '>=
|
|
25
|
+
s.add_runtime_dependency 'rails', '>= 5.0.0'
|
|
26
|
+
s.add_runtime_dependency 'devise', '>= 4.0.0'
|
|
27
27
|
|
|
28
28
|
s.add_development_dependency 'bundler'
|
|
29
29
|
end
|
|
@@ -4,7 +4,7 @@ module DeviseChallengeQuestionable
|
|
|
4
4
|
extend ActiveSupport::Concern
|
|
5
5
|
|
|
6
6
|
included do
|
|
7
|
-
|
|
7
|
+
before_action :handle_challenge_questions
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
private
|
|
@@ -51,4 +51,4 @@ module DeviseChallengeQuestionable
|
|
|
51
51
|
|
|
52
52
|
end
|
|
53
53
|
end
|
|
54
|
-
end
|
|
54
|
+
end
|
|
@@ -2,7 +2,7 @@ module DeviseChallengeQuestionable
|
|
|
2
2
|
module Mailer
|
|
3
3
|
# Deliver reset challenge question instructions when is requested
|
|
4
4
|
def reset_challenge_questions_instructions(record)
|
|
5
|
-
|
|
5
|
+
devise_mail(record, :reset_challenge_questions_instructions)
|
|
6
6
|
end
|
|
7
7
|
end
|
|
8
|
-
end
|
|
8
|
+
end
|
|
@@ -3,12 +3,12 @@ module Devise
|
|
|
3
3
|
module Models
|
|
4
4
|
module ChallengeQuestionable
|
|
5
5
|
extend ActiveSupport::Concern
|
|
6
|
-
|
|
6
|
+
|
|
7
7
|
# Update challenge questions saving the record and clearing token. Returns true if
|
|
8
8
|
# the challenge questions are valid and the record was saved, false otherwise.
|
|
9
9
|
def reset_challenge_questions!(attributes)
|
|
10
10
|
self.send("#{self.class.name.underscore}_challenge_questions").destroy_all
|
|
11
|
-
self.attributes = {"#{self.class.name.underscore}_challenge_questions_attributes" => attributes["#{self.class.name.underscore}_challenge_questions_attributes"]}
|
|
11
|
+
self.attributes = {"#{self.class.name.underscore}_challenge_questions_attributes" => attributes["#{self.class.name.underscore}_challenge_questions_attributes"]}
|
|
12
12
|
clear_reset_challenge_questions_token if self.valid?
|
|
13
13
|
self.save
|
|
14
14
|
end
|
|
@@ -16,11 +16,11 @@ module Devise
|
|
|
16
16
|
def login_challenge_questions?(request)
|
|
17
17
|
true
|
|
18
18
|
end
|
|
19
|
-
|
|
19
|
+
|
|
20
20
|
def set_challenge_questions?(request)
|
|
21
21
|
true
|
|
22
22
|
end
|
|
23
|
-
|
|
23
|
+
|
|
24
24
|
def max_challenge_question_lock_account
|
|
25
25
|
self.lock_access! if self.class.lock_strategy_enabled?(:failed_attempts)
|
|
26
26
|
end
|
|
@@ -28,18 +28,18 @@ module Devise
|
|
|
28
28
|
def max_challenge_question_attempts?
|
|
29
29
|
challenge_question_failed_attempts >= self.class.max_challenge_question_attempts
|
|
30
30
|
end
|
|
31
|
-
|
|
31
|
+
|
|
32
32
|
# Resets reset challenge question token and send reset challenge question instructions by email
|
|
33
33
|
def send_reset_challenge_questions_instructions
|
|
34
34
|
generate_reset_challenge_questions_token!
|
|
35
35
|
::Devise.mailer.reset_challenge_questions_instructions(self).deliver
|
|
36
36
|
end
|
|
37
|
-
|
|
37
|
+
|
|
38
38
|
# Generates a new random token for reset challenge_question
|
|
39
39
|
def set_reset_challenge_questions_token
|
|
40
40
|
generate_reset_challenge_questions_token!
|
|
41
41
|
end
|
|
42
|
-
|
|
42
|
+
|
|
43
43
|
def unlock_access_including_challenge_questions!
|
|
44
44
|
if_access_locked do
|
|
45
45
|
self.locked_at = nil
|
|
@@ -49,7 +49,7 @@ module Devise
|
|
|
49
49
|
save(:validate => false)
|
|
50
50
|
end
|
|
51
51
|
end
|
|
52
|
-
|
|
52
|
+
|
|
53
53
|
protected
|
|
54
54
|
|
|
55
55
|
# Generates a new random token for reset challenge_question
|
|
@@ -67,14 +67,14 @@ module Devise
|
|
|
67
67
|
def clear_reset_challenge_questions_token
|
|
68
68
|
self.reset_challenge_questions_token = nil
|
|
69
69
|
end
|
|
70
|
-
|
|
70
|
+
|
|
71
71
|
def clear_challenge_question_failed_attempts
|
|
72
72
|
self.challenge_question_failed_attempts = 0
|
|
73
73
|
end
|
|
74
|
-
|
|
74
|
+
|
|
75
75
|
module ClassMethods
|
|
76
76
|
::Devise::Models.config(self, :max_challenge_question_attempts)
|
|
77
|
-
|
|
77
|
+
|
|
78
78
|
# Attempt to find a user by it's email. If a record is found, send new
|
|
79
79
|
# challenge_question instructions to it. If not user is found, returns a new user
|
|
80
80
|
# with an email not found error.
|
|
@@ -87,7 +87,10 @@ module Devise
|
|
|
87
87
|
|
|
88
88
|
# Generate a token checking if one does not already exist in the database.
|
|
89
89
|
def reset_challenge_questions_token
|
|
90
|
-
|
|
90
|
+
loop do
|
|
91
|
+
token = Devise.friendly_token
|
|
92
|
+
break token unless User.find_by(:reset_challenge_questions_token => token)
|
|
93
|
+
end
|
|
91
94
|
end
|
|
92
95
|
|
|
93
96
|
# Attempt to find a user by it's reset_challenge_questions_token to reset it's
|
|
@@ -103,4 +106,4 @@ module Devise
|
|
|
103
106
|
end
|
|
104
107
|
end
|
|
105
108
|
end
|
|
106
|
-
end
|
|
109
|
+
end
|
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
class <%= class_name %>ChallengeQuestion < ActiveRecord::Base
|
|
2
|
-
|
|
2
|
+
|
|
3
3
|
belongs_to :<%= class_name.underscore %>
|
|
4
|
-
|
|
4
|
+
|
|
5
5
|
validates :challenge_question, :uniqueness => {:scope => :<%= class_name.underscore %>_id}
|
|
6
6
|
validates :challenge_answer, :presence => true
|
|
7
|
-
|
|
7
|
+
|
|
8
8
|
before_save :digest_challenge_answer
|
|
9
|
-
|
|
9
|
+
|
|
10
10
|
def digest_challenge_answer
|
|
11
|
-
|
|
11
|
+
if ENV['PASSWORD_PEPPER']
|
|
12
|
+
write_attribute(:challenge_answer, ::BCrypt::Password.create(self.challenge_answer.downcase + ENV['PASSWORD_PEPPER'], :cost => Devise.stretches)) unless self.challenge_answer.nil?
|
|
13
|
+
else
|
|
14
|
+
write_attribute(:challenge_answer, ::BCrypt::Password.create(self.challenge_answer.downcase, :cost => Devise.stretches)) unless self.challenge_answer.nil?
|
|
15
|
+
end
|
|
12
16
|
end
|
|
13
|
-
|
|
14
|
-
end
|
|
17
|
+
|
|
18
|
+
end
|
metadata
CHANGED
|
@@ -1,58 +1,68 @@
|
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: devise_challenge_questionable
|
|
3
|
-
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 3.3.2
|
|
5
5
|
platform: ruby
|
|
6
|
-
authors:
|
|
6
|
+
authors:
|
|
7
7
|
- Andrew Kennedy
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
- !ruby/object:Gem::Dependency
|
|
11
|
+
date: 2020-05-27 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
15
14
|
name: rails
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
requirements:
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
19
17
|
- - ">="
|
|
20
|
-
- !ruby/object:Gem::Version
|
|
21
|
-
version:
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: 5.0.0
|
|
22
20
|
type: :runtime
|
|
23
|
-
version_requirements: *id001
|
|
24
|
-
- !ruby/object:Gem::Dependency
|
|
25
|
-
name: devise
|
|
26
21
|
prerelease: false
|
|
27
|
-
|
|
28
|
-
requirements:
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
29
24
|
- - ">="
|
|
30
|
-
- !ruby/object:Gem::Version
|
|
31
|
-
version:
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: 5.0.0
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: devise
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - ">="
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: 4.0.0
|
|
32
34
|
type: :runtime
|
|
33
|
-
version_requirements: *id002
|
|
34
|
-
- !ruby/object:Gem::Dependency
|
|
35
|
-
name: bundler
|
|
36
35
|
prerelease: false
|
|
37
|
-
|
|
38
|
-
requirements:
|
|
39
|
-
-
|
|
40
|
-
-
|
|
41
|
-
|
|
42
|
-
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ">="
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: 4.0.0
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: bundler
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - ">="
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '0'
|
|
43
48
|
type: :development
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - ">="
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '0'
|
|
55
|
+
description: |2
|
|
56
|
+
### Features ###
|
|
57
|
+
* configure max challenge question attempts
|
|
58
|
+
* per user level control if they really need challenge questions
|
|
59
|
+
email:
|
|
47
60
|
- andrew@akennedy.io
|
|
48
61
|
executables: []
|
|
49
|
-
|
|
50
62
|
extensions: []
|
|
51
|
-
|
|
52
63
|
extra_rdoc_files: []
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
- .gitignore
|
|
64
|
+
files:
|
|
65
|
+
- ".gitignore"
|
|
56
66
|
- Gemfile
|
|
57
67
|
- README.md
|
|
58
68
|
- Rakefile
|
|
@@ -82,26 +92,25 @@ files:
|
|
|
82
92
|
- lib/generators/devise_challenge_questionable/views_generator.rb
|
|
83
93
|
homepage: https://github.com/akennedy/devise_challenge_questionable
|
|
84
94
|
licenses: []
|
|
85
|
-
|
|
86
95
|
metadata: {}
|
|
87
|
-
|
|
88
96
|
post_install_message:
|
|
89
97
|
rdoc_options: []
|
|
90
|
-
|
|
91
|
-
require_paths:
|
|
98
|
+
require_paths:
|
|
92
99
|
- lib
|
|
93
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
|
94
|
-
requirements:
|
|
95
|
-
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
100
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
101
|
+
requirements:
|
|
102
|
+
- - ">="
|
|
103
|
+
- !ruby/object:Gem::Version
|
|
104
|
+
version: '0'
|
|
105
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
106
|
+
requirements:
|
|
107
|
+
- - ">="
|
|
108
|
+
- !ruby/object:Gem::Version
|
|
109
|
+
version: '0'
|
|
99
110
|
requirements: []
|
|
100
|
-
|
|
101
111
|
rubyforge_project: devise_challenge_questionable
|
|
102
|
-
rubygems_version: 2.
|
|
112
|
+
rubygems_version: 2.7.8
|
|
103
113
|
signing_key:
|
|
104
114
|
specification_version: 4
|
|
105
115
|
summary: Challenge question plugin for devise
|
|
106
116
|
test_files: []
|
|
107
|
-
|