devise_custom_authenticatable 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +1 -1
- data/CHANGELOG.md +5 -0
- data/README.md +23 -2
- data/devise_custom_authenticatable.gemspec +1 -0
- data/lib/devise/models/custom_authenticatable.rb +11 -0
- data/lib/devise/strategies/custom_authenticatable.rb +5 -16
- data/lib/devise_custom_authenticatable/version.rb +1 -1
- data/spec/devise/models/custom_authenticatable_spec.rb +0 -4
- data/spec/devise/strategies/custom_authenticatable_spec.rb +55 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/support/helpers.rb +9 -0
- metadata +44 -10
- checksums.yaml +0 -7
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -13,3 +13,8 @@
|
|
13
13
|
## v0.1.1
|
14
14
|
|
15
15
|
* Checked and confirmed that all functionality work with devise >= 2.0
|
16
|
+
|
17
|
+
## v0.2.0
|
18
|
+
|
19
|
+
* Feature: fail authentication if `#valid_for_custom_authentication?` returns false (use `#skip_custom_strategies` in order to pass to another stategy)
|
20
|
+
* Feature: `#after_custom_authentication` method added
|
data/README.md
CHANGED
@@ -25,7 +25,7 @@ Or install it yourself as:
|
|
25
25
|
|
26
26
|
## Usage
|
27
27
|
|
28
|
-
[Devise](http://github.com/plataformatec/devise) should be already installed and enabled for any resource in your app. Open Devise enabled model and add `:custom_authenticatable`. When strategy is enabled it'll try to call `#valid_for_custom_authentication?` method on resource model with password. Define this method and return true in order to authenticate user. If there is no such method for model
|
28
|
+
[Devise](http://github.com/plataformatec/devise) should be already installed and enabled for any resource in your app. Open Devise enabled model and add `:custom_authenticatable`. When strategy is enabled it'll try to call `#valid_for_custom_authentication?` method on resource model with password. Define this method and return true in order to authenticate user or false in order to fail authentication. If there is no such method for model then authentication handling will be passed to next strategy e.g. `:database_authenticatable`, if there is no other strategies left for resource then authentication will be failed. For example:
|
29
29
|
|
30
30
|
```ruby
|
31
31
|
devise :custom_authenticatable, :database_authenticatable, :trackable, :lockable, :timeoutable
|
@@ -40,7 +40,9 @@ Or install it yourself as:
|
|
40
40
|
end
|
41
41
|
```
|
42
42
|
|
43
|
-
This gem also provide handy
|
43
|
+
###This gem also provide few handy helpers
|
44
|
+
|
45
|
+
Use `#authenticated_by_any_custom_strategy?` when for example you would like to provide LDAP authentication for users, but also would like to have some dummy password in development environments. You can write something like this:
|
44
46
|
|
45
47
|
```ruby
|
46
48
|
class User
|
@@ -75,6 +77,25 @@ It will call all `authenticated_by_<strategy_name>_strategy?(password)` in turn
|
|
75
77
|
end
|
76
78
|
```
|
77
79
|
|
80
|
+
Use `#skip_custom_strategies` when you would like to conditionaly skip entire custom authentication, so for example in order to provide some custom care for admin users you could write something like this:
|
81
|
+
|
82
|
+
```ruby
|
83
|
+
class User
|
84
|
+
devise :custom_authenticatable, :trackable, :lockable, :timeoutable
|
85
|
+
# ...
|
86
|
+
|
87
|
+
def valid_for_custom_authentication?(password)
|
88
|
+
if self.has_role?(:admin)
|
89
|
+
# Your admin user authentication logic goes here and returns either true or false
|
90
|
+
else
|
91
|
+
skip_custom_strategies
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
```
|
96
|
+
|
97
|
+
Use `#after_custom_authentication` in order to insert your own logic that is only run after the user successfully authenticates
|
98
|
+
|
78
99
|
|
79
100
|
## TODO
|
80
101
|
|
@@ -19,6 +19,7 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
21
|
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
22
23
|
spec.add_development_dependency "rspec", "~> 2.0"
|
23
24
|
|
24
25
|
spec.add_dependency "devise", ">= 2", "< 4"
|
@@ -14,5 +14,16 @@ module Devise::Models
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
+
def skip_custom_strategies
|
18
|
+
throw :skip_custom_strategies
|
19
|
+
end
|
20
|
+
|
21
|
+
# A callback initiated after successfully authenticating. This can be
|
22
|
+
# used to insert your own logic that is only run after the user successfully
|
23
|
+
# authenticates.
|
24
|
+
def after_custom_authentication
|
25
|
+
|
26
|
+
end
|
27
|
+
|
17
28
|
end
|
18
29
|
end
|
@@ -8,22 +8,11 @@ module Devise::Strategies
|
|
8
8
|
resource = valid_password? && mapping.to.find_for_authentication(authentication_hash)
|
9
9
|
return pass unless resource.respond_to?(:valid_for_custom_authentication?)
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
end
|
17
|
-
|
18
|
-
# Override default Devise::Strategies::Authenticatable#validate method in order to *not* return fail! on flase,
|
19
|
-
# but pass handling to other strategies in stack, e.g default :database_authenticatable or other similar
|
20
|
-
# authentication will be failed with default message anyway if there are no strategies left
|
21
|
-
def validate(resource, &block)
|
22
|
-
if resource && resource.valid_for_authentication?(&block)
|
23
|
-
decorate(resource)
|
24
|
-
true
|
25
|
-
else
|
26
|
-
false
|
11
|
+
catch(:skip_custom_strategies) do
|
12
|
+
if validate(resource){ resource.valid_for_custom_authentication?(password) }
|
13
|
+
resource.after_custom_authentication
|
14
|
+
success!(resource)
|
15
|
+
end
|
27
16
|
end
|
28
17
|
end
|
29
18
|
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Devise::Models::CustomAuthenticatable do
|
4
|
+
before(:each) do
|
5
|
+
@resource = CustomAuthenticatableTestClass.new
|
6
|
+
@it = Devise::Strategies::CustomAuthenticatable.new(env_with_params, :user)
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "#authenticate!" do
|
10
|
+
before(:each) do
|
11
|
+
password_hash = { password: 'password' }
|
12
|
+
@it.stub( password_hash )
|
13
|
+
@it.stub(authentication_hash: password_hash)
|
14
|
+
@it.stub_chain(:mapping, :to, :find_for_authentication).and_return(@resource)
|
15
|
+
@it.stub(:validate) do |resource, &block|
|
16
|
+
expect(resource).to eq @resource
|
17
|
+
block.call
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should pass to another strategy if #valid_for_custom_authentication? is not defined" do
|
22
|
+
expect(@resource).to receive(:after_custom_authentication).never
|
23
|
+
expect(@it).to receive(:validate).never
|
24
|
+
expect(@it).to receive(:pass).once.and_return('skip')
|
25
|
+
expect(@it.authenticate!).to eq 'skip'
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should pass to another strategy if #skip_custom_strategies called in #valid_for_custom_authentication?" do
|
29
|
+
expect(@resource).to receive(:valid_for_custom_authentication?).with('password') do
|
30
|
+
@resource.skip_custom_strategies
|
31
|
+
end
|
32
|
+
expect(@resource).to receive(:after_custom_authentication).never
|
33
|
+
expect(@it).to receive(:success!).never
|
34
|
+
@it.authenticate!
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should fail if #valid_for_custom_authentication? is defined and return false" do
|
38
|
+
expect(@resource).to receive(:valid_for_custom_authentication?).with('password').and_return(false)
|
39
|
+
expect(@resource).to receive(:after_custom_authentication).never
|
40
|
+
expect(@it).to receive(:pass).never
|
41
|
+
expect(@it).to receive(:success!).never
|
42
|
+
@it.authenticate!
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should return with success! if #valid_for_custom_authentication? is defined and return true" do
|
46
|
+
expect(@resource).to receive(:valid_for_custom_authentication?).with('password').and_return(true)
|
47
|
+
expect(@it).to receive(:pass).never
|
48
|
+
expect(@resource).to receive(:after_custom_authentication).once
|
49
|
+
expect(@it).to receive(:success!).once.with(@resource).and_return('success')
|
50
|
+
expect(@it.authenticate!).to eq 'success'
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -0,0 +1,9 @@
|
|
1
|
+
class CustomAuthenticatableTestClass
|
2
|
+
include Devise::Models::CustomAuthenticatable
|
3
|
+
end
|
4
|
+
|
5
|
+
def env_with_params(path = "/", params = {}, env = {})
|
6
|
+
method = params.delete(:method) || "GET"
|
7
|
+
env = { 'HTTP_VERSION' => '1.1', 'REQUEST_METHOD' => "#{method}" }.merge(env)
|
8
|
+
Rack::MockRequest.env_for("#{path}?#{Rack::Utils.build_query(params)}", env)
|
9
|
+
end
|
metadata
CHANGED
@@ -1,18 +1,20 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: devise_custom_authenticatable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
|
+
prerelease:
|
5
6
|
platform: ruby
|
6
7
|
authors:
|
7
8
|
- Artūrs Mekšs
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date: 2014-02-
|
12
|
+
date: 2014-02-24 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
15
|
name: bundler
|
15
16
|
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
16
18
|
requirements:
|
17
19
|
- - ~>
|
18
20
|
- !ruby/object:Gem::Version
|
@@ -20,13 +22,31 @@ dependencies:
|
|
20
22
|
type: :development
|
21
23
|
prerelease: false
|
22
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
23
26
|
requirements:
|
24
27
|
- - ~>
|
25
28
|
- !ruby/object:Gem::Version
|
26
29
|
version: '1.3'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rake
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
27
46
|
- !ruby/object:Gem::Dependency
|
28
47
|
name: rspec
|
29
48
|
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
30
50
|
requirements:
|
31
51
|
- - ~>
|
32
52
|
- !ruby/object:Gem::Version
|
@@ -34,6 +54,7 @@ dependencies:
|
|
34
54
|
type: :development
|
35
55
|
prerelease: false
|
36
56
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
37
58
|
requirements:
|
38
59
|
- - ~>
|
39
60
|
- !ruby/object:Gem::Version
|
@@ -41,8 +62,9 @@ dependencies:
|
|
41
62
|
- !ruby/object:Gem::Dependency
|
42
63
|
name: devise
|
43
64
|
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
44
66
|
requirements:
|
45
|
-
- - '>='
|
67
|
+
- - ! '>='
|
46
68
|
- !ruby/object:Gem::Version
|
47
69
|
version: '2'
|
48
70
|
- - <
|
@@ -51,8 +73,9 @@ dependencies:
|
|
51
73
|
type: :runtime
|
52
74
|
prerelease: false
|
53
75
|
version_requirements: !ruby/object:Gem::Requirement
|
76
|
+
none: false
|
54
77
|
requirements:
|
55
|
-
- - '>='
|
78
|
+
- - ! '>='
|
56
79
|
- !ruby/object:Gem::Version
|
57
80
|
version: '2'
|
58
81
|
- - <
|
@@ -80,32 +103,43 @@ files:
|
|
80
103
|
- lib/devise_custom_authenticatable.rb
|
81
104
|
- lib/devise_custom_authenticatable/version.rb
|
82
105
|
- spec/devise/models/custom_authenticatable_spec.rb
|
106
|
+
- spec/devise/strategies/custom_authenticatable_spec.rb
|
83
107
|
- spec/spec_helper.rb
|
108
|
+
- spec/support/helpers.rb
|
84
109
|
homepage: https://github.com/AMekss/devise_custom_authenticatable
|
85
110
|
licenses:
|
86
111
|
- MIT
|
87
|
-
metadata: {}
|
88
112
|
post_install_message:
|
89
113
|
rdoc_options: []
|
90
114
|
require_paths:
|
91
115
|
- lib
|
92
116
|
required_ruby_version: !ruby/object:Gem::Requirement
|
117
|
+
none: false
|
93
118
|
requirements:
|
94
|
-
- - '>='
|
119
|
+
- - ! '>='
|
95
120
|
- !ruby/object:Gem::Version
|
96
121
|
version: '0'
|
122
|
+
segments:
|
123
|
+
- 0
|
124
|
+
hash: 1558931694658309700
|
97
125
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
126
|
+
none: false
|
98
127
|
requirements:
|
99
|
-
- - '>='
|
128
|
+
- - ! '>='
|
100
129
|
- !ruby/object:Gem::Version
|
101
130
|
version: '0'
|
131
|
+
segments:
|
132
|
+
- 0
|
133
|
+
hash: 1558931694658309700
|
102
134
|
requirements: []
|
103
135
|
rubyforge_project:
|
104
|
-
rubygems_version:
|
136
|
+
rubygems_version: 1.8.25
|
105
137
|
signing_key:
|
106
|
-
specification_version:
|
107
|
-
summary: 'Extends Devise with new module :custom_authenticatable, when enabled it
|
138
|
+
specification_version: 3
|
139
|
+
summary: ! 'Extends Devise with new module :custom_authenticatable, when enabled it
|
108
140
|
will call #valid_for_custom_authentication? method on resource model for your customizations'
|
109
141
|
test_files:
|
110
142
|
- spec/devise/models/custom_authenticatable_spec.rb
|
143
|
+
- spec/devise/strategies/custom_authenticatable_spec.rb
|
111
144
|
- spec/spec_helper.rb
|
145
|
+
- spec/support/helpers.rb
|
checksums.yaml
DELETED
@@ -1,7 +0,0 @@
|
|
1
|
-
---
|
2
|
-
SHA1:
|
3
|
-
metadata.gz: 12bd7f8777135a62852d2ba22efd0f7cec1a16e6
|
4
|
-
data.tar.gz: 26405720e35ba421a11e456f164096eeb2567527
|
5
|
-
SHA512:
|
6
|
-
metadata.gz: 87ced17afe13cdf57cce3938a046045651f06ff7498fa9a0341d2e284fdae4b54b08f5be835db149ad07209ecd87f0baeb8a6dffb32aeb5e2452bcaa470b0a21
|
7
|
-
data.tar.gz: 6bb9e8176658e0aa3d5551071555077c734547b7b4bc606fad84f5c82cad7c7e6b64a432eb9e61554e6a35be7333e636b5057ea6eb19f59a083f3172ae282528
|