authlogic-oid 1.0.2 → 1.0.3

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,11 @@
1
+ == 1.0.3 released 2009-4-3
2
+
3
+ * Added find_by_openid_identifier config option for AuthlogicOpenid::Session.
4
+ * Set the openid_identifier by the one passed back by the provider in AuthlogicOpenid::ActsAsAuthentic.
5
+ * Added required_fields and optional_fields config options for AuthlogicOpenid::ActsAsAuthentic.
6
+ * Added map_openid_registration, attributes_to_save, and map_saved_attributes methods to customize how attributes are set for AuthlogicOpenid::ActsAsAuthentic.
7
+ * Make authenticating_with_openid? method a little more stringent to avoid trying to double authenticate. Ex: finding a session in the save block during a successful save.
8
+
1
9
  == 1.0.2 released 2009-3-30
2
10
 
3
11
  * Remove config block in initializer.
data/README.rdoc CHANGED
@@ -4,7 +4,7 @@ Authlogic OpenID is an extension of the Authlogic library to add OpenID support.
4
4
 
5
5
  == Helpful links
6
6
 
7
- * <b>Documentation:</b> http://authlogic.rubyforge.org
7
+ * <b>Documentation:</b> http://authlogic-oid.rubyforge.org
8
8
  * <b>Authlogic:</b> http://github.com/binarylogic/authlogic
9
9
  * <b>Live example:</b> http://authlogicexample.binarylogic.com
10
10
 
@@ -8,10 +8,35 @@ module AuthlogicOpenid
8
8
  # OpenID is being used.
9
9
  def self.included(klass)
10
10
  klass.class_eval do
11
+ extend Config
11
12
  add_acts_as_authentic_module(Methods, :prepend)
12
13
  end
13
14
  end
14
15
 
16
+ module Config
17
+ # Some OpenID providers support a lightweight profile exchange protocol, for those that do, you can require
18
+ # certain fields. This is convenient for new registrations, as it will basically fill out the fields in the
19
+ # form for them, so they don't have to re-type information already stored with their OpenID account.
20
+ #
21
+ # For more info and what fields you can use see: http://openid.net/specs/openid-simple-registration-extension-1_0.html
22
+ #
23
+ # * <tt>Default:</tt> []
24
+ # * <tt>Accepts:</tt> Array of symbols
25
+ def required_fields(value = nil)
26
+ config(:required_fields, value, [])
27
+ end
28
+ alias_method :required_fields=, :required_fields
29
+
30
+ # Same as required_fields, but optional instead.
31
+ #
32
+ # * <tt>Default:</tt> []
33
+ # * <tt>Accepts:</tt> Array of symbols
34
+ def optional_fields(value = nil)
35
+ config(:optional_fields, value, [])
36
+ end
37
+ alias_method :optional_fields=, :optional_fields
38
+ end
39
+
15
40
  module Methods
16
41
  # Set up some simple validations
17
42
  def self.included(klass)
@@ -57,27 +82,22 @@ module AuthlogicOpenid
57
82
  @openid_error = nil
58
83
 
59
84
  if !openid_complete?
60
- attrs_to_persist = attributes.delete_if do |k, v|
61
- [:password, crypted_password_field, password_salt_field, :persistence_token, :perishable_token, :single_access_token, :login_count,
62
- :failed_login_count, :last_request_at, :current_login_at, :last_login_at, :current_login_ip, :last_login_ip, :created_at,
63
- :updated_at, :lock_version].include?(k.to_sym)
64
- end
65
- attrs_to_persist.merge!(:password => password, :password_confirmation => password_confirmation)
66
- session_class.controller.session[:openid_attributes] = attrs_to_persist
85
+ session_class.controller.session[:openid_attributes] = attributes_to_save
67
86
  else
68
- self.attributes = session_class.controller.session[:openid_attributes]
87
+ map_saved_attributes(session_class.controller.session[:openid_attributes])
69
88
  session_class.controller.session[:openid_attributes] = nil
70
89
  end
71
90
 
72
91
  options = {}
73
- options[:required_field] = [self.class.login_field, self.class.email_field].compact
74
- options[:optional_fields] = [:fullname]
92
+ options[:required] = self.class.required_fields
93
+ options[:optional] = self.class.optional_fields
75
94
  options[:return_to] = session_class.controller.url_for(:for_model => "1")
76
95
 
77
96
  session_class.controller.send(:authenticate_with_open_id, openid_identifier, options) do |result, openid_identifier, registration|
78
97
  if result.unsuccessful?
79
98
  @openid_error = result.message
80
99
  else
