devise_openid_authenticatable 1.0.0.alpha7 → 1.0.0.beta2

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/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