pager-restful_open_id_authentication 1.0.20080507

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.
Files changed (29) hide show
  1. data/README +63 -0
  2. data/Rakefile +22 -0
  3. data/generators/open_id_authenticated/USAGE +1 -0
  4. data/generators/open_id_authenticated/open_id_authenticated_generator.rb +215 -0
  5. data/generators/open_id_authenticated/templates/activation.rhtml +3 -0
  6. data/generators/open_id_authenticated/templates/authenticated_system.rb +120 -0
  7. data/generators/open_id_authenticated/templates/authenticated_test_helper.rb +113 -0
  8. data/generators/open_id_authenticated/templates/controller.rb +94 -0
  9. data/generators/open_id_authenticated/templates/fixtures.yml +17 -0
  10. data/generators/open_id_authenticated/templates/functional_test.rb +85 -0
  11. data/generators/open_id_authenticated/templates/helper.rb +2 -0
  12. data/generators/open_id_authenticated/templates/login.rhtml +20 -0
  13. data/generators/open_id_authenticated/templates/migration.rb +45 -0
  14. data/generators/open_id_authenticated/templates/model.rb +93 -0
  15. data/generators/open_id_authenticated/templates/model_controller.rb +30 -0
  16. data/generators/open_id_authenticated/templates/model_functional_test.rb +72 -0
  17. data/generators/open_id_authenticated/templates/model_helper.rb +2 -0
  18. data/generators/open_id_authenticated/templates/notifier.rb +25 -0
  19. data/generators/open_id_authenticated/templates/notifier_test.rb +31 -0
  20. data/generators/open_id_authenticated/templates/observer.rb +11 -0
  21. data/generators/open_id_authenticated/templates/open_id_form.rhtml +14 -0
  22. data/generators/open_id_authenticated/templates/signup.rhtml +22 -0
  23. data/generators/open_id_authenticated/templates/signup_notification.rhtml +8 -0
  24. data/generators/open_id_authenticated/templates/unit_test.rb +101 -0
  25. data/install.rb +1 -0
  26. data/lib/controller_methods.rb +137 -0
  27. data/lib/open_id_store.rb +69 -0
  28. data/rails/init.rb +15 -0
  29. metadata +81 -0
