amrita2 1.9.6 → 2.0.0
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/README +112 -0
- data/init.rb +6 -0
- data/lib/amrita2/gettext.rb +116 -0
- data/lib/amrita2/macro.rb +153 -0
- data/lib/amrita2/rails_bridge.rb +172 -26
- data/lib/amrita2/template.rb +2634 -234
- data/lib/amrita2/testsupport.rb +171 -0
- data/lib/amrita2/version.rb +3 -3
- data/lib/amrita2.rb +1 -0
- data/sample/depot/app/controllers/admin_controller.rb +59 -0
- data/sample/depot/app/controllers/application.rb +20 -0
- data/sample/depot/app/controllers/info_controller.rb +19 -0
- data/sample/depot/app/controllers/login_controller.rb +85 -0
- data/sample/depot/app/controllers/store_controller.rb +68 -0
- data/sample/depot/app/helpers/admin_helper.rb +7 -0
- data/sample/depot/app/helpers/application_helper.rb +10 -0
- data/sample/depot/app/helpers/ar_form.rb +169 -0
- data/sample/depot/app/helpers/form_tag.rb +24 -0
- data/sample/depot/app/helpers/info_helper.rb +7 -0
- data/sample/depot/app/helpers/standard_form.rb +73 -0
- data/sample/depot/app/helpers/store_helper.rb +14 -0
- data/sample/depot/app/models/cart.rb +36 -0
- data/sample/depot/app/models/cart_item.rb +26 -0
- data/sample/depot/app/models/line_item.rb +34 -0
- data/sample/depot/app/models/order.rb +57 -0
- data/sample/depot/app/models/product.rb +41 -0
- data/sample/depot/app/models/user.rb +83 -0
- data/sample/depot/config/boot.rb +49 -0
- data/sample/depot/config/environment.rb +83 -0
- data/sample/depot/config/environments/development.rb +24 -0
- data/sample/depot/config/environments/production.rb +24 -0
- data/sample/depot/config/environments/test.rb +24 -0
- data/sample/depot/config/routes.rb +10 -0
- data/sample/depot/db/migrate/001_create_products.rb +18 -0
- data/sample/depot/db/migrate/002_add_price.rb +14 -0
- data/sample/depot/db/migrate/003_add_test_data.rb +68 -0
- data/sample/depot/db/migrate/004_add_sessions.rb +20 -0
- data/sample/depot/db/migrate/005_create_orders.rb +21 -0
- data/sample/depot/db/migrate/006_create_line_items.rb +27 -0
- data/sample/depot/db/migrate/007_create_users.rb +18 -0
- data/sample/depot/db/schema.rb +45 -0
- data/sample/depot/public/dispatch.rb +15 -0
- data/sample/depot/test/functional/admin_controller_test.rb +54 -0
- data/sample/depot/test/functional/info_controller_test.rb +23 -0
- data/sample/depot/test/functional/login_controller_test.rb +74 -0
- data/sample/depot/test/functional/store_controller_test.rb +57 -0
- data/sample/depot/test/integration/dsl_user_stories_test.rb +126 -0
- data/sample/depot/test/integration/user_stories_test.rb +70 -0
- data/sample/depot/test/performance/order_speed_test.rb +58 -0
- data/sample/depot/test/test_helper.rb +16 -0
- data/sample/depot/test/unit/cart_test.rb +39 -0
- data/sample/depot/test/unit/cart_test1.rb +31 -0
- data/sample/depot/test/unit/line_item_test.rb +15 -0
- data/sample/depot/test/unit/order_test.rb +15 -0
- data/sample/depot/test/unit/product_test.rb +98 -0
- data/sample/depot/vendor/plugins/amrita2/init.rb +6 -0
- data/sample/hello/hello.rb +22 -0
- data/sample/login_engine/app/controllers/application.rb +16 -0
- data/sample/login_engine/app/controllers/user_controller.rb +265 -0
- data/sample/login_engine/app/helpers/application_helper.rb +3 -0
- data/sample/login_engine/app/helpers/form_tag.rb +16 -0
- data/sample/login_engine/app/helpers/two_columns.rb +24 -0
- data/sample/login_engine/app/helpers/two_columns_form.rb +47 -0
- data/sample/login_engine/app/helpers/user_helper.rb +88 -0
- data/sample/login_engine/app/models/user.rb +7 -0
- data/sample/login_engine/app/models/user_notify.rb +75 -0
- data/sample/login_engine/config/boot.rb +45 -0
- data/sample/login_engine/config/environment.rb +140 -0
- data/sample/login_engine/config/environments/development.rb +21 -0
- data/sample/login_engine/config/environments/production.rb +18 -0
- data/sample/login_engine/config/environments/test.rb +19 -0
- data/sample/login_engine/config/routes.rb +23 -0
- data/sample/login_engine/db/migrate/001_create_users.rb +25 -0
- data/sample/login_engine/db/schema.rb +25 -0
- data/sample/login_engine/lib/config.rb +113 -0
- data/sample/login_engine/lib/hpricot_test_extension.rb +80 -0
- data/sample/login_engine/lib/login_engine/authenticated_system.rb +113 -0
- data/sample/login_engine/lib/login_engine/authenticated_user.rb +155 -0
- data/sample/login_engine/lib/login_engine.rb +62 -0
- data/sample/login_engine/public/dispatch.rb +10 -0
- data/sample/login_engine/test/functional/amrita2_test.rb +267 -0
- data/sample/login_engine/test/functional/user_controller_test.rb +544 -0
- data/sample/login_engine/test/mocks/mail.rb +14 -0
- data/sample/login_engine/test/mocks/time.rb +19 -0
- data/sample/login_engine/test/test_helper.rb +31 -0
- data/sample/login_engine/test/unit/user_test.rb +116 -0
- data/sample/login_engine/vendor/plugins/amrita2/init.rb +6 -0
- data/specs/attribute.rb +201 -0
- data/specs/datatypes.rb +231 -0
- data/specs/dictionary.rb +68 -0
- data/specs/erb_cdata.rb +187 -0
- data/specs/filters.rb +513 -0
- data/specs/gettext/erb_gettext.rb +42 -0
- data/specs/gettext/gettext_util.rb +65 -0
- data/specs/gettext/static_text.rb +103 -0
- data/specs/impl/code_generator.rb +87 -0
- data/specs/impl/dynamic_element.rb +92 -0
- data/specs/impl/hash_delegator.rb +57 -0
- data/specs/impl/parse_opt.rb +34 -0
- data/specs/impl/preprocess.rb +823 -0
- data/specs/impl/testsupport.rb +89 -0
- data/specs/inlineruby.rb +429 -0
- data/specs/intro.rb +654 -0
- data/specs/loop.rb +203 -0
- data/specs/macro.rb +532 -0
- data/specs/sample.rb +34 -0
- data/specs/sanitize.rb +110 -0
- data/specs/template.rb +189 -0
- data/specs/trace.rb +97 -0
- metadata +138 -19
- data/lib/amrita2/core.rb +0 -1897
- data/lib/amrita2/rd.rb +0 -314
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
module LoginEngine
|
|
2
|
+
module AuthenticatedSystem
|
|
3
|
+
|
|
4
|
+
protected
|
|
5
|
+
|
|
6
|
+
# overwrite this if you want to restrict access to only a few actions
|
|
7
|
+
# or if you want to check if the user has the correct rights
|
|
8
|
+
# example:
|
|
9
|
+
#
|
|
10
|
+
# # only allow nonbobs
|
|
11
|
+
# def authorize?(user)
|
|
12
|
+
# user.login != "bob"
|
|
13
|
+
# end
|
|
14
|
+
def authorize?(user)
|
|
15
|
+
true
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# overwrite this method if you only want to protect certain actions of the controller
|
|
19
|
+
# example:
|
|
20
|
+
#
|
|
21
|
+
# # don't protect the login and the about method
|
|
22
|
+
# def protect?(action)
|
|
23
|
+
# if ['action', 'about'].include?(action)
|
|
24
|
+
# return false
|
|
25
|
+
# else
|
|
26
|
+
# return true
|
|
27
|
+
# end
|
|
28
|
+
# end
|
|
29
|
+
def protect?(action)
|
|
30
|
+
true
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# login_required filter. add
|
|
34
|
+
#
|
|
35
|
+
# before_filter :login_required
|
|
36
|
+
#
|
|
37
|
+
# if the controller should be under any rights management.
|
|
38
|
+
# for finer access control you can overwrite
|
|
39
|
+
#
|
|
40
|
+
# def authorize?(user)
|
|
41
|
+
#
|
|
42
|
+
def login_required
|
|
43
|
+
if not protect?(action_name)
|
|
44
|
+
return true
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
if user? and authorize?(session[:user])
|
|
48
|
+
return true
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# store current location so that we can
|
|
52
|
+
# come back after the user logged in
|
|
53
|
+
store_location
|
|
54
|
+
|
|
55
|
+
# call overwriteable reaction to unauthorized access
|
|
56
|
+
access_denied
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# overwrite if you want to have special behavior in case the user is not authorized
|
|
60
|
+
# to access the current operation.
|
|
61
|
+
# the default action is to redirect to the login screen
|
|
62
|
+
# example use :
|
|
63
|
+
# a popup window might just close itself for instance
|
|
64
|
+
def access_denied
|
|
65
|
+
redirect_to :controller => "/user", :action => "login"
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# store current uri in the session.
|
|
69
|
+
# we can return to this location by calling return_location
|
|
70
|
+
def store_location
|
|
71
|
+
session['return-to'] = request.request_uri
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# move to the last store_location call or to the passed default one
|
|
75
|
+
def redirect_to_stored_or_default(default=nil)
|
|
76
|
+
if session['return-to'].nil?
|
|
77
|
+
redirect_to default
|
|
78
|
+
else
|
|
79
|
+
redirect_to_url session['return-to']
|
|
80
|
+
session['return-to'] = nil
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def redirect_back_or_default(default=nil)
|
|
85
|
+
if request.env["HTTP_REFERER"].nil?
|
|
86
|
+
redirect_to default
|
|
87
|
+
else
|
|
88
|
+
redirect_to(request.env["HTTP_REFERER"]) # same as redirect_to :back
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def user?
|
|
93
|
+
# First, is the user already authenticated?
|
|
94
|
+
return true if not session[:user].nil?
|
|
95
|
+
|
|
96
|
+
# If not, is the user being authenticated by a token?
|
|
97
|
+
id = params[:user_id]
|
|
98
|
+
key = params[:key]
|
|
99
|
+
if id and key
|
|
100
|
+
session[:user] = User.authenticate_by_token(id, key)
|
|
101
|
+
return true if not session[:user].nil?
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Everything failed
|
|
105
|
+
return false
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Returns the current user from the session, if any exists
|
|
109
|
+
def current_user
|
|
110
|
+
session[:user]
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
require 'digest/sha1'
|
|
2
|
+
|
|
3
|
+
# this model expects a certain database layout and its based on the name/login pattern.
|
|
4
|
+
|
|
5
|
+
module LoginEngine
|
|
6
|
+
module AuthenticatedUser
|
|
7
|
+
|
|
8
|
+
def self.included(base)
|
|
9
|
+
base.class_eval do
|
|
10
|
+
|
|
11
|
+
# use the table name given
|
|
12
|
+
set_table_name LoginEngine.config(:user_table)
|
|
13
|
+
|
|
14
|
+
attr_accessor :new_password
|
|
15
|
+
|
|
16
|
+
validates_presence_of :login
|
|
17
|
+
validates_length_of :login, :within => 3..40
|
|
18
|
+
validates_uniqueness_of :login
|
|
19
|
+
validates_uniqueness_of :email
|
|
20
|
+
validates_format_of :email, :with => /^[^@]+@.+$/
|
|
21
|
+
|
|
22
|
+
validates_presence_of :password, :if => :validate_password?
|
|
23
|
+
validates_confirmation_of :password, :if => :validate_password?
|
|
24
|
+
validates_length_of :password, { :minimum => 5, :if => :validate_password? }
|
|
25
|
+
validates_length_of :password, { :maximum => 40, :if => :validate_password? }
|
|
26
|
+
|
|
27
|
+
protected
|
|
28
|
+
|
|
29
|
+
attr_accessor :password, :password_confirmation
|
|
30
|
+
|
|
31
|
+
after_save :falsify_new_password
|
|
32
|
+
after_validation :crypt_password
|
|
33
|
+
|
|
34
|
+
end
|
|
35
|
+
base.extend(ClassMethods)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
module ClassMethods
|
|
39
|
+
|
|
40
|
+
def authenticate(login, pass)
|
|
41
|
+
u = find(:first, :conditions => ["login = ? AND verified = 1 AND deleted = 0", login])
|
|
42
|
+
return nil if u.nil?
|
|
43
|
+
find(:first, :conditions => ["login = ? AND salted_password = ? AND verified = 1", login, AuthenticatedUser.salted_password(u.salt, AuthenticatedUser.hashed(pass))])
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def authenticate_by_token(id, token)
|
|
47
|
+
# Allow logins for deleted accounts, but only via this method (and
|
|
48
|
+
# not the regular authenticate call)
|
|
49
|
+
u = find(:first, :conditions => ["#{User.primary_key} = ? AND security_token = ?", id, token])
|
|
50
|
+
return nil if u.nil? or u.token_expired?
|
|
51
|
+
return nil if false == u.update_expiry
|
|
52
|
+
u
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
protected
|
|
59
|
+
|
|
60
|
+
def self.hashed(str)
|
|
61
|
+
# check if a salt has been set...
|
|
62
|
+
if LoginEngine.config(:salt) == nil
|
|
63
|
+
raise "You must define a :salt value in the configuration for the LoginEngine module."
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
return Digest::SHA1.hexdigest("#{LoginEngine.config(:salt)}--#{str}--}")[0..39]
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def self.salted_password(salt, hashed_password)
|
|
70
|
+
hashed(salt + hashed_password)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
public
|
|
74
|
+
|
|
75
|
+
# hmmm, how does this interact with the developer's own User model initialize?
|
|
76
|
+
# We would have to *insist* that the User.initialize method called 'super'
|
|
77
|
+
#
|
|
78
|
+
def initialize(attributes = nil)
|
|
79
|
+
super
|
|
80
|
+
@new_password = false
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def token_expired?
|
|
84
|
+
self.security_token and self.token_expiry and (Time.now > self.token_expiry)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def update_expiry
|
|
88
|
+
write_attribute('token_expiry', [self.token_expiry, Time.at(Time.now.to_i + 600 * 1000)].min)
|
|
89
|
+
write_attribute('authenticated_by_token', true)
|
|
90
|
+
write_attribute("verified", 1)
|
|
91
|
+
update_without_callbacks
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def generate_security_token(hours = nil)
|
|
95
|
+
if not hours.nil? or self.security_token.nil? or self.token_expiry.nil? or
|
|
96
|
+
(Time.now.to_i + token_lifetime / 2) >= self.token_expiry.to_i
|
|
97
|
+
return new_security_token(hours)
|
|
98
|
+
else
|
|
99
|
+
return self.security_token
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def set_delete_after
|
|
104
|
+
hours = LoginEngine.config(:delayed_delete_days) * 24
|
|
105
|
+
write_attribute('deleted', 1)
|
|
106
|
+
write_attribute('delete_after', Time.at(Time.now.to_i + hours * 60 * 60))
|
|
107
|
+
|
|
108
|
+
# Generate and return a token here, so that it expires at
|
|
109
|
+
# the same time that the account deletion takes effect.
|
|
110
|
+
return generate_security_token(hours)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def change_password(pass, confirm = nil)
|
|
114
|
+
self.password = pass
|
|
115
|
+
self.password_confirmation = confirm.nil? ? pass : confirm
|
|
116
|
+
@new_password = true
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
protected
|
|
120
|
+
|
|
121
|
+
def validate_password?
|
|
122
|
+
@new_password
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def crypt_password
|
|
127
|
+
if @new_password
|
|
128
|
+
write_attribute("salt", AuthenticatedUser.hashed("salt-#{Time.now}"))
|
|
129
|
+
write_attribute("salted_password", AuthenticatedUser.salted_password(salt, AuthenticatedUser.hashed(@password)))
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def falsify_new_password
|
|
134
|
+
@new_password = false
|
|
135
|
+
true
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def new_security_token(hours = nil)
|
|
139
|
+
write_attribute('security_token', AuthenticatedUser.hashed(self.salted_password + Time.now.to_i.to_s + rand.to_s))
|
|
140
|
+
write_attribute('token_expiry', Time.at(Time.now.to_i + token_lifetime(hours)))
|
|
141
|
+
update_without_callbacks
|
|
142
|
+
return self.security_token
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def token_lifetime(hours = nil)
|
|
146
|
+
if hours.nil?
|
|
147
|
+
LoginEngine.config(:security_token_life_hours) * 60 * 60
|
|
148
|
+
else
|
|
149
|
+
hours * 60 * 60
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
require 'login_engine/authenticated_user'
|
|
2
|
+
require 'login_engine/authenticated_system'
|
|
3
|
+
|
|
4
|
+
module LoginEngine
|
|
5
|
+
include AuthenticatedSystem # re-include the helper module
|
|
6
|
+
|
|
7
|
+
#--
|
|
8
|
+
# Define the configuration values. config sets the value of the
|
|
9
|
+
# constant ONLY if it has not already been set, i.e. by the user in
|
|
10
|
+
# environment.rb
|
|
11
|
+
#++
|
|
12
|
+
|
|
13
|
+
# Source address for user emails
|
|
14
|
+
config :email_from, 'webmaster@your.company'
|
|
15
|
+
|
|
16
|
+
# Destination email for system errors
|
|
17
|
+
config :admin_email, 'webmaster@your.company'
|
|
18
|
+
|
|
19
|
+
# Sent in emails to users
|
|
20
|
+
config :app_url, 'http://localhost:3000/'
|
|
21
|
+
|
|
22
|
+
# Sent in emails to users
|
|
23
|
+
config :app_name, 'TestApp'
|
|
24
|
+
|
|
25
|
+
# Email charset
|
|
26
|
+
config :mail_charset, 'utf-8'
|
|
27
|
+
|
|
28
|
+
# Security token lifetime in hours
|
|
29
|
+
config :security_token_life_hours, 24
|
|
30
|
+
|
|
31
|
+
# Two column form input
|
|
32
|
+
config :two_column_input, true
|
|
33
|
+
|
|
34
|
+
# Add all changeable user fields to this array.
|
|
35
|
+
# They will then be able to be edited from the edit action. You
|
|
36
|
+
# should NOT include the email field in this array.
|
|
37
|
+
config :changeable_fields, [ 'firstname', 'lastname' ]
|
|
38
|
+
|
|
39
|
+
# Set to true to allow delayed deletes (i.e., delete of record
|
|
40
|
+
# doesn't happen immediately after user selects delete account,
|
|
41
|
+
# but rather after some expiration of time to allow this action
|
|
42
|
+
# to be reverted).
|
|
43
|
+
config :delayed_delete, false
|
|
44
|
+
|
|
45
|
+
# Default is one week
|
|
46
|
+
config :delayed_delete_days, 7
|
|
47
|
+
|
|
48
|
+
# the table to store user information in
|
|
49
|
+
if ActiveRecord::Base.pluralize_table_names
|
|
50
|
+
config :user_table, "users"
|
|
51
|
+
else
|
|
52
|
+
config :user_table, "user"
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# controls whether or not email is used
|
|
56
|
+
config :use_email_notification, true
|
|
57
|
+
|
|
58
|
+
# Controls whether accounts must be confirmed after signing up
|
|
59
|
+
# ONLY if this and use_email_notification are both true
|
|
60
|
+
config :confirm_account, true
|
|
61
|
+
|
|
62
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#!/usr/local/bin/ruby
|
|
2
|
+
|
|
3
|
+
require File.dirname(__FILE__) + "/../config/environment" unless defined?(RAILS_ROOT)
|
|
4
|
+
|
|
5
|
+
# If you're using RubyGems and mod_ruby, this require should be changed to an absolute path one, like:
|
|
6
|
+
# "/usr/local/lib/ruby/gems/1.8/gems/rails-0.8.0/lib/dispatcher" -- otherwise performance is severely impaired
|
|
7
|
+
require "dispatcher"
|
|
8
|
+
|
|
9
|
+
ADDITIONAL_LOAD_PATHS.reverse.each { |dir| $:.unshift(dir) if File.directory?(dir) } if defined?(Apache::RubyRun)
|
|
10
|
+
Dispatcher.dispatch
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
|
|
2
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
|
3
|
+
require 'user_controller'
|
|
4
|
+
require 'amrita2/testsupport'
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
# Re-raise errors caught by the controller.
|
|
8
|
+
class UserController; def rescue_action(e) raise e end; end
|
|
9
|
+
|
|
10
|
+
class UserControllerTestWithAmrita2 < Test::Unit::TestCase
|
|
11
|
+
include Amrita2::TestSupport
|
|
12
|
+
fixtures :users
|
|
13
|
+
|
|
14
|
+
def setup
|
|
15
|
+
LoginEngine::CONFIG[:salt] = "test-salt"
|
|
16
|
+
|
|
17
|
+
@controller = UserController.new
|
|
18
|
+
@request, @response = ActionController::TestRequest.new, ActionController::TestResponse.new
|
|
19
|
+
@request.host = "localhost"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def test_invalid_login
|
|
23
|
+
post :login, :user => { :login => "bob", :password => "wrong_password" }
|
|
24
|
+
assert_response :success
|
|
25
|
+
|
|
26
|
+
assert_nil session[:user]
|
|
27
|
+
assert_template "login"
|
|
28
|
+
#puts @response.body
|
|
29
|
+
assert_equal_as_xml @response.body, <<EOF
|
|
30
|
+
<html>
|
|
31
|
+
<head>
|
|
32
|
+
<title>MyApp</title>
|
|
33
|
+
<link href='/stylesheets/login_engine.css' media='screen' rel='Stylesheet' type='text/css' />
|
|
34
|
+
</head>
|
|
35
|
+
<body>
|
|
36
|
+
<div id='warning'>Login unsuccessful</div>
|
|
37
|
+
<div title="UserController login" class="form">
|
|
38
|
+
<h3>Please Login</h3>
|
|
39
|
+
<div class="form-padding">
|
|
40
|
+
<form action="/user/login" method="post">
|
|
41
|
+
<table>
|
|
42
|
+
<tr class="two_columns">
|
|
43
|
+
<td class="prompt"><label>Login ID:</label></td>
|
|
44
|
+
<td class="value"><input id="user_login" name="user[login]" size="30" type="text" value="bob"/></td>
|
|
45
|
+
</tr>
|
|
46
|
+
<tr class="two_columns">
|
|
47
|
+
<td class="prompt"><label>Password:</label></td>
|
|
48
|
+
<td class="value"><input id="user_password" name="user[password]" size="30" type="password" value=""/></td>
|
|
49
|
+
</tr>
|
|
50
|
+
</table>
|
|
51
|
+
<div class="button-bar">
|
|
52
|
+
<input name="commit" type="submit" value="Login" />
|
|
53
|
+
<a href="/user/signup">Register for an account</a> |
|
|
54
|
+
<a href="/user/forgot_password">Forgot my password</a>
|
|
55
|
+
</div>
|
|
56
|
+
</form>
|
|
57
|
+
</div>
|
|
58
|
+
</div>
|
|
59
|
+
</body>
|
|
60
|
+
</html>
|
|
61
|
+
EOF
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def test_invalid_login_ja
|
|
65
|
+
post :login, :user => { :login => "bob", :password => "wrong_password" }, :lang=>'ja'
|
|
66
|
+
assert_response :success
|
|
67
|
+
|
|
68
|
+
assert_nil session[:user]
|
|
69
|
+
assert_template "login"
|
|
70
|
+
assert_equal_as_xml @response.body, <<EOF
|
|
71
|
+
<html>
|
|
72
|
+
<head>
|
|
73
|
+
<title>MyApp</title>
|
|
74
|
+
<link href='/stylesheets/login_engine.css' media='screen' rel='Stylesheet' type='text/css' />
|
|
75
|
+
</head>
|
|
76
|
+
<body>
|
|
77
|
+
<div id='warning'>ログイン失敗</div>
|
|
78
|
+
<div title="UserController login" class="form">
|
|
79
|
+
<h3>ログインしてください</h3>
|
|
80
|
+
<div class="form-padding">
|
|
81
|
+
<form action="/user/login" method="post">
|
|
82
|
+
<table>
|
|
83
|
+
<tr class="two_columns">
|
|
84
|
+
<td class="prompt"><label>ログインID</label></td>
|
|
85
|
+
<td class="value"><input id="user_login" name="user[login]" size="30" type="text" value="bob"/></td>
|
|
86
|
+
</tr>
|
|
87
|
+
<tr class="two_columns">
|
|
88
|
+
<td class="prompt"><label>パスワード</label></td>
|
|
89
|
+
<td class="value"><input id="user_password" name="user[password]" size="30" type="password" value=""/></td>
|
|
90
|
+
</tr>
|
|
91
|
+
</table>
|
|
92
|
+
<div class="button-bar">
|
|
93
|
+
<input name="commit" type="submit" value="ログイン" />
|
|
94
|
+
<a href="/user/signup">新規登録する</a> |
|
|
95
|
+
<a href="/user/forgot_password">パスワードを忘れた時はこちら</a>
|
|
96
|
+
</div>
|
|
97
|
+
</form>
|
|
98
|
+
</div>
|
|
99
|
+
</div>
|
|
100
|
+
</body>
|
|
101
|
+
</html>
|
|
102
|
+
EOF
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def test_signup_bad_password
|
|
106
|
+
LoginEngine::CONFIG[:use_email_notification] = true
|
|
107
|
+
ActionMailer::Base.deliveries = []
|
|
108
|
+
|
|
109
|
+
@request.session['return-to'] = "/bogus/location"
|
|
110
|
+
post :signup, :user => { :login => "newbob", :password => "bad", :password_confirmation => "bad", :email => "newbob@test.com" }
|
|
111
|
+
assert_nil session[:user]
|
|
112
|
+
#assert_invalid_column_on_record "user", "password"
|
|
113
|
+
assert assigns["user"].errors.invalid?("password")
|
|
114
|
+
|
|
115
|
+
assert_response :success
|
|
116
|
+
assert_equal 0, ActionMailer::Base.deliveries.size
|
|
117
|
+
|
|
118
|
+
#puts @response.body
|
|
119
|
+
assert_equal_as_xml @response.body, <<EOF
|
|
120
|
+
<html>
|
|
121
|
+
<head>
|
|
122
|
+
<title>MyApp</title>
|
|
123
|
+
<link href='/stylesheets/login_engine.css' media='screen' rel='Stylesheet' type='text/css' />
|
|
124
|
+
</head>
|
|
125
|
+
<body>
|
|
126
|
+
|
|
127
|
+
<div title="UserController signup" class="form">
|
|
128
|
+
<h3>Signup</h3>
|
|
129
|
+
|
|
130
|
+
<div class="errorExplanation" id="errorExplanation"><h2>1 error prohibited this user from being saved</h2><p>There was a problem with the following field:</p><ul><li>Password is too short (minimum is 5 characters)</li></ul></div>
|
|
131
|
+
|
|
132
|
+
<div class="form-padding">
|
|
133
|
+
<form action="/user/signup" method="post">
|
|
134
|
+
<div class="user_edit">
|
|
135
|
+
<table>
|
|
136
|
+
<tr class="two_columns">
|
|
137
|
+
<td class="prompt"><label>First Name:</label></td>
|
|
138
|
+
<td class="value"><input id="user_firstname" name="user[firstname]" size="30" type="text" /></td>
|
|
139
|
+
</tr>
|
|
140
|
+
|
|
141
|
+
<tr class="two_columns">
|
|
142
|
+
<td class="prompt"><label>Last Name:</label></td>
|
|
143
|
+
<td class="value"><input id="user_lastname" name="user[lastname]" size="30" type="text" /></td>
|
|
144
|
+
</tr>
|
|
145
|
+
|
|
146
|
+
<tr class="two_columns">
|
|
147
|
+
<td class="prompt"><label>Login ID:</label></td>
|
|
148
|
+
<td class="value"><input id="user_login" name="user[login]" size="30" type="text" value="newbob" /></td>
|
|
149
|
+
</tr>
|
|
150
|
+
<tr class="two_columns">
|
|
151
|
+
<td class="prompt"><label>Email:</label></td>
|
|
152
|
+
<td class="value"><input id="user_email" name="user[email]" size="30" type="text" value="newbob@test.com" /></td>
|
|
153
|
+
</tr>
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
</table>
|
|
157
|
+
</div>
|
|
158
|
+
<br/>
|
|
159
|
+
<div class="user_password">
|
|
160
|
+
<table>
|
|
161
|
+
<tr class="two_columns">
|
|
162
|
+
<td class="prompt"><label>Password:</label></td>
|
|
163
|
+
<td class="value"><div class="fieldWithErrors"><input id="user_password" name="user[password]" size="30" type="password" value="" /></div></td>
|
|
164
|
+
</tr>
|
|
165
|
+
|
|
166
|
+
<tr class="two_columns">
|
|
167
|
+
<td class="prompt"><label>Password Confirmation:</label></td>
|
|
168
|
+
<td class="value"><input id="user_password_confirmation" name="user[password_confirmation]" size="30" type="password" value="" /></td>
|
|
169
|
+
</tr>
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
</table>
|
|
173
|
+
</div>
|
|
174
|
+
|
|
175
|
+
<div class="button-bar">
|
|
176
|
+
<input name="commit" type="submit" value="Signup" />
|
|
177
|
+
<a href="/user/login">Cancel</a>
|
|
178
|
+
</div>
|
|
179
|
+
</form>
|
|
180
|
+
</div>
|
|
181
|
+
</div>
|
|
182
|
+
</body>
|
|
183
|
+
</html>
|
|
184
|
+
EOF
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def test_edit
|
|
188
|
+
post :login, :user => { :login => "bob", :password => "atest" }
|
|
189
|
+
assert(@response.has_session_object?(:user))
|
|
190
|
+
|
|
191
|
+
get :edit
|
|
192
|
+
assert_response :success
|
|
193
|
+
|
|
194
|
+
#puts @response.body
|
|
195
|
+
assert_equal_as_xml @response.body, <<EOF
|
|
196
|
+
|
|
197
|
+
<html>
|
|
198
|
+
<head>
|
|
199
|
+
<title>MyApp</title>
|
|
200
|
+
<link href='/stylesheets/login_engine.css' media='screen' rel='Stylesheet' type='text/css' />
|
|
201
|
+
</head>
|
|
202
|
+
<body>
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
<div id="notice">Login successful</div>
|
|
206
|
+
|
|
207
|
+
<div title="UserController edit" class="form">
|
|
208
|
+
<h3>Edit user</h3>
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
<form action="/user/edit" method="post">
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
<div class = "user_edit"><table><tr class = "two_columns"><td class = "prompt"> <label> First Name: </label>
|
|
216
|
+
</td> <td class = "value"> <input id="user_firstname" name="user[firstname]" size="30" type="text" /> </td>
|
|
217
|
+
</tr><tr class = "two_columns"><td class = "prompt"> <label> Last Name: </label>
|
|
218
|
+
</td> <td class = "value"> <input id="user_lastname" name="user[lastname]" size="30" type="text" /> </td>
|
|
219
|
+
</tr><tr class = "two_columns"><td class = "prompt"> <label> Login ID: </label>
|
|
220
|
+
</td> <td class = "value"> <input id="user_login" name="user[login]" size="30" type="text" value="bob" /> </td>
|
|
221
|
+
</tr><tr class = "two_columns"><td class = "prompt"> <label> Email: </label>
|
|
222
|
+
</td> <td class = "value"> <input id="user_email" name="user[email]" size="30" type="text" value="bob@test.com" />
|
|
223
|
+
</td>
|
|
224
|
+
</tr></table>
|
|
225
|
+
<input name="submit" type="submit" value="Change Settings" />
|
|
226
|
+
</div>
|
|
227
|
+
</form>
|
|
228
|
+
<br/>
|
|
229
|
+
<form action="/user/change_password" method="post">
|
|
230
|
+
<input id="back_to" name="back_to" type="hidden" value="edit" />
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
<div class = "user_password"><table><tr class = "two_columns"><td class = "prompt"> <label> Password:
|
|
236
|
+
</label>
|
|
237
|
+
</td> <td class = "value"> <input id="user_password" name="user[password]" size="30" type="password" value="" />
|
|
238
|
+
</td>
|
|
239
|
+
</tr><tr class = "two_columns"><td class = "prompt"> <label> Password Confirmation: </label>
|
|
240
|
+
</td> <td class = "value"> <input id="user_password_confirmation" name="user[password_confirmation]" size="30" type="password" value="" /> </td>
|
|
241
|
+
</tr></table>
|
|
242
|
+
<input name="submit" type="submit" value="Change password" />
|
|
243
|
+
|
|
244
|
+
</div>
|
|
245
|
+
</form>
|
|
246
|
+
|
|
247
|
+
<form action="/user/delete" method="post">
|
|
248
|
+
<div class="user_delete">
|
|
249
|
+
<input id="user_form" name="user[form]" type="hidden" value="delete" />
|
|
250
|
+
<input name="submit" type="submit" value="Delete Account" />
|
|
251
|
+
</div>
|
|
252
|
+
</form>
|
|
253
|
+
</div>
|
|
254
|
+
</div>
|
|
255
|
+
</body>
|
|
256
|
+
</html>
|
|
257
|
+
|
|
258
|
+
EOF
|
|
259
|
+
post :edit, :user => { "firstname" => "Bob", "form" => "edit" }
|
|
260
|
+
assert_equal @response.session[:user].firstname, "Bob"
|
|
261
|
+
|
|
262
|
+
post :edit, :user => { "firstname" => "", "form" => "edit" }
|
|
263
|
+
assert_equal @response.session[:user].firstname, ""
|
|
264
|
+
|
|
265
|
+
get :logout
|
|
266
|
+
end
|
|
267
|
+
end
|