login_sugar_generator 0.9.4 → 0.9.5
Sign up to get free protection for your applications and to get access to all the features.
- data/templates/README +10 -10
- data/templates/controller.rb +33 -27
- data/templates/controller_test.rb +13 -0
- data/templates/default_setup.zip +0 -0
- data/templates/helper.rb +4 -9
- data/templates/user.rb +6 -5
- data/templates/users.yml +1 -1
- data/templates/view_change_password.rhtml +2 -2
- data/templates/view_edit.rhtml +6 -6
- data/templates/view_forgot_password.rhtml +2 -2
- data/templates/view_login.rhtml +2 -2
- data/templates/view_signup.rhtml +2 -2
- metadata +4 -3
data/templates/README
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
== About
|
2
2
|
|
3
3
|
login_sugar is a modification of salted_login generator 1.1.1 that works
|
4
|
-
out of the box on Rails 1.
|
4
|
+
out of the box on Rails 1.2.3
|
5
5
|
|
6
6
|
Changes:
|
7
|
-
- tests all pass out of the box on Rails
|
7
|
+
- tests all pass out of the box on Rails 1.2.3
|
8
8
|
- using ActiveRecord::Migrations for db setup
|
9
9
|
- put underscores in first_name and last_name user attributes
|
10
10
|
- replaced Mock Time extension with a Mock Clock.
|
@@ -12,6 +12,7 @@ Changes:
|
|
12
12
|
- contains a default configuration zip
|
13
13
|
- session references se symbols
|
14
14
|
- localization removed
|
15
|
+
- removed deprecated code
|
15
16
|
|
16
17
|
More about salted_login_generator at http://rubyforge.org/projects/salted-login
|
17
18
|
|
@@ -21,7 +22,7 @@ If you are on Windoze, see http://wiki.rubyonrails.com/rails/pages/iconv/
|
|
21
22
|
|
22
23
|
== Installation
|
23
24
|
|
24
|
-
If you are working with a fresh rails 1.
|
25
|
+
If you are working with a fresh rails 1.2.3 project, you can unzip the included
|
25
26
|
default_login_sugar_setup.zip file in your RAILS_ROOT directory. It contains
|
26
27
|
preconfigured application controller, environment.rb, application_helper.rb and
|
27
28
|
test_helper.rb that should work if you used User as your controller names when
|
@@ -41,7 +42,6 @@ this:
|
|
41
42
|
class ApplicationController < ActionController::Base
|
42
43
|
include <%= class_name %>System
|
43
44
|
helper :<%= singular_name %>
|
44
|
-
model :<%= singular_name %>
|
45
45
|
before_filter :authenticate_user
|
46
46
|
|
47
47
|
Add the following at the end of your config/environment.rb file:
|
@@ -60,15 +60,14 @@ Edit this file as necessary.
|
|
60
60
|
Import the <%= singular_name %> model into the database.
|
61
61
|
|
62
62
|
You'll have to create your development and test databases first and configure your
|
63
|
-
config/database.yml appropriately.
|
64
|
-
test/fixtures/users.yml and make the indicated change on the last fixture.
|
63
|
+
config/database.yml appropriately.
|
65
64
|
|
66
65
|
You can use the provided migration script in
|
67
66
|
db/migrate/migration_login_sugar__rename_this_to_fit_your_project.rb.
|
68
67
|
|
69
|
-
This
|
70
|
-
|
71
|
-
|
68
|
+
This migration table is meant as an example and you can extend it, however I suggest first
|
69
|
+
completing the stock installation and running the tests to confirm installation, then create
|
70
|
+
a new migration to add your new columns.
|
72
71
|
|
73
72
|
Rename db/migrate/migration_login_sugar__rename_this_to_fit_your_project.rb to
|
74
73
|
db/migrate/###_login_sugar.rb where ### is the proper new migration level. For example,
|
@@ -78,7 +77,7 @@ of the migration in the class definition as well.
|
|
78
77
|
|
79
78
|
Then run:
|
80
79
|
|
81
|
-
rake
|
80
|
+
rake db:migrate
|
82
81
|
|
83
82
|
Go ahead and run the unit and functional tests now:
|
84
83
|
|
@@ -178,6 +177,7 @@ automatically on startup.
|
|
178
177
|
== Changelog
|
179
178
|
|
180
179
|
login_sugar
|
180
|
+
0.9.5 security updates. compatible with rails 1.2.3
|
181
181
|
0.9.4 removed scaffold references, removed localization, added generator rake task
|
182
182
|
0.9.3 fixed Clock.now, symbolized session references
|
183
183
|
0.9.2 fixed localization reference for sign in form (thanks Nym)
|
data/templates/controller.rb
CHANGED
@@ -5,31 +5,37 @@ class <%= class_name %>Controller < ApplicationController
|
|
5
5
|
|
6
6
|
def login
|
7
7
|
return if generate_blank_form
|
8
|
-
@<%= singular_name %> = <%= class_name %>.new(
|
9
|
-
<%= singular_name %> = <%= class_name %>.authenticate(
|
8
|
+
@<%= singular_name %> = <%= class_name %>.new(params['<%= singular_name %>'])
|
9
|
+
<%= singular_name %> = <%= class_name %>.authenticate(params['<%= singular_name %>']['login'], params['<%= singular_name %>']['password'])
|
10
10
|
if <%= singular_name %>
|
11
11
|
@current_<%= singular_name %> = <%= singular_name %>
|
12
|
-
|
12
|
+
session[:<%= singular_name %>_id] = <%= singular_name %>.id
|
13
13
|
flash['notice'] = 'Login succeeded'
|
14
14
|
redirect_back_or_default :action => 'welcome'
|
15
15
|
else
|
16
|
-
@login =
|
16
|
+
@login = params['<%= singular_name %>']['login']
|
17
17
|
flash['message'] = 'Login failed'
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
21
|
def signup
|
22
22
|
return if generate_blank_form
|
23
|
-
|
24
|
-
|
23
|
+
@<%= singular_name %> = <%= class_name %>.new(
|
24
|
+
:login => params['<%= singular_name %>'][:login],
|
25
|
+
:password => params['<%= singular_name %>'][:password],
|
26
|
+
:password_confirmation => params['<%= singular_name %>'][:password_confirmation],
|
27
|
+
:email => params['<%= singular_name %>'][:email],
|
28
|
+
:first_name => params['<%= singular_name %>'][:first_name],
|
29
|
+
:last_name => params['<%= singular_name %>'][:last_name]
|
30
|
+
)
|
25
31
|
begin
|
26
|
-
<%= class_name %>.transaction
|
32
|
+
<%= class_name %>.transaction do
|
27
33
|
@<%= singular_name %>.password_needs_confirmation = true
|
28
34
|
if @<%= singular_name %>.save
|
29
35
|
key = @<%= singular_name %>.generate_security_token
|
30
36
|
url = url_for(:action => 'welcome')
|
31
37
|
url += "?<%= singular_name %>[id]=#{@<%= singular_name %>.id}&key=#{key}"
|
32
|
-
<%= class_name %>Notify.deliver_signup(@<%= singular_name %>,
|
38
|
+
<%= class_name %>Notify.deliver_signup(@<%= singular_name %>, params['<%= singular_name %>']['password'], url)
|
33
39
|
flash['notice'] = 'Signup successful! Please check your registered email account to verify your account registration and continue with the login.'
|
34
40
|
redirect_to :action => 'login'
|
35
41
|
end
|
@@ -41,16 +47,16 @@ class <%= class_name %>Controller < ApplicationController
|
|
41
47
|
end
|
42
48
|
|
43
49
|
def logout
|
44
|
-
|
50
|
+
session[:<%= singular_name %>_id] = nil
|
45
51
|
@current_<%= singular_name %> = nil
|
46
52
|
redirect_to :action => 'login'
|
47
53
|
end
|
48
54
|
|
49
55
|
def change_password
|
50
56
|
return if generate_filled_in
|
51
|
-
|
57
|
+
params['<%= singular_name %>'].delete('form')
|
52
58
|
begin
|
53
|
-
@<%= singular_name %>.change_password(
|
59
|
+
@<%= singular_name %>.change_password(params['<%= singular_name %>']['password'], params['<%= singular_name %>']['password_confirmation'])
|
54
60
|
@<%= singular_name %>.save!
|
55
61
|
rescue Exception => ex
|
56
62
|
report_exception ex
|
@@ -58,7 +64,7 @@ class <%= class_name %>Controller < ApplicationController
|
|
58
64
|
render and return
|
59
65
|
end
|
60
66
|
begin
|
61
|
-
<%= class_name %>Notify.deliver_change_password(@<%= singular_name %>,
|
67
|
+
<%= class_name %>Notify.deliver_change_password(@<%= singular_name %>, params['<%= singular_name %>']['password'])
|
62
68
|
rescue Exception => ex
|
63
69
|
report_exception ex
|
64
70
|
end
|
@@ -74,18 +80,18 @@ class <%= class_name %>Controller < ApplicationController
|
|
74
80
|
|
75
81
|
return if generate_blank_form
|
76
82
|
|
77
|
-
if
|
83
|
+
if params['<%= singular_name %>']['email'].empty?
|
78
84
|
flash.now['message'] = 'Please enter a valid email address.'
|
79
|
-
elsif (<%= singular_name %> = <%= class_name %>.find_by_email(
|
80
|
-
flash.now['message'] = "We could not find a <%= singular_name %> with the email address #{CGI.escapeHTML(
|
85
|
+
elsif (<%= singular_name %> = <%= class_name %>.find_by_email(params['<%= singular_name %>']['email'])).nil?
|
86
|
+
flash.now['message'] = "We could not find a <%= singular_name %> with the email address #{CGI.escapeHTML(params['<%= singular_name %>']['email'])}"
|
81
87
|
else
|
82
88
|
begin
|
83
|
-
<%= class_name %>.transaction
|
89
|
+
<%= class_name %>.transaction do
|
84
90
|
key = <%= singular_name %>.generate_security_token
|
85
91
|
url = url_for(:action => 'change_password')
|
86
92
|
url += "?<%= singular_name %>[id]=#{<%= singular_name %>.id}&key=#{key}"
|
87
93
|
<%= class_name %>Notify.deliver_forgot_password(<%= singular_name %>, url)
|
88
|
-
flash['notice'] = "Instructions on resetting your password have been emailed to #{CGI.escapeHTML(
|
94
|
+
flash['notice'] = "Instructions on resetting your password have been emailed to #{CGI.escapeHTML(params['<%= singular_name %>']['email'])}."
|
89
95
|
unless authenticated_<%= singular_name %>?
|
90
96
|
redirect_to :action => 'login'
|
91
97
|
return
|
@@ -94,21 +100,21 @@ class <%= class_name %>Controller < ApplicationController
|
|
94
100
|
end
|
95
101
|
rescue Exception => ex
|
96
102
|
report_exception ex
|
97
|
-
flash.now['message'] = "Your password could not be emailed to #{CGI.escapeHTML(
|
103
|
+
flash.now['message'] = "Your password could not be emailed to #{CGI.escapeHTML(params['<%= singular_name %>']['email'])}"
|
98
104
|
end
|
99
105
|
end
|
100
106
|
end
|
101
107
|
|
102
108
|
def edit
|
103
109
|
return if generate_filled_in
|
104
|
-
if
|
105
|
-
form =
|
110
|
+
if params['<%= singular_name %>']['form']
|
111
|
+
form = params['<%= singular_name %>'].delete('form')
|
106
112
|
begin
|
107
113
|
case form
|
108
114
|
when "edit"
|
109
|
-
|
110
|
-
|
111
|
-
@<%= singular_name %>.attributes =
|
115
|
+
unclean_params = params['<%= singular_name %>']
|
116
|
+
<%= singular_name %>_params = unclean_params.delete_if { |k,v| not <%= class_name %>::CHANGEABLE_FIELDS.include?(k) }
|
117
|
+
@<%= singular_name %>.attributes = <%= singular_name %>_params
|
112
118
|
@<%= singular_name %>.save
|
113
119
|
flash.now['notice'] = "<%= class_name %> has been updated."
|
114
120
|
when "change_password"
|
@@ -126,7 +132,7 @@ class <%= class_name %>Controller < ApplicationController
|
|
126
132
|
end
|
127
133
|
|
128
134
|
def delete
|
129
|
-
@<%= singular_name %> = @current_<%= singular_name %> || <%= class_name %>.find_by_id(
|
135
|
+
@<%= singular_name %> = @current_<%= singular_name %> || <%= class_name %>.find_by_id( session[:<%= singular_name %>_id] )
|
130
136
|
begin
|
131
137
|
@<%= singular_name %>.update_attribute( :deleted, true )
|
132
138
|
logout
|
@@ -151,7 +157,7 @@ class <%= class_name %>Controller < ApplicationController
|
|
151
157
|
|
152
158
|
# Generate a template <%= singular_name %> for certain actions on get
|
153
159
|
def generate_blank_form
|
154
|
-
case
|
160
|
+
case request.method
|
155
161
|
when :get
|
156
162
|
@<%= singular_name %> = <%= class_name %>.new
|
157
163
|
render
|
@@ -162,8 +168,8 @@ class <%= class_name %>Controller < ApplicationController
|
|
162
168
|
|
163
169
|
# Generate a template <%= singular_name %> for certain actions on get
|
164
170
|
def generate_filled_in
|
165
|
-
@<%= singular_name %> = @current_<%= singular_name %> || <%= class_name %>.find_by_id(
|
166
|
-
case
|
171
|
+
@<%= singular_name %> = @current_<%= singular_name %> || <%= class_name %>.find_by_id( session[:<%= singular_name %>_id] )
|
172
|
+
case request.method
|
167
173
|
when :get
|
168
174
|
render
|
169
175
|
return true
|
@@ -72,6 +72,18 @@ class <%= class_name %>ControllerTest < Test::Unit::TestCase
|
|
72
72
|
assert !<%= singular_name %>.verified
|
73
73
|
end
|
74
74
|
|
75
|
+
|
76
|
+
def test_signup__cannot_set_arbitrary_attributes
|
77
|
+
post_signup :login => "new<%= singular_name %>",
|
78
|
+
:password => "password", :password_confirmation => "password",
|
79
|
+
:email => "skunk@example.com",
|
80
|
+
:verified => '1',
|
81
|
+
:role => 'superadmin'
|
82
|
+
<%= singular_name %> = <%= class_name %>.find_by_email("skunk@example.com")
|
83
|
+
assert !<%= singular_name %>.verified
|
84
|
+
assert_nil <%= singular_name %>.role
|
85
|
+
end
|
86
|
+
|
75
87
|
def test_signup__validates_password_min_length
|
76
88
|
post_signup :login => "tesla_rhea", :password => "bad", :password_confirmation => "bad", :email => "someone@example.com"
|
77
89
|
assert_password_validation_fails
|
@@ -107,6 +119,7 @@ class <%= class_name %>ControllerTest < Test::Unit::TestCase
|
|
107
119
|
<%= singular_name %>.reload
|
108
120
|
assert <%= singular_name %>.verified
|
109
121
|
assert_logged_in( <%= singular_name %> )
|
122
|
+
assert <%= singular_name %>.token_expired?
|
110
123
|
end
|
111
124
|
|
112
125
|
def test_welcome__fails_if_expired_token
|
data/templates/default_setup.zip
CHANGED
Binary file
|
data/templates/helper.rb
CHANGED
@@ -15,12 +15,12 @@ module <%= class_name %>Helper
|
|
15
15
|
opts = DEFAULT_HEAD_OPTIONS.dup
|
16
16
|
opts.update(options.symbolize_keys)
|
17
17
|
s = "<h3>#{label}</h3>"
|
18
|
-
if
|
19
|
-
notice = "<div><p>#{
|
18
|
+
if flash['notice'] and not opts[:notice].nil? and opts[:notice]
|
19
|
+
notice = "<div><p>#{flash['notice']}</p></div>"
|
20
20
|
s = s + notice
|
21
21
|
end
|
22
|
-
if
|
23
|
-
message = "<div id=\"ErrorExplanation\"><p>#{
|
22
|
+
if flash['message'] and not opts[:message].nil? and opts[:message]
|
23
|
+
message = "<div id=\"ErrorExplanation\"><p>#{flash['message']}</p></div>"
|
24
24
|
s = s + message
|
25
25
|
end
|
26
26
|
if not opts[:error].nil? and opts[:error]
|
@@ -33,9 +33,4 @@ module <%= class_name %>Helper
|
|
33
33
|
return s
|
34
34
|
end
|
35
35
|
|
36
|
-
def start_form_tag_helper(options = {})
|
37
|
-
url = url_for(:action => "#{@controller.action_name}")
|
38
|
-
"#{self.send(:start_form_tag, url, options)}"
|
39
|
-
end
|
40
|
-
|
41
36
|
end
|
data/templates/user.rb
CHANGED
@@ -2,6 +2,7 @@ require 'digest/sha1'
|
|
2
2
|
|
3
3
|
# this model expects a certain database layout and its based on the name/login pattern.
|
4
4
|
class <%= class_name %> < ActiveRecord::Base
|
5
|
+
CHANGEABLE_FIELDS = ['first_name', 'last_name', 'email']
|
5
6
|
attr_accessor :password_needs_confirmation
|
6
7
|
|
7
8
|
after_save '@password_needs_confirmation = false'
|
@@ -23,28 +24,28 @@ class <%= class_name %> < ActiveRecord::Base
|
|
23
24
|
end
|
24
25
|
|
25
26
|
def self.authenticate(login, pass)
|
26
|
-
u =
|
27
|
+
u = find( :first, :conditions => ["login = ? AND verified = TRUE AND deleted = FALSE", login])
|
27
28
|
return nil if u.nil?
|
28
|
-
|
29
|
+
find( :first, :conditions => ["login = ? AND salted_password = ? AND verified = TRUE", login, salted_password(u.salt, hashed(pass))])
|
29
30
|
end
|
30
31
|
|
31
32
|
def self.authenticate_by_token(id, token)
|
32
33
|
# Allow logins for deleted accounts, but only via this method (and
|
33
34
|
# not the regular authenticate call)
|
34
35
|
logger.info "Attempting authorization of #{id} with #{token}"
|
35
|
-
u =
|
36
|
+
u = find( :first, :conditions => ["id = ? AND security_token = ?", id, token])
|
36
37
|
if u
|
37
38
|
logger.info "Authenticated by token: #{u.inspect}"
|
38
39
|
else
|
39
40
|
logger.info "Not authenticated" if u.nil?
|
40
41
|
end
|
41
42
|
return nil if (u.nil? or u.token_expired?)
|
42
|
-
u.
|
43
|
+
u.update_attributes :verified => true, :token_expiry => Clock.now
|
43
44
|
return u
|
44
45
|
end
|
45
46
|
|
46
47
|
def token_expired?
|
47
|
-
self.security_token and self.token_expiry and (Clock.now
|
48
|
+
self.security_token and self.token_expiry and (Clock.now >= self.token_expiry)
|
48
49
|
end
|
49
50
|
|
50
51
|
def generate_security_token
|
data/templates/users.yml
CHANGED
@@ -44,5 +44,5 @@ unverified_<%= singular_name %>:
|
|
44
44
|
email: unverified_<%= singular_name %>@example.com
|
45
45
|
verified: false
|
46
46
|
security_token: random_token_string
|
47
|
-
token_expiry: <%%= (Clock.now + 1.day) %> # for mysql, add .strftime("%y-%m-%d %H:%M:%S")
|
47
|
+
token_expiry: <%%= (Clock.now + 1.day).strftime("%y-%m-%d %H:%M:%S") %> # for mysql, add .strftime("%y-%m-%d %H:%M:%S")
|
48
48
|
deleted: false
|
@@ -4,12 +4,12 @@
|
|
4
4
|
<div class="form-padding">
|
5
5
|
Enter your new password in the fields below and click 'Change Password' to have a new password sent to your email inbox.
|
6
6
|
|
7
|
-
|
7
|
+
<%% form_tag(url_for(:action => "#{@controller.action_name}")) do %>
|
8
8
|
<%%= render_partial 'password', :<%= singular_name %> => @<%= singular_name %>, :submit => false %>
|
9
9
|
<div class="button-bar">
|
10
10
|
<%%= submit_tag 'Change Password' %>
|
11
11
|
<%%= link_to 'Cancel', :action => 'welcome' %>
|
12
12
|
</div>
|
13
|
-
|
13
|
+
<%% end %>
|
14
14
|
</div>
|
15
15
|
</div>
|
data/templates/view_edit.rhtml
CHANGED
@@ -1,19 +1,19 @@
|
|
1
1
|
<div title="<%%= title_helper %>" class="form">
|
2
2
|
<%%= head_helper 'Edit <%= class_name %>', :error => true %>
|
3
3
|
|
4
|
-
|
4
|
+
<%% form_tag(url_for(:action => "#{@controller.action_name}")) do %>
|
5
5
|
<%%= render_partial 'edit', :<%= singular_name %> => @<%= singular_name %>, :submit => true %>
|
6
|
-
|
6
|
+
<%% end %>
|
7
7
|
</br>
|
8
|
-
|
8
|
+
<%% form_tag(url_for(:action => "#{@controller.action_name}")) do %>
|
9
9
|
<%%= render_partial 'password', :submit => true %>
|
10
|
-
|
10
|
+
<%% end %>
|
11
11
|
|
12
|
-
|
12
|
+
<%% form_tag(url_for(:action => "#{@controller.action_name}")) do %>
|
13
13
|
<div class="<%= singular_name %>_delete">
|
14
14
|
<%%= hidden_field '<%= singular_name %>', 'form', :value => 'delete' %>
|
15
15
|
<%%= submit_tag 'Delete' %>
|
16
16
|
</div>
|
17
|
-
|
17
|
+
<%% end %>
|
18
18
|
</div>
|
19
19
|
</div>
|
@@ -7,13 +7,13 @@
|
|
7
7
|
to have instructions on how to retrieve your forgotten password emailed to you.
|
8
8
|
</p>
|
9
9
|
|
10
|
-
|
10
|
+
<%% form_tag(url_for(:action => "#{@controller.action_name}")) do %>
|
11
11
|
<%%= text_field '<%= singular_name %>', "email", :size => 30 %><br/>
|
12
12
|
|
13
13
|
<div class="button-bar">
|
14
14
|
<%%= submit_tag 'Send instructions' %>
|
15
15
|
<%%= link_to 'Cancel', :action => 'login' %>
|
16
16
|
</div>
|
17
|
-
|
17
|
+
<%% end %>
|
18
18
|
</div>
|
19
19
|
</div>
|
data/templates/view_login.rhtml
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
<%%= head_helper 'Please login' %>
|
3
3
|
|
4
4
|
<div class="form-padding">
|
5
|
-
|
5
|
+
<%% form_tag(url_for(:action => "#{@controller.action_name}")) do %>
|
6
6
|
<table>
|
7
7
|
<tr class="two_columns">
|
8
8
|
<td class="prompt"><label>Login:</label></td>
|
@@ -18,7 +18,7 @@
|
|
18
18
|
<%%= submit_tag 'login' %>
|
19
19
|
<%%= link_to 'Register for an account', :action => 'signup' %> |
|
20
20
|
<%%= link_to 'Forgot my password', :action => 'forgot_password' %> </div>
|
21
|
-
|
21
|
+
<%% end %>
|
22
22
|
</div>
|
23
23
|
</div>
|
24
24
|
|
data/templates/view_signup.rhtml
CHANGED
@@ -2,13 +2,13 @@
|
|
2
2
|
<%%= head_helper 'Sign Up', :error => true %>
|
3
3
|
|
4
4
|
<div class="form-padding">
|
5
|
-
|
5
|
+
<%% form_tag(url_for(:action => "#{@controller.action_name}")) do %>
|
6
6
|
<%%= render_partial 'edit', :<%= singular_name %> => @<%= singular_name %>, :submit => false %></br>
|
7
7
|
<%%= render_partial 'password', :submit => false %>
|
8
8
|
|
9
9
|
<div class="button-bar">
|
10
10
|
<%%= submit_tag 'Sign up' %>
|
11
11
|
</div>
|
12
|
-
|
12
|
+
<%% end %>
|
13
13
|
</div>
|
14
14
|
</div>
|
metadata
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: 0.
|
2
|
+
rubygems_version: 0.9.2
|
3
3
|
specification_version: 1
|
4
4
|
name: login_sugar_generator
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.9.
|
7
|
-
date: 2007-
|
6
|
+
version: 0.9.5
|
7
|
+
date: 2007-05-30 00:00:00 -07:00
|
8
8
|
summary: A modification of the Salted Hash Login Generator that works with Rails 1.1.[456]
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -25,6 +25,7 @@ required_ruby_version: !ruby/object:Gem::Version::Requirement
|
|
25
25
|
platform: ruby
|
26
26
|
signing_key:
|
27
27
|
cert_chain:
|
28
|
+
post_install_message:
|
28
29
|
authors:
|
29
30
|
- Dav Yaginuma
|
30
31
|
files:
|