devise-bootstrap 0.0.1

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.
Files changed (104) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/Gemfile +31 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +29 -0
  6. data/Rakefile +1 -0
  7. data/app/controllers/devise/confirmations_controller.rb +47 -0
  8. data/app/controllers/devise/omniauth_callbacks_controller.rb +30 -0
  9. data/app/controllers/devise/passwords_controller.rb +70 -0
  10. data/app/controllers/devise/registrations_controller.rb +137 -0
  11. data/app/controllers/devise/sessions_controller.rb +53 -0
  12. data/app/controllers/devise/unlocks_controller.rb +46 -0
  13. data/app/controllers/devise_controller.rb +176 -0
  14. data/app/helpers/devise_helper.rb +25 -0
  15. data/app/mailers/devise/mailer.rb +20 -0
  16. data/app/views/devise/confirmations/new.html.erb +12 -0
  17. data/app/views/devise/mailer/confirmation_instructions.html.erb +5 -0
  18. data/app/views/devise/mailer/reset_password_instructions.html.erb +8 -0
  19. data/app/views/devise/mailer/unlock_instructions.html.erb +7 -0
  20. data/app/views/devise/passwords/edit.html.erb +16 -0
  21. data/app/views/devise/passwords/new.html.erb +12 -0
  22. data/app/views/devise/registrations/edit.html.erb +29 -0
  23. data/app/views/devise/registrations/new.html.erb +18 -0
  24. data/app/views/devise/sessions/new.html.erb +17 -0
  25. data/app/views/devise/shared/_links.erb +25 -0
  26. data/app/views/devise/unlocks/new.html.erb +12 -0
  27. data/config/locales/en.yml +59 -0
  28. data/devise-bootstrap.gemspec +30 -0
  29. data/gemfiles/Gemfile.rails-3.2-stable +29 -0
  30. data/gemfiles/Gemfile.rails-4.0-stable +29 -0
  31. data/gemfiles/Gemfile.rails-head +29 -0
  32. data/lib/devise/bootstrap.rb +7 -0
  33. data/lib/devise/bootstrap/version.rb +5 -0
  34. data/lib/devise/devise.rb +491 -0
  35. data/lib/devise/devise/controllers/helpers.rb +213 -0
  36. data/lib/devise/devise/controllers/rememberable.rb +47 -0
  37. data/lib/devise/devise/controllers/scoped_views.rb +17 -0
  38. data/lib/devise/devise/controllers/sign_in_out.rb +103 -0
  39. data/lib/devise/devise/controllers/store_location.rb +50 -0
  40. data/lib/devise/devise/controllers/url_helpers.rb +67 -0
  41. data/lib/devise/devise/delegator.rb +16 -0
  42. data/lib/devise/devise/failure_app.rb +205 -0
  43. data/lib/devise/devise/hooks/activatable.rb +11 -0
  44. data/lib/devise/devise/hooks/csrf_cleaner.rb +5 -0
  45. data/lib/devise/devise/hooks/forgetable.rb +9 -0
  46. data/lib/devise/devise/hooks/lockable.rb +7 -0
  47. data/lib/devise/devise/hooks/proxy.rb +21 -0
  48. data/lib/devise/devise/hooks/rememberable.rb +7 -0
  49. data/lib/devise/devise/hooks/timeoutable.rb +28 -0
  50. data/lib/devise/devise/hooks/trackable.rb +9 -0
  51. data/lib/devise/devise/mailers/helpers.rb +90 -0
  52. data/lib/devise/devise/mapping.rb +172 -0
  53. data/lib/devise/devise/models.rb +119 -0
  54. data/lib/devise/devise/models/authenticatable.rb +284 -0
  55. data/lib/devise/devise/models/confirmable.rb +295 -0
  56. data/lib/devise/devise/models/database_authenticatable.rb +164 -0
  57. data/lib/devise/devise/models/lockable.rb +196 -0
  58. data/lib/devise/devise/models/omniauthable.rb +27 -0
  59. data/lib/devise/devise/models/recoverable.rb +131 -0
  60. data/lib/devise/devise/models/registerable.rb +25 -0
  61. data/lib/devise/devise/models/rememberable.rb +129 -0
  62. data/lib/devise/devise/models/timeoutable.rb +49 -0
  63. data/lib/devise/devise/models/trackable.rb +35 -0
  64. data/lib/devise/devise/models/validatable.rb +66 -0
  65. data/lib/devise/devise/modules.rb +28 -0
  66. data/lib/devise/devise/omniauth.rb +28 -0
  67. data/lib/devise/devise/omniauth/config.rb +45 -0
  68. data/lib/devise/devise/omniauth/url_helpers.rb +18 -0
  69. data/lib/devise/devise/orm/active_record.rb +3 -0
  70. data/lib/devise/devise/orm/mongoid.rb +3 -0
  71. data/lib/devise/devise/parameter_filter.rb +40 -0
  72. data/lib/devise/devise/parameter_sanitizer.rb +99 -0
  73. data/lib/devise/devise/rails.rb +56 -0
  74. data/lib/devise/devise/rails/routes.rb +496 -0
  75. data/lib/devise/devise/rails/warden_compat.rb +22 -0
  76. data/lib/devise/devise/strategies/authenticatable.rb +167 -0
  77. data/lib/devise/devise/strategies/base.rb +20 -0
  78. data/lib/devise/devise/strategies/database_authenticatable.rb +23 -0
  79. data/lib/devise/devise/strategies/rememberable.rb +55 -0
  80. data/lib/devise/devise/test_helpers.rb +132 -0
  81. data/lib/devise/devise/time_inflector.rb +14 -0
  82. data/lib/devise/devise/token_generator.rb +70 -0
  83. data/lib/devise/devise/version.rb +3 -0
  84. data/lib/devise/generators/active_record/devise_generator.rb +73 -0
  85. data/lib/devise/generators/active_record/templates/migration.rb +18 -0
  86. data/lib/devise/generators/active_record/templates/migration_existing.rb +25 -0
  87. data/lib/devise/generators/devise/devise_generator.rb +26 -0
  88. data/lib/devise/generators/devise/install_generator.rb +29 -0
  89. data/lib/devise/generators/devise/orm_helpers.rb +51 -0
  90. data/lib/devise/generators/devise/views_generator.rb +135 -0
  91. data/lib/devise/generators/mongoid/devise_generator.rb +55 -0
  92. data/lib/devise/generators/templates/README +35 -0
  93. data/lib/devise/generators/templates/devise.rb +260 -0
  94. data/lib/devise/generators/templates/markerb/confirmation_instructions.markerb +5 -0
  95. data/lib/devise/generators/templates/markerb/reset_password_instructions.markerb +8 -0
  96. data/lib/devise/generators/templates/markerb/unlock_instructions.markerb +7 -0
  97. data/lib/devise/generators/templates/simple_form_for/confirmations/new.html.erb +16 -0
  98. data/lib/devise/generators/templates/simple_form_for/passwords/edit.html.erb +19 -0
  99. data/lib/devise/generators/templates/simple_form_for/passwords/new.html.erb +15 -0
  100. data/lib/devise/generators/templates/simple_form_for/registrations/edit.html.erb +27 -0
  101. data/lib/devise/generators/templates/simple_form_for/registrations/new.html.erb +17 -0
  102. data/lib/devise/generators/templates/simple_form_for/sessions/new.html.erb +15 -0
  103. data/lib/devise/generators/templates/simple_form_for/unlocks/new.html.erb +16 -0
  104. metadata +250 -0
