devise-stormpath 0.1.1 → 0.2.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.
- data/README.md +10 -0
- data/app/controllers/devise/stormpath_passwords_controller.rb +9 -0
- data/config/locales/en.yml +10 -0
- data/devise-stormpath.gemspec +2 -1
- data/lib/devise-stormpath.rb +6 -4
- data/lib/devise/{stormpath/model.rb → models/stormpath_authenticatable.rb} +4 -0
- data/lib/devise/models/stormpath_recoverable.rb +66 -0
- data/lib/devise/stormpath/rails.rb +9 -0
- data/lib/devise/stormpath/routes.rb +8 -0
- data/lib/devise/stormpath/version.rb +1 -1
- data/lib/devise/{stormpath/strategy.rb → strategies/stormpath_authenticatable.rb} +0 -0
- data/spec/devise/{stormpath/model_spec.rb → models/stormpath_authenticatable_spec.rb} +5 -8
- data/spec/devise/models/stormpath_recoverable_spec.rb +42 -0
- data/spec/spec_helper.rb +2 -0
- data/spec/support/resource_error.rb +2 -0
- metadata +23 -10
data/README.md
CHANGED
@@ -10,3 +10,13 @@ In the Gemfile for your application:
|
|
10
10
|
In devise model:
|
11
11
|
|
12
12
|
devise :stormpath_authenticatable
|
13
|
+
|
14
|
+
Password reset
|
15
|
+
--------------
|
16
|
+
|
17
|
+
Model:
|
18
|
+
|
19
|
+
devise :stormpath_authenticatable, :stormpath_recoverable
|
20
|
+
|
21
|
+
Setup Password Reset Workflow at https://api.stormpath.com
|
22
|
+
Set Base URL to //<app host>/<devise scope>/password/edit (i.e. https://example.com/users/password/edit)
|
@@ -0,0 +1,10 @@
|
|
1
|
+
#TODO Customize messages
|
2
|
+
|
3
|
+
en:
|
4
|
+
devise:
|
5
|
+
stormpath_passwords:
|
6
|
+
send_instructions: 'You will receive an email with instructions about how to reset your password in a few minutes.'
|
7
|
+
updated: 'Your password was changed successfully. You are now signed in.'
|
8
|
+
updated_not_active: 'Your password was changed successfully.'
|
9
|
+
send_paranoid_instructions: "If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes."
|
10
|
+
no_token: "You can't access this page without coming from a password reset email. If you do come from a password reset email, please make sure you used the full URL provided."
|
data/devise-stormpath.gemspec
CHANGED
@@ -7,6 +7,7 @@ Gem::Specification.new do |s|
|
|
7
7
|
s.platform = Gem::Platform::RUBY
|
8
8
|
s.summary = 'Devise extension to allow authentication via Stormpath'
|
9
9
|
s.email = 'liquidautumn@gmail.com'
|
10
|
+
s.homepage = "http://www.stormpath.com"
|
10
11
|
s.description = s.summary
|
11
12
|
s.author = 'Denis Grankin'
|
12
13
|
|
@@ -16,7 +17,7 @@ Gem::Specification.new do |s|
|
|
16
17
|
s.require_paths = ["lib"]
|
17
18
|
|
18
19
|
s.add_dependency('devise')
|
19
|
-
s.add_dependency('stormpath-rails')
|
20
|
+
s.add_dependency('stormpath-rails', '~> 0.4.0')
|
20
21
|
s.add_dependency('activesupport')
|
21
22
|
|
22
23
|
s.add_development_dependency('rake', '~> 10.0.2')
|
data/lib/devise-stormpath.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
|
-
require 'devise'
|
2
1
|
require 'stormpath-rails'
|
3
2
|
|
4
|
-
require 'devise
|
3
|
+
require 'devise'
|
4
|
+
require 'devise/stormpath/routes'
|
5
|
+
require 'devise/stormpath/rails'
|
6
|
+
require 'devise/strategies/stormpath_authenticatable'
|
5
7
|
|
6
8
|
Warden::Strategies.add(:stormpath_authenticatable, Devise::Strategies::StormpathAuthenticatable)
|
7
9
|
|
8
|
-
Devise.add_module(:stormpath_authenticatable,
|
9
|
-
|
10
|
+
Devise.add_module(:stormpath_authenticatable, :route => :session, :strategy => true, :controller => :sessions, :model => 'devise/models/stormpath_authenticatable')
|
11
|
+
Devise.add_module(:stormpath_recoverable, :route => :password, :controller => :stormpath_passwords, :model => 'devise/models/stormpath_recoverable')
|
@@ -5,6 +5,10 @@ module Devise
|
|
5
5
|
module StormpathAuthenticatable
|
6
6
|
extend ActiveSupport::Concern
|
7
7
|
|
8
|
+
def self.required_fields(klass)
|
9
|
+
[:current_password, :password, :password_confirmation]
|
10
|
+
end
|
11
|
+
|
8
12
|
included do
|
9
13
|
attr_accessor :password_confirmation, :password
|
10
14
|
attr_reader :current_password
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module Devise
|
2
|
+
module Models
|
3
|
+
module StormpathRecoverable
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
def self.required_fields(klass)
|
7
|
+
[:reset_password_token, :password, :password_confirmation]
|
8
|
+
end
|
9
|
+
|
10
|
+
included do
|
11
|
+
attr_accessible :reset_password_token, :password_confirmation
|
12
|
+
attr_accessor :reset_password_token
|
13
|
+
end
|
14
|
+
|
15
|
+
protected
|
16
|
+
|
17
|
+
def after_password_reset
|
18
|
+
end
|
19
|
+
|
20
|
+
module ClassMethods
|
21
|
+
def send_reset_password_instructions(attributes={})
|
22
|
+
begin
|
23
|
+
identifier = attributes[:email] || attributes[:username]
|
24
|
+
raise RuntimeError.new "Email or username required" unless identifier
|
25
|
+
account = ::Stormpath::Rails::Client.send_password_reset_email(identifier)
|
26
|
+
return self.where(stormpath_url: account.get_href).first
|
27
|
+
rescue RuntimeError => error
|
28
|
+
build_invalid_account(attributes, error)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def reset_password_by_token(attributes={})
|
33
|
+
begin
|
34
|
+
validate_attributes(attributes)
|
35
|
+
account = ::Stormpath::Rails::Client.verify_password_reset_token(attributes[:reset_password_token])
|
36
|
+
account.set_password attributes[:password]
|
37
|
+
account.save
|
38
|
+
self.where(stormpath_url: account.get_href).first
|
39
|
+
rescue RuntimeError => error
|
40
|
+
build_invalid_account(attributes, error)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def build_invalid_account(attributes, error)
|
45
|
+
u = self.new(attributes)
|
46
|
+
u.errors[:base] << error.message
|
47
|
+
u
|
48
|
+
end
|
49
|
+
|
50
|
+
#TODO work on better error handling and move strings to locales
|
51
|
+
def validate_attributes(attributes)
|
52
|
+
raise RuntimeError.new "Password reset token required" unless attributes[:reset_password_token]
|
53
|
+
raise RuntimeError.new "Password should match confirmation" unless attributes[:password] == attributes[:password_confirmation]
|
54
|
+
raise RuntimeError.new "Password required" unless attributes[:password] && !attributes[:password].empty?
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
#mimic default devise recoverable
|
61
|
+
class Mapping
|
62
|
+
def recoverable?
|
63
|
+
@recoverable ||= self.modules.any? { |m| m.to_s =~ /recoverable/ }
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
ActionDispatch::Routing::Mapper.class_eval do
|
2
|
+
protected
|
3
|
+
|
4
|
+
def devise_password(mapping, controllers)
|
5
|
+
resource :password, :only => [:new, :create, :edit, :update],
|
6
|
+
:path => mapping.path_names[:password], :controller => controllers[:stormpath_passwords]
|
7
|
+
end
|
8
|
+
end
|
File without changes
|
@@ -1,18 +1,15 @@
|
|
1
1
|
require "spec_helper"
|
2
|
-
require "devise/
|
2
|
+
require "devise/models/stormpath_authenticatable"
|
3
3
|
|
4
|
-
class User
|
5
|
-
include Devise::Models::StormpathAuthenticatable
|
6
|
-
end
|
7
|
-
|
8
|
-
class ResourceError < Exception
|
9
|
-
end
|
10
4
|
|
11
5
|
describe Devise::Models::StormpathAuthenticatable do
|
6
|
+
class User
|
7
|
+
include Devise::Models::StormpathAuthenticatable
|
8
|
+
end
|
12
9
|
|
13
10
|
let(:user) { mock("user") }
|
14
11
|
|
15
|
-
describe "
|
12
|
+
describe "::authenticate_with_stormpath" do
|
16
13
|
it "should return user if authenticated on stormpath and local user exists with returned href" do
|
17
14
|
Stormpath::Rails::Client.should_receive(:authenticate_account).with("username", "password").and_return(mock("account", get_href: "user href"))
|
18
15
|
User.should_receive(:where).with(stormpath_url: "user href").and_return([user])
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "devise/models/stormpath_recoverable"
|
3
|
+
|
4
|
+
describe Devise::Models::StormpathRecoverable do
|
5
|
+
class User
|
6
|
+
def self.attr_accessible(*args)
|
7
|
+
end
|
8
|
+
|
9
|
+
include Devise::Models::StormpathRecoverable
|
10
|
+
end
|
11
|
+
|
12
|
+
let(:base) { mock("base") }
|
13
|
+
let(:errors) { mock("errors", :[] => base) }
|
14
|
+
let(:user) { mock("user", errors: errors) }
|
15
|
+
|
16
|
+
describe "::send_reset_password_instructions" do
|
17
|
+
it "should return user if password reset email sent and local user exists with returned href" do
|
18
|
+
Stormpath::Rails::Client.should_receive(:send_password_reset_email).with("john@example.com").and_return(mock("account", get_href: "user href"))
|
19
|
+
User.should_receive(:where).with(stormpath_url: "user href").and_return([user])
|
20
|
+
User.send_reset_password_instructions(email: "john@example.com").should == user
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should return errored user instance if no email provided" do
|
24
|
+
Stormpath::Rails::Client.should_receive(:send_password_reset_email).and_raise(ResourceError.new("Error"))
|
25
|
+
User.stub(:new).and_return(user)
|
26
|
+
base.should_receive(:<<).with("Error")
|
27
|
+
User.send_reset_password_instructions(email: "").should == user
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "::reset_password_by_token" do
|
32
|
+
let(:account) { mock("account", get_href: "user href") }
|
33
|
+
|
34
|
+
it "should update password at Stormpath and return user if password reset token is valid" do
|
35
|
+
Stormpath::Rails::Client.should_receive(:verify_password_reset_token).with("token").and_return(account)
|
36
|
+
account.should_receive(:set_password).with("password")
|
37
|
+
account.should_receive(:save)
|
38
|
+
User.should_receive(:where).with(stormpath_url: "user href").and_return([user])
|
39
|
+
User.reset_password_by_token(reset_password_token: "token", password: "password", password_confirmation: "password").should == user
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: devise-stormpath
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-01-29 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: devise
|
@@ -32,17 +32,17 @@ dependencies:
|
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|
33
33
|
none: false
|
34
34
|
requirements:
|
35
|
-
- -
|
35
|
+
- - ~>
|
36
36
|
- !ruby/object:Gem::Version
|
37
|
-
version:
|
37
|
+
version: 0.4.0
|
38
38
|
type: :runtime
|
39
39
|
prerelease: false
|
40
40
|
version_requirements: !ruby/object:Gem::Requirement
|
41
41
|
none: false
|
42
42
|
requirements:
|
43
|
-
- -
|
43
|
+
- - ~>
|
44
44
|
- !ruby/object:Gem::Version
|
45
|
-
version:
|
45
|
+
version: 0.4.0
|
46
46
|
- !ruby/object:Gem::Dependency
|
47
47
|
name: activesupport
|
48
48
|
requirement: !ruby/object:Gem::Requirement
|
@@ -136,15 +136,22 @@ files:
|
|
136
136
|
- LICENSE
|
137
137
|
- README.md
|
138
138
|
- Rakefile
|
139
|
+
- app/controllers/devise/stormpath_passwords_controller.rb
|
140
|
+
- config/locales/en.yml
|
139
141
|
- devise-stormpath.gemspec
|
140
142
|
- lib/devise-stormpath.rb
|
141
|
-
- lib/devise/
|
142
|
-
- lib/devise/
|
143
|
+
- lib/devise/models/stormpath_authenticatable.rb
|
144
|
+
- lib/devise/models/stormpath_recoverable.rb
|
145
|
+
- lib/devise/stormpath/rails.rb
|
146
|
+
- lib/devise/stormpath/routes.rb
|
143
147
|
- lib/devise/stormpath/version.rb
|
144
|
-
-
|
148
|
+
- lib/devise/strategies/stormpath_authenticatable.rb
|
149
|
+
- spec/devise/models/stormpath_authenticatable_spec.rb
|
150
|
+
- spec/devise/models/stormpath_recoverable_spec.rb
|
145
151
|
- spec/spec_helper.rb
|
146
152
|
- spec/support/client.rb
|
147
|
-
|
153
|
+
- spec/support/resource_error.rb
|
154
|
+
homepage: http://www.stormpath.com
|
148
155
|
licenses: []
|
149
156
|
post_install_message:
|
150
157
|
rdoc_options: []
|
@@ -156,12 +163,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
156
163
|
- - ! '>='
|
157
164
|
- !ruby/object:Gem::Version
|
158
165
|
version: '0'
|
166
|
+
segments:
|
167
|
+
- 0
|
168
|
+
hash: 434371363033819234
|
159
169
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
160
170
|
none: false
|
161
171
|
requirements:
|
162
172
|
- - ! '>='
|
163
173
|
- !ruby/object:Gem::Version
|
164
174
|
version: '0'
|
175
|
+
segments:
|
176
|
+
- 0
|
177
|
+
hash: 434371363033819234
|
165
178
|
requirements: []
|
166
179
|
rubyforge_project:
|
167
180
|
rubygems_version: 1.8.24
|