devise_openid_authenticatable 1.0.0.alpha7 → 1.0.0.beta2

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.rdoc CHANGED
@@ -1,3 +1,12 @@
1
+ == 1.0.0.beta1
2
+ * Implement support for build_from_identity_url. create_from_identity_url is now deprecated.
3
+ * build_from_identity_url should return a new, unsaved model instance rather than a persisted one.
4
+ * This has multiple benefits: validation should become easier, and we can avoid doing multiple modification queries during the initial registration.
5
+ * Switching over should be straightforward but is not a simple matter of changing the method's name. Its behavior needs to be altered to return an unsaved instance.
6
+ * This affects all users of devise_openid_authenticatable.
7
+ * Attempt to pass a more correct trust_root to the OpenID provider.
8
+ * Fill out Dimitrij's test suite a bit more.
9
+
1
10
  == 1.0.0.alpha7
2
11
 
3
12
  * GH-3: Add support for rememberable.
data/Gemfile CHANGED
@@ -2,8 +2,8 @@ source "http://rubygems.org"
2
2
 
3
3
  gem 'rails', '3.0.0'
4
4
  gem "devise", ">= 1.1.2"
5
- gem "rspec", ">= 2.0.0.beta.17"
6
- gem "rspec-rails", ">= 2.0.0.beta.17"
5
+ gem "rspec", "~> 2.3"
6
+ gem "rspec-rails", "~> 2.3"
7
7
  gem "rack-openid", ">= 1.2.0"
8
8
  gem "mocha"
9
9
  gem "sqlite3-ruby"
data/README.md CHANGED
@@ -77,14 +77,14 @@ Automatically creating users
77
77
  ----------------------------
78
78
 
79
79
  If you want to have users automatically created when a new OpenID identity URL is
80
- successfully used to sign in, you can implement a method called "create_from_identity_url"
80
+ successfully used to sign in, you can implement a method called "build_from_identity_url"
81
81
  to your user model class:
82
82
 
83
83
  class User < ActiveRecord::Base
84
84
  devise :openid_authenticatable
85
85
 
86
- def self.create_from_identity_url(identity_url)
87
- User.create(:identity_url => identity_url)
86
+ def self.build_from_identity_url(identity_url)
87
+ User.new(:identity_url => identity_url)
88
88
  end
89
89
  end
90
90
 
@@ -155,6 +155,4 @@ See also
155
155
  TODO
156
156
  ----
157
157
 
158
- * Add sreg attributes support
159
- * Write test suite
160
158
  * Test on non-ActiveRecord ORMs
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.0.alpha7
1
+ 1.0.0.beta2
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{devise_openid_authenticatable}
8
- s.version = "1.0.0.alpha7"
8
+ s.version = "1.0.0.beta2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Nat Budin"]
12
- s.date = %q{2010-09-08}
12
+ s.date = %q{2010-12-21}
13
13
  s.description = %q{OpenID authentication module for Devise using Rack::OpenID}
14
14
  s.email = %q{natbudin@gmail.com}
