kingsman 0.0.0.beta → 0.1.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 (116) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +10 -0
  3. data/README.md +5 -4
  4. data/app/controllers/kingsman/confirmations_controller.rb +54 -0
  5. data/app/controllers/kingsman/omniauth_callbacks_controller.rb +36 -0
  6. data/app/controllers/kingsman/passwords_controller.rb +83 -0
  7. data/app/controllers/kingsman/registrations_controller.rb +168 -0
  8. data/app/controllers/kingsman/sessions_controller.rb +83 -0
  9. data/app/controllers/kingsman/unlocks_controller.rb +52 -0
  10. data/app/controllers/kingsman_controller.rb +252 -0
  11. data/app/jobs/application_job.rb +2 -0
  12. data/app/mailers/kingsman/mailer.rb +30 -0
  13. data/app/views/kingsman/confirmations/new.html.erb +16 -0
  14. data/app/views/kingsman/home/index.html.erb +1 -0
  15. data/app/views/kingsman/mailer/confirmation_instructions.html.erb +5 -0
  16. data/app/views/kingsman/mailer/email_changed.html.erb +7 -0
  17. data/app/views/kingsman/mailer/password_change.html.erb +3 -0
  18. data/app/views/kingsman/mailer/reset_password_instructions.html.erb +8 -0
  19. data/app/views/kingsman/mailer/unlock_instructions.html.erb +7 -0
  20. data/app/views/kingsman/passwords/edit.html.erb +25 -0
  21. data/app/views/kingsman/passwords/new.html.erb +16 -0
  22. data/app/views/kingsman/registrations/edit.html.erb +42 -0
  23. data/app/views/kingsman/registrations/new.html.erb +29 -0
  24. data/app/views/kingsman/sessions/new.html.erb +26 -0
  25. data/app/views/kingsman/shared/_error_messages.html.erb +15 -0
  26. data/app/views/kingsman/shared/_links.html.erb +25 -0
  27. data/app/views/kingsman/unlocks/new.html.erb +16 -0
  28. data/app/views/kingsman/up/index.html.erb +11 -0
  29. data/config/application.rb +0 -0
  30. data/config/locales/en.yml +63 -0
  31. data/config.ru +6 -0
  32. data/lib/generators/active_record/kingsman_generator.rb +127 -0
  33. data/lib/generators/active_record/templates/migration.rb +20 -0
  34. data/lib/generators/active_record/templates/migration_existing.rb +27 -0
  35. data/lib/generators/kingsman/controllers_generator.rb +46 -0
  36. data/lib/generators/kingsman/install_generator.rb +42 -0
  37. data/lib/generators/kingsman/kingsman_generator.rb +28 -0
  38. data/lib/generators/kingsman/orm_helpers.rb +40 -0
  39. data/lib/generators/kingsman/views_generator.rb +145 -0
  40. data/lib/generators/mongoid/kingsman_generator.rb +57 -0
  41. data/lib/generators/templates/README +36 -0
  42. data/lib/generators/templates/controllers/README +14 -0
  43. data/lib/generators/templates/controllers/confirmations_controller.rb +30 -0
  44. data/lib/generators/templates/controllers/omniauth_callbacks_controller.rb +30 -0
  45. data/lib/generators/templates/controllers/passwords_controller.rb +34 -0
  46. data/lib/generators/templates/controllers/registrations_controller.rb +62 -0
  47. data/lib/generators/templates/controllers/sessions_controller.rb +27 -0
  48. data/lib/generators/templates/controllers/unlocks_controller.rb +30 -0
  49. data/lib/generators/templates/kingsman.rb +313 -0
  50. data/lib/generators/templates/markerb/confirmation_instructions.markerb +5 -0
  51. data/lib/generators/templates/markerb/email_changed.markerb +7 -0
  52. data/lib/generators/templates/markerb/password_change.markerb +3 -0
  53. data/lib/generators/templates/markerb/reset_password_instructions.markerb +8 -0
  54. data/lib/generators/templates/markerb/unlock_instructions.markerb +7 -0
  55. data/lib/generators/templates/simple_form_for/confirmations/new.html.erb +20 -0
  56. data/lib/generators/templates/simple_form_for/passwords/edit.html.erb +27 -0
  57. data/lib/generators/templates/simple_form_for/passwords/new.html.erb +18 -0
  58. data/lib/generators/templates/simple_form_for/registrations/edit.html.erb +35 -0
  59. data/lib/generators/templates/simple_form_for/registrations/new.html.erb +25 -0
  60. data/lib/generators/templates/simple_form_for/sessions/new.html.erb +20 -0
  61. data/lib/generators/templates/simple_form_for/unlocks/new.html.erb +19 -0
  62. data/lib/kingsman/autoloader.rb +31 -0
  63. data/lib/kingsman/controllers/helpers.rb +221 -0
  64. data/lib/kingsman/controllers/rememberable.rb +57 -0
  65. data/lib/kingsman/controllers/responder.rb +35 -0
  66. data/lib/kingsman/controllers/scoped_views.rb +19 -0
  67. data/lib/kingsman/controllers/sign_in_out.rb +112 -0
  68. data/lib/kingsman/controllers/store_location.rb +76 -0
  69. data/lib/kingsman/controllers/url_helpers.rb +72 -0
  70. data/lib/kingsman/delegator.rb +18 -0
  71. data/lib/kingsman/encryptor.rb +19 -0
  72. data/lib/kingsman/failure_app.rb +280 -0
  73. data/lib/kingsman/hooks/activatable.rb +12 -0
  74. data/lib/kingsman/hooks/csrf_cleaner.rb +14 -0
  75. data/lib/kingsman/hooks/forgetable.rb +11 -0
  76. data/lib/kingsman/hooks/lockable.rb +9 -0
  77. data/lib/kingsman/hooks/proxy.rb +23 -0
  78. data/lib/kingsman/hooks/rememberable.rb +9 -0
  79. data/lib/kingsman/hooks/timeoutable.rb +35 -0
  80. data/lib/kingsman/hooks/trackable.rb +11 -0
  81. data/lib/kingsman/hooks.rb +6 -0
  82. data/lib/kingsman/jets/routes.rb +195 -0
  83. data/lib/kingsman/jets/warden_compat.rb +15 -0
  84. data/lib/kingsman/jets.rb +39 -0
  85. data/lib/kingsman/mailers/helpers.rb +93 -0
  86. data/lib/kingsman/mapping.rb +148 -0
  87. data/lib/kingsman/models/authenticatable.rb +310 -0
  88. data/lib/kingsman/models/confirmable.rb +369 -0
  89. data/lib/kingsman/models/database_authenticatable.rb +206 -0
  90. data/lib/kingsman/models/lockable.rb +214 -0
  91. data/lib/kingsman/models/omniauthable.rb +29 -0
  92. data/lib/kingsman/models/recoverable.rb +156 -0
  93. data/lib/kingsman/models/registerable.rb +29 -0
  94. data/lib/kingsman/models/rememberable.rb +158 -0
  95. data/lib/kingsman/models/timeoutable.rb +45 -0
  96. data/lib/kingsman/models/trackable.rb +51 -0
  97. data/lib/kingsman/models/validatable.rb +68 -0
  98. data/lib/kingsman/models.rb +122 -0
  99. data/lib/kingsman/modules.rb +33 -0
  100. data/lib/kingsman/omniauth/config.rb +47 -0
  101. data/lib/kingsman/omniauth/url_helpers.rb +28 -0
  102. data/lib/kingsman/omniauth.rb +20 -0
  103. data/lib/kingsman/orm/active_record.rb +13 -0
  104. data/lib/kingsman/orm/mongoid.rb +8 -0
  105. data/lib/kingsman/orm.rb +37 -0
  106. data/lib/kingsman/parameter_filter.rb +44 -0
  107. data/lib/kingsman/parameter_sanitizer.rb +173 -0
  108. data/lib/kingsman/secret_key_finder.rb +27 -0
  109. data/lib/kingsman/strategies/authenticatable.rb +178 -0
  110. data/lib/kingsman/strategies/base.rb +22 -0
  111. data/lib/kingsman/strategies/database_authenticatable.rb +31 -0
  112. data/lib/kingsman/strategies/rememberable.rb +67 -0
  113. data/lib/kingsman/token_generator.rb +32 -0
  114. data/lib/kingsman/version.rb +1 -1
  115. data/lib/kingsman.rb +427 -3
  116. metadata +304 -11