@@ -0,0 +1,2 @@
1
+ module <%= model_controller_class_name %>Helper
2
+ end
@@ -0,0 +1,25 @@
1
+ class <%= class_name %>Notifier < ActionMailer::Base
2
+ def signup_notification(<%= file_name %>)
3
+ setup_email(<%= file_name %>)
4
+ @subject += 'Please activate your new account'
5
+ <% if options[:include_activation] %>
6
+ @body[:url] = "http://YOURSITE/activate/#{<%= file_name %>.activation_code}"
7
+ <% else %>
8
+ @body[:url] = "http://YOURSITE/login/" <% end %>
9
+ end
10
+
11
+ def activation(<%= file_name %>)
12
+ setup_email(<%= file_name %>)
13
+ @subject += 'Your account has been activated!'
14
+ @body[:url] = "http://YOURSITE/"
15
+ end
16
+
17
+ protected
18
+ def setup_email(<%= file_name %>)
19
+ @recipients = "#{<%= file_name %>.email}"
20
+ @from = "ADMINEMAIL"
21
+ @subject = "[YOURSITE] "
22
+ @sent_on = Time.now
23
+ @body[:<%= file_name %>] = <%= file_name %>
24
+ end
25
+ end
@@ -0,0 +1,31 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+ require '<%= file_name %>_notifier'
3
+
4
+ class <%= class_name %>NotifierTest < Test::Unit::TestCase
5
+ FIXTURES_PATH = File.dirname(__FILE__) + '/../fixtures'
6
+ CHARSET = "utf-8"
7
+
8
+ include ActionMailer::Quoting
9
+
10
+ def setup
11
+ ActionMailer::Base.delivery_method = :test
12
+ ActionMailer::Base.perform_deliveries = true
13
+ ActionMailer::Base.deliveries = []
14
+
15
+ @expected = TMail::Mail.new
16
+ @expected.set_content_type "text", "plain", { "charset" => CHARSET }
17
+ end
18
+
19
+ def test_dummy_test
20
+ #do nothing
21
+ end
22
+
23
+ private
24
+ def read_fixture(action)
25
+ IO.readlines("#{FIXTURES_PATH}/<%= file_name %>_notifier/#{action}")
26
+ end
27
+
28
+ def encode(subject)
29
+ quoted_printable(subject, CHARSET)
30
+ end
31
+ end
@@ -0,0 +1,11 @@
1
+ class <%= class_name %>Observer < ActiveRecord::Observer
2
+ def after_create(<%= file_name %>)
3
+ <%= class_name %>Notifier.deliver_signup_notification(<%= file_name %>)
4
+ end
5
+
6
+ def after_save(<%= file_name %>)
7
+ <% if options[:include_activation] %>
8
+ <%= class_name %>Notifier.deliver_activation(<%= file_name %>) if <%= file_name %>.recently_activated?
9
+ <% end %>
10
+ end
11
+ end
@@ -0,0 +1,14 @@
1
+ <%% form_tag begin_<%= controller_singular_name %>_path do -%>
2
+ <p>
3
+ <label>
4
+ Identity URL:
5
+ <%%= text_field_tag :open_id_url, nil, :style => 'width:250px' %>
6
+ </label>
7
+ <%%= submit_tag :Verify %>
8
+ </p>
9
+ <!-- Uncomment this if you want this functionality
10
+ <p><label for="remember_me">Remember me:</label>
11
+ <%%= check_box_tag 'remember_me' %></p>
12
+ -->
13
+
14
+ <%% end -%>
@@ -0,0 +1,22 @@
1
+ <h2>Signup with OpenID</h2>
2
+
3
+ <%%= render :partial => "<%= controller_file_name %>/open_id_form" %>
4
+
5
+ <h2>or create a <%= class_name %> Profile</h2>
6
+
7
+ <%%= error_messages_for :<%= file_name %> %>
8
+ <%% form_for @<%= file_name %> do |f| -%>
9
+ <p><label for="login">Login</label><br/>
10
+ <%%= f.text_field :login %></p>
11
+
12
+ <p><label for="email">Email</label><br/>
13
+ <%%= f.text_field :email %></p>
14
+
15
+ <p><label for="password">Password</label><br/>
16
+ <%%= f.password_field :password %></p>
17
+
18
+ <p><label for="password_confirmation">Confirm Password</label><br/>
19
+ <%%= f.password_field :password_confirmation %></p>
20
+
21
+ <p><%%= submit_tag 'Sign up' %></p>
22
+ <%% end -%>
@@ -0,0 +1,8 @@
1
+ Your account has been created.
2
+
3
+ Username: <%%= @<%= file_name %>.login %>
4
+ Password: <%%= @<%= file_name %>.password %>
5
+
6
+ Visit this url to activate your account:
7
+
8
+ <%%= @url %>
@@ -0,0 +1,101 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class <%= class_name %>Test < Test::Unit::TestCase
4
+ # Be sure to include AuthenticatedTestHelper in test/test_helper.rb instead.
5
+ # Then, you can remove it from this and the functional test.
6
+ include AuthenticatedTestHelper
7
+ fixtures :<%= table_name %>
8
+
9
+ def test_should_create_<%= file_name %>
10
+ assert_difference <%= class_name %>, :count do
11
+ <%= file_name %> = create_<%= file_name %>
12
+ assert !<%= file_name %>.new_record?, "#{<%= file_name %>.errors.full_messages.to_sentence}"
13
+ end
14
+ end
15
+
16
+ def test_should_require_login
17
+ assert_no_difference <%= class_name %>, :count do
18
+ u = create_<%= file_name %>(:login => nil)
19
+ assert u.errors.on(:login)
20
+ end
21
+ end
22
+
23
+ def test_should_require_password
24
+ assert_no_difference <%= class_name %>, :count do
25
+ u = create_<%= file_name %>(:password => nil)
26
+ assert u.errors.on(:password)
27
+ end
28
+ end
29
+
30
+ def test_should_require_password_confirmation
31
+ assert_no_difference <%= class_name %>, :count do
32
+ u = create_<%= file_name %>(:password_confirmation => nil)
33
+ assert u.errors.on(:password_confirmation)
34
+ end
35
+ end
36
+
37
+ def test_should_require_email
38
+ assert_no_difference <%= class_name %>, :count do
39
+ u = create_<%= file_name %>(:email => nil)
40
+ assert u.errors.on(:email)
41
+ end
42
+ end
43
+
44
+ def test_should_reset_password
45
+ <%= table_name %>(:quentin).update_attributes(:password => 'new password', :password_confirmation => 'new password')
46
+ assert_equal <%= table_name %>(:quentin), <%= class_name %>.authenticate('quentin', 'new password')
47
+ end
48
+
49
+ def test_should_not_rehash_password
50
+ <%= table_name %>(:quentin).update_attributes(:login => 'quentin2')
51
+ assert_equal <%= table_name %>(:quentin), <%= class_name %>.authenticate('quentin2', 'test')
52
+ end
53
+
54
+ def test_should_authenticate_<%= file_name %>
55
+ assert_equal <%= table_name %>(:quentin), <%= class_name %>.authenticate('quentin', 'test')
56
+ end
57
+
58
+ def test_should_set_remember_token
59
+ <%= table_name %>(:quentin).remember_me
60
+ assert_not_nil <%= table_name %>(:quentin).remember_token
61
+ assert_not_nil <%= table_name %>(:quentin).remember_token_expires_at
62
+ end
63
+
64
+ def test_should_unset_remember_token
65
+ <%= table_name %>(:quentin).remember_me
66
+ assert_not_nil <%= table_name %>(:quentin).remember_token
67
+ <%= table_name %>(:quentin).forget_me
68
+ assert_nil <%= table_name %>(:quentin).remember_token
69
+ end
70
+
71
+ def test_should_remember_me_for_one_week
72
+ before = 1.week.from_now.utc
73
+ <%= table_name %>(:quentin).remember_me_for 1.week
74
+ after = 1.week.from_now.utc
75
+ assert_not_nil <%= table_name %>(:quentin).remember_token
76
+ assert_not_nil <%= table_name %>(:quentin).remember_token_expires_at
77
+ assert <%= table_name %>(:quentin).remember_token_expires_at.between?(before, after)
78
+ end
79
+
80
+ def test_should_remember_me_until_one_week
81
+ time = 1.week.from_now.utc
82
+ <%= table_name %>(:quentin).remember_me_until time
83
+ assert_not_nil <%= table_name %>(:quentin).remember_token
84
+ assert_not_nil <%= table_name %>(:quentin).remember_token_expires_at
85
+ assert_equal <%= table_name %>(:quentin).remember_token_expires_at, time
86
+ end
87
+
88
+ def test_should_remember_me_default_two_weeks
89
+ before = 2.weeks.from_now.utc
90
+ <%= table_name %>(:quentin).remember_me
91
+ after = 2.weeks.from_now.utc
92
+ assert_not_nil <%= table_name %>(:quentin).remember_token
93
+ assert_not_nil <%= table_name %>(:quentin).remember_token_expires_at
94
+ assert <%= table_name %>(:quentin).remember_token_expires_at.between?(before, after)
95
+ end
96
+
97
+ protected
98
+ def create_<%= file_name %>(options = {})
99
+ <%= class_name %>.create({ :login => 'quire', :email => 'quire@example.com', :password => 'quire', :password_confirmation => 'quire' }.merge(options))
100
+ end
101
+ end
data/install.rb ADDED
@@ -0,0 +1 @@
1
+ puts IO.read(File.join(File.dirname(__FILE__), 'README'))
@@ -0,0 +1,137 @@
1
+ module OpenIdConsumer
2
+ module ControllerMethods
3
+ def self.included(controller)
4
+ controller.class_eval do
5
+ verify :method => :post, :only => :begin, :params => :open_id_url, :redirect_to => { :action => 'index' },
6
+ :add_flash => { :error => "Enter an Identity URL to verify." }
7
+ verify :method => :get, :only => :complete, :redirect_to => { :action => 'index' }
8
+ before_filter :begin_open_id_auth, :only => :begin
9
+ before_filter :complete_open_id_auth, :only => :complete
10
+ attr_reader :open_id_response
11
+ attr_reader :open_id_fields
12
+ cattr_accessor :open_id_consumer_options
13
+ end
14
+ end
15
+
16
+ protected
17
+
18
+ def open_id_consumer
19
+ @open_id_consumer ||= OpenID::Consumer.new(
20
+ session[:open_id_session] ||= {},
21
+ ActiveRecordStore.new)
22
+ end
23
+
24
+ def begin_open_id_auth
25
+ @open_id_response = open_id_consumer.begin(params[:open_id_url])
26
+ def @open_id_response.status; OpenID::Consumer::SUCCESS end
27
+ add_sreg_params!(@open_id_response)# if @open_id_response.status == OpenID::SUCCESS
28
+ rescue OpenID::DiscoveryFailure
29
+ def @open_id_response.status; OpenID::Consumer::FAILURE end
30
+ end
31
+
32
+ def complete_open_id_auth
33
+ return_to = url_for :only_path => false, :action => 'complete'
34
+ parameters = params.reject{|k,v| request.path_parameters[k]}
35
+ @open_id_response = open_id_consumer.complete(parameters, return_to)
36
+ return unless open_id_response.status == OpenID::Consumer::SUCCESS
37
+
38
+ @open_id_fields = open_id_response.extension_response('sreg', true)
39
+ logger.debug "***************** sreg params ***************"
40
+ logger.debug @open_id_fields.inspect
41
+ logger.debug "***************** sreg params ***************"
42
+ end
43
+
44
+
45
+ def authenticate_with_open_id(identity_url)
46
+ @open_id_response = open_id_consumer.begin(identity_url)
47
+ yield(@open_id_response.status.to_sum)
48
+
49
+ # If the URL was unusable (either because of network conditions, a server error,
50
+ # or that the response returned was not an OpenID identity page), the library
51
+ # will return HTTP_FAILURE or PARSE_ERROR. Let the user know that the URL is unusable.
52
+ case open_id_response.status
53
+ when OpenID::Consumer::SUCCESS
54
+ add_sreg_params!(@open_id_response)
55
+ redirect_to open_id_response.redirect_url((request.protocol + request.host_with_port + "/"), complete_session_url)
56
+ else
57
+ flash[:error] = "Unable to find OpenID server for <q>#{params[:open_id_url]}</q>"
58
+ render :action => :new
59
+ end
60
+ end
61
+
62
+ def complete
63
+ case open_id_response.status
64
+ when OpenID::Consumer::FAILURE
65
+ # In the case of failure, if info is non-nil, it is the URL that we were verifying.
66
+ # We include it in the error message to help the user figure out what happened.
67
+ flash[:notice] = if open_id_response.identity_url
68
+ "Verification of #{open_id_response.identity_url} failed. "
69
+ else
70
+ "Verification failed. "
71
+ end
72
+ flash[:notice] += open_id_response.msg.to_s
73
+ when OpenID::Consumer::SUCCESS
74
+ # Success means that the transaction completed without error. If info is nil,
75
+ # it means that the user cancelled the verification.
76
+ flash[:notice] = "You have successfully verified #{open_id_response.identity_url} as your identity."
77
+ if open_id_fields.any?
78
+ @user = User.find_by_open_id_url(open_id_response.identity_url)
79
+ @user ||= User.new(:open_id_url => open_id_response.identity_url)
80
+ @user.login = open_id_fields['nickname'] if open_id_fields['nickname']
81
+ @user.email = open_id_fields['email'] if open_id_fields['email']
82
+ if @user.save
83
+ self.current_user = @user
84
+ if params[:remember_me] == "1"
85
+ self.current_user.remember_me
86
+ cookies[:auth_token] = { :value => self.current_user.remember_token , :expires => self.current_user.remember_token_expires_at }
87
+ end
88
+ flash[:notice] = "You have successfully verified #{open_id_response.identity_url} as your identity."
89
+ return redirect_back_or_default('/')
90
+ else
91
+ flash[:notice] = @user.errors.full_messages.join('<br />')
92
+ render :action => 'new' and return
93
+ end
94
+ end
95
+ when OpenID::CANCEL
96
+ flash[:notice] = "Verification cancelled."
97
+ else
98
+ flash[:notice] = "Unknown response status: #{open_id_response.status}"
99
+ end
100
+ redirect_to :action => 'new'
101
+ end
102
+
103
+
104
+ def authenticate_with_open_id(identity_url)
105
+
106
+
107
+ case status
108
+ when :missing
109
+ failed_authentication "Sorry, the OpenID server couldn't be found"
110
+
111
+ when :canceled
112
+ failed_authentication "OpenID verification was canceled"
113
+
114
+ when :failed
115
+ failed_authentication "Sorry, the OpenID verification failed"
116
+
117
+ when :successful
118
+ if @current_user =
119
+ @account.users.find_by_identity_url(identity_url)
120
+ successful_authentication
121
+ else
122
+ failed_authentication "Sorry, no user by that identity URL exists"
123
+ end
124
+ end
125
+ end
126
+
127
+
128
+
129
+ def add_sreg_params!(openid_response)
130
+ open_id_consumer_options.keys.inject({}) do |params, key|
131
+ value = open_id_consumer_options[key]
132
+ value = value.collect { |v| v.to_s.strip } * ',' if value.respond_to?(:collect)
133
+ openid_response.add_extension_arg('sreg', key.to_s, value.to_s)
134
+ end
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,69 @@
1
+ require 'openid/store/interface'
2
+
3
+ class ActiveRecordStore < OpenID::Store::Interface
4
+ def store_association(server_url, assoc)
5
+ remove_association(server_url, assoc.handle)
6
+ Association.create(:server_url => server_url,
7
+ :handle => assoc.handle,
8
+ :secret => assoc.secret,
9
+ :issued => assoc.issued,
10
+ :lifetime => assoc.lifetime,
11
+ :assoc_type => assoc.assoc_type)
12
+ end
13
+
14
+ def get_association(server_url, handle=nil)
15
+ assocs = if handle.blank?
16
+ Association.find_all_by_server_url(server_url)
17
+ else
18
+ Association.find_all_by_server_url_and_handle(server_url, handle)
19
+ end
20
+
21
+ assocs.reverse.each do |assoc|
22
+ a = assoc.from_record
23
+ if a.expires_in == 0
24
+ assoc.destroy
25
+ else
26
+ return a
27
+ end
28
+ end if assocs.any?
29
+
30
+ return nil
31
+ end
32
+
33
+ def remove_association(server_url, handle)
34
+ Association.delete_all(['server_url = ? AND handle = ?', server_url, handle]) > 0
35
+ end
36
+
37
+ def use_nonce(server_url, timestamp, salt)
38
+ return false if Nonce.find_by_server_url_and_timestamp_and_salt(server_url, timestamp, salt)
39
+ return false if (timestamp - Time.now.to_i).abs > OpenID::Nonce.skew
40
+ Nonce.create(:server_url => server_url, :timestamp => timestamp, :salt => salt)
41
+ return true
42
+ end
43
+
44
+ def cleanup_nonces
45
+ now = Time.now.to_i
46
+ Nonce.delete_all(["timestamp > ? OR timestamp < ?", now + OpenID::Nonce.skew, now - OpenID::Nonce.skew])
47
+ end
48
+
49
+ def cleanup_associations
50
+ now = Time.now.to_i
51
+ Association.delete_all(['issued + lifetime > ?',now])
52
+ end
53
+ end
54
+
55
+ class Setting < ActiveRecord::Base
56
+ set_table_name 'open_id_settings'
57
+ validates_uniqueness_of :setting
58
+ end
59
+
60
+ class Nonce < ActiveRecord::Base
61
+ set_table_name 'open_id_nonces'
62
+ end
63
+
64
+ class Association < ActiveRecord::Base
65
+ set_table_name 'open_id_associations'
66
+ def from_record
67
+ OpenID::Association.new(handle, secret, issued, lifetime, assoc_type)
68
+ end
69
+ end
data/rails/init.rb ADDED
@@ -0,0 +1,15 @@
1
+ begin
2
+ gem 'ruby-openid'
3
+ require 'openid'
4
+ rescue LoadError
5
+ puts "Install the ruby-openid gem to enable OpenID support"
6
+ end
7
+ require 'open_id_store'
8
+ require 'controller_methods'
9
+
10
+ class << ActionController::Base
11
+ def open_id_consumer(options = {})
12
+ include OpenIdConsumer::ControllerMethods
13
+ self.open_id_consumer_options = options
14
+ end
15
+ end