openid_fu_generator 0.0.1

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 (49) hide show
  1. data/History.txt +4 -0
  2. data/License.txt +20 -0
  3. data/Manifest.txt +48 -0
  4. data/README.txt +48 -0
  5. data/Rakefile +4 -0
  6. data/config/hoe.rb +72 -0
  7. data/config/requirements.rb +15 -0
  8. data/lib/openid_fu.rb +10 -0
  9. data/lib/openid_fu/association.rb +12 -0
  10. data/lib/openid_fu/controller_methods.rb +97 -0
  11. data/lib/openid_fu/nonce.rb +5 -0
  12. data/lib/openid_fu/openid_ar_store.rb +62 -0
  13. data/lib/openid_fu/openid_attribute_types.rb +79 -0
  14. data/lib/openid_fu/openid_ax_ext.rb +12 -0
  15. data/lib/openid_fu/openid_setting.rb +5 -0
  16. data/lib/openid_fu/version.rb +9 -0
  17. data/openid_fu_generator.rb +246 -0
  18. data/script/console +10 -0
  19. data/script/destroy +14 -0
  20. data/script/generate +14 -0
  21. data/script/txt2html +74 -0
  22. data/setup.rb +1585 -0
  23. data/tasks/deployment.rake +34 -0
  24. data/tasks/environment.rake +7 -0
  25. data/tasks/website.rake +17 -0
  26. data/templates/activation.html.erb +3 -0
  27. data/templates/authenticated_system.rb +155 -0
  28. data/templates/authenticated_test_helper.rb +94 -0
  29. data/templates/controller.rb +111 -0
  30. data/templates/fixtures.yml +15 -0
  31. data/templates/functional_test.rb +87 -0
  32. data/templates/helper.rb +2 -0
  33. data/templates/login.html.erb +20 -0
  34. data/templates/migration.rb +55 -0
  35. data/templates/model.rb +92 -0
  36. data/templates/model_controller.rb +30 -0
  37. data/templates/model_functional_test.rb +64 -0
  38. data/templates/model_helper.rb +2 -0
  39. data/templates/notifier.rb +25 -0
  40. data/templates/notifier_test.rb +31 -0
  41. data/templates/observer.rb +11 -0
  42. data/templates/open_id_form.html.erb +13 -0
  43. data/templates/restore_location.html.erb +30 -0
  44. data/templates/signup.html.erb +19 -0
  45. data/templates/signup_notification.html.erb +8 -0
  46. data/templates/unit_test.rb +94 -0
  47. data/test/test_helper.rb +4 -0
  48. data/test/test_openid_fu.rb +11 -0
  49. metadata +108 -0