@@ -0,0 +1,46 @@
1
+ class Devise::UnlocksController < DeviseController
2
+ prepend_before_filter :require_no_authentication
3
+
4
+ # GET /resource/unlock/new
5
+ def new
6
+ self.resource = resource_class.new
7
+ end
8
+
9
+ # POST /resource/unlock
10
+ def create
11
+ self.resource = resource_class.send_unlock_instructions(resource_params)
12
+ yield resource if block_given?
13
+
14
+ if successfully_sent?(resource)
15
+ respond_with({}, location: after_sending_unlock_instructions_path_for(resource))
16
+ else
17
+ respond_with(resource)
18
+ end
19
+ end
20
+
21
+ # GET /resource/unlock?unlock_token=abcdef
22
+ def show
23
+ self.resource = resource_class.unlock_access_by_token(params[:unlock_token])
24
+ yield resource if block_given?
25
+
26
+ if resource.errors.empty?
27
+ set_flash_message :notice, :unlocked if is_flashing_format?
28
+ respond_with_navigational(resource){ redirect_to after_unlock_path_for(resource) }
29
+ else
30
+ respond_with_navigational(resource.errors, status: :unprocessable_entity){ render :new }
31
+ end
32
+ end
33
+
34
+ protected
35
+
36
+ # The path used after sending unlock password instructions
37
+ def after_sending_unlock_instructions_path_for(resource)
38
+ new_session_path(resource) if is_navigational_format?
39
+ end
40
+
41
+ # The path used after unlocking the resource
42
+ def after_unlock_path_for(resource)
43
+ new_session_path(resource) if is_navigational_format?
44
+ end
45
+
46
+ end
@@ -0,0 +1,176 @@
1
+ # All Devise controllers are inherited from here.
2
+ class DeviseController < Devise.parent_controller.constantize
3
+ include Devise::Controllers::ScopedViews
4
+
5
+ helper DeviseHelper
6
+
7
+ helpers = %w(resource scope_name resource_name signed_in_resource
8
+ resource_class resource_params devise_mapping)
9
+ hide_action *helpers
10
+ helper_method *helpers
11
+
12
+ prepend_before_filter :assert_is_devise_resource!
13
+ respond_to :html if mimes_for_respond_to.empty?
14
+
15
+ # Gets the actual resource stored in the instance variable
16
+ def resource
17
+ instance_variable_get(:"@#{resource_name}")
18
+ end
19
+
20
+ # Proxy to devise map name
21
+ def resource_name
22
+ devise_mapping.name
23
+ end
24
+ alias :scope_name :resource_name
25
+
26
+ # Proxy to devise map class
27
+ def resource_class
28
+ devise_mapping.to
29
+ end
30
+
31
+ # Returns a signed in resource from session (if one exists)
32
+ def signed_in_resource
33
+ warden.authenticate(scope: resource_name)
34
+ end
35
+
36
+ # Attempt to find the mapped route for devise based on request path
37
+ def devise_mapping
38
+ @devise_mapping ||= request.env["devise.mapping"]
39
+ end
40
+
41
+ # Override prefixes to consider the scoped view.
42
+ # Notice we need to check for the request due to a bug in
43
+ # Action Controller tests that forces _prefixes to be
44
+ # loaded before even having a request object.
45
+ def _prefixes #:nodoc:
46
+ @_prefixes ||= if self.class.scoped_views? && request && devise_mapping
47
+ super.unshift("#{devise_mapping.scoped_path}/#{controller_name}")
48
+ else
49
+ super
50
+ end
51
+ end
52
+
53
+ hide_action :_prefixes
54
+
55
+ protected
56
+
57
+ # Checks whether it's a devise mapped resource or not.
58
+ def assert_is_devise_resource! #:nodoc:
59
+ unknown_action! <<-MESSAGE unless devise_mapping
60
+ Could not find devise mapping for path #{request.fullpath.inspect}.
61
+ This may happen for two reasons:
62
+
63
+ 1) You forgot to wrap your route inside the scope block. For example:
64
+
65
+ devise_scope :user do
66
+ get "/some/route" => "some_devise_controller"
67
+ end
68
+
69
+ 2) You are testing a Devise controller bypassing the router.
70
+ If so, you can explicitly tell Devise which mapping to use:
71
+
72
+ @request.env["devise.mapping"] = Devise.mappings[:user]
73
+
74
+ MESSAGE
75
+ end
76
+
77
+ # Returns real navigational formats which are supported by Rails
78
+ def navigational_formats
79
+ @navigational_formats ||= Devise.navigational_formats.select { |format| Mime::EXTENSION_LOOKUP[format.to_s] }
80
+ end
81
+
82
+ def unknown_action!(msg)
83
+ logger.debug "[Devise] #{msg}" if logger
84
+ raise AbstractController::ActionNotFound, msg
85
+ end
86
+
87
+ # Sets the resource creating an instance variable
88
+ def resource=(new_resource)
89
+ instance_variable_set(:"@#{resource_name}", new_resource)
90
+ end
91
+
92
+ # Helper for use in before_filters where no authentication is required.
93
+ #
94
+ # Example:
95
+ # before_filter :require_no_authentication, only: :new
96
+ def require_no_authentication
97
+ assert_is_devise_resource!
98
+ return unless is_navigational_format?
99
+ no_input = devise_mapping.no_input_strategies
100
+
101
+ authenticated = if no_input.present?
102
+ args = no_input.dup.push scope: resource_name
103
+ warden.authenticate?(*args)
104
+ else
105
+ warden.authenticated?(resource_name)
106
+ end
107
+
108
+ if authenticated && resource = warden.user(resource_name)
109
+ flash[:alert] = I18n.t("devise.failure.already_authenticated")
110
+ redirect_to after_sign_in_path_for(resource)
111
+ end
112
+ end
113
+
114
+ # Helper for use after calling send_*_instructions methods on a resource.
115
+ # If we are in paranoid mode, we always act as if the resource was valid
116
+ # and instructions were sent.
117
+ def successfully_sent?(resource)
118
+ notice = if Devise.paranoid
119
+ resource.errors.clear
120
+ :send_paranoid_instructions
121
+ elsif resource.errors.empty?
122
+ :send_instructions
123
+ end
124
+
125
+ if notice
126
+ set_flash_message :notice, notice if is_flashing_format?
127
+ true
128
+ end
129
+ end
130
+
131
+ # Sets the flash message with :key, using I18n. By default you are able
132
+ # to setup your messages using specific resource scope, and if no one is
133
+ # found we look to default scope.
134
+ # Example (i18n locale file):
135
+ #
136
+ # en:
137
+ # devise:
138
+ # passwords:
139
+ # #default_scope_messages - only if resource_scope is not found
140
+ # user:
141
+ # #resource_scope_messages
142
+ #
143
+ # Please refer to README or en.yml locale file to check what messages are
144
+ # available.
145
+ def set_flash_message(key, kind, options = {})
146
+ message = find_message(kind, options)
147
+ flash[key] = message if message.present?
148
+ end
149
+
150
+ def devise_i18n_options(options)
151
+ options
152
+ end
153
+
154
+ # Get message for given
155
+ def find_message(kind, options = {})
156
+ options[:scope] = "devise.#{controller_name}"
157
+ options[:default] = Array(options[:default]).unshift(kind.to_sym)
158
+ options[:resource_name] = resource_name
159
+ options = devise_i18n_options(options)
160
+ I18n.t("#{options[:resource_name]}.#{kind}", options)
161
+ end
162
+
163
+ def clean_up_passwords(object)
164
+ object.clean_up_passwords if object.respond_to?(:clean_up_passwords)
165
+ end
166
+
167
+ def respond_with_navigational(*args, &block)
168
+ respond_with(*args) do |format|
169
+ format.any(*navigational_formats, &block)
170
+ end
171
+ end
172
+
173
+ def resource_params
174
+ params.fetch(resource_name, {})
175
+ end
176
+ end
@@ -0,0 +1,25 @@
1
+ module DeviseHelper
2
+ # A simple way to show error messages for the current devise resource. If you need
3
+ # to customize this method, you can either overwrite it in your application helpers or
4
+ # copy the views to your application.
5
+ #
6
+ # This method is intended to stay simple and it is unlikely that we are going to change
7
+ # it to add more behavior or options.
8
+ def devise_error_messages!
9
+ return "" if resource.errors.empty?
10
+
11
+ messages = resource.errors.full_messages.map { |msg| content_tag(:li, msg) }.join
12
+ sentence = I18n.t("errors.messages.not_saved",
13
+ count: resource.errors.count,
14
+ resource: resource.class.model_name.human.downcase)
15
+
16
+ html = <<-HTML
17
+ <div id="error_explanation">
18
+ <h2>#{sentence}</h2>
19
+ <ul>#{messages}</ul>
20
+ </div>
21
+ HTML
22
+
23
+ html.html_safe
24
+ end
25
+ end
@@ -0,0 +1,20 @@
1
+ if defined?(ActionMailer)
2
+ class Devise::Mailer < Devise.parent_mailer.constantize
3
+ include Devise::Mailers::Helpers
4
+
5
+ def confirmation_instructions(record, token, opts={})
6
+ @token = token
7
+ devise_mail(record, :confirmation_instructions, opts)
8
+ end
9
+
10
+ def reset_password_instructions(record, token, opts={})
11
+ @token = token
12
+ devise_mail(record, :reset_password_instructions, opts)
13
+ end
14
+
15
+ def unlock_instructions(record, token, opts={})
16
+ @token = token
17
+ devise_mail(record, :unlock_instructions, opts)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,12 @@
1
+ <h2>Resend confirmation instructions</h2>
2
+
3
+ <%= form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post }) do |f| %>
4
+ <%= devise_error_messages! %>
5
+
6
+ <div><%= f.label :email %><br />
7
+ <%= f.email_field :email, autofocus: true %></div>
8
+
9
+ <div><%= f.submit "Resend confirmation instructions" %></div>
10
+ <% end %>
11
+
12
+ <%= render "devise/shared/links" %>
@@ -0,0 +1,5 @@
1
+ <p>Welcome <%= @email %>!</p>
2
+
3
+ <p>You can confirm your account email through the link below:</p>
4
+
5
+ <p><%= link_to 'Confirm my account', confirmation_url(@resource, confirmation_token: @token) %></p>
@@ -0,0 +1,8 @@
1
+ <p>Hello <%= @resource.email %>!</p>
2
+
3
+ <p>Someone has requested a link to change your password. You can do this through the link below.</p>
4
+
5
+ <p><%= link_to 'Change my password', edit_password_url(@resource, reset_password_token: @token) %></p>
6
+
7
+ <p>If you didn't request this, please ignore this email.</p>
8
+ <p>Your password won't change until you access the link above and create a new one.</p>
@@ -0,0 +1,7 @@
1
+ <p>Hello <%= @resource.email %>!</p>
2
+
3
+ <p>Your account has been locked due to an excessive number of unsuccessful sign in attempts.</p>
4
+
5
+ <p>Click the link below to unlock your account:</p>
6
+
7
+ <p><%= link_to 'Unlock my account', unlock_url(@resource, unlock_token: @token) %></p>
@@ -0,0 +1,16 @@
1
+ <h2>Change your password</h2>
2
+
3
+ <%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put }) do |f| %>
4
+ <%= devise_error_messages! %>
5
+ <%= f.hidden_field :reset_password_token %>
6
+
7
+ <div><%= f.label :password, "New password" %><br />
8
+ <%= f.password_field :password, autofocus: true, autocomplete: "off" %></div>
9
+
10
+ <div><%= f.label :password_confirmation, "Confirm new password" %><br />
11
+ <%= f.password_field :password_confirmation, autocomplete: "off" %></div>
12
+
13
+ <div><%= f.submit "Change my password" %></div>
14
+ <% end %>
15
+
16
+ <%= render "devise/shared/links" %>
@@ -0,0 +1,12 @@
1
+ <h2>Forgot your password?</h2>
2
+
3
+ <%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f| %>
4
+ <%= devise_error_messages! %>
5
+
6
+ <div><%= f.label :email %><br />
7
+ <%= f.email_field :email, autofocus: true %></div>
8
+
9
+ <div><%= f.submit "Send me reset password instructions" %></div>
10
+ <% end %>
11
+
12
+ <%= render "devise/shared/links" %>
@@ -0,0 +1,29 @@
1
+ <h2>Edit <%= resource_name.to_s.humanize %></h2>
2
+
3
+ <%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %>
4
+ <%= devise_error_messages! %>
5
+
6
+ <div><%= f.label :email %><br />
7
+ <%= f.email_field :email, autofocus: true %></div>
8
+
9
+ <% if devise_mapping.confirmable? && resource.pending_reconfirmation? %>
10
+ <div>Currently waiting confirmation for: <%= resource.unconfirmed_email %></div>
11
+ <% end %>
12
+
13
+ <div><%= f.label :password %> <i>(leave blank if you don't want to change it)</i><br />
14
+ <%= f.password_field :password, autocomplete: "off" %></div>
15
+
16
+ <div><%= f.label :password_confirmation %><br />
17
+ <%= f.password_field :password_confirmation, autocomplete: "off" %></div>
18
+
19
+ <div><%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
20
+ <%= f.password_field :current_password, autocomplete: "off" %></div>
21
+
22
+ <div><%= f.submit "Update" %></div>
23
+ <% end %>
24
+
25
+ <h3>Cancel my account</h3>
26
+
27
+ <p>Unhappy? <%= button_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?" }, method: :delete %></p>
28
+
29
+ <%= link_to "Back", :back %>
@@ -0,0 +1,18 @@
1
+ <h2>Sign up</h2>
2
+
3
+ <%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
4
+ <%= devise_error_messages! %>
5
+
6
+ <div><%= f.label :email %><br />
7
+ <%= f.email_field :email, autofocus: true %></div>
8
+
9
+ <div><%= f.label :password %><br />
10
+ <%= f.password_field :password, autocomplete: "off" %></div>
11
+
12
+ <div><%= f.label :password_confirmation %><br />
13
+ <%= f.password_field :password_confirmation, autocomplete: "off" %></div>
14
+
15
+ <div><%= f.submit "Sign up" %></div>
16
+ <% end %>
17
+
18
+ <%= render "devise/shared/links" %>
@@ -0,0 +1,17 @@
1
+ <h2>Sign in</h2>
2
+
3
+ <%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
4
+ <div><%= f.label :email %><br />
5
+ <%= f.email_field :email, autofocus: true %></div>
6
+
7
+ <div><%= f.label :password %><br />
8
+ <%= f.password_field :password, autocomplete: "off" %></div>
9
+
10
+ <% if devise_mapping.rememberable? -%>
11
+ <div><%= f.check_box :remember_me %> <%= f.label :remember_me %></div>
12
+ <% end -%>
13
+
14
+ <div><%= f.submit "Sign in" %></div>
15
+ <% end %>
16
+
17
+ <%= render "devise/shared/links" %>
@@ -0,0 +1,25 @@
1
+ <%- if controller_name != 'sessions' %>
2
+ <%= link_to "Sign in", new_session_path(resource_name) %><br />
3
+ <% end -%>
4
+
5
+ <%- if devise_mapping.registerable? && controller_name != 'registrations' %>
6
+ <%= link_to "Sign up", new_registration_path(resource_name) %><br />
7
+ <% end -%>
8
+
9
+ <%- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' %>
10
+ <%= link_to "Forgot your password?", new_password_path(resource_name) %><br />
11
+ <% end -%>
12
+
13
+ <%- if devise_mapping.confirmable? && controller_name != 'confirmations' %>
14
+ <%= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) %><br />
15
+ <% end -%>
16
+
17
+ <%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %>
18
+ <%= link_to "Didn't receive unlock instructions?", new_unlock_path(resource_name) %><br />
19
+ <% end -%>
20
+
21
+ <%- if devise_mapping.omniauthable? %>
22
+ <%- resource_class.omniauth_providers.each do |provider| %>
23
+ <%= link_to "Sign in with #{provider.to_s.titleize}", omniauth_authorize_path(resource_name, provider) %><br />
24
+ <% end -%>
25
+ <% end -%>
@@ -0,0 +1,12 @@
1
+ <h2>Resend unlock instructions</h2>
2
+
3
+ <%= form_for(resource, as: resource_name, url: unlock_path(resource_name), html: { method: :post }) do |f| %>
4
+ <%= devise_error_messages! %>
5
+
6
+ <div><%= f.label :email %><br />
7
+ <%= f.email_field :email, autofocus: true %></div>
8
+
9
+ <div><%= f.submit "Resend unlock instructions" %></div>
10
+ <% end %>
11
+
12
+ <%= render "devise/shared/links" %>