salted_login_generator 1.0.5 → 1.0.6
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/salted_login_generator.rb +2 -2
- data/templates/README +2 -1
- data/templates/_view_edit.rhtml +0 -1
- data/templates/_view_password.rhtml +0 -1
- data/templates/controller.rb +36 -5
- data/templates/controller_test.rb +57 -2
- data/templates/en.yaml +10 -5
- data/templates/login_environment.rb +9 -0
- data/templates/mock_time.rb +4 -4
- data/templates/notify.rb +25 -0
- data/templates/notify_delete.rhtml +5 -0
- data/templates/notify_pending_delete.rhtml +9 -0
- data/templates/notify_signup.rhtml +1 -1
- data/templates/user.rb +26 -10
- data/templates/user_model.erbsql +3 -1
- data/templates/users.yml +16 -0
- data/templates/view_edit.rhtml +9 -1
- metadata +4 -2
data/salted_login_generator.rb
CHANGED
@@ -58,7 +58,7 @@ class SaltedLoginGenerator < LocalizationGenerator #Rails::Generator::NamedBase
|
|
58
58
|
attr_accessor :controller_class_name
|
59
59
|
|
60
60
|
def login_views
|
61
|
-
%w(welcome login logout signup forgot_password change_password)
|
61
|
+
%w(welcome login logout edit signup forgot_password change_password)
|
62
62
|
end
|
63
63
|
|
64
64
|
def partial_views
|
@@ -66,6 +66,6 @@ class SaltedLoginGenerator < LocalizationGenerator #Rails::Generator::NamedBase
|
|
66
66
|
end
|
67
67
|
|
68
68
|
def notify_views
|
69
|
-
%w(signup forgot_password change_password)
|
69
|
+
%w(signup forgot_password change_password delete pending_delete)
|
70
70
|
end
|
71
71
|
end
|
data/templates/README
CHANGED
@@ -8,7 +8,7 @@ this:
|
|
8
8
|
|
9
9
|
class ApplicationController < ActionController::Base
|
10
10
|
include <%= class_name %>System
|
11
|
-
helper: <%=
|
11
|
+
helper: <%= singular_name %>
|
12
12
|
before_filter :login_required
|
13
13
|
|
14
14
|
After you have done the modifications the the ApplicationController and its
|
@@ -132,5 +132,6 @@ You can find more help at http://wiki.rubyonrails.com/rails/show/SaltedLoginGene
|
|
132
132
|
|
133
133
|
== Changelog
|
134
134
|
|
135
|
+
1.0.6 Proper delete support and bug fixes
|
135
136
|
1.0.5 Lots of fixes and changes (see rubyforge.org/salted-login)
|
136
137
|
1.0.0 First gem release
|
data/templates/_view_edit.rhtml
CHANGED
data/templates/controller.rb
CHANGED
@@ -96,7 +96,6 @@ class <%= class_name %>Controller < ApplicationController
|
|
96
96
|
generate_filled_in
|
97
97
|
if @params['<%= singular_name %>']['form']
|
98
98
|
form = @params['<%= singular_name %>'].delete('form')
|
99
|
-
oid = @params['<%= singular_name %>'].delete('id')
|
100
99
|
begin
|
101
100
|
case form
|
102
101
|
when "edit"
|
@@ -106,6 +105,8 @@ class <%= class_name %>Controller < ApplicationController
|
|
106
105
|
@<%= singular_name %>.save
|
107
106
|
when "change_password"
|
108
107
|
change_password
|
108
|
+
when "delete"
|
109
|
+
delete
|
109
110
|
else
|
110
111
|
raise "unknown edit action"
|
111
112
|
end
|
@@ -114,11 +115,35 @@ class <%= class_name %>Controller < ApplicationController
|
|
114
115
|
end
|
115
116
|
|
116
117
|
def delete
|
117
|
-
|
118
|
-
|
119
|
-
<%=
|
118
|
+
@<%= singular_name %> = @session['<%= singular_name %>']
|
119
|
+
begin
|
120
|
+
if <%= class_name %>System::CONFIG[:delayed_delete]
|
121
|
+
<%= class_name %>.transaction(@<%= singular_name %>) do
|
122
|
+
key = @<%= singular_name %>.set_delete_after
|
123
|
+
url = url_for(:action => 'restore_deleted')
|
124
|
+
url += "?<%= singular_name %>[id]=#{@<%= singular_name %>.id}&key=#{key}"
|
125
|
+
<%= class_name %>Notify.deliver_pending_delete(@<%= singular_name %>, url)
|
126
|
+
end
|
127
|
+
else
|
128
|
+
destroy(@<%= singular_name %>)
|
129
|
+
end
|
130
|
+
logout
|
131
|
+
redirect_to :action => 'login'
|
132
|
+
rescue
|
133
|
+
flash.now['message'] = l(:<%= singular_name %>_delete_email_error, "#{@<%= singular_name %>['email']}")
|
134
|
+
redirect_back_or_default :action => 'welcome'
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def restore_deleted
|
139
|
+
@<%= singular_name %> = @session['<%= singular_name %>']
|
140
|
+
@<%= singular_name %>.deleted = 0
|
141
|
+
if not @<%= singular_name %>.save
|
142
|
+
flash.now['notice'] = l(:<%= singular_name %>_restore_deleted_error, "#{@<%= singular_name %>['login']}")
|
143
|
+
redirect_to :action => 'login'
|
144
|
+
else
|
145
|
+
redirect_to :action => 'welcome'
|
120
146
|
end
|
121
|
-
redirect_to :action => 'login'
|
122
147
|
end
|
123
148
|
|
124
149
|
def welcome
|
@@ -126,6 +151,12 @@ class <%= class_name %>Controller < ApplicationController
|
|
126
151
|
|
127
152
|
protected
|
128
153
|
|
154
|
+
def destroy(user)
|
155
|
+
<%= class_name %>Notify.deliver_delete(<%= singular_name %>)
|
156
|
+
flash['notice'] = l(:<%= singular_name %>_delete_finished, "#{<%= singular_name %>['login']}")
|
157
|
+
<%= singular_name %>.destroy()
|
158
|
+
end
|
159
|
+
|
129
160
|
def protect?(action)
|
130
161
|
if ['login', 'signup', 'forgot_password'].include?(action)
|
131
162
|
return false
|
@@ -48,9 +48,9 @@ class <%= class_name %>ControllerTest < Test::Unit::TestCase
|
|
48
48
|
assert_equal 0, <%= singular_name %>.verified
|
49
49
|
|
50
50
|
# First past the expiration.
|
51
|
-
Time.
|
51
|
+
Time.advance_by_days = 1
|
52
52
|
get :welcome, "<%= singular_name %>"=> { "id" => "#{<%= singular_name %>.id}" }, "key" => "#{key}"
|
53
|
-
Time.
|
53
|
+
Time.advance_by_days = 0
|
54
54
|
<%= singular_name %> = <%= class_name %>.find_by_email("newbob@test.com")
|
55
55
|
assert_equal 0, <%= singular_name %>.verified
|
56
56
|
|
@@ -83,6 +83,61 @@ class <%= class_name %>ControllerTest < Test::Unit::TestCase
|
|
83
83
|
assert false
|
84
84
|
end
|
85
85
|
end
|
86
|
+
|
87
|
+
def test_edit
|
88
|
+
post :login, "<%= singular_name %>" => { "login" => "bob", "password" => "atest" }
|
89
|
+
assert_session_has "<%= singular_name %>"
|
90
|
+
|
91
|
+
post :edit, "<%= singular_name %>" => { "firstname" => "Bob", "form" => "edit" }
|
92
|
+
assert_equal @response.session['<%= singular_name %>'].firstname, "Bob"
|
93
|
+
|
94
|
+
post :edit, "<%= singular_name %>" => { "firstname" => "", "form" => "edit" }
|
95
|
+
assert_equal @response.session['<%= singular_name %>'].firstname, ""
|
96
|
+
|
97
|
+
get :logout
|
98
|
+
end
|
99
|
+
|
100
|
+
def test_delete
|
101
|
+
ActionMailer::Base.deliveries = []
|
102
|
+
|
103
|
+
# Immediate delete
|
104
|
+
post :login, "<%= singular_name %>" => { "login" => "deletebob1", "password" => "alongtest" }
|
105
|
+
assert_session_has "<%= singular_name %>"
|
106
|
+
|
107
|
+
<%= class_name %>System::CONFIG[:delayed_delete] = false
|
108
|
+
post :edit, "<%= singular_name %>" => { "form" => "delete" }
|
109
|
+
assert_equal 1, ActionMailer::Base.deliveries.size
|
110
|
+
|
111
|
+
assert_session_has_no "<%= singular_name %>"
|
112
|
+
post :login, "<%= singular_name %>" => { "login" => "deletebob1", "password" => "alongtest" }
|
113
|
+
assert_session_has_no "<%= singular_name %>"
|
114
|
+
|
115
|
+
# Now try delayed delete
|
116
|
+
ActionMailer::Base.deliveries = []
|
117
|
+
|
118
|
+
post :login, "<%= singular_name %>" => { "login" => "deletebob2", "password" => "alongtest" }
|
119
|
+
assert_session_has "<%= singular_name %>"
|
120
|
+
|
121
|
+
<%= class_name %>System::CONFIG[:delayed_delete] = true
|
122
|
+
post :edit, "<%= singular_name %>" => { "form" => "delete" }
|
123
|
+
assert_equal 1, ActionMailer::Base.deliveries.size
|
124
|
+
mail = ActionMailer::Base.deliveries[0]
|
125
|
+
mail.encoded =~ /user\[id\]=(.*?)&key=(.*?)"/
|
126
|
+
id = $1
|
127
|
+
key = $2
|
128
|
+
post :restore_deleted, "<%= singular_name %>" => { "id" => "#{id}" }, "key" => "badkey"
|
129
|
+
assert_session_has_no "<%= singular_name %>"
|
130
|
+
|
131
|
+
# Advance the time past the delete date
|
132
|
+
Time.advance_by_days = <%= class_name %>System::CONFIG[:delayed_delete_days]
|
133
|
+
post :restore_deleted, "<%= singular_name %>" => { "id" => "#{id}" }, "key" => "#{key}"
|
134
|
+
assert_session_has_no "<%= singular_name %>"
|
135
|
+
Time.advance_by_days = 0
|
136
|
+
|
137
|
+
post :restore_deleted, "<%= singular_name %>" => { "id" => "#{id}" }, "key" => "#{key}"
|
138
|
+
assert_session_has "<%= singular_name %>"
|
139
|
+
get :logout
|
140
|
+
end
|
86
141
|
|
87
142
|
def test_signup
|
88
143
|
do_test_signup(true, false)
|
data/templates/en.yaml
CHANGED
@@ -15,12 +15,16 @@ active_record_errors_not_a_number: is not a number
|
|
15
15
|
<%= singular_name %>_login_failed: Login unsuccessful
|
16
16
|
<%= singular_name %>_signup_succeeded: Signup successful! Please check your registered email account to verify your account registration and continue with the login.
|
17
17
|
<%= singular_name %>_confirmation_email_error: 'Error creating account: confirmation email not sent'
|
18
|
-
<%= singular_name %>_updated_password: Your updated password has been emailed to %s
|
18
|
+
<%= singular_name %>_updated_password: Your updated password has been emailed to %s.
|
19
19
|
<%= singular_name %>_change_password_email_error: Your password could not be changed at this time. Please retry.
|
20
|
-
<%= singular_name %>_enter_valid_email_address: Please enter a valid email address
|
21
|
-
<%= singular_name %>_email_address_not_found: We could not find a user with the email address %s
|
22
|
-
<%= singular_name %>_forgotten_password_emailed: Instructions on resetting your password have been emailed to %s
|
23
|
-
<%= singular_name %>_forgotten_password_email_error: Your password could not be emailed to %s
|
20
|
+
<%= singular_name %>_enter_valid_email_address: Please enter a valid email address.
|
21
|
+
<%= singular_name %>_email_address_not_found: We could not find a user with the email address %s.
|
22
|
+
<%= singular_name %>_forgotten_password_emailed: Instructions on resetting your password have been emailed to %s.
|
23
|
+
<%= singular_name %>_forgotten_password_email_error: Your password could not be emailed to %s.
|
24
|
+
<%= singular_name %>_delete_emailed: Instructions on deleting your account have been emailed to %s.
|
25
|
+
<%= singular_name %>_delete_email_error: The delete instructions were not sent. Please try again later.
|
26
|
+
<%= singular_name %>_delete_finished: The account for %s was successfully deleted.
|
27
|
+
<%= singular_name %>_restore_deleted_error: The account for %s was not restored. Please try the link again.
|
24
28
|
<%= singular_name %>_account_verified: Account verified!
|
25
29
|
|
26
30
|
# Views
|
@@ -67,3 +71,4 @@ active_record_errors_not_a_number: is not a number
|
|
67
71
|
# Edit
|
68
72
|
<%= singular_name %>_edit_head: Edit <%= singular_name %>
|
69
73
|
<%= singular_name %>_change_settings_button: Change settings
|
74
|
+
<%= singular_name %>_delete_account_button: Delete account
|
@@ -26,6 +26,15 @@ module <%= class_name %>System
|
|
26
26
|
# should NOT include the email field in this array.
|
27
27
|
:changeable_fields => [ 'firstname', 'lastname' ],
|
28
28
|
|
29
|
+
# Set to true to allow delayed deletes (i.e., delete of record
|
30
|
+
# doesn't happen immediately after user selects delete account,
|
31
|
+
# but rather after some expiration of time to allow this action
|
32
|
+
# to be reverted).
|
33
|
+
:delayed_delete => false,
|
34
|
+
|
35
|
+
# Default is one week
|
36
|
+
:delayed_delete_days => 7,
|
37
|
+
|
29
38
|
# Server environment
|
30
39
|
:server_env => "#{RAILS_ENV}"
|
31
40
|
}
|
data/templates/mock_time.rb
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
require 'time'
|
2
2
|
|
3
3
|
Time.class_eval {
|
4
|
-
@@
|
5
|
-
cattr_accessor :
|
4
|
+
@@advance_by_days = 0
|
5
|
+
cattr_accessor :advance_by_days
|
6
6
|
|
7
7
|
class << Time
|
8
8
|
alias now_old now
|
9
9
|
def now
|
10
|
-
if Time.
|
11
|
-
return Time.at(now_old.to_i + 60 * 60 * 24 + 1)
|
10
|
+
if Time.advance_by_days != 0
|
11
|
+
return Time.at(now_old.to_i + Time.advance_by_days * 60 * 60 * 24 + 1)
|
12
12
|
else
|
13
13
|
now_old
|
14
14
|
end
|
data/templates/notify.rb
CHANGED
@@ -40,6 +40,31 @@ class <%= class_name %>Notify < ActionMailer::Base
|
|
40
40
|
@body["app_name"] = <%= class_name %>System::CONFIG[:app_name].to_s
|
41
41
|
end
|
42
42
|
|
43
|
+
def pending_delete(<%= singular_name %>, url=nil)
|
44
|
+
setup_email(<%= singular_name %>)
|
45
|
+
|
46
|
+
# Email header info
|
47
|
+
@subject += "Delete <%= singular_name %> notification"
|
48
|
+
|
49
|
+
# Email body substitutions
|
50
|
+
@body["name"] = "#{<%= singular_name %>.firstname} #{<%= singular_name %>.lastname}"
|
51
|
+
@body["url"] = url || <%= class_name %>System::CONFIG[:app_url].to_s
|
52
|
+
@body["app_name"] = <%= class_name %>System::CONFIG[:app_name].to_s
|
53
|
+
@body["days"] = <%= class_name %>System::CONFIG[:delayed_delete_days].to_s
|
54
|
+
end
|
55
|
+
|
56
|
+
def delete(<%= singular_name %>, url=nil)
|
57
|
+
setup_email(<%= singular_name %>)
|
58
|
+
|
59
|
+
# Email header info
|
60
|
+
@subject += "Delete <%= singular_name %> notification"
|
61
|
+
|
62
|
+
# Email body substitutions
|
63
|
+
@body["name"] = "#{<%= singular_name %>.firstname} #{<%= singular_name %>.lastname}"
|
64
|
+
@body["url"] = url || <%= class_name %>System::CONFIG[:app_url].to_s
|
65
|
+
@body["app_name"] = <%= class_name %>System::CONFIG[:app_name].to_s
|
66
|
+
end
|
67
|
+
|
43
68
|
def setup_email(<%= singular_name %>)
|
44
69
|
@recipients = "#{<%= singular_name %>.email}"
|
45
70
|
@from = <%= class_name %>System::CONFIG[:email_from].to_s
|
@@ -0,0 +1,9 @@
|
|
1
|
+
Dear <%%= @name %>,
|
2
|
+
|
3
|
+
At your request, <%%= @app_name %> has marked your account for deletion. If it was not at your request, then you should be aware that someone has access to your account and requested this change.
|
4
|
+
|
5
|
+
The following link is provided for you to restore your deleted account. If you click on this link within the next <%%= @days %> days, your account will not be deleted. Otherwise, simply ignore this email and your account will be permanently deleted after that time.
|
6
|
+
|
7
|
+
<a href="<%%= @url%>">Click me!</a>
|
8
|
+
|
9
|
+
<%%= @url %>
|
data/templates/user.rb
CHANGED
@@ -27,12 +27,14 @@ class <%= class_name %> < ActiveRecord::Base
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def self.authenticate(login, pass)
|
30
|
-
u = find_first(["login = ? AND verified = 1", login])
|
30
|
+
u = find_first(["login = ? AND verified = 1 AND deleted = 0", login])
|
31
31
|
return nil if u.nil?
|
32
32
|
find_first(["login = ? AND salted_password = ? AND verified = 1", login, salted_password(u.salt, hashed(pass))])
|
33
33
|
end
|
34
34
|
|
35
35
|
def self.authenticate_by_token(id, token)
|
36
|
+
# Allow logins for deleted accounts, but only via this method (and
|
37
|
+
# not the regular authenticate call)
|
36
38
|
u = find_first(["id = ? AND security_token = ?", id, token])
|
37
39
|
return nil if u.nil? or u.token_expired?
|
38
40
|
return nil if false == u.update_expiry
|
@@ -50,15 +52,25 @@ class <%= class_name %> < ActiveRecord::Base
|
|
50
52
|
update_without_callbacks
|
51
53
|
end
|
52
54
|
|
53
|
-
def generate_security_token
|
54
|
-
if self.security_token.nil? or self.token_expiry.nil? or
|
55
|
+
def generate_security_token(hours = nil)
|
56
|
+
if not hours.nil? or self.security_token.nil? or self.token_expiry.nil? or
|
55
57
|
(Time.now.to_i + token_lifetime / 2) >= self.token_expiry.to_i
|
56
|
-
return new_security_token
|
58
|
+
return new_security_token(hours)
|
57
59
|
else
|
58
60
|
return self.security_token
|
59
61
|
end
|
60
62
|
end
|
61
63
|
|
64
|
+
def set_delete_after
|
65
|
+
hours = <%= class_name %>System::CONFIG[:delayed_delete_days] * 24
|
66
|
+
write_attribute('deleted', 1)
|
67
|
+
write_attribute('delete_after', Time.at(Time.now.to_i + hours * 60 * 60))
|
68
|
+
|
69
|
+
# Generate and return a token here, so that it expires at
|
70
|
+
# the same time that the account deletion takes effect.
|
71
|
+
return generate_security_token(hours)
|
72
|
+
end
|
73
|
+
|
62
74
|
def change_password(pass, confirm = nil)
|
63
75
|
self.password = pass
|
64
76
|
self.password_confirmation = confirm.nil? ? pass : confirm
|
@@ -67,7 +79,7 @@ class <%= class_name %> < ActiveRecord::Base
|
|
67
79
|
|
68
80
|
def valid?
|
69
81
|
super
|
70
|
-
run_validations(:validate_on_virtual) if
|
82
|
+
run_validations(:validate_on_virtual) if virtual_validations?
|
71
83
|
errors.empty?
|
72
84
|
end
|
73
85
|
|
@@ -75,7 +87,7 @@ class <%= class_name %> < ActiveRecord::Base
|
|
75
87
|
|
76
88
|
attr_accessor :password, :password_confirmation
|
77
89
|
|
78
|
-
def
|
90
|
+
def virtual_validations?
|
79
91
|
@new_password
|
80
92
|
end
|
81
93
|
|
@@ -92,15 +104,19 @@ class <%= class_name %> < ActiveRecord::Base
|
|
92
104
|
end
|
93
105
|
end
|
94
106
|
|
95
|
-
def new_security_token
|
107
|
+
def new_security_token(hours = nil)
|
96
108
|
write_attribute('security_token', self.class.hashed(self.salted_password + Time.now.to_i.to_s + rand.to_s))
|
97
|
-
write_attribute('token_expiry', Time.at(Time.now.to_i + token_lifetime))
|
109
|
+
write_attribute('token_expiry', Time.at(Time.now.to_i + token_lifetime(hours)))
|
98
110
|
update_without_callbacks
|
99
111
|
return self.security_token
|
100
112
|
end
|
101
113
|
|
102
|
-
def token_lifetime
|
103
|
-
|
114
|
+
def token_lifetime(hours = nil)
|
115
|
+
if hours.nil?
|
116
|
+
<%= class_name %>System::CONFIG[:security_token_life_hours] * 60 * 60
|
117
|
+
else
|
118
|
+
hours * 60 * 60
|
119
|
+
end
|
104
120
|
end
|
105
121
|
|
106
122
|
def self.salted_password(salt, hashed_password)
|
data/templates/user_model.erbsql
CHANGED
@@ -12,5 +12,7 @@ CREATE TABLE users (
|
|
12
12
|
token_expiry <%= @datetime %> default NULL,
|
13
13
|
created_at <%= @datetime %> default NULL,
|
14
14
|
updated_at <%= @datetime %> default NULL,
|
15
|
-
logged_in_at <%= @datetime %> default NULL
|
15
|
+
logged_in_at <%= @datetime %> default NULL,
|
16
|
+
deleted INT default 0,
|
17
|
+
delete_after <%= @datetime %> default NULL
|
16
18
|
) <%= @options %>;
|
data/templates/users.yml
CHANGED
@@ -22,4 +22,20 @@ longbob:
|
|
22
22
|
salted_password: c841391e1d29100a4920de7a8fbb4b0fd180c6c0 # alongtest
|
23
23
|
salt: c068e3671780f16898c0a8295ae8d82cc59713e2
|
24
24
|
email: longbob@test.com
|
25
|
+
verified: 1
|
26
|
+
|
27
|
+
deletebob1:
|
28
|
+
id: 1000004
|
29
|
+
login: deletebob1
|
30
|
+
salted_password: c841391e1d29100a4920de7a8fbb4b0fd180c6c0 # alongtest
|
31
|
+
salt: c068e3671780f16898c0a8295ae8d82cc59713e2
|
32
|
+
email: deletebob1@test.com
|
33
|
+
verified: 1
|
34
|
+
|
35
|
+
deletebob2:
|
36
|
+
id: 1000005
|
37
|
+
login: deletebob2
|
38
|
+
salted_password: c841391e1d29100a4920de7a8fbb4b0fd180c6c0 # alongtest
|
39
|
+
salt: c068e3671780f16898c0a8295ae8d82cc59713e2
|
40
|
+
email: deletebob2@test.com
|
25
41
|
verified: 1
|
data/templates/view_edit.rhtml
CHANGED
@@ -8,5 +8,13 @@
|
|
8
8
|
<%%= start_form_tag_helper %>
|
9
9
|
<%%= render_partial 'password', :submit => true %>
|
10
10
|
<%%= end_form_tag %>
|
11
|
+
|
12
|
+
<%%= start_form_tag_helper %>
|
13
|
+
<div class="<%= singular_name %>_delete">
|
14
|
+
<%%= form_input :hidden_field, 'form', :value => 'delete' %>
|
15
|
+
|
16
|
+
<%%= form_input :submit_button, 'delete_account' %>
|
17
|
+
</div>
|
18
|
+
<%%= end_form_tag %>
|
11
19
|
</div>
|
12
|
-
</div>
|
20
|
+
</div>
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.8
|
|
3
3
|
specification_version: 1
|
4
4
|
name: salted_login_generator
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 1.0.
|
7
|
-
date: 2005-04
|
6
|
+
version: 1.0.6
|
7
|
+
date: 2005-05-04
|
8
8
|
summary: "[Rails] Login generator with salted passwords."
|
9
9
|
require_paths:
|
10
10
|
- "."
|
@@ -51,6 +51,8 @@ files:
|
|
51
51
|
- templates/view_change_password.rhtml
|
52
52
|
- templates/notify_signup.rhtml
|
53
53
|
- templates/notify_forgot_password.rhtml
|
54
|
+
- templates/notify_pending_delete.rhtml
|
55
|
+
- templates/notify_delete.rhtml
|
54
56
|
- templates/notify_change_password.rhtml
|
55
57
|
- templates/mock_notify.rb
|
56
58
|
- templates/mock_time.rb
|