@@ -0,0 +1,87 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+ require '<%= controller_file_name %>_controller'
3
+
4
+ # Re-raise errors caught by the controller.
5
+ class <%= controller_class_name %>Controller; def rescue_action(e) raise e end; end
6
+
7
+ class <%= controller_class_name %>ControllerTest < Test::Unit::TestCase
8
+ # Be sure to include AuthenticatedTestHelper in test/test_helper.rb instead
9
+ # Then, you can remove it from this and the units test.
10
+ include AuthenticatedTestHelper
11
+
12
+ fixtures :<%= table_name %>
13
+
14
+ def setup
15
+ @controller = <%= controller_class_name %>Controller.new
16
+ @request = ActionController::TestRequest.new
17
+ @response = ActionController::TestResponse.new
18
+ end
19
+
20
+ def test_should_login_and_redirect
21
+ post :create, :email => 'quentin@example.com', :password => 'test'
22
+ assert session[:<%= file_name %>]
23
+ assert_response :redirect
24
+ end
25
+
26
+ def test_should_fail_login_and_not_redirect
27
+ post :create, :email => 'quentin@example.com', :password => 'bad password'
28
+ assert_nil session[:<%= file_name %>]
29
+ assert_response :success
30
+ end
31
+
32
+ def test_should_logout
33
+ login_as :quentin
34
+ get :destroy
35
+ assert_nil session[:<%= file_name %>]
36
+ assert_response :redirect
37
+ end
38
+
39
+ def test_should_remember_me
40
+ post :create, :email => 'quentin@example.com',
41
+ :password => 'test', :remember_me => "1"
42
+ assert_not_nil @response.cookies["auth_token"]
43
+ end
44
+
45
+ def test_should_not_remember_me
46
+ post :create, :email => 'quentin@example.com',
47
+ :password => 'test', :remember_me => "0"
48
+ assert_nil @response.cookies["auth_token"]
49
+ end
50
+
51
+ def test_should_delete_token_on_logout
52
+ login_as :quentin
53
+ get :destroy
54
+ assert_equal @response.cookies["auth_token"], []
55
+ end
56
+
57
+ def test_should_login_with_cookie
58
+ <%= table_name %>(:quentin).remember_me
59
+ @request.cookies["auth_token"] = cookie_for(:quentin)
60
+ get :new
61
+ assert @controller.send(:logged_in?)
62
+ end
63
+
64
+ def test_should_fail_expired_cookie_login
65
+ <%= table_name %>(:quentin).remember_me
66
+ <%= table_name %>(:quentin).update_attribute :remember_token_expires_at, 5.minutes.ago
67
+ @request.cookies["auth_token"] = cookie_for(:quentin)
68
+ get :new
69
+ assert !@controller.send(:logged_in?)
70
+ end
71
+
72
+ def test_should_fail_cookie_login
73
+ <%= table_name %>(:quentin).remember_me
74
+ @request.cookies["auth_token"] = auth_token('invalid_auth_token')
75
+ get :new
76
+ assert !@controller.send(:logged_in?)
77
+ end
78
+
79
+ protected
80
+ def auth_token(token)
81
+ CGI::Cookie.new('name' => 'auth_token', 'value' => token)
82
+ end
83
+
84
+ def cookie_for(<%= file_name %>)
85
+ auth_token <%= table_name %>(<%= file_name %>).remember_token
86
+ end
87
+ end
@@ -0,0 +1,2 @@
1
+ module <%= controller_class_name %>Helper
2
+ end
@@ -0,0 +1,20 @@
1
+ <h2>Sign in with OpenID</h2>
2
+ <%%= render :partial => "<%= controller_file_name %>/open_id_form" %>
3
+
4
+ <p>If you don't already have an OpenID account you can easily create one at <%%= link_to 'MyOpenID', 'http://www.myopenid.com' -%>.</p>
5
+
6
+ <h2>Or use your email/password</h2>
7
+ <%% form_tag <%= controller_singular_name %>_path do -%>
8
+ <p><label for="email">email</label><br/>
9
+ <%%= text_field_tag 'email' %></p>
10
+
11
+ <p><label for="password">Password</label><br/>
12
+ <%%= password_field_tag 'password' %></p>
13
+
14
+ <!-- Uncomment this if you want this functionality
15
+ <p><label for="remember_me">Remember me:</label>
16
+ <%%= check_box_tag 'remember_me' %></p>
17
+ -->
18
+
19
+ <p><%%= submit_tag 'Log in' %></p>
20
+ <%% end -%>
@@ -0,0 +1,55 @@
1
+ class <%= migration_name %> < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :<%= table_name %>, :force => true do |t|
4
+ t.string :nickname
5
+ t.string :email
6
+ t.string :claimed_id
7
+ t.string :crypted_password, :limit => 40
8
+ t.string :salt, :limit => 40
9
+ t.string :remember_token
10
+ t.datetime :remember_token_expires_at
11
+ t.string :open_id_claimed_identifier
12
+ <% if options[:include_activation] %>
13
+ t.string :activation_code, :limit => 40
14
+ t.datetime :activated_at
15
+ <% end %>
16
+ <% unless options[:exclude_personal_identity] %>
17
+ # Common properties among SREG and AX
18
+ t.string :fullname
19
+ t.string :birth_date
20
+ t.integer :gender, :limit => 1
21
+ t.string :postcode
22
+ t.string :country
23
+ t.string :language
24
+ t.string :timezone
25
+ <% end %>
26
+ t.timestamps
27
+ end
28
+
29
+ create_table :open_id_associations, :force => true do |t|
30
+ t.binary :server_url
31
+ t.string :handle
32
+ t.binary :secret
33
+ t.integer :issued
34
+ t.integer :lifetime
35
+ t.string :assoc_type
36
+
37
+ t.timestamps
38
+ end
39
+
40
+ create_table :open_id_nonces, :force => true do |t|
41
+ t.string :server_url, :null => false
42
+ t.integer :timestamp, :null => false
43
+ t.string :salt, :null => false
44
+
45
+ t.timestamps
46
+ end
47
+
48
+ end
49
+
50
+ def self.down
51
+ drop_table :<%= table_name %>
52
+ drop_table :open_id_associations
53
+ drop_table :open_id_nonces
54
+ end
55
+ end
@@ -0,0 +1,92 @@
1
+ require 'digest/sha1'
2
+ class <%= class_name %> < ActiveRecord::Base
3
+ # Virtual attribute for the unencrypted password
4
+ attr_accessor :password
5
+
6
+ validates_presence_of :email
7
+ validates_presence_of :password, :if => :password_required?
8
+ validates_presence_of :password_confirmation, :if => :password_required?
9
+ validates_length_of :password, :within => 4..40, :if => :password_required?
10
+ validates_confirmation_of :password, :if => :password_required?
11
+ validates_length_of :email, :within => 3..100
12
+ validates_uniqueness_of :email, :case_sensitive => false
13
+ before_save :encrypt_password
14
+ <% if options[:include_activation] %> before_create :make_activation_code <% end %>
15
+ <% if options[:include_activation] %>
16
+ # Activates the user in the database.
17
+ def activate
18
+ @activated = true
19
+ self.attributes = {:activated_at => Time.now.utc, :activation_code => nil}
20
+ save(false)
21
+ end
22
+
23
+ def activated?
24
+ !! activation_code.nil?
25
+ end
26
+
27
+ # Returns true if the user has just been activated.
28
+ def recently_activated?
29
+ @activated
30
+ end <% end %>
31
+ # Authenticates a user by their email and unencrypted password. Returns the user or nil.
32
+ def self.authenticate(email, password)
33
+ u = <% if options[:include_activation] %>find :first, :conditions => ['email = ? and activated_at IS NOT NULL', email]<% else %>find_by_email(email)<% end %> # need to get the salt
34
+ u && u.authenticated?(password) ? u : nil
35
+ end
36
+
37
+ # Encrypts some data with the salt.
38
+ def self.encrypt(password, salt)
39
+ Digest::SHA1.hexdigest("--#{salt}--#{password}--")
40
+ end
41
+
42
+ # Encrypts the password with the user salt
43
+ def encrypt(password)
44
+ self.class.encrypt(password, salt)
45
+ end
46
+
47
+ def authenticated?(password)
48
+ crypted_password == encrypt(password)
49
+ end
50
+
51
+ def remember_token?
52
+ remember_token_expires_at && Time.now.utc < remember_token_expires_at
53
+ end
54
+
55
+ # These create and unset the fields required for remembering users between browser closes
56
+ def remember_me
57
+ remember_me_for 2.weeks
58
+ end
59
+
60
+ def remember_me_for(time)
61
+ remember_me_until time.from_now.utc
62
+ end
63
+
64
+ def remember_me_until(time)
65
+ self.remember_token_expires_at = time
66
+ self.remember_token = encrypt("#{email}--#{remember_token_expires_at}")
67
+ save(false)
68
+ end
69
+
70
+ def forget_me
71
+ self.remember_token_expires_at = nil
72
+ self.remember_token = nil
73
+ save(false)
74
+ end
75
+
76
+ protected
77
+ # before filter
78
+ def encrypt_password
79
+ return if password.blank?
80
+ self.salt = Digest::SHA1.hexdigest("--#{Time.now.to_s}--#{email}--") if new_record?
81
+ self.crypted_password = encrypt(password)
82
+ end
83
+
84
+ def password_required?
85
+ claimed_id.nil? && (crypted_password.blank? || !password.blank?)
86
+ end
87
+
88
+ <% if options[:include_activation] %>
89
+ def make_activation_code
90
+ self.activation_code = Digest::SHA1.hexdigest( Time.now.to_s.split(//).sort_by {rand}.join )
91
+ end <% end %>
92
+ end
@@ -0,0 +1,30 @@
1
+ class <%= model_controller_class_name %>Controller < ApplicationController
2
+ # Be sure to include AuthenticationSystem in Application Controller instead
3
+ include AuthenticatedSystem
4
+ # If you want "remember me" functionality, add this before_filter to Application Controller
5
+ before_filter :login_from_cookie
6
+
7
+ # render new.rhtml
8
+ def new
9
+ end
10
+
11
+ def create
12
+ @<%= file_name %> = <%= class_name %>.new(params[:<%= file_name %>])
13
+ @<%= file_name %>.save!
14
+ self.current_<%= file_name %> = @<%= file_name %>
15
+ redirect_back_or_default('/')
16
+ flash[:notice] = "Thanks for signing up!"
17
+ rescue ActiveRecord::RecordInvalid
18
+ render :action => 'new'
19
+ end
20
+ <% if options[:include_activation] %>
21
+ def activate
22
+ self.current_<%= file_name %> = <%= class_name %>.find_by_activation_code(params[:activation_code])
23
+ if logged_in? && !current_<%= file_name %>.activated?
24
+ current_<%= file_name %>.activate
25
+ flash[:notice] = "Signup complete!"
26
+ end
27
+ redirect_back_or_default('/')
28
+ end
29
+ <% end %>
30
+ end
@@ -0,0 +1,64 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+ require '<%= model_controller_file_name %>_controller'
3
+
4
+ # Re-raise errors caught by the controller.
5
+ class <%= model_controller_class_name %>Controller; def rescue_action(e) raise e end; end
6
+
7
+ class <%= model_controller_class_name %>ControllerTest < Test::Unit::TestCase
8
+ # Be sure to include AuthenticatedTestHelper in test/test_helper.rb instead
9
+ # Then, you can remove it from this and the units test.
10
+ include AuthenticatedTestHelper
11
+
12
+ fixtures :<%= table_name %>
13
+
14
+ def setup
15
+ @controller = <%= model_controller_class_name %>Controller.new
16
+ @request = ActionController::TestRequest.new
17
+ @response = ActionController::TestResponse.new
18
+ end
19
+
20
+ def test_should_allow_signup
21
+ assert_difference "<%= class_name %>.count" do
22
+ create_<%= file_name %>
23
+ assert_response :redirect
24
+ end
25
+ end
26
+
27
+ def test_should_require_password_on_signup
28
+ assert_no_difference "<%= class_name %>.count" do
29
+ create_<%= file_name %>(:password => nil)
30
+ assert assigns(:<%= file_name %>).errors.on(:password)
31
+ assert_response :success
32
+ end
33
+ end
34
+
35
+ def test_should_require_password_confirmation_on_signup
36
+ assert_no_difference "<%= class_name %>.count" do
37
+ create_<%= file_name %>(:password_confirmation => nil)
38
+ assert assigns(:<%= file_name %>).errors.on(:password_confirmation)
39
+ assert_response :success
40
+ end
41
+ end
42
+
43
+ def test_should_require_email_on_signup
44
+ assert_no_difference "<%= class_name %>.count" do
45
+ create_<%= file_name %>(:email => nil)
46
+ assert assigns(:<%= file_name %>).errors.on(:email)
47
+ assert_response :success
48
+ end
49
+ end
50
+ <% if options[:include_activation] %>
51
+ def test_should_activate_user
52
+ assert_nil <%= class_name %>.authenticate('aaron', 'test')
53
+ get :activate, :activation_code => <%= table_name %>(:aaron).activation_code
54
+ assert_redirected_to '/'
55
+ assert_not_nil flash[:notice]
56
+ assert_equal <%= table_name %>(:aaron), <%= class_name %>.authenticate('aaron', 'test')
57
+ end <% end %>
58
+
59
+ protected
60
+ def create_<%= file_name %>(options = {})
61
+ post :create, :<%= file_name %> => { :nickname => 'quire', :email => 'quire@example.com',
62
+ :password => 'quire', :password_confirmation => 'quire' }.merge(options)
63
+ end
64
+ end
@@ -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,13 @@
1
+ <%% form_tag begin_<%= controller_singular_name %>_path do -%>
2
+ <p>
3
+ <label>
4
+ Identity URL:
5
+ <%%= text_field_tag :open_id_claimed_id, 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
+ <%% end -%>