@@ -0,0 +1,252 @@
1
+ class KingsmanController < Kingsman.parent_controller.constantize
2
+ include Kingsman::Controllers::ScopedViews
3
+
4
+ self.responder = Kingsman.responder
5
+ respond_to :html if mimes_for_respond_to.empty?
6
+
7
+ # Generic methods below
8
+ def build_resource(hash = {})
9
+ self.resource = resource_class.new(hash)
10
+ end
11
+
12
+ # Helper for use in before_actions where no authentication is required.
13
+ #
14
+ # Example:
15
+ # before_action :require_no_authentication, only: :new
16
+ def require_no_authentication
17
+ return unless is_navigational_format?
18
+ no_input = kingsman_mapping.no_input_strategies
19
+
20
+ authenticated = if no_input.present?
21
+ args = no_input.dup.push scope: resource_name
22
+ warden.authenticate?(*args)
23
+ else
24
+ warden.authenticated?(resource_name)
25
+ end
26
+
27
+ if authenticated && resource = warden.user(resource_name)
28
+ set_flash_message(:alert, 'already_authenticated', scope: 'kingsman.failure')
29
+ redirect_to after_sign_in_path_for(resource)
30
+ end
31
+ end
32
+
33
+ # Sets the flash message with :key, using I18n. By default you are able
34
+ # to set up your messages using specific resource scope, and if no message is
35
+ # found we look to the default scope. Set the "now" options key to a true
36
+ # value to populate the flash.now hash in lieu of the default flash hash (so
37
+ # the flash message will be available to the current action instead of the
38
+ # next action).
39
+ # Example (i18n locale file):
40
+ #
41
+ # en:
42
+ # kingsman:
43
+ # passwords:
44
+ # #default_scope_messages - only if resource_scope is not found
45
+ # user:
46
+ # #resource_scope_messages
47
+ #
48
+ # Please refer to README or en.yml locale file to check what messages are
49
+ # available.
50
+ def set_flash_message(key, kind, options = {})
51
+ message = find_message(kind, options)
52
+ if options[:now]
53
+ flash.now[key] = message if message.present?
54
+ else
55
+ flash[key] = message if message.present?
56
+ end
57
+ end
58
+
59
+ # Sets flash message if is_flashing_format? equals true
60
+ def set_flash_message!(key, kind, options = {})
61
+ if is_flashing_format?
62
+ set_flash_message(key, kind, options)
63
+ end
64
+ end
65
+ # Sets minimum password length to show to user
66
+ def set_minimum_password_length
67
+ if kingsman_mapping.validatable?
68
+ @minimum_password_length = resource_class.password_length.min
69
+ end
70
+ end
71
+
72
+ helpers = %w(resource resource_name resource_class resource_params kingsman_mapping)
73
+ helper_method(*helpers)
74
+
75
+ protected
76
+
77
+ # Gets the actual resource stored in the instance variable
78
+ def resource
79
+ instance_variable_get(:"@#{resource_name}")
80
+ end
81
+
82
+ # Proxy to kingsman map name
83
+ def resource_name
84
+ kingsman_mapping.name
85
+ end
86
+ alias :scope_name :resource_name
87
+
88
+ # Proxy to kingsman map class
89
+ def resource_class
90
+ kingsman_mapping.to
91
+ end
92
+
93
+ # Returns a signed in resource from session (if one exists)
94
+ def signed_in_resource
95
+ warden.authenticate(scope: resource_name)
96
+ end
97
+
98
+ # Attempt to find the mapped route for kingsman based on request path
99
+ def kingsman_mapping
100
+ @kingsman_mapping ||= request.env["kingsman.mapping"]
101
+ end
102
+
103
+ # Checks whether it's a kingsman mapped resource or not.
104
+ def assert_is_kingsman_resource! #:nodoc:
105
+ unknown_action! <<-MESSAGE unless kingsman_mapping
106
+ Could not find kingsman mapping for path #{request.fullpath.inspect}.
107
+ This may happen for two reasons:
108
+
109
+ 1) You forgot to wrap your route inside the scope block. For example:
110
+
111
+ kingsman_scope :user do
112
+ get "/some/route" => "some_kingsman_controller"
113
+ end
114
+
115
+ 2) You are testing a Kingsman controller bypassing the router.
116
+ If so, you can explicitly tell Kingsman which mapping to use:
117
+
118
+ @request.env["kingsman.mapping"] = Kingsman.mappings[:user]
119
+
120
+ MESSAGE
121
+ end
122
+
123
+ # Returns real navigational formats which are supported by Rails
124
+ def navigational_formats
125
+ @navigational_formats ||= Kingsman.navigational_formats.select { |format| Mime::EXTENSION_LOOKUP[format.to_s] }
126
+ end
127
+
128
+ def unknown_action!(msg)
129
+ logger.debug "[Kingsman] #{msg}" if logger
130
+ raise AbstractController::ActionNotFound, msg
131
+ end
132
+
133
+ # Sets the resource creating an instance variable
134
+ def resource=(new_resource)
135
+ instance_variable_set(:"@#{resource_name}", new_resource)
136
+ end
137
+
138
+ # Helper for use in before_actions where no authentication is required.
139
+ #
140
+ # Example:
141
+ # before_action :require_no_authentication, only: :new
142
+ def require_no_authentication
143
+ # assert_is_kingsman_resource!
144
+ return unless is_navigational_format?
145
+ no_input = kingsman_mapping.no_input_strategies
146
+
147
+ authenticated = if no_input.present?
148
+ args = no_input.dup.push scope: resource_name
149
+ warden.authenticate?(*args)
150
+ else
151
+ warden.authenticated?(resource_name)
152
+ end
153
+
154
+ if authenticated && resource = warden.user(resource_name)
155
+ set_flash_message(:alert, 'already_authenticated', scope: 'kingsman.failure')
156
+ redirect_to after_sign_in_path_for(resource)
157
+ end
158
+ end
159
+
160
+ # Helper for use after calling send_*_instructions methods on a resource.
161
+ # If we are in paranoid mode, we always act as if the resource was valid
162
+ # and instructions were sent.
163
+ def successfully_sent?(resource)
164
+ notice = if Kingsman.paranoid
165
+ resource.errors.clear
166
+ :send_paranoid_instructions
167
+ elsif resource.errors.empty?
168
+ :send_instructions
169
+ end
170
+
171
+ if notice
172
+ set_flash_message! :notice, notice
173
+ true
174
+ end
175
+ end
176
+
177
+ # Sets the flash message with :key, using I18n. By default you are able
178
+ # to set up your messages using specific resource scope, and if no message is
179
+ # found we look to the default scope. Set the "now" options key to a true
180
+ # value to populate the flash.now hash in lieu of the default flash hash (so
181
+ # the flash message will be available to the current action instead of the
182
+ # next action).
183
+ # Example (i18n locale file):
184
+ #
185
+ # en:
186
+ # kingsman:
187
+ # passwords:
188
+ # #default_scope_messages - only if resource_scope is not found
189
+ # user:
190
+ # #resource_scope_messages
191
+ #
192
+ # Please refer to README or en.yml locale file to check what messages are
193
+ # available.
194
+ def set_flash_message(key, kind, options = {})
195
+ message = find_message(kind, options)
196
+ if options[:now]
197
+ flash.now[key] = message if message.present?
198
+ else
199
+ flash[key] = message if message.present?
200
+ end
201
+ end
202
+
203
+ # Sets flash message if is_flashing_format? equals true
204
+ def set_flash_message!(key, kind, options = {})
205
+ if is_flashing_format?
206
+ set_flash_message(key, kind, options)
207
+ end
208
+ end
209
+
210
+ # Sets minimum password length to show to user
211
+ def set_minimum_password_length
212
+ if kingsman_mapping.validatable?
213
+ @minimum_password_length = resource_class.password_length.min
214
+ end
215
+ end
216
+
217
+ def kingsman_i18n_options(options)
218
+ options
219
+ end
220
+
221
+ # Get message for given
222
+ def find_message(kind, options = {})
223
+ options[:scope] ||= translation_scope
224
+ options[:default] = Array(options[:default]).unshift(kind.to_sym)
225
+ options[:resource_name] = resource_name
226
+ options = kingsman_i18n_options(options)
227
+ I18n.t("#{options[:resource_name]}.#{kind}", **options)
228
+ end
229
+
230
+ # Controllers inheriting KingsmanController are advised to override this
231
+ # method so that other controllers inheriting from them would use
232
+ # existing translations.
233
+ def translation_scope
234
+ "kingsman.#{controller_name}"
235
+ end
236
+
237
+ def clean_up_passwords(object)
238
+ object.clean_up_passwords if object.respond_to?(:clean_up_passwords)
239
+ end
240
+
241
+ def respond_with_navigational(*args, &block)
242
+ respond_with(*args) do |format|
243
+ format.any(*navigational_formats, &block)
244
+ end
245
+ end
246
+
247
+ def resource_params
248
+ params.fetch(resource_name, {})
249
+ end
250
+
251
+ ActiveSupport.run_load_hooks(:kingmans_controller, self)
252
+ end
@@ -0,0 +1,2 @@
1
+ class ApplicationJob < Jets::Job::Base
2
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ if defined?(ActionMailer)
4
+ class Kingsman::Mailer < Kingsman.parent_mailer.constantize
5
+ include Kingsman::Mailers::Helpers
6
+
7
+ def confirmation_instructions(record, token, opts = {})
8
+ @token = token
9
+ kingsman_mail(record, :confirmation_instructions, opts)
10
+ end
11
+
12
+ def reset_password_instructions(record, token, opts = {})
13
+ @token = token
14
+ kingsman_mail(record, :reset_password_instructions, opts)
15
+ end
16
+
17
+ def unlock_instructions(record, token, opts = {})
18
+ @token = token
19
+ kingsman_mail(record, :unlock_instructions, opts)
20
+ end
21
+
22
+ def email_changed(record, opts = {})
23
+ kingsman_mail(record, :email_changed, opts)
24
+ end
25
+
26
+ def password_change(record, opts = {})
27
+ kingsman_mail(record, :password_change, opts)
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,16 @@
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
+ <%= render "kingsman/shared/error_messages", resource: resource %>
5
+
6
+ <div class="field">
7
+ <%= f.label :email %><br />
8
+ <%= f.email_field :email, autofocus: true, autocomplete: "email", value: (resource.pending_reconfirmation? ? resource.unconfirmed_email : resource.email) %>
9
+ </div>
10
+
11
+ <div class="actions">
12
+ <%= f.submit "Resend confirmation instructions" %>
13
+ </div>
14
+ <% end %>
15
+
16
+ <%= render "kingsman/shared/links" %>
@@ -0,0 +1 @@
1
+ home index: unprotected page
@@ -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,7 @@
1
+ <p>Hello <%= @email %>!</p>
2
+
3
+ <% if @resource.try(:unconfirmed_email?) %>
4
+ <p>We're contacting you to notify you that your email is being changed to <%= @resource.unconfirmed_email %>.</p>
5
+ <% else %>
6
+ <p>We're contacting you to notify you that your email has been changed to <%= @resource.email %>.</p>
7
+ <% end %>
@@ -0,0 +1,3 @@
1
+ <p>Hello <%= @resource.email %>!</p>
2
+
3
+ <p>We're contacting you to notify you that your password has been changed.</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,25 @@
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
+ <%= render "kingsman/shared/error_messages", resource: resource %>
5
+ <%= f.hidden_field :reset_password_token %>
6
+
7
+ <div class="field">
8
+ <%= f.label :password, "New password" %><br />
9
+ <% if @minimum_password_length %>
10
+ <em>(<%= @minimum_password_length %> characters minimum)</em><br />
11
+ <% end %>
12
+ <%= f.password_field :password, autofocus: true, autocomplete: "new-password" %>
13
+ </div>
14
+
15
+ <div class="field">
16
+ <%= f.label :password_confirmation, "Confirm new password" %><br />
17
+ <%= f.password_field :password_confirmation, autocomplete: "new-password" %>
18
+ </div>
19
+
20
+ <div class="actions">
21
+ <%= f.submit "Change my password" %>
22
+ </div>
23
+ <% end %>
24
+
25
+ <%= render "kingsman/shared/links" %>
@@ -0,0 +1,16 @@
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
+ <%= render "kingsman/shared/error_messages", resource: resource %>
5
+
6
+ <div class="field">
7
+ <%= f.label :email %><br />
8
+ <%= f.email_field :email, autofocus: true, autocomplete: "email" %>
9
+ </div>
10
+
11
+ <div class="actions">
12
+ <%= f.submit "Send me reset password instructions" %>
13
+ </div>
14
+ <% end %>
15
+
16
+ <%= render "kingsman/shared/links" %>
@@ -0,0 +1,42 @@
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
+ <%= render "kingsman/shared/error_messages", resource: resource %>
5
+
6
+ <div class="field">
7
+ <p><%= f.label :email %></p>
8
+ <p><%= f.email_field :email, autofocus: true, autocomplete: "email" %></p>
9
+ </div>
10
+
11
+ <% if kingsman_mapping.confirmable? && resource.pending_reconfirmation? %>
12
+ <div>Currently waiting confirmation for: <%= resource.unconfirmed_email %></div>
13
+ <% end %>
14
+
15
+ <div class="field">
16
+ <p><%= f.label :password %> <i>(leave blank if you don't want to change it)</i></p>
17
+ <p><%= f.password_field :password, autocomplete: "new-password" %></p>
18
+ <% if @minimum_password_length %>
19
+ <p><em><%= @minimum_password_length %> characters minimum</em></p>
20
+ <% end %>
21
+ </div>
22
+
23
+ <div class="field">
24
+ <p><%= f.label :password_confirmation %></p>
25
+ <p><%= f.password_field :password_confirmation, autocomplete: "new-password" %></p>
26
+ </div>
27
+
28
+ <div class="field">
29
+ <p><%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i></p>
30
+ <p><%= f.password_field :current_password, autocomplete: "current-password" %></p>
31
+ </div>
32
+
33
+ <div class="actions">
34
+ <%= f.submit "Update" %>
35
+ </div>
36
+ <% end %>
37
+
38
+ <h3>Cancel my account</h3>
39
+
40
+ <div>Unhappy? <%= button_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?", turbo_confirm: "Are you sure?" }, method: :delete %></div>
41
+
42
+ <%= link_to "Back", :back %>
@@ -0,0 +1,29 @@
1
+ <h2>Sign up</h2>
2
+
3
+ <%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
4
+ <%= render "kingsman/shared/error_messages", resource: resource %>
5
+
6
+ <div class="field">
7
+ <p><%= f.label :email %></p>
8
+ <p><%= f.email_field :email, autofocus: true, autocomplete: "email" %></p>
9
+ </div>
10
+
11
+ <div class="field">
12
+ <p><%= f.label :password %></p>
13
+ <% if @minimum_password_length %>
14
+ <p><em>(<%= @minimum_password_length %> characters minimum)</em></p>
15
+ <% end %>
16
+ <p><%= f.password_field :password, autocomplete: "new-password" %></p>
17
+ </div>
18
+
19
+ <div class="field">
20
+ <p><%= f.label :password_confirmation %></p>
21
+ <p><%= f.password_field :password_confirmation, autocomplete: "new-password" %></p>
22
+ </div>
23
+
24
+ <div class="actions">
25
+ <%= f.submit "Sign up" %>
26
+ </div>
27
+ <% end %>
28
+
29
+ <%= render "kingsman/shared/links" %>
@@ -0,0 +1,26 @@
1
+ <h1>Log in</h1>
2
+
3
+ <%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
4
+ <div class="field">
5
+ <%= f.label :email %><br />
6
+ <%= f.email_field :email, autofocus: true, autocomplete: "email" %>
7
+ </div>
8
+
9
+ <div class="field">
10
+ <%= f.label :password %><br />
11
+ <%= f.password_field :password, autocomplete: "current-password" %>
12
+ </div>
13
+
14
+ <% if kingsman_mapping.rememberable? %>
15
+ <div class="field">
16
+ <%= f.check_box :remember_me %>
17
+ <%= f.label :remember_me %>
18
+ </div>
19
+ <% end %>
20
+
21
+ <div class="actions">
22
+ <%= f.submit "Log in" %>
23
+ </div>
24
+ <% end %>
25
+
26
+ <%= render "kingsman/shared/links" %>
@@ -0,0 +1,15 @@
1
+ <% if resource.errors.any? %>
2
+ <div id="error_explanation" data-turbo-cache="false">
3
+ <h2>
4
+ <%= I18n.t("errors.messages.not_saved",
5
+ count: resource.errors.count,
6
+ resource: resource.class.model_name.human.downcase)
7
+ %>
8
+ </h2>
9
+ <ul>
10
+ <% resource.errors.full_messages.each do |message| %>
11
+ <li><%= message %></li>
12
+ <% end %>
13
+ </ul>
14
+ </div>
15
+ <% end %>
@@ -0,0 +1,25 @@
1
+ <%- if controller_name != 'sessions' %>
2
+ <%= link_to "Log in", new_session_path(resource_name) %><br />
3
+ <% end %>
4
+
5
+ <%- if kingsman_mapping.registerable? && controller_name != 'registrations' %>
6
+ <%= link_to "Sign up", new_registration_path(resource_name) %><br />
7
+ <% end %>
8
+
9
+ <%- if kingsman_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 kingsman_mapping.confirmable? && controller_name != 'confirmations' %>
14
+ <%= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) %><br />
15
+ <% end %>
16
+
17
+ <%- if kingsman_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 kingsman_mapping.omniauthable? %>
22
+ <%- resource_class.omniauth_providers.each do |provider| %>
23
+ <%= button_to "Sign in with #{OmniAuth::Utils.camelize(provider)}", omniauth_authorize_path(resource_name, provider), data: { turbo: false } %><br />
24
+ <% end %>
25
+ <% end %>
@@ -0,0 +1,16 @@
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
+ <%= render "kingsman/shared/error_messages", resource: resource %>
5
+
6
+ <div class="field">
7
+ <%= f.label :email %><br />
8
+ <%= f.email_field :email, autofocus: true, autocomplete: "email" %>
9
+ </div>
10
+
11
+ <div class="actions">
12
+ <%= f.submit "Resend unlock instructions" %>
13
+ </div>
14
+ <% end %>
15
+
16
+ <%= render "kingsman/shared/links" %>
@@ -0,0 +1,11 @@
1
+ <h1>Up Index</h1>
2
+
3
+ <h2>Engine helpers</h2>
4
+ <p>kingsman.up_path: <%= kingsman.up_path %></p>
5
+ <p>up_path: <%= up_path %></p>
6
+ <p>kingsman.root_path: <%= kingsman.root_path %></p>
7
+
8
+ <h2>Main app helpers</h2>
9
+ <p>main_app.home_path: <%= main_app.home_path %></p>
10
+ <p>home_path: <%= home_path %></p>
11
+ <p>root_path: <%= root_path %></p>
File without changes
@@ -0,0 +1,63 @@
1
+ en:
2
+ kingsman:
3
+ confirmations:
4
+ confirmed: "Your email address has been successfully confirmed."
5
+ send_instructions: "You will receive an email with instructions for how to confirm your email address in a few minutes."
6
+ send_paranoid_instructions: "If your email address exists in our database, you will receive an email with instructions for how to confirm your email address in a few minutes."
7
+ failure:
8
+ already_authenticated: "You are already signed in."
9
+ inactive: "Your account is not activated yet."
10
+ invalid: "Invalid %{authentication_keys} or password."
11
+ locked: "Your account is locked."
12
+ last_attempt: "You have one more attempt before your account is locked."
13
+ not_found_in_database: "Invalid %{authentication_keys} or password."
14
+ timeout: "Your session expired. Please sign in again to continue."
15
+ unauthenticated: "You need to sign in or sign up before continuing."
16
+ unconfirmed: "You have to confirm your email address before continuing."
17
+ mailer:
18
+ confirmation_instructions:
19
+ subject: "Confirmation instructions"
20
+ reset_password_instructions:
21
+ subject: "Reset password instructions"
22
+ unlock_instructions:
23
+ subject: "Unlock instructions"
24
+ email_changed:
25
+ subject: "Email Changed"
26
+ password_change:
27
+ subject: "Password Changed"
28
+ omniauth_callbacks:
29
+ failure: "Could not authenticate you from %{kind} because \"%{reason}\"."
30
+ success: "Successfully authenticated from %{kind} account."
31
+ passwords:
32
+ no_token: "You can't access this page without coming from a password reset email. If you do come from a password reset email, please make sure you used the full URL provided."
33
+ send_instructions: "You will receive an email with instructions on how to reset your password in a few minutes."
34
+ send_paranoid_instructions: "If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes."
35
+ updated: "Your password has been changed successfully. You are now signed in."
36
+ updated_not_active: "Your password has been changed successfully."
37
+ registrations:
38
+ destroyed: "Bye! Your account has been successfully cancelled. We hope to see you again soon."
39
+ signed_up: "Welcome! You have signed up successfully."
40
+ signed_up_but_inactive: "You have signed up successfully. However, we could not sign you in because your account is not yet activated."
41
+ signed_up_but_locked: "You have signed up successfully. However, we could not sign you in because your account is locked."
42
+ signed_up_but_unconfirmed: "A message with a confirmation link has been sent to your email address. Please follow the link to activate your account."
43
+ update_needs_confirmation: "You updated your account successfully, but we need to verify your new email address. Please check your email and follow the confirmation link to confirm your new email address."
44
+ updated: "Your account has been updated successfully."
45
+ updated_but_not_signed_in: "Your account has been updated successfully, but since your password was changed, you need to sign in again."
46
+ sessions:
47
+ signed_in: "Signed in successfully."
48
+ signed_out: "Signed out successfully."
49
+ already_signed_out: "Signed out successfully."
50
+ unlocks:
51
+ send_instructions: "You will receive an email with instructions for how to unlock your account in a few minutes."
52
+ send_paranoid_instructions: "If your account exists, you will receive an email with instructions for how to unlock it in a few minutes."
53
+ unlocked: "Your account has been unlocked successfully. Please sign in to continue."
54
+ errors:
55
+ messages:
56
+ already_confirmed: "was already confirmed, please try signing in"
57
+ confirmation_period_expired: "needs to be confirmed within %{period}, please request a new one"
58
+ expired: "has expired, please request a new one"
59
+ not_found: "not found"
60
+ not_locked: "was not locked"
61
+ not_saved:
62
+ one: "1 error prohibited this %{resource} from being saved:"
63
+ other: "%{count} errors prohibited this %{resource} from being saved:"
data/config.ru ADDED
@@ -0,0 +1,6 @@
1
+ # This file is used by Rack-based servers to start the application.
2
+
3
+ require "jets"
4
+ Jets.boot
5
+ require_relative "lib/kingsman/engine"
6
+ run Kingsman::Engine.instance