100
+ self.openid_identifier = openid_identifier
81
101
  map_openid_registration(registration)
82
102
  end
83
103
 
@@ -87,10 +107,43 @@ module AuthlogicOpenid
87
107
  return false
88
108
  end
89
109
 
90
- def map_openid_registration(registration)
110
+ # Override this method to map the OpenID registration fields with fields in your model. See the required_fields and
111
+ # optional_fields configuration options to enable this feature.
112
+ #
113
+ # Basically you will get a hash of values passed as a single argument. Then just map them as you see fit. Check out
114
+ # the source of this method for an example.
115
+ def map_openid_registration(registration) # :doc:
91
116
  self.name ||= registration[:fullname] if respond_to?(:name) && !registration[:fullname].blank?
92
117
  self.first_name ||= registration[:fullname].split(" ").first if respond_to?(:first_name) && !registration[:fullname].blank?
93
- self.first_name ||= registration[:fullname].split(" ").last if respond_to?(:last_name) && !registration[:last_name].blank?
118
+ self.last_name ||= registration[:fullname].split(" ").last if respond_to?(:last_name) && !registration[:last_name].blank?
119
+ end
120
+
121
+ # This method works in conjunction with map_saved_attributes.
122
+ #
123
+ # Let's say a user fills out a registration form, provides an OpenID and submits the form. They are then redirected to their
124
+ # OpenID provider. All is good and they are redirected back. All of those fields they spent time filling out are forgetten
125
+ # and they have to retype them all. To avoid this, AuthlogicOpenid saves all of these attributes in the session and then
126
+ # attempts to restore them. See the source for what attributes it saves. If you need to block more attributes, or save
127
+ # more just override this method and do whatever you want.
128
+ def attributes_to_save # :doc:
129
+ attrs_to_save = attributes.clone.delete_if do |k, v|
130
+ [:password, crypted_password_field, password_salt_field, :persistence_token, :perishable_token, :single_access_token, :login_count,
131
+ :failed_login_count, :last_request_at, :current_login_at, :last_login_at, :current_login_ip, :last_login_ip, :created_at,
132
+ :updated_at, :lock_version].include?(k.to_sym)
133
+ end
134
+ attrs_to_save.merge!(:password => password, :password_confirmation => password_confirmation)
135
+ end
136
+
137
+ # This method works in conjunction with attributes_to_save. See that method for a description of the why these methods exist.
138
+ #
139
+ # If the default behavior of this method is not sufficient for you because you have attr_protected or attr_accessible then
140
+ # override this method and set them individually. Maybe something like this would be good:
141
+ #
142
+ # attrs.each do |key, value|
143
+ # send("#{key}=", value)
144
+ # end
145
+ def map_saved_attributes(attrs) # :doc:
146
+ self.attributes = attrs
94
147
  end
95
148
 
96
149
  def validate_openid
@@ -4,58 +4,92 @@ module AuthlogicOpenid
4
4
  # Add a simple openid_identifier attribute and some validations for the field.
5
5
  def self.included(klass)
6
6
  klass.class_eval do
7
- attr_reader :openid_identifier
8
- validate :validate_openid_error
9
- validate :validate_by_openid, :if => :authenticating_with_openid?
7
+ extend Config
8
+ include Methods
10
9
  end
11
10
  end
12
11
 
13
- # Hooks into credentials so that you can pass an :openid_identifier key.
14
- def credentials=(value)
15
- super
16
- values = value.is_a?(Array) ? value : [value]
17
- hash = values.first.is_a?(Hash) ? values.first.with_indifferent_access : nil
18
- self.openid_identifier = hash[:openid_identifier] if !hash.nil? && hash.key?(:openid_identifier)
19
- end
20
-
21
- def openid_identifier=(value)
22
- @openid_identifier = value.blank? ? nil : OpenIdAuthentication.normalize_identifier(value)
23
- @openid_error = nil
24
- rescue OpenIdAuthentication::InvalidOpenId => e
25
- @openid_identifier = nil
26
- @openid_error = e.message
27
- end
28
-
29
- # Cleaers out the block if we are authenticating with OpenID, so that we can redirect without a DoubleRender
30
- # error.
31
- def save(&block)
32
- block = nil if !openid_identifier.blank?
33
- super(&block)
34
- end
35
-
36
- private
37
- def authenticating_with_openid?
38
- !openid_identifier.blank? || (controller.params[:open_id_complete] && controller.params[:for_session])
12
+ module Config
13
+ # What method should we call to find a record by the openid_identifier?
14
+ # This is useful if you want to store multiple openid_identifiers for a single record.
15
+ # You could do something like:
16
+ #
17
+ # class User < ActiveRecord::Base
18
+ # def self.find_by_openid_identifier(identifier)
19
+ # user.first(:conditions => {:openid_identifiers => {:identifier => identifier}})
20
+ # end
21
+ # end
22
+ #
23
+ # Obviously the above depends on what you are calling your assocition, etc. But you get the point.
24
+ #
25
+ # * <tt>Default:</tt> :find_by_openid_identifier
26
+ # * <tt>Accepts:</tt> Symbol
27
+ def find_by_openid_identifier_method(value = nil)
28
+ config(:find_by_openid_identifier_method, value, :find_by_openid_identifier)
39
29
  end
