openid_fu_generator 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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 -%>