15
15
  s.extra_rdoc_files = [
@@ -33,6 +33,8 @@ Gem::Specification.new do |s|
33
33
  "spec/scenario/app/controllers/application_controller.rb",
34
34
  "spec/scenario/app/controllers/home_controller.rb",
35
35
  "spec/scenario/app/controllers/sessions_controller.rb",
36
+ "spec/scenario/app/models/database_user.rb",
37
+ "spec/scenario/app/models/legacy_user.rb",
36
38
  "spec/scenario/app/models/user.rb",
37
39
  "spec/scenario/app/views/layouts/application.html.erb",
38
40
  "spec/scenario/app/views/sessions/new.html.erb",
@@ -63,6 +65,8 @@ Gem::Specification.new do |s|
63
65
  "spec/scenario/app/controllers/application_controller.rb",
64
66
  "spec/scenario/app/controllers/home_controller.rb",
65
67
  "spec/scenario/app/controllers/sessions_controller.rb",
68
+ "spec/scenario/app/models/database_user.rb",
69
+ "spec/scenario/app/models/legacy_user.rb",
66
70
  "spec/scenario/app/models/user.rb",
67
71
  "spec/scenario/config/application.rb",
68
72
  "spec/scenario/config/boot.rb",
@@ -19,7 +19,7 @@ class Devise::Strategies::OpenidAuthenticatable < base_class
19
19
  if provider_response
20
20
  handle_response!
21
21
  else # Delegate authentication to Rack::OpenID by throwing a 401
22
- opts = { :identifier => params[scope]["identity_url"], :return_to => return_url, :method => 'post' }
22
+ opts = { :identifier => params[scope]["identity_url"], :return_to => return_url, :trust_root => trust_root, :method => 'post' }
23
23
  opts[:optional] = mapping.to.openid_optional_fields if mapping.to.respond_to?(:openid_optional_fields)
24
24
  opts[:required] = mapping.to.openid_required_fields if mapping.to.respond_to?(:openid_required_fields)
25
25
  custom! [401, { Rack::OpenID::AUTHENTICATE_HEADER => Rack::OpenID.build_header(opts) }, "Sign in with OpenID"]
@@ -34,14 +34,16 @@ class Devise::Strategies::OpenidAuthenticatable < base_class
34
34
 
35
35
  case provider_response.status
36
36
  when :success
37
- resource = mapping.to.find_by_identity_url(provider_response.identity_url)
38
- if resource.nil? && mapping.to.respond_to?(:create_from_identity_url)
39
- resource = mapping.to.create_from_identity_url(provider_response.identity_url)
40
- end
41
-
37
+ resource = find_resource || build_resource || create_resource
38
+
42
39
  if resource
43
- update_resource!(resource)
44
- success!(resource)
40
+ begin
41
+ update_resource!(resource)
42
+ rescue
43
+ fail! $!
44
+ else
45
+ success!(resource)
46
+ end
45
47
  else
46
48
  fail! "This OpenID URL is not associated with any registered user"
47
49
  end
@@ -70,26 +72,47 @@ class Devise::Strategies::OpenidAuthenticatable < base_class
70
72
  def identity_param?
71
73
  params[scope].try(:[], 'identity_url').present?
72
74
  end
75
+
76
+ def find_resource
77
+ mapping.to.find_by_identity_url(provider_response.identity_url)
78
+ end
79
+
80
+ def build_resource
81
+ if mapping.to.respond_to?(:build_from_identity_url)
82
+ mapping.to.build_from_identity_url(provider_response.identity_url)
83
+ end
84
+ end
85
+
86
+ def create_resource
87
+ if mapping.to.respond_to?(:create_from_identity_url)
88
+ logger.warn "DEPRECATION WARNING: create_from_identity_url is deprecated. Please implement build_from_identity_url instead. For more information, please see the devise_openid_authenticatable CHANGELOG for version 1.0.0.beta1."
89
+ mapping.to.create_from_identity_url(provider_response.identity_url)
90
+ end
91
+ end
73
92
 
74
93
  def update_resource!(resource)
75
- return unless resource.respond_to?(:openid_fields=)
76
-
77
- fields = nil
94
+ if fields && resource.respond_to?(:openid_fields=)
95
+ resource.openid_fields = fields
96
+ end
97
+
98
+ resource.save!
99
+ end
100
+
101
+ def fields
102
+ return @fields unless @fields.nil?
103
+
78
104
  if axr = OpenID::AX::FetchResponse.from_success_response(provider_response)
79
- fields = axr.data
105
+ @fields = axr.data
80
106
  else
81
107
  provider_response.message.namespaces.each do |uri, ns_alias|
82
108
  if ns_alias.to_s == "sreg"
83
- fields = provider_response.extension_response(uri, true)
109
+ @fields = provider_response.extension_response(uri, true)
84
110
  break
85
111
  end
86
112
  end
87
113
  end
88
-
89
- if fields
90
- resource.openid_fields = fields
91
- resource.save
92
- end
114
+
115
+ return @fields
93
116
  end
94
117
 
95
118
  def logger
@@ -107,6 +130,12 @@ class Devise::Strategies::OpenidAuthenticatable < base_class
107
130
  return_to.to_s
108
131
  end
109
132
 
133
+ def trust_root
134
+ trust_root = URI.parse(request.url)
135
+ trust_root.path = ""
136
+ trust_root.query = nil
137
+ trust_root.to_s
138
+ end
110
139
  end
111
140
 
112
141
  Warden::Strategies.add :openid_authenticatable, Devise::Strategies::OpenidAuthenticatable
@@ -0,0 +1,15 @@
1
+ class DatabaseUser < ActiveRecord::Base
2
+ devise :database_authenticatable, :openid_authenticatable, :validatable
3
+
4
+ def self.build_from_identity_url(identity_url)
5
+ new(:identity_url => identity_url)
6
+ end
7
+
8
+ def self.openid_required_fields
9
+ ["http://axschema.org/contact/email"]
10
+ end
11
+
12
+ def openid_fields=(fields)
13
+ self.email = fields["http://axschema.org/contact/email"].first
14
+ end
15
+ end
@@ -0,0 +1,18 @@
1
+ class LegacyUser < ActiveRecord::Base
2
+ devise :openid_authenticatable, :rememberable
3
+
4
+ def self.create_from_identity_url(identity_url)
5
+ create do |user|
6
+ user.identity_url = identity_url
7
+ end
8
+ end
9
+
10
+ def self.openid_required_fields
11
+ ["http://axschema.org/contact/email"]
12
+ end
13
+
14
+ def openid_fields=(fields)
15
+ self.email = fields["http://axschema.org/contact/email"].first
16
+ end
17
+
18
+ end
@@ -1,8 +1,8 @@
1
1
  class User < ActiveRecord::Base
2
2
  devise :openid_authenticatable, :rememberable
3
3
 
4
- def self.create_from_identity_url(identity_url)
5
- create do |user|
4
+ def self.build_from_identity_url(identity_url)
5
+ new do |user|
6
6
  user.identity_url = identity_url
7
7
  end
8
8
  end
@@ -1,4 +1,6 @@
1
1
  Rails.application.routes.draw do
2
2
  devise_for :users, :controllers => { :sessions => 'sessions' }
3
+ devise_for :database_users, :controllers => { :sessions => 'sessions' }
4
+ devise_for :legacy_users, :controllers => { :sessions => 'sessions' }
3
5
  root :to => "home#index"
4
6
  end
@@ -6,9 +6,24 @@ class CreateTables < ActiveRecord::Migration
6
6
  t.string :email
7
7
  t.timestamps
8
8
  end
9
+
10
+ create_table :database_users do |t|
11
+ t.openid_authenticatable
12
+ t.database_authenticatable
13
+ t.timestamps
14
+ end
15
+
16
+ create_table :legacy_users do |t|
17
+ t.openid_authenticatable
18
+ t.rememberable
19
+ t.string :email
20
+ t.timestamps
21
+ end
9
22
  end
10
23
 
11
24
  def self.down
12
25
  drop_table :users
26
+ drop_table :database_users
27
+ drop_table :legacy_users
13
28
  end
14
29
  end
@@ -39,10 +39,22 @@ describe Devise::Strategies::OpenidAuthenticatable do
39
39
  User.create! do |u|
40
40
  u.identity_url = "http://openid.example.org/myid"
41
41
  end
42
+
43
+ LegacyUser.create! do |u|
44
+ u.identity_url = "http://openid.example.org/myid"
45
+ end
46
+
47
+ DatabaseUser.create! do |u|
48
+ u.email = "dbuser@example.com"
49
+ u.password = "password"
50
+ u.identity_url = "http://openid.example.org/myid"
51
+ end
42
52
  end
43
53
 
44
54
  after do
45
55
  User.delete_all
56
+ LegacyUser.delete_all
57
+ DatabaseUser.delete_all
46
58
  end
47
59
 
48
60
  describe "GET /protected/resource" do
@@ -198,5 +210,123 @@ describe Devise::Strategies::OpenidAuthenticatable do
198
210
  User.order(:id).last.email.should == 'dimitrij@example.com'
199
211
  end
200
212
  end
213
+
214
+ describe "POST /legacy_users/sign_in (from OpenID provider, success, new user)" do
215
+
216
+ before do
217
+ @previous_logger = Rails.logger
218
+ @log_output = StringIO.new
219
+ Rails.logger = Logger.new(@log_output)
220
+
221
+ @identity = 'http://openid.example.org/newid'
222
+ stub_completion
223
+ post '/legacy_users/sign_in', openid_params.merge("_method"=>"post")
224
+ end
225
+
226
+ after do
227
+ Rails.logger = @previous_logger
228
+ end
201
229
 
230
+ it 'should accept authentication with success' do
231
+ response.should be_redirect
232
+ response.should redirect_to('http://www.example.com/')
233
+ flash[:notice].should match(/success/i)
234
+ end
235
+
236
+ it 'should auto-create user-records (if supported)' do
237
+ LegacyUser.should have(2).records
238
+ end
239
+
240
+ it 'should update new user-records with retrieved information' do
241
+ LegacyUser.order(:id).last.email.should == 'dimitrij@example.com'
242
+ end
243
+
244
+ it 'should issue a deprecation warning' do
245
+ @log_output.string.should =~ /DEPRECATION WARNING: create_from_identity_url/
246
+ end
247
+ end
248
+
249
+ describe "POST /database_users/sign_in (using database authentication)" do
250
+
251
+ before do
252
+ post '/database_users/sign_in', :database_user => { :email => "dbuser@example.com", :password => "password" }
253
+ end
254
+
255
+ it 'should accept authentication with success' do
256
+ response.should be_redirect
257
+ response.should redirect_to('http://www.example.com/')
258
+ flash[:notice].should match(/success/i)
259
+ end
260
+
261
+ end
262
+
263
+ describe "POST /database_users/sign_in (using OpenID, begin_authentication)" do
264
+ before do
265
+ Rack::OpenID.any_instance.stubs(:begin_authentication).returns([302, {'location' => 'http://openid.example.org/server'}, ''])
266
+ post '/database_users/sign_in', 'database_user' => { 'identity_url' => 'http://openid.example.org/myid' }
267
+ end
268
+
269
+ it 'should forward request to provider' do
270
+ response.should be_redirect
271
+ response.should redirect_to('http://openid.example.org/server')
272
+ end
273
+ end
274
+
275
+ describe "POST /database_users/sign_in (using OpenID, from provider, existing user)" do
276
+ before do
277
+ stub_completion
278
+ post '/database_users/sign_in', openid_params.merge("_method"=>"post")
279
+ end
280
+
281
+ it 'should accept authentication with success' do
282
+ response.should be_redirect
283
+ response.should redirect_to('http://www.example.com/')
284
+ flash[:notice].should match(/success/i)
285
+ end
286
+
287
+ it 'should update user-records with retrieved information' do
288
+ DatabaseUser.should have(1).record
289
+ DatabaseUser.first.email.should == 'dimitrij@example.com'
290
+ end
291
+ end
292
+
293
+ describe "POST /database_users/sign_in (using OpenID, from provider, existing email)" do
294
+ before do
295
+ DatabaseUser.delete_all
296
+ DatabaseUser.create! do |u|
297
+ u.email = "dimitrij@example.com"
298
+ u.password = "password"
299
+ end
300
+
301
+ stub_completion
302
+ post '/database_users/sign_in', openid_params.merge("_method"=>"post")
303
+ end
304
+
305
+ it 'should fail to authenticate with existing email error' do
306
+ response.should be_success
307
+ response.should render_template("sessions/new")
308
+ flash[:alert].should match(/email/i)
309
+ DatabaseUser.should have(1).record
310
+ end
311
+ end
312
+
313
+ describe "POST /database_users/sign_in (using OpenID, from provider, forgery attempt)" do
314
+ before do
315
+ DatabaseUser.delete_all
316
+ DatabaseUser.create! do |u|
317
+ u.email = "dimitrij@example.com"
318
+ u.password = "password"
319
+ u.identity_url = "http://openid.example.org/different_id"
320
+ end
321
+
322
+ stub_completion
323
+ post '/database_users/sign_in', openid_params.merge("_method"=>"post")
324
+ end
325
+
326
+ it 'should fail authentication with existing email error' do
327
+ response.should be_success
328
+ response.should render_template("sessions/new")
329
+ flash[:alert].should match(/email/i)
330
+ end
331
+ end
202
332
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: devise_openid_authenticatable
3
3
  version: !ruby/object:Gem::Version
4
- hash: -1710980387
4
+ hash: -1848230054
5
5
  prerelease: true
6
6
  segments:
7
7
  - 1
8
8
  - 0
9
9
  - 0
10
- - alpha7
11
- version: 1.0.0.alpha7
10
+ - beta2
11
+ version: 1.0.0.beta2
12
12
  platform: ruby
13
13
  authors:
14
14
  - Nat Budin
@@ -16,7 +16,7 @@ autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
18
 
19
- date: 2010-09-08 00:00:00 -04:00
19
+ date: 2010-12-21 00:00:00 -05:00
20
20
  default_executable:
21
21
  dependencies:
22
22
  - !ruby/object:Gem::Dependency
@@ -77,6 +77,8 @@ files:
77
77
  - spec/scenario/app/controllers/application_controller.rb
78
78
  - spec/scenario/app/controllers/home_controller.rb
79
79
  - spec/scenario/app/controllers/sessions_controller.rb
80
+ - spec/scenario/app/models/database_user.rb
81
+ - spec/scenario/app/models/legacy_user.rb
80
82
  - spec/scenario/app/models/user.rb
81
83
  - spec/scenario/app/views/layouts/application.html.erb
82
84
  - spec/scenario/app/views/sessions/new.html.erb
@@ -137,6 +139,8 @@ test_files:
137
139
  - spec/scenario/app/controllers/application_controller.rb
138
140
  - spec/scenario/app/controllers/home_controller.rb
139
141
  - spec/scenario/app/controllers/sessions_controller.rb
142
+ - spec/scenario/app/models/database_user.rb
143
+ - spec/scenario/app/models/legacy_user.rb
140
144
  - spec/scenario/app/models/user.rb
141
145
  - spec/scenario/config/application.rb
142
146
  - spec/scenario/config/boot.rb