30
+ alias_method :find_by_openid_identifier_method=, :find_by_openid_identifier_method
31
+ end
40
32
 
41
- def validate_by_openid
42
- controller.send(:authenticate_with_open_id, openid_identifier, :return_to => controller.url_for(:for_session => "1")) do |result, openid_identifier|
43
- if result.unsuccessful?
44
- errors.add_to_base(result.message)
45
- return
46
- end
47
-
48
- self.attempted_record = klass.find_by_openid_identifier(openid_identifier)
49
-
50
- if !attempted_record
51
- errors.add(:openid_identifier, "did not match any users in our database, have you set up your account to use OpenID?")
52
- return
53
- end
33
+ module Methods
34
+ def self.included(klass)
35
+ klass.class_eval do
36
+ attr_reader :openid_identifier
37
+ validate :validate_openid_error
38
+ validate :validate_by_openid, :if => :authenticating_with_openid?
54
39
  end
55
40
  end
56
41
 
57
- def validate_openid_error
58
- errors.add(:openid_identifier, @openid_error) if @openid_error
42
+ # Hooks into credentials so that you can pass an :openid_identifier key.
43
+ def credentials=(value)
44
+ super
45
+ values = value.is_a?(Array) ? value : [value]
46
+ hash = values.first.is_a?(Hash) ? values.first.with_indifferent_access : nil
47
+ self.openid_identifier = hash[:openid_identifier] if !hash.nil? && hash.key?(:openid_identifier)
48
+ end
49
+
50
+ def openid_identifier=(value)
51
+ @openid_identifier = value.blank? ? nil : OpenIdAuthentication.normalize_identifier(value)
52
+ @openid_error = nil
53
+ rescue OpenIdAuthentication::InvalidOpenId => e
54
+ @openid_identifier = nil
55
+ @openid_error = e.message
59
56
  end
57
+
58
+ # Cleaers out the block if we are authenticating with OpenID, so that we can redirect without a DoubleRender
59
+ # error.
60
+ def save(&block)
61
+ block = nil if !openid_identifier.blank?
62
+ super(&block)
63
+ end
64
+
65
+ private
66
+ def authenticating_with_openid?
67
+ attempted_record.nil? && errors.empty? && (!openid_identifier.blank? || (controller.params[:open_id_complete] && controller.params[:for_session]))
68
+ end
69
+
70
+ def find_by_openid_identifier_method
71
+ self.class.find_by_openid_identifier_method
72
+ end
73
+
74
+ def validate_by_openid
75
+ controller.send(:authenticate_with_open_id, openid_identifier, :return_to => controller.url_for(:for_session => "1")) do |result, openid_identifier|
76
+ if result.unsuccessful?
77
+ errors.add_to_base(result.message)
78
+ return
79
+ end
80
+
81
+ self.attempted_record = klass.send(find_by_openid_identifier_method, openid_identifier)
82
+
83
+ if !attempted_record
84
+ errors.add(:openid_identifier, "did not match any users in our database, have you set up your account to use OpenID?")
85
+ return
86
+ end
87
+ end
88
+ end
89
+
90
+ def validate_openid_error
91
+ errors.add(:openid_identifier, @openid_error) if @openid_error
92
+ end
93
+ end
60
94
  end
61
95
  end
@@ -41,7 +41,7 @@ module AuthlogicOpenid
41
41
 
42
42
  MAJOR = 1
43
43
  MINOR = 0
44
- TINY = 2
44
+ TINY = 3
45
45
 
46
46
  # The current version as a Version instance
47
47
  CURRENT = new(MAJOR, MINOR, TINY)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: authlogic-oid
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Johnson of Binary Logic
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-03-30 00:00:00 -04:00
12
+ date: 2009-04-03 00:00:00 -04:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -30,7 +30,7 @@ dependencies:
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 1.11.0
33
+ version: 1.12.1
34
34
  version:
35
35
  description: Extension of the Authlogic library to add OpenID support.
36
36
  email: bjohnson@binarylogic.com