active_authentication 0.1.0

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 (44) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +120 -0
  3. data/Rakefile +8 -0
  4. data/app/controllers/active_authentication/confirmations_controller.rb +29 -0
  5. data/app/controllers/active_authentication/passwords_controller.rb +37 -0
  6. data/app/controllers/active_authentication/registrations_controller.rb +42 -0
  7. data/app/controllers/active_authentication/sessions_controller.rb +36 -0
  8. data/app/controllers/active_authentication/unlocks_controller.rb +29 -0
  9. data/app/mailers/active_authentication/mailer.rb +21 -0
  10. data/app/views/active_authentication/confirmations/new.html.erb +14 -0
  11. data/app/views/active_authentication/mailer/email_confirmation_instructions.html.erb +5 -0
  12. data/app/views/active_authentication/mailer/password_reset_instructions.html.erb +5 -0
  13. data/app/views/active_authentication/mailer/unlock_instructions.html.erb +5 -0
  14. data/app/views/active_authentication/passwords/edit.html.erb +28 -0
  15. data/app/views/active_authentication/passwords/new.html.erb +14 -0
  16. data/app/views/active_authentication/registrations/edit.html.erb +42 -0
  17. data/app/views/active_authentication/registrations/new.html.erb +35 -0
  18. data/app/views/active_authentication/sessions/new.html.erb +19 -0
  19. data/app/views/active_authentication/shared/_links.html.erb +19 -0
  20. data/app/views/active_authentication/unlocks/new.html.erb +14 -0
  21. data/config/i18n-tasks.yml +159 -0
  22. data/config/locales/en.yml +90 -0
  23. data/config/locales/es.yml +90 -0
  24. data/lib/active_authentication/controller/lockable.rb +31 -0
  25. data/lib/active_authentication/controller/trackable.rb +17 -0
  26. data/lib/active_authentication/controller.rb +48 -0
  27. data/lib/active_authentication/current.rb +5 -0
  28. data/lib/active_authentication/engine.rb +16 -0
  29. data/lib/active_authentication/model/authenticatable.rb +16 -0
  30. data/lib/active_authentication/model/confirmable.rb +54 -0
  31. data/lib/active_authentication/model/lockable.rb +42 -0
  32. data/lib/active_authentication/model/recoverable.rb +16 -0
  33. data/lib/active_authentication/model/registerable.rb +7 -0
  34. data/lib/active_authentication/model/trackable.rb +23 -0
  35. data/lib/active_authentication/model.rb +21 -0
  36. data/lib/active_authentication/routes.rb +34 -0
  37. data/lib/active_authentication/test/helpers.rb +13 -0
  38. data/lib/active_authentication/version.rb +3 -0
  39. data/lib/active_authentication.rb +42 -0
  40. data/lib/generators/active_authentication/install/install_generator.rb +53 -0
  41. data/lib/generators/active_authentication/install/templates/initializer.rb +14 -0
  42. data/lib/generators/active_authentication/install/templates/migration.rb +26 -0
  43. data/lib/generators/active_authentication/views/views_generator.rb +17 -0
  44. metadata +116 -0
@@ -0,0 +1,159 @@
1
+ # i18n-tasks finds and manages missing and unused translations: https://github.com/glebm/i18n-tasks
2
+
3
+ # The "main" locale.
4
+ base_locale: en
5
+ ## All available locales are inferred from the data by default. Alternatively, specify them explicitly:
6
+ # locales: [es, fr]
7
+ ## Reporting locale, default: en. Available: en, ru.
8
+ # internal_locale: en
9
+
10
+ # Read and write translations.
11
+ data:
12
+ ## Translations are read from the file system. Supported format: YAML, JSON.
13
+ ## Provide a custom adapter:
14
+ # adapter: I18n::Tasks::Data::FileSystem
15
+
16
+ # Locale files or `Find.find` patterns where translations are read from:
17
+ read:
18
+ ## Default:
19
+ # - config/locales/%{locale}.yml
20
+ ## More files:
21
+ # - config/locales/**/*.%{locale}.yml
22
+
23
+ # Locale files to write new keys to, based on a list of key pattern => file rules. Matched from top to bottom:
24
+ # `i18n-tasks normalize -p` will force move the keys according to these rules
25
+ write:
26
+ ## For example, write devise and simple form keys to their respective files:
27
+ # - ['{devise, simple_form}.*', 'config/locales/\1.%{locale}.yml']
28
+ ## Catch-all default:
29
+ # - config/locales/%{locale}.yml
30
+
31
+ # External locale data (e.g. gems).
32
+ # This data is not considered unused and is never written to.
33
+ external:
34
+ ## Example (replace %#= with %=):
35
+ # - "<%#= %x[bundle info vagrant --path].chomp %>/templates/locales/%{locale}.yml"
36
+
37
+ ## Specify the router (see Readme for details). Valid values: conservative_router, pattern_router, or a custom class.
38
+ # router: conservative_router
39
+
40
+ yaml:
41
+ write:
42
+ # do not wrap lines at 80 characters
43
+ line_width: -1
44
+
45
+ ## Pretty-print JSON:
46
+ # json:
47
+ # write:
48
+ # indent: ' '
49
+ # space: ' '
50
+ # object_nl: "\n"
51
+ # array_nl: "\n"
52
+
53
+ # Find translate calls
54
+ search:
55
+ ## Paths or `Find.find` patterns to search in:
56
+ # paths:
57
+ # - app/
58
+
59
+ ## Root directories for relative keys resolution.
60
+ # relative_roots:
61
+ # - app/controllers
62
+ # - app/helpers
63
+ # - app/mailers
64
+ # - app/presenters
65
+ # - app/views
66
+
67
+ ## Directories where method names which should not be part of a relative key resolution.
68
+ # By default, if a relative translation is used inside a method, the name of the method will be considered part of the resolved key.
69
+ # Directories listed here will not consider the name of the method part of the resolved key
70
+ #
71
+ # relative_exclude_method_name_paths:
72
+ # -
73
+
74
+ ## Files or `File.fnmatch` patterns to exclude from search. Some files are always excluded regardless of this setting:
75
+ ## *.jpg *.jpeg *.png *.gif *.svg *.ico *.eot *.otf *.ttf *.woff *.woff2 *.pdf *.css *.sass *.scss *.less
76
+ ## *.yml *.json *.zip *.tar.gz *.swf *.flv *.mp3 *.wav *.flac *.webm *.mp4 *.ogg *.opus *.webp *.map *.xlsx
77
+ exclude:
78
+ - app/assets/images
79
+ - app/assets/fonts
80
+ - app/assets/videos
81
+ - app/assets/builds
82
+
83
+ ## Alternatively, the only files or `File.fnmatch patterns` to search in `paths`:
84
+ ## If specified, this settings takes priority over `exclude`, but `exclude` still applies.
85
+ # only: ["*.rb", "*.html.slim"]
86
+
87
+ ## If `strict` is `false`, guess usages such as t("categories.#{category}.title"). The default is `true`.
88
+ # strict: true
89
+
90
+ ## Allows adding ast_matchers for finding translations using the AST-scanners
91
+ ## The available matchers are:
92
+ ## - RailsModelMatcher
93
+ ## Matches ActiveRecord translations like
94
+ ## User.human_attribute_name(:email) and User.model_name.human
95
+ ##
96
+ ## To implement your own, please see `I18n::Tasks::Scanners::AstMatchers::BaseMatcher`.
97
+ # <%# I18n::Tasks.add_ast_matcher('I18n::Tasks::Scanners::AstMatchers::RailsModelMatcher') %>
98
+
99
+ ## Multiple scanners can be used. Their results are merged.
100
+ ## The options specified above are passed down to each scanner. Per-scanner options can be specified as well.
101
+ ## See this example of a custom scanner: https://github.com/glebm/i18n-tasks/wiki/A-custom-scanner-example
102
+
103
+ ## Translation Services
104
+ # translation:
105
+ # # Google Translate
106
+ # # Get an API key and set billing info at https://code.google.com/apis/console to use Google Translate
107
+ # google_translate_api_key: "AbC-dEf5"
108
+ # # DeepL Pro Translate
109
+ # # Get an API key and subscription at https://www.deepl.com/pro to use DeepL Pro
110
+ # deepl_api_key: "48E92789-57A3-466A-9959-1A1A1A1A1A1A"
111
+ # # deepl_host: "https://api.deepl.com"
112
+ # # deepl_version: "v2"
113
+ # # add additional options to the DeepL.translate call: https://www.deepl.com/docs-api/translate-text/translate-text/
114
+ # deepl_options:
115
+ # formality: prefer_less
116
+ ## Do not consider these keys missing:
117
+ # ignore_missing:
118
+ # - 'errors.messages.{accepted,blank,invalid,too_short,too_long}'
119
+ # - '{devise,simple_form}.*'
120
+
121
+ ## Consider these keys used:
122
+ # ignore_unused:
123
+ # - 'activerecord.attributes.*'
124
+ # - '{devise,kaminari,will_paginate}.*'
125
+ # - 'simple_form.{yes,no}'
126
+ # - 'simple_form.{placeholders,hints,labels}.*'
127
+ # - 'simple_form.{error_notification,required}.:'
128
+ ignore_unused:
129
+ - activerecord.attributes.*
130
+ - active_authentication.failure.*
131
+ - active_authentication.mailer.*.subject
132
+
133
+ ## Exclude these keys from the `i18n-tasks eq-base' report:
134
+ # ignore_eq_base:
135
+ # all:
136
+ # - common.ok
137
+ # fr,es:
138
+ # - common.brand
139
+
140
+ ## Exclude these keys from the `i18n-tasks check-consistent-interpolations` report:
141
+ # ignore_inconsistent_interpolations:
142
+ # - 'activerecord.attributes.*'
143
+
144
+ ## Ignore these keys completely:
145
+ # ignore:
146
+ # - kaminari.*
147
+
148
+ ## Sometimes, it isn't possible for i18n-tasks to match the key correctly,
149
+ ## e.g. in case of a relative key defined in a helper method.
150
+ ## In these cases you can use the built-in PatternMapper to map patterns to keys, e.g.:
151
+ #
152
+ # <%# I18n::Tasks.add_scanner 'I18n::Tasks::Scanners::PatternMapper',
153
+ # only: %w(*.html.haml *.html.slim),
154
+ # patterns: [['= title\b', '.page_title']] %>
155
+ #
156
+ # The PatternMapper can also match key literals via a special %{key} interpolation, e.g.:
157
+ #
158
+ # <%# I18n::Tasks.add_scanner 'I18n::Tasks::Scanners::PatternMapper',
159
+ # patterns: [['\bSpree\.t[( ]\s*%{key}', 'spree.%{key}']] %>
@@ -0,0 +1,90 @@
1
+ ---
2
+ en:
3
+ active_authentication:
4
+ confirmations:
5
+ create:
6
+ success: Email confirmation instructions will be sent to your email.
7
+ new:
8
+ email_confirmation_instructions: Send email confirmation instructions
9
+ set_user:
10
+ invalid_token: Email confirmation token is invalid.
11
+ show:
12
+ success: Your email has been successfully confirmed.
13
+ failure:
14
+ already_signed_in: You are already signed in.
15
+ form_errors: "%{errors} prohibited this user from being saved:"
16
+ locked: Your account has been locked after %{count} failed attempts. Unlock instructions will be sent to your email.
17
+ unauthenticated: You need to sign in or sign up before continuing.
18
+ mailer:
19
+ email_confirmation_instructions:
20
+ confirm_email: Confirm my account
21
+ confirm_email_below: 'You can confirm your account email by clicking the link below:'
22
+ hello: Hello, %{email}!
23
+ subject: Confirmation instructions
24
+ password_reset_instructions:
25
+ hello: Hello, %{email}!
26
+ reset_password: Reset your password
27
+ reset_password_below: 'You can reset your password by clicking the link below:'
28
+ subject: Password reset instructions
29
+ unlock_instructions:
30
+ hello: Hello, %{email}!
31
+ subject: Unlock instructions
32
+ unlock: Unlock your account
33
+ unlock_below: 'You can unlock your account by clicking the link below:'
34
+ passwords:
35
+ create:
36
+ success: Password reset instructions will be sent to your email.
37
+ edit:
38
+ set_new_password: Set new password
39
+ new:
40
+ reset_password_instructions: Send reset password instructions
41
+ set_user:
42
+ invalid_token: Password reset token is invalid.
43
+ update:
44
+ success: Your password has been successfully updated.
45
+ registrations:
46
+ create:
47
+ success: You have signed up successfully.
48
+ destroy:
49
+ success: Your account has been successfully cancelled.
50
+ edit:
51
+ cancel_account: Cancel account
52
+ confirm: Are you sure?
53
+ danger_zone: Danger zone
54
+ edit_profile: Edit profile
55
+ pending_confirmation: 'You need to confirm your new email address: %{unconfirmed_email}'
56
+ save: Save
57
+ new:
58
+ sign_up: Sign up
59
+ update:
60
+ success: Your account has been successfully updated.
61
+ sessions:
62
+ create:
63
+ invalid_email_or_password: Invalid email or password.
64
+ success: Signed in successfully.
65
+ destroy:
66
+ success: Signed out successfully.
67
+ new:
68
+ sign_in: Sign in
69
+ shared:
70
+ links:
71
+ reset_password: Reset password
72
+ send_email_confirmation_instructions: Didn't receive confirmation instructions?
73
+ send_unlock_instructions: Didn't receive unlock instructions?
74
+ sign_in: Sign in
75
+ sign_up: Sign up
76
+ unlocks:
77
+ create:
78
+ success: Unlock instructions will be sent to your email.
79
+ new:
80
+ unlock_instructions: Send unlock instructions
81
+ set_user:
82
+ invalid_token: Unlock token is invalid.
83
+ show:
84
+ success: Your account has been successfully unlocked.
85
+ activerecord:
86
+ attributes:
87
+ user:
88
+ email: Email
89
+ password: Password
90
+ password_confirmation: Password confirmation
@@ -0,0 +1,90 @@
1
+ ---
2
+ es:
3
+ active_authentication:
4
+ confirmations:
5
+ create:
6
+ success: Te enviaremos un email con las instrucciones para confirmar tu cuenta.
7
+ new:
8
+ email_confirmation_instructions: Enviar instrucciones de confirmación
9
+ set_user:
10
+ invalid_token: El token es inválido.
11
+ show:
12
+ success: Tu cuenta fue confirmada exitosamente.
13
+ failure:
14
+ already_signed_in: Ya iniciaste sesión.
15
+ form_errors: "%{errors} no permitieron guardar este elemento:"
16
+ locked: Tu cuenta fue bloqueada después de %{count} intentos fallidos. Te enviaremos un email con las instrucciones de desbloqueo.
17
+ unauthenticated: Tenés que iniciar sesión antes de continuar.
18
+ mailer:
19
+ email_confirmation_instructions:
20
+ confirm_email: Confirmar mi cuenta
21
+ confirm_email_below: 'Podés confirmar tu cuenta haciendo click en el siguiente link:'
22
+ hello: Hola, %{email}!
23
+ subject: Instrucciones de confirmación
24
+ password_reset_instructions:
25
+ hello: Hola, %{email}!
26
+ reset_password: Recuperar contraseña
27
+ reset_password_below: 'Podés recuperar tu contraseña haciendo click en el siguiente link:'
28
+ subject: Instrucciones de recuperación de contraseña
29
+ unlock_instructions:
30
+ hello: Hola, %{email}!
31
+ subject: Instrucciones de desbloqueo
32
+ unlock: Desbloquear cuenta
33
+ unlock_below: 'Podés desbloquear tu contraseña haciendo click en el siguiente link:'
34
+ passwords:
35
+ create:
36
+ success: Te enviaremos un email con las instrucciones de para recuperar tu contraseña.
37
+ edit:
38
+ set_new_password: Cambiar contraseña
39
+ new:
40
+ reset_password_instructions: Enviar instrucciones para recuperar contraseña
41
+ set_user:
42
+ invalid_token: El token es inválido.
43
+ update:
44
+ success: Tu contraseña fue actualizada exitosamente.
45
+ registrations:
46
+ create:
47
+ success: Te registraste exitosamente.
48
+ destroy:
49
+ success: Tu cuenta fue cancelada exitosamente.
50
+ edit:
51
+ cancel_account: Cancelar cuenta
52
+ confirm: "¿Estás seguro?"
53
+ danger_zone: Zona de peligro
54
+ edit_profile: Editar perfil
55
+ pending_confirmation: 'Tenés que confirmar tu nuevo email: %{unconfirmed_email}'
56
+ save: Guardar
57
+ new:
58
+ sign_up: Crear una cuenta
59
+ update:
60
+ success: Tu cuenta fue actualizada exitosamente.
61
+ sessions:
62
+ create:
63
+ invalid_email_or_password: Email o contraseña inválidos.
64
+ success: Inicio de sesión existoso.
65
+ destroy:
66
+ success: Cierre de sesión exitoso.
67
+ new:
68
+ sign_in: Iniciar sesión
69
+ shared:
70
+ links:
71
+ reset_password: Recuperar contraseña
72
+ send_email_confirmation_instructions: "¿No recibiste las instrucciones de confirmación?"
73
+ send_unlock_instructions: "¿No recibiste las instrucciones de desbloqueo?"
74
+ sign_in: Iniciar sesión
75
+ sign_up: Crear una cuenta
76
+ unlocks:
77
+ create:
78
+ success: Te enviaremos un email con las instrucciones de desbloqueo.
79
+ new:
80
+ unlock_instructions: Enviar instrucciones de desbloqueo
81
+ set_user:
82
+ invalid_token: El token es inválido.
83
+ show:
84
+ success: Tu cuenta fue desbloqueada exitosamente.
85
+ activerecord:
86
+ attributes:
87
+ user:
88
+ email: Email
89
+ password: Contraseña
90
+ password_confirmation: Repetir contraseña
@@ -0,0 +1,31 @@
1
+ module ActiveAuthentication
2
+ module Controller
3
+ module Lockable
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ set_callback :failed_sign_in, :before, :increment_failed_attempts
8
+ set_callback :failed_sign_in, :after, :set_alert
9
+
10
+ private
11
+
12
+ def increment_failed_attempts
13
+ user = User.find_by email: params[:email]
14
+ user&.increment_failed_attempts
15
+ end
16
+
17
+ def scope
18
+ User.unlocked
19
+ end
20
+
21
+ def set_alert
22
+ user = User.find_by email: params[:email]
23
+
24
+ if user.locked?
25
+ flash[:alert] = t "active_authentication.failure.locked", count: user.failed_attempts
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,17 @@
1
+ module ActiveAuthentication
2
+ module Controller
3
+ module Trackable
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ set_callback :successful_sign_in, :after, :track
8
+
9
+ private
10
+
11
+ def track
12
+ current_user.track request
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,48 @@
1
+ module ActiveAuthentication
2
+ module Controller
3
+ extend ActiveSupport::Concern
4
+ include ActiveSupport::Callbacks
5
+
6
+ included do
7
+ helper_method :current_user
8
+ helper_method :user_signed_in?
9
+ end
10
+
11
+ def authenticate_user!
12
+ redirect_to new_session_path, alert: t("active_authentication.failure.unauthenticated") unless user_signed_in?
13
+ end
14
+
15
+ def current_user
16
+ Current.user ||= user_from_session
17
+ end
18
+
19
+ def require_no_authentication
20
+ redirect_to root_path, alert: t("active_authentication.failure.already_signed_in") if user_signed_in?
21
+ end
22
+
23
+ def sign_in(user)
24
+ reset_session
25
+ Current.user = user
26
+ session[:user_id] = user.id
27
+ end
28
+
29
+ def sign_out
30
+ reset_session
31
+ Current.user = nil
32
+ end
33
+
34
+ def user_signed_in?
35
+ current_user.present?
36
+ end
37
+
38
+ private
39
+
40
+ def scope
41
+ User
42
+ end
43
+
44
+ def user_from_session
45
+ User.find_by id: session[:user_id]
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,5 @@
1
+ module ActiveAuthentication
2
+ class Current < ActiveSupport::CurrentAttributes
3
+ attribute :user
4
+ end
5
+ end
@@ -0,0 +1,16 @@
1
+ require "active_authentication/controller"
2
+ require "active_authentication/model"
3
+
4
+ module ActiveAuthentication
5
+ class Engine < ::Rails::Engine
6
+ initializer :active_authentication_controller do
7
+ ActiveSupport.on_load :action_controller_base do
8
+ include ActiveAuthentication::Controller
9
+ end
10
+
11
+ ActiveSupport.on_load :active_record do
12
+ include ActiveAuthentication::Model
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ module ActiveAuthentication
2
+ module Model
3
+ module Authenticatable
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ has_secure_password
8
+
9
+ normalizes :email, with: -> { _1.strip.downcase }
10
+
11
+ validates :email, format: {with: URI::MailTo::EMAIL_REGEXP}, presence: true, uniqueness: true
12
+ validates :password, length: {minimum: ActiveAuthentication.min_password_length}, allow_blank: true
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,54 @@
1
+ module ActiveAuthentication
2
+ module Model
3
+ module Confirmable
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ generates_token_for :email_confirmation, expires_in: ActiveAuthentication.email_confirmation_token_expires_in
8
+
9
+ normalizes :unconfirmed_email, with: -> { _1.strip.downcase }
10
+
11
+ validates :unconfirmed_email, format: {with: URI::MailTo::EMAIL_REGEXP}, allow_blank: true
12
+
13
+ after_initialize do
14
+ @set_unconfirmed_email = true
15
+ @send_email_confirmation_instructions = true
16
+ end
17
+
18
+ before_update :set_unconfirmed_email, if: :set_unconfirmed_email?
19
+ after_save :send_email_confirmation_instructions, if: :send_email_confirmation_instructions?
20
+ end
21
+
22
+ def confirm
23
+ @send_email_confirmation_instructions = false
24
+ @set_unconfirmed_email = false
25
+
26
+ update email: unconfirmed_email, unconfirmed_email: nil
27
+ end
28
+
29
+ def send_email_confirmation_instructions
30
+ token = generate_token_for :email_confirmation
31
+ ActiveAuthentication::Mailer.with(token: token, user: self).email_confirmation_instructions.deliver
32
+ end
33
+
34
+ def send_email_confirmation_instructions?
35
+ @send_email_confirmation_instructions && unconfirmed_email.present?
36
+ end
37
+
38
+ def unconfirmed?
39
+ unconfirmed_email.present?
40
+ end
41
+
42
+ private
43
+
44
+ def set_unconfirmed_email
45
+ self.unconfirmed_email = email
46
+ self.email = email_was
47
+ end
48
+
49
+ def set_unconfirmed_email?
50
+ @set_unconfirmed_email && email_changed?
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,42 @@
1
+ module ActiveAuthentication
2
+ module Model
3
+ module Lockable
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ ActiveAuthentication::SessionsController.send :include, ActiveAuthentication::Controller::Lockable
8
+
9
+ generates_token_for :unlock, expires_in: ActiveAuthentication.unlock_token_expires_in
10
+
11
+ scope :unlocked, -> { where locked_at: nil }
12
+ end
13
+
14
+ def increment_failed_attempts
15
+ increment :failed_attempts
16
+
17
+ lock if failed_attempts == ActiveAuthentication.max_failed_attempts
18
+
19
+ save
20
+ end
21
+
22
+ def locked?
23
+ locked_at.present?
24
+ end
25
+
26
+ def lock
27
+ update locked_at: Time.now
28
+
29
+ send_unlock_instructions
30
+ end
31
+
32
+ def send_unlock_instructions
33
+ token = generate_token_for :unlock
34
+ ActiveAuthentication::Mailer.with(token: token, user: self).unlock_instructions.deliver
35
+ end
36
+
37
+ def unlock
38
+ update failed_attempts: 0, locked_at: nil
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,16 @@
1
+ module ActiveAuthentication
2
+ module Model
3
+ module Recoverable
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ generates_token_for :password_reset, expires_in: ActiveAuthentication.password_reset_token_expires_in
8
+ end
9
+
10
+ def send_password_reset_instructions
11
+ token = generate_token_for :password_reset
12
+ ActiveAuthentication::Mailer.with(token: token, user: self).password_reset_instructions.deliver
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,7 @@
1
+ module ActiveAuthentication
2
+ module Model
3
+ module Registerable
4
+ extend ActiveSupport::Concern
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,23 @@
1
+ module ActiveAuthentication
2
+ module Model
3
+ module Trackable
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ ActiveAuthentication::SessionsController.send :include, ActiveAuthentication::Controller::Trackable
8
+ end
9
+
10
+ def track(request)
11
+ self.sign_in_count += 1
12
+
13
+ self.last_sign_in_at = current_sign_in_at
14
+ self.current_sign_in_at = Time.now
15
+
16
+ self.last_sign_in_ip = current_sign_in_ip
17
+ self.current_sign_in_ip = request.remote_ip
18
+
19
+ save
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,21 @@
1
+ module ActiveAuthentication
2
+ module Model
3
+ extend ActiveSupport::Concern
4
+
5
+ CONCERNS = %i[authenticatable confirmable lockable recoverable registerable trackable]
6
+
7
+ class_methods do
8
+ def authenticates_with(*concerns)
9
+ include Authenticatable
10
+ concerns.each do |concern|
11
+ include const_get(concern.to_s.classify)
12
+ end
13
+ end
14
+ alias_method :authenticates, :authenticates_with
15
+
16
+ CONCERNS.each do |concern|
17
+ define_method(:"#{concern}?") { User.included_modules.include? const_get(concern.to_s.classify) }
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,34 @@
1
+ module ActionDispatch::Routing
2
+ class Mapper
3
+ def active_authentication
4
+ scope module: :active_authentication do
5
+ ActiveAuthentication::Model::CONCERNS.each do |concern|
6
+ send(concern) if User.send(:"#{concern}?") && respond_to?(concern, true)
7
+ end
8
+ end
9
+ end
10
+
11
+ private
12
+
13
+ def authenticatable
14
+ resource :session, only: [:new, :create, :destroy]
15
+ end
16
+
17
+ def confirmable
18
+ resources :confirmations, param: :token, only: [:new, :create, :show]
19
+ end
20
+
21
+ def lockable
22
+ resources :unlocks, param: :token, only: [:new, :create, :show]
23
+ end
24
+
25
+ def registerable
26
+ resources :registrations, only: [:new, :create]
27
+ resource :profile, only: [:edit, :update, :destroy], path: :profile, controller: :registrations
28
+ end
29
+
30
+ def recoverable
31
+ resources :passwords, param: :token, only: [:new, :create, :edit, :update]
32
+ end
33
+ end
34
+ end