caleb-restful-authentication 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. data/CHANGELOG +68 -0
  2. data/README.textile +240 -0
  3. data/Rakefile +32 -0
  4. data/TODO +15 -0
  5. data/generators/authenticated/USAGE +1 -0
  6. data/generators/authenticated/authenticated_generator.rb +508 -0
  7. data/generators/authenticated/lib/insert_routes.rb +54 -0
  8. data/generators/authenticated/templates/_model_partial.html.erb +8 -0
  9. data/generators/authenticated/templates/activation.erb +3 -0
  10. data/generators/authenticated/templates/authenticated_system.rb +189 -0
  11. data/generators/authenticated/templates/authenticated_test_helper.rb +22 -0
  12. data/generators/authenticated/templates/controller.rb +43 -0
  13. data/generators/authenticated/templates/helper.rb +2 -0
  14. data/generators/authenticated/templates/login.html.erb +21 -0
  15. data/generators/authenticated/templates/mailer.rb +33 -0
  16. data/generators/authenticated/templates/migration.rb +29 -0
  17. data/generators/authenticated/templates/model.rb +101 -0
  18. data/generators/authenticated/templates/model_controller.rb +117 -0
  19. data/generators/authenticated/templates/model_helper.rb +93 -0
  20. data/generators/authenticated/templates/model_helper_spec.rb +158 -0
  21. data/generators/authenticated/templates/observer.rb +14 -0
  22. data/generators/authenticated/templates/signup.html.erb +21 -0
  23. data/generators/authenticated/templates/signup_notification.erb +8 -0
  24. data/generators/authenticated/templates/site_keys.rb +38 -0
  25. data/generators/authenticated/templates/spec/controllers/access_control_spec.rb +90 -0
  26. data/generators/authenticated/templates/spec/controllers/authenticated_system_spec.rb +102 -0
  27. data/generators/authenticated/templates/spec/controllers/sessions_controller_spec.rb +139 -0
  28. data/generators/authenticated/templates/spec/controllers/users_controller_spec.rb +200 -0
  29. data/generators/authenticated/templates/spec/fixtures/users.yml +66 -0
  30. data/generators/authenticated/templates/spec/helpers/users_helper_spec.rb +141 -0
  31. data/generators/authenticated/templates/spec/models/user_spec.rb +295 -0
  32. data/generators/authenticated/templates/stories/rest_auth_stories.rb +22 -0
  33. data/generators/authenticated/templates/stories/rest_auth_stories_helper.rb +81 -0
  34. data/generators/authenticated/templates/stories/steps/ra_navigation_steps.rb +49 -0
  35. data/generators/authenticated/templates/stories/steps/ra_resource_steps.rb +179 -0
  36. data/generators/authenticated/templates/stories/steps/ra_response_steps.rb +171 -0
  37. data/generators/authenticated/templates/stories/steps/user_steps.rb +153 -0
  38. data/generators/authenticated/templates/stories/users/accounts.story +194 -0
  39. data/generators/authenticated/templates/stories/users/sessions.story +134 -0
  40. data/generators/authenticated/templates/test/functional_test.rb +82 -0
  41. data/generators/authenticated/templates/test/mailer_test.rb +31 -0
  42. data/generators/authenticated/templates/test/model_functional_test.rb +95 -0
  43. data/generators/authenticated/templates/test/unit_test.rb +166 -0
  44. data/init.rb +1 -0
  45. data/lib/authentication.rb +40 -0
  46. data/lib/authentication/by_cookie_token.rb +82 -0
  47. data/lib/authentication/by_password.rb +64 -0
  48. data/lib/authorization.rb +14 -0
  49. data/lib/authorization/aasm_roles.rb +64 -0
  50. data/lib/authorization/stateful_roles.rb +63 -0
  51. data/lib/trustification.rb +14 -0
  52. data/lib/trustification/email_validation.rb +20 -0
  53. data/rails/init.rb +6 -0
  54. metadata +115 -0
@@ -0,0 +1,117 @@
1
+ class <%= model_controller_class_name %>Controller < ApplicationController
2
+ # Be sure to include AuthenticationSystem in Application Controller instead
3
+ include AuthenticatedSystem
4
+ <% if options[:stateful] %>
5
+ # Protect these actions behind an admin login
6
+ # before_filter :admin_required, :only => [:suspend, :unsuspend, :destroy, :purge]
7
+ before_filter :find_<%= file_name %>, :only => [:suspend, :unsuspend, :destroy, :purge]
8
+ <% end %>
9
+
10
+ # render new.rhtml
11
+ def new
12
+ @<%= file_name %> = <%= class_name %>.new
13
+ end
14
+
15
+ def create
16
+ logout_keeping_session!
17
+ @<%= file_name %> = <%= class_name %>.new(params[:<%= file_name %>])
18
+ <% if options[:stateful] -%>
19
+ @<%= file_name %>.register! if @<%= file_name %> && @<%= file_name %>.valid?
20
+ success = @<%= file_name %> && @<%= file_name %>.valid?
21
+ <% else -%>
22
+ success = @<%= file_name %> && @<%= file_name %>.save
23
+ <% end -%>
24
+ if success && @<%= file_name %>.errors.empty?
25
+ <% if !options[:include_activation] -%>
26
+ # Protects against session fixation attacks, causes request forgery
27
+ # protection if visitor resubmits an earlier form using back
28
+ # button. Uncomment if you understand the tradeoffs.
29
+ # reset session
30
+ self.current_<%= file_name %> = @<%= file_name %> # !! now logged in
31
+ <% end -%>redirect_back_or_default('/')
32
+ flash[:notice] = "Thanks for signing up! We're sending you an email with your activation code."
33
+ else
34
+ flash[:error] = "We couldn't set up that account, sorry. Please try again, or contact an admin (link is above)."
35
+ render :action => 'new'
36
+ end
37
+ end
38
+ <% if options[:include_activation] %>
39
+ def activate
40
+ logout_keeping_session!
41
+ <%= file_name %> = <%= class_name %>.find_by_activation_code(params[:activation_code]) unless params[:activation_code].blank?
42
+ case
43
+ when (!params[:activation_code].blank?) && <%= file_name %> && !<%= file_name %>.active?
44
+ <%= file_name %>.activate!
45
+ flash[:notice] = "Signup complete! Please sign in to continue."
46
+ redirect_to '/login'
47
+ when params[:activation_code].blank?
48
+ flash[:error] = "The activation code was missing. Please follow the URL from your email."
49
+ redirect_back_or_default('/')
50
+ else
51
+ flash[:error] = "We couldn't find a <%= file_name %> with that activation code -- check your email? Or maybe you've already activated -- try signing in."
52
+ redirect_back_or_default('/')
53
+ end
54
+ end
55
+ <% end %><% if options[:include_forgot_password] %>
56
+ def forgot
57
+ if request.post?
58
+ <%= file_name %> = <%= class_name %>.find_by_email(params[:<%= file_name %>][:email]) unless params[:<%= file_name %>][:email].blank?
59
+ case
60
+ when (!params[:<%= file_name %>][:email].blank?) && <%= file_name %> && <%= file_name %>.active?
61
+ <%= file_name %>.make_reset_code!
62
+ flash[:notice] = "A password reset link was sent to #{<%= file_name %>.email}"
63
+ redirect_back_or_default('/')
64
+ when params[:<%= file_name %>][:email].blank?
65
+ flash[:error] = "The email address was missing. Please enter your email address."
66
+ redirect_back_or_default('/')
67
+ else
68
+ flash[:error] = "We couldn't find a <%= file_name %> with the email address, '#{params[:<%= file_name %>][:email]}' or the <%= file_name %> is suspended, deleted, or not activated."
69
+ redirect_back_or_default('/')
70
+ end
71
+ end
72
+ end
73
+
74
+ def reset
75
+ if request.post?
76
+ @<%= file_name %> = <%= class_name %>.find_by_email_and_reset_code(params[:<%= file_name %>][:email], params[:reset_code])
77
+ if @<%= file_name %>.update_attributes(:password => params[:<%= file_name %>][:password], :password_confirmation => params[:<%= file_name %>][:password_confirmation])
78
+ @<%= file_name %>.clear_reset_code!
79
+ self.current_user = @<%= file_name %>
80
+ flash[:notice] = "Password reset successfully for #{@<%= file_name %>.email}"
81
+ redirect_back_or_default("/")
82
+ else
83
+ render :action => :reset
84
+ end
85
+ end
86
+ end
87
+ <% end %><% if options[:stateful] %>
88
+ def suspend
89
+ @<%= file_name %>.suspend!
90
+ redirect_to <%= model_controller_routing_name %>_path
91
+ end
92
+
93
+ def unsuspend
94
+ @<%= file_name %>.unsuspend!
95
+ redirect_to <%= model_controller_routing_name %>_path
96
+ end
97
+
98
+ def destroy
99
+ @<%= file_name %>.delete!
100
+ redirect_to <%= model_controller_routing_name %>_path
101
+ end
102
+
103
+ def purge
104
+ @<%= file_name %>.destroy
105
+ redirect_to <%= model_controller_routing_name %>_path
106
+ end
107
+
108
+ # There's no page here to update or destroy a <%= file_name %>. If you add those, be
109
+ # smart -- make sure you check that the visitor is authorized to do so, that they
110
+ # supply their old password along with a new one to update it, etc.
111
+
112
+ protected
113
+ def find_<%= file_name %>
114
+ @<%= file_name %> = <%= class_name %>.find(params[:id])
115
+ end
116
+ <% end -%>
117
+ end
@@ -0,0 +1,93 @@
1
+ module <%= model_controller_class_name %>Helper
2
+
3
+ #
4
+ # Use this to wrap view elements that the user can't access.
5
+ # !! Note: this is an *interface*, not *security* feature !!
6
+ # You need to do all access control at the controller level.
7
+ #
8
+ # Example:
9
+ # <%%= if_authorized?(:index, User) do link_to('List all users', users_path) end %> |
10
+ # <%%= if_authorized?(:edit, @user) do link_to('Edit this user', edit_user_path) end %> |
11
+ # <%%= if_authorized?(:destroy, @user) do link_to 'Destroy', @user, :confirm => 'Are you sure?', :method => :delete end %>
12
+ #
13
+ #
14
+ def if_authorized?(action, resource, &block)
15
+ if authorized?(action, resource)
16
+ yield action, resource
17
+ end
18
+ end
19
+
20
+ #
21
+ # Link to user's page ('<%= table_name %>/1')
22
+ #
23
+ # By default, their <%= options[:login_field_name] -%> is used as link text and link title (tooltip)
24
+ #
25
+ # Takes options
26
+ # * :content_text => 'Content text in place of <%= file_name %>.<%= options[:login_field_name] -%>', escaped with
27
+ # the standard h() function.
28
+ # * :content_method => :<%= file_name %>_instance_method_to_call_for_content_text
29
+ # * :title_method => :<%= file_name %>_instance_method_to_call_for_title_attribute
30
+ # * as well as link_to()'s standard options
31
+ #
32
+ # Examples:
33
+ # link_to_<%= file_name %> @<%= file_name %>
34
+ # # => <a href="/<%= table_name %>/3" title="barmy">barmy</a>
35
+ #
36
+ # # if you've added a .name attribute:
37
+ # content_tag :span, :class => :vcard do
38
+ # (link_to_<%= file_name %> <%= file_name %>, :class => 'fn n', :title_method => :<%= options[:login_field_name] -%>, :content_method => :name) +
39
+ # ': ' + (content_tag :span, <%= file_name %>.email, :class => 'email')
40
+ # end
41
+ # # => <span class="vcard"><a href="/<%= table_name %>/3" title="barmy" class="fn n">Cyril Fotheringay-Phipps</a>: <span class="email">barmy@blandings.com</span></span>
42
+ #
43
+ # link_to_<%= file_name %> @<%= file_name %>, :content_text => 'Your user page'
44
+ # # => <a href="/<%= table_name %>/3" title="barmy" class="nickname">Your user page</a>
45
+ #
46
+ def link_to_<%= file_name %>(<%= file_name %>, options={})
47
+ raise "Invalid <%= file_name %>" unless <%= file_name %>
48
+ options.reverse_merge! :content_method => :<%= options[:login_field_name] -%>, :title_method => :<%= options[:login_field_name] -%>, :class => :nickname
49
+ content_text = options.delete(:content_text)
50
+ content_text ||= <%= file_name %>.send(options.delete(:content_method))
51
+ options[:title] ||= <%= file_name %>.send(options.delete(:title_method))
52
+ link_to h(content_text), <%= model_controller_routing_name.singularize %>_path(<%= file_name %>), options
53
+ end
54
+
55
+ #
56
+ # Link to login page using remote ip address as link content
57
+ #
58
+ # The :title (and thus, tooltip) is set to the IP address
59
+ #
60
+ # Examples:
61
+ # link_to_login_with_IP
62
+ # # => <a href="/login" title="169.69.69.69">169.69.69.69</a>
63
+ #
64
+ # link_to_login_with_IP :content_text => 'not signed in'
65
+ # # => <a href="/login" title="169.69.69.69">not signed in</a>
66
+ #
67
+ def link_to_login_with_IP content_text=nil, options={}
68
+ ip_addr = request.remote_ip
69
+ content_text ||= ip_addr
70
+ options.reverse_merge! :title => ip_addr
71
+ if tag = options.delete(:tag)
72
+ content_tag tag, h(content_text), options
73
+ else
74
+ link_to h(content_text), login_path, options
75
+ end
76
+ end
77
+
78
+ #
79
+ # Link to the current user's page (using link_to_<%= file_name %>) or to the login page
80
+ # (using link_to_login_with_IP).
81
+ #
82
+ def link_to_current_<%= file_name %>(options={})
83
+ if current_<%= file_name %>
84
+ link_to_<%= file_name %> current_<%= file_name %>, options
85
+ else
86
+ content_text = options.delete(:content_text) || 'not signed in'
87
+ # kill ignored options from link_to_<%= file_name %>
88
+ [:content_method, :title_method].each{|opt| options.delete(opt)}
89
+ link_to_login_with_IP content_text, options
90
+ end
91
+ end
92
+
93
+ end
@@ -0,0 +1,158 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+ include ApplicationHelper
3
+ include <%= model_controller_class_name %>Helper
4
+
5
+ describe "<%= model_controller_class_name %>Helper.link_to_<%= file_name %>" do
6
+ before do
7
+ @<%= file_name %> = <%= class_name %>.new({
8
+ :name => '<%= class_name %> Name',
9
+ :<%= options[:login_field_name] -%> => '<%= file_name %>_name',
10
+ })
11
+ @<%= file_name %>.id = 1 # set non-attr_accessible specifically
12
+ end
13
+
14
+ it "should give an error on a nil <%= file_name %>" do
15
+ lambda { link_to_<%= file_name %>(nil) }.should raise_error('Invalid <%= file_name %>')
16
+ end
17
+
18
+ it "should link to the given <%= file_name %>" do
19
+ link_to_<%= file_name %>(@<%= file_name %>).should have_tag("a[href='/<%= table_name %>/1']")
20
+ end
21
+
22
+ it "should use given link text if :content_text is specified" do
23
+ link_to_<%= file_name %>(@<%= file_name %>, :content_text => 'Hello there!').should have_tag("a", 'Hello there!')
24
+ end
25
+
26
+ it "should use the <%= options[:login_field_name] -%> as link text with no :content_method specified" do
27
+ link_to_<%= file_name %>(@<%= file_name %>).should have_tag("a", '<%= file_name %>_name')
28
+ end
29
+
30
+ it "should use the name as link text with :content_method => :name" do
31
+ link_to_<%= file_name %>(@<%= file_name %>, :content_method => :name).should have_tag("a", '<%= class_name %> Name')
32
+ end
33
+
34
+ it "should use the <%= options[:login_field_name] -%> as title with no :title_method specified" do
35
+ link_to_<%= file_name %>(@<%= file_name %>).should have_tag("a[title='<%= file_name %>_name']")
36
+ end
37
+
38
+ it "should use the name as link title with :content_method => :name" do
39
+ link_to_<%= file_name %>(@<%= file_name %>, :title_method => :name).should have_tag("a[title='<%= class_name %> Name']")
40
+ end
41
+
42
+ it "should have nickname as a class by default" do
43
+ link_to_<%= file_name %>(@<%= file_name %>).should have_tag("a.nickname")
44
+ end
45
+
46
+ it "should take other classes and no longer have the nickname class" do
47
+ result = link_to_<%= file_name %>(@<%= file_name %>, :class => 'foo bar')
48
+ result.should have_tag("a.foo")
49
+ result.should have_tag("a.bar")
50
+ end
51
+ end
52
+
53
+ describe "<%= model_controller_class_name %>Helper.link_to_signin_with_IP" do
54
+ before do
55
+ end
56
+
57
+ it "should link to the signin_path" do
58
+ link_to_signin_with_IP().should have_tag("a[href='/signin']")
59
+ end
60
+
61
+ it "should use given link text if :content_text is specified" do
62
+ link_to_signin_with_IP(:content_text => 'Hello there!').should have_tag("a", 'Hello there!')
63
+ end
64
+
65
+ it "should use the <%= options[:login_field_name] -%> as link text with no :content_method specified" do
66
+ link_to_signin_with_IP().should have_tag("a", '0.0.0.0')
67
+ end
68
+
69
+ it "should use the ip address as title" do
70
+ link_to_signin_with_IP().should have_tag("a[title='0.0.0.0']")
71
+ end
72
+
73
+ it "should by default be like school in summer and have no class" do
74
+ link_to_signin_with_IP().should_not have_tag("a.nickname")
75
+ end
76
+
77
+ it "should have some class if you tell it to" do
78
+ result = link_to_signin_with_IP(:class => 'foo bar')
79
+ result.should have_tag("a.foo")
80
+ result.should have_tag("a.bar")
81
+ end
82
+ end
83
+
84
+ describe "<%= model_controller_class_name %>Helper.link_to_current_<%= file_name %>, When logged in" do
85
+ fixtures :<%= table_name %>
86
+ include AuthenticatedTestHelper
87
+ before do
88
+ login_as(:quentin)
89
+ end
90
+
91
+ it "should link to the given <%= file_name %>" do
92
+ link_to_current_<%= file_name %>().should have_tag("a[href='/<%= table_name %>/1']")
93
+ end
94
+
95
+ it "should use given link text if :content_text is specified" do
96
+ link_to_current_user(:content_text => 'Hello there!').should have_tag("a", 'Hello there!')
97
+ end
98
+
99
+ it "should use the <%= options[:login_field_name] -%> as link text with no :content_method specified" do
100
+ link_to_current_user().should have_tag("a", 'quentin')
101
+ end
102
+
103
+ it "should use the name as link text with :content_method => :name" do
104
+ link_to_current_user(:content_method => :name).should have_tag("a", 'Quentin')
105
+ end
106
+
107
+ it "should use the <%= options[:login_field_name] -%> as title with no :title_method specified" do
108
+ link_to_current_user().should have_tag("a[title='quentin']")
109
+ end
110
+
111
+ it "should use the name as link title with :content_method => :name" do
112
+ link_to_current_user(:title_method => :name).should have_tag("a[title='Quentin']")
113
+ end
114
+
115
+ it "should have nickname as a class" do
116
+ link_to_current_user().should have_tag("a.nickname")
117
+ end
118
+
119
+ it "should take other classes and no longer have the nickname class" do
120
+ result = link_to_current_user(:class => 'foo bar')
121
+ result.should have_tag("a.foo")
122
+ result.should have_tag("a.bar")
123
+ end
124
+ end
125
+
126
+
127
+
128
+ describe "<%= model_controller_class_name %>Helper.link_to_current_user, When logged out" do
129
+ include AuthenticatedTestHelper
130
+ before do
131
+ end
132
+
133
+ it "should link to the signin_path" do
134
+ link_to_current_user().should have_tag("a[href='/signin']")
135
+ end
136
+
137
+ it "should use given link text if :content_text is specified" do
138
+ link_to_current_user(:content_text => 'Hello there!').should have_tag("a", 'Hello there!')
139
+ end
140
+
141
+ it "should use the IP address as link text with no :content_method specified" do
142
+ link_to_current_user().should have_tag("a", '0.0.0.0')
143
+ end
144
+
145
+ it "should use the ip address as title" do
146
+ link_to_current_user().should have_tag("a[title='0.0.0.0']")
147
+ end
148
+
149
+ it "should by default be like school in summer and have no class" do
150
+ link_to_current_user().should_not have_tag("a.nickname")
151
+ end
152
+
153
+ it "should have some class if you tell it to" do
154
+ result = link_to_current_user(:class => 'foo bar')
155
+ result.should have_tag("a.foo")
156
+ result.should have_tag("a.bar")
157
+ end
158
+ end
@@ -0,0 +1,14 @@
1
+ class <%= class_name %>Observer < ActiveRecord::Observer
2
+ def after_create(<%= file_name %>)
3
+ <%= class_name %>Mailer.deliver_signup_notification(<%= file_name %>)
4
+ end
5
+
6
+ def after_save(<%= file_name %>)
7
+ <% if options[:include_activation] -%>
8
+ <%= class_name %>Mailer.deliver_activation(<%= file_name %>) if <%= file_name %>.recently_activated?
9
+ <% end -%>
10
+ <% if options[:include_forgot_password] -%>
11
+ <%= class_name %>Mailer.deliver_reset_password(<%= file_name %>) if <%= file_name %>.recently_reset_password?
12
+ <% end -%>
13
+ end
14
+ end
@@ -0,0 +1,21 @@
1
+ <h1>Sign up as a new user</h1>
2
+ <%% @<%= file_name %>.password = @<%= file_name %>.password_confirmation = nil %>
3
+
4
+ <%%= error_messages_for :<%= file_name %> %>
5
+ <%% form_for :<%= file_name %>, :url => <%= model_controller_routing_name %>_path do |f| -%>
6
+ <% unless options[:email_as_login] -%>
7
+ <p><%%= label_tag 'login' %><br/>
8
+ <%%= f.text_field :login %></p>
9
+ <% end -%>
10
+
11
+ <p><%%= label_tag 'email' %><br/>
12
+ <%%= f.text_field :email %></p>
13
+
14
+ <p><%%= label_tag 'password' %><br/>
15
+ <%%= f.password_field :password %></p>
16
+
17
+ <p><%%= label_tag 'password_confirmation', 'Confirm Password' %><br/>
18
+ <%%= f.password_field :password_confirmation %></p>
19
+
20
+ <p><%%= submit_tag 'Sign up' %></p>
21
+ <%% end -%>
@@ -0,0 +1,8 @@
1
+ Your account has been created.
2
+
3
+ Username: <%%=h @<%= file_name %>.<%= options[:login_field_name] -%> %>
4
+ Password: <%%=h @<%= file_name %>.password %>
5
+
6
+ Visit this url to activate your account:
7
+
8
+ <%%=h @url %>
@@ -0,0 +1,38 @@
1
+
2
+ # A Site key gives additional protection against a dictionary attack if your
3
+ # DB is ever compromised. With no site key, we store
4
+ # DB_password = hash(user_password, DB_user_salt)
5
+ # If your database were to be compromised you'd be vulnerable to a dictionary
6
+ # attack on all your stupid users' passwords. With a site key, we store
7
+ # DB_password = hash(user_password, DB_user_salt, Code_site_key)
8
+ # That means an attacker needs access to both your site's code *and* its
9
+ # database to mount an "offline dictionary attack.":http://www.dwheeler.com/secure-programs/Secure-Programs-HOWTO/web-authentication.html
10
+ #
11
+ # It's probably of minor importance, but recommended by best practices: 'defense
12
+ # in depth'. Needless to say, if you upload this to github or the youtubes or
13
+ # otherwise place it in public view you'll kinda defeat the point. Your users'
14
+ # passwords are still secure, and the world won't end, but defense_in_depth -= 1.
15
+ #
16
+ # Please note: if you change this, all the passwords will be invalidated, so DO
17
+ # keep it someplace secure. Use the random value given or type in the lyrics to
18
+ # your favorite Jay-Z song or something; any moderately long, unpredictable text.
19
+ REST_AUTH_SITE_KEY = '<%= $rest_auth_site_key_from_generator %>'
20
+
21
+ # Repeated applications of the hash make brute force (even with a compromised
22
+ # database and site key) harder, and scale with Moore's law.
23
+ #
24
+ # bq. "To squeeze the most security out of a limited-entropy password or
25
+ # passphrase, we can use two techniques [salting and stretching]... that are
26
+ # so simple and obvious that they should be used in every password system.
27
+ # There is really no excuse not to use them." http://tinyurl.com/37lb73
28
+ # Practical Security (Ferguson & Scheier) p350
29
+ #
30
+ # A modest 10 foldings (the default here) adds 3ms. This makes brute forcing 10
31
+ # times harder, while reducing an app that otherwise serves 100 reqs/s to 78 signin
32
+ # reqs/s, an app that does 10reqs/s to 9.7 reqs/s
33
+ #
34
+ # More:
35
+ # * http://www.owasp.org/index.php/Hashing_Java
36
+ # * "An Illustrated Guide to Cryptographic Hashes":http://www.unixwiz.net/techtips/iguide-crypto-hashes.html
37
+
38
+ REST_AUTH_DIGEST_STRETCHES = <%= $rest_auth_digest_stretches_from_generator %>