active_authentication 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bcea0e32ac726157bf24da3c6eedfc34ede7c74e69300db47ec93932aa6a1150
4
- data.tar.gz: 92bc3f0bf9c9529816af4b018c5890ed11b94706f25b68a8669e76ff78cb9519
3
+ metadata.gz: 6f71840fc4d08d8eb9ec344aeb3f779e276b09c9812e5a380d1e3455d4d4f29b
4
+ data.tar.gz: 602d85a21c8cea03d629ca0abfd3698344cb9560e376745aea5d964a6e9b9064
5
5
  SHA512:
6
- metadata.gz: 777d5861edbc543fef9d24c88ce0f39bc8457f46d9c4f78ea9335e68455de6c0aa1ac08f06f3e9e1c57e78d5542ea57e06e48ff08d380db6182dd73591e70533
7
- data.tar.gz: 7ff2c591a3ae8169f91607ba2916f62dac48cd96e0566cc3507738067e065cce572b5cec312be40459d4089081d8854ee31b30d748b246f1769fcd0498c230d2
6
+ metadata.gz: d4307d0af7c4d2a319f2714c1ada81b60956f5a41e7e4d11f17a917e33bf2d2bfa7eeff3d41d3c7ded2a846af2eec55937230f8db6c44c548529d4f21bd4a8a2
7
+ data.tar.gz: f6e78e92c1298baa72ddf0be06f2bd90553fac04ece61813b0d3829eacc0861d5028ff73200131a4b8e4df51155253f8cd016a79b426c20f50be5d558535a933
data/README.md CHANGED
@@ -13,6 +13,7 @@ A pure Rails authentication solution.
13
13
  * Authenticatable: provides the standard email/password authentication. It's the only concern that can't be turned off.
14
14
  * Confirmable: allows users to confirm their email addresses.
15
15
  * Lockable: locks users after a number of failed sign in attempts.
16
+ * MagicLinkable: allows users to sign in with a magic link.
16
17
  * Omniauthable: allows users to sign up and sign in using a third party service through Omniauth. Turned off by default.
17
18
  * Recoverable: allows users to reset their password.
18
19
  * Registerable: allows users to sign up and edit their profile.
@@ -21,7 +22,6 @@ A pure Rails authentication solution.
21
22
 
22
23
  Planned concerns:
23
24
 
24
- * MagicLinkable: to allow users to sign in with a magic link.
25
25
  * Invitable: to allow users to invite other users.
26
26
 
27
27
  ## Installation
@@ -98,6 +98,12 @@ Then, to verify if there's an authenticated user, you can use the `user_signed_i
98
98
 
99
99
  Similarly, you can use `current_user` to access the current authenticated user.
100
100
 
101
+ If you want to close your application entirely, you can add the before action to your application controller, in conjunction with `active_authentication_controller?`, like this:
102
+
103
+ ```ruby
104
+ before_action :authenticate_user!, unless: :active_authentication_controller?
105
+ ```
106
+
101
107
  ### Omniauthable
102
108
 
103
109
  ActiveAuthentication's implementation of OmniAuth allows you to sign in and/or sign up with your third party accounts or sign up with ActiveAuthentication and later connect your third party accounts to ActiveAuthentication's User. To accomplish this, ActiveAuthentication relies on an `Authentication` model which can be created with the `active_authentication:omniauthable` generator.
@@ -133,6 +139,21 @@ The sign in and sign up views will show a link to sign in or sign up with each p
133
139
 
134
140
  When you run the `active_authentication:install` generator, an initializer will be copied to your app at `config/initializers/active_authentication.rb`. There's a section per concern where you can configure certain aspects of their behavior.
135
141
 
142
+ ### Customize registration and profile params
143
+
144
+ If you add extra fields to your User model, you will likely want to allow users to fill in those fields upon registration or when editing their profile. By default, only email, password and password confirmation are allowed. To change this behavior, just add these lines to your `config/initializers/active_authentication.rb` file:
145
+
146
+ ```ruby
147
+ ActiveAuthentication.configure do |config|
148
+ config.profile_params = ->(controller) {
149
+ controller.params.require(:user).permit(:first_name, :email, :last_name, :password, :password_confirmation) # first_name and last_name were added in this example
150
+ }
151
+ config.registration_params = config.profile_params
152
+ end
153
+ ```
154
+
155
+ We believe that the configuration of a gem should be placed in just one place. For this gem, it's the initializer. The `profile_params` and `registration_params` take a lambda and that lambda receives a controller. Why a lambda? and why does it take a controller? We could have allowed the params to be just an array of symbols instead of the whole `params.require.permit` call, but in edge cases you might want to post-process the required params, or call tap, or whatever. And to be able to call `params.require.permit`, you need to run this lambda in the context of the registrations controller. That's why the lambda receives the controller.
156
+
136
157
  ### Views
137
158
 
138
159
  The default views are good enough to get you started, but you'll want to customize them sooner than later. To copy the default views into your app, run the following command:
@@ -1,4 +1,4 @@
1
- class ActiveAuthentication::ConfirmationsController < ApplicationController
1
+ class ActiveAuthentication::ConfirmationsController < ActiveAuthenticationController
2
2
  before_action :require_no_authentication, except: :show
3
3
  before_action :set_user, only: :show
4
4
 
@@ -0,0 +1,28 @@
1
+ class ActiveAuthentication::MagicLinksController < ActiveAuthenticationController
2
+ before_action :require_no_authentication
3
+ before_action :set_user, only: :show
4
+
5
+ def new
6
+ end
7
+
8
+ def create
9
+ @user = User.find_by email: params[:email]
10
+ @user&.send_magic_link
11
+
12
+ redirect_to root_path, notice: t(".success")
13
+ end
14
+
15
+ def show
16
+ sign_in @user
17
+
18
+ redirect_to root_url, notice: t(".success")
19
+ end
20
+
21
+ private
22
+
23
+ def set_user
24
+ @user = User.find_by_token_for :magic_link, params[:token]
25
+
26
+ redirect_to root_url, alert: t(".invalid_token") unless @user.present?
27
+ end
28
+ end
@@ -1,4 +1,4 @@
1
- class ActiveAuthentication::OmniauthCallbacksController < ApplicationController
1
+ class ActiveAuthentication::OmniauthCallbacksController < ActiveAuthenticationController
2
2
  def create
3
3
  auth = request.env["omniauth.auth"]
4
4
  provider = auth["provider"]
@@ -1,4 +1,4 @@
1
- class ActiveAuthentication::PasswordsController < ApplicationController
1
+ class ActiveAuthentication::PasswordsController < ActiveAuthenticationController
2
2
  before_action :require_no_authentication
3
3
  before_action :set_user, only: [:edit, :update]
4
4
 
@@ -1,4 +1,4 @@
1
- class ActiveAuthentication::RegistrationsController < ApplicationController
1
+ class ActiveAuthentication::RegistrationsController < ActiveAuthenticationController
2
2
  before_action :require_no_authentication, only: [:new, :create]
3
3
  before_action :authenticate_user!, only: [:edit, :update, :destroy]
4
4
 
@@ -7,7 +7,7 @@ class ActiveAuthentication::RegistrationsController < ApplicationController
7
7
  end
8
8
 
9
9
  def create
10
- @user = User.new user_params
10
+ @user = User.new registration_params
11
11
 
12
12
  if @user.save
13
13
  sign_in @user
@@ -21,7 +21,7 @@ class ActiveAuthentication::RegistrationsController < ApplicationController
21
21
  end
22
22
 
23
23
  def update
24
- if current_user.update(user_params)
24
+ if current_user.update(profile_params)
25
25
  redirect_to edit_profile_path, notice: t(".success")
26
26
  else
27
27
  render :edit, status: :unprocessable_entity
@@ -36,7 +36,11 @@ class ActiveAuthentication::RegistrationsController < ApplicationController
36
36
 
37
37
  private
38
38
 
39
- def user_params
40
- params.require(:user).permit(:email, :password, :password_confirmation)
39
+ def profile_params
40
+ ActiveAuthentication.profile_params.call self
41
+ end
42
+
43
+ def registration_params
44
+ ActiveAuthentication.registration_params.call self
41
45
  end
42
46
  end
@@ -1,4 +1,4 @@
1
- class ActiveAuthentication::SessionsController < ApplicationController
1
+ class ActiveAuthentication::SessionsController < ActiveAuthenticationController
2
2
  include ActiveSupport::Callbacks
3
3
 
4
4
  before_action :require_no_authentication, except: :destroy
@@ -1,4 +1,4 @@
1
- class ActiveAuthentication::UnlocksController < ApplicationController
1
+ class ActiveAuthentication::UnlocksController < ActiveAuthenticationController
2
2
  before_action :require_no_authentication
3
3
  before_action :set_user, only: :show
4
4
 
@@ -0,0 +1,2 @@
1
+ class ActiveAuthenticationController < ApplicationController
2
+ end
@@ -6,6 +6,12 @@ module ActiveAuthentication
6
6
  mail to: @user.unconfirmed_email
7
7
  end
8
8
 
9
+ def magic_link
10
+ @token, @user = params[:token], params[:user]
11
+
12
+ mail to: @user.email
13
+ end
14
+
9
15
  def password_reset_instructions
10
16
  @token, @user = params[:token], params[:user]
11
17
 
@@ -0,0 +1,14 @@
1
+ <h1 class="text-4xl font-bold"><%=t ".send_magic_link" %></h1>
2
+
3
+ <%= form_with url: magic_links_path, data: {turbo: false} do |form| %>
4
+ <div>
5
+ <%= form.label :email, t("activerecord.attributes.user.email") %>
6
+ <%= form.email_field :email %>
7
+ </div>
8
+
9
+ <div>
10
+ <%= form.submit t(".send_magic_link") %>
11
+ </div>
12
+ <% end %>
13
+
14
+ <%= render "active_authentication/shared/links" %>
@@ -0,0 +1,5 @@
1
+ <p><%=t ".hello", email: @user.email %></p>
2
+
3
+ <p><%=t ".magic_link_below" %></p>
4
+
5
+ <p><%= link_to t(".sign_in"), magic_link_url(token: @token) %></p>
@@ -2,6 +2,10 @@
2
2
  <p><%= link_to t(".sign_in"), new_session_path %></p>
3
3
  <% end %>
4
4
 
5
+ <% if controller_name != "magic_links" %>
6
+ <p><%= link_to t(".send_magic_link"), new_magic_link_path %></p>
7
+ <% end %>
8
+
5
9
  <% if User.registerable? && controller_name != "registrations" %>
6
10
  <p><%= link_to t(".sign_up"), new_registration_path %></p>
7
11
  <% end %>
@@ -16,12 +16,26 @@ en:
16
16
  locked: Your account has been locked after %{count} failed attempts. Unlock instructions will be sent to your email.
17
17
  timedout: Your session expired. Sign in again to continue.
18
18
  unauthenticated: You need to sign in or sign up before continuing.
19
+ magic_links:
20
+ create:
21
+ success: Magic link will be sent to your email.
22
+ new:
23
+ send_magic_link: Send magic link
24
+ set_user:
25
+ invalid_token: Magic link is invalid.
26
+ show:
27
+ success: Signed in successfully.
19
28
  mailer:
20
29
  email_confirmation_instructions:
21
30
  confirm_email: Confirm my account
22
31
  confirm_email_below: 'You can confirm your account email by clicking the link below:'
23
32
  hello: Hello, %{email}!
24
33
  subject: Confirmation instructions
34
+ magic_link:
35
+ hello: Hello, %{email}!
36
+ magic_link_below: 'You can sign in to your account by clicking the link below:'
37
+ sign_in: Sign in
38
+ subject: Magic link
25
39
  password_reset_instructions:
26
40
  hello: Hello, %{email}!
27
41
  reset_password: Reset your password
@@ -76,6 +90,7 @@ en:
76
90
  links:
77
91
  reset_password: Reset password
78
92
  send_email_confirmation_instructions: Didn't receive confirmation instructions?
93
+ send_magic_link: Send me a magic link
79
94
  send_unlock_instructions: Didn't receive unlock instructions?
80
95
  sign_in: Sign in
81
96
  sign_in_or_sign_up_with: Sign in or sign up with %{provider}
@@ -16,12 +16,26 @@ es:
16
16
  locked: Tu cuenta fue bloqueada después de %{count} intentos fallidos. Te enviaremos un email con las instrucciones de desbloqueo.
17
17
  timedout: Tu sesión expiró. Iniciá sesión nuevamente para continuar.
18
18
  unauthenticated: Tenés que iniciar sesión antes de continuar.
19
+ magic_links:
20
+ create:
21
+ success: Te enviaremos un email con un enlace mágico para iniciar sesión.
22
+ new:
23
+ send_magic_link: Enviar enlace mágico
24
+ set_user:
25
+ invalid_token: El enlace mágico es inválido.
26
+ show:
27
+ success: Inicio de sesión existoso.
19
28
  mailer:
20
29
  email_confirmation_instructions:
21
30
  confirm_email: Confirmar mi cuenta
22
31
  confirm_email_below: 'Podés confirmar tu cuenta haciendo click en el siguiente link:'
23
32
  hello: Hola, %{email}!
24
33
  subject: Instrucciones de confirmación
34
+ magic_link:
35
+ hello: Hola, %{email}!
36
+ magic_link_below: 'Podés iniciar sesión haciendo click en el siguiente link:'
37
+ sign_in: Iniciar sesión
38
+ subject: Enlace mágico
25
39
  password_reset_instructions:
26
40
  hello: Hola, %{email}!
27
41
  reset_password: Recuperar contraseña
@@ -76,6 +90,7 @@ es:
76
90
  links:
77
91
  reset_password: Recuperar contraseña
78
92
  send_email_confirmation_instructions: "¿No recibiste las instrucciones de confirmación?"
93
+ send_magic_link: Enviarme un enlace mágico
79
94
  send_unlock_instructions: "¿No recibiste las instrucciones de desbloqueo?"
80
95
  sign_in: Iniciar sesión
81
96
  sign_in_or_sign_up_with: Iniciar sesión o crear una cuenta con %{provider}
@@ -8,6 +8,10 @@ module ActiveAuthentication
8
8
  helper_method :user_signed_in?
9
9
  end
10
10
 
11
+ def active_authentication_controller?
12
+ is_a? ::ActiveAuthenticationController
13
+ end
14
+
11
15
  def authenticate_user!
12
16
  redirect_to new_session_path, alert: t("active_authentication.failure.unauthenticated") unless user_signed_in?
13
17
  end
@@ -0,0 +1,16 @@
1
+ module ActiveAuthentication
2
+ module Model
3
+ module Magiclinkable
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ generates_token_for :magic_link, expires_in: ActiveAuthentication.magic_link_token_expires_in
8
+ end
9
+
10
+ def send_magic_link
11
+ token = generate_token_for :magic_link
12
+ ActiveAuthentication::Mailer.with(token: token, user: self).magic_link.deliver
13
+ end
14
+ end
15
+ end
16
+ end
@@ -2,7 +2,7 @@ module ActiveAuthentication
2
2
  module Model
3
3
  extend ActiveSupport::Concern
4
4
 
5
- CONCERNS = %i[authenticatable confirmable lockable omniauthable recoverable registerable timeoutable trackable]
5
+ CONCERNS = %i[authenticatable confirmable lockable magiclinkable omniauthable recoverable registerable timeoutable trackable]
6
6
 
7
7
  class_methods do
8
8
  def authenticates_with(*concerns)
@@ -22,6 +22,10 @@ module ActionDispatch::Routing
22
22
  resources :unlocks, param: :token, only: [:new, :create, :show]
23
23
  end
24
24
 
25
+ def magiclinkable
26
+ resources :magic_links, param: :token, only: [:new, :create, :show]
27
+ end
28
+
25
29
  def omniauthable
26
30
  get "auth/:provider", to: "omniauth_callbacks#pass", as: :omniauth
27
31
  get "auth/:provider/callback", to: "omniauth_callbacks#create", as: :omniauth_callback
@@ -1,3 +1,3 @@
1
1
  module ActiveAuthentication
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.0"
3
3
  end
@@ -20,6 +20,7 @@ module ActiveAuthentication
20
20
  autoload :Authenticatable, "active_authentication/model/authenticatable"
21
21
  autoload :Confirmable, "active_authentication/model/confirmable"
22
22
  autoload :Lockable, "active_authentication/model/lockable"
23
+ autoload :Magiclinkable, "active_authentication/model/magiclinkable"
23
24
  autoload :Omniauthable, "active_authentication/model/omniauthable"
24
25
  autoload :Recoverable, "active_authentication/model/recoverable"
25
26
  autoload :Registerable, "active_authentication/model/registerable"
@@ -41,12 +42,21 @@ module ActiveAuthentication
41
42
  config_accessor :unlock_token_expires_in, default: 24.hours
42
43
  config_accessor :max_failed_attempts, default: 10
43
44
 
45
+ # magiclinkable
46
+ config_accessor :magic_link_token_expires_in, default: 24.hours
47
+
44
48
  # omniauthable
45
49
  config_accessor :omniauth_providers, default: []
46
50
 
47
51
  # recoverable
48
52
  config_accessor :password_reset_token_expires_in, default: 1.hour
49
53
 
54
+ # registerable
55
+ config_accessor :profile_params, default: ->(controller) {
56
+ controller.params.require(:user).permit(:email, :password, :password_confirmation)
57
+ }
58
+ config_accessor :registration_params, default: profile_params
59
+
50
60
  # timeoutable
51
61
  config_accessor :timeout_in, default: 30.minutes
52
62
  end
@@ -9,9 +9,21 @@ ActiveAuthentication.configure do |config|
9
9
  # config.unlock_token_expires_in = 24.hours
10
10
  # config.max_failed_attempts = 10
11
11
 
12
+ # configuration for the magiclinkable concern
13
+ # config.magic_link_token_expires_in = 24.hours
14
+
12
15
  # configuration for the recoverable concern
13
16
  # config.password_reset_token_expires_in = 1.hour
14
17
 
18
+ # configuration for the registerable concern
19
+ # config_accessor :profile_params, default: ->(controller) {
20
+ # controller.params.require(:user).permit(:email, :password, :password_confirmation)
21
+ # }
22
+ # by default the registration_params take the same lambda as the profile_params. if you redefine the
23
+ # profile_params setting, you will need to uncomment this line as otherwise it will take the default value,
24
+ # previously defined.
25
+ # config_accessor :registration_params, default: profile_params
26
+
15
27
  # configuration for the timeoutable concern
16
28
  # config.timeout_in = 30.minutes
17
29
  end
@@ -3,7 +3,7 @@ class ActiveAuthentication::ViewsGenerator < Rails::Generators::Base
3
3
 
4
4
  desc "Generates active_authentication's views."
5
5
 
6
- class_option :views, aliases: "-v", type: :array, desc: "Views to generate (available: confirmations, mailer, passwords, registrations, sessions, shared, unlocks)"
6
+ class_option :views, aliases: "-v", type: :array, desc: "Views to generate (available: confirmations, magic_links, mailer, passwords, registrations, sessions, shared, unlocks)"
7
7
 
8
8
  def copy_views
9
9
  if options[:views]
metadata CHANGED
@@ -1,27 +1,27 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_authentication
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Patricio Mac Adden
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-05-03 00:00:00.000000000 Z
11
+ date: 2024-12-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '7.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '7.0'
27
27
  - !ruby/object:Gem::Dependency
@@ -49,14 +49,18 @@ files:
49
49
  - README.md
50
50
  - Rakefile
51
51
  - app/controllers/active_authentication/confirmations_controller.rb
52
+ - app/controllers/active_authentication/magic_links_controller.rb
52
53
  - app/controllers/active_authentication/omniauth_callbacks_controller.rb
53
54
  - app/controllers/active_authentication/passwords_controller.rb
54
55
  - app/controllers/active_authentication/registrations_controller.rb
55
56
  - app/controllers/active_authentication/sessions_controller.rb
56
57
  - app/controllers/active_authentication/unlocks_controller.rb
58
+ - app/controllers/active_authentication_controller.rb
57
59
  - app/mailers/active_authentication/mailer.rb
58
60
  - app/views/active_authentication/confirmations/new.html.erb
61
+ - app/views/active_authentication/magic_links/new.html.erb
59
62
  - app/views/active_authentication/mailer/email_confirmation_instructions.html.erb
63
+ - app/views/active_authentication/mailer/magic_link.html.erb
60
64
  - app/views/active_authentication/mailer/password_reset_instructions.html.erb
61
65
  - app/views/active_authentication/mailer/unlock_instructions.html.erb
62
66
  - app/views/active_authentication/passwords/edit.html.erb
@@ -81,6 +85,7 @@ files:
81
85
  - lib/active_authentication/model/authenticatable.rb
82
86
  - lib/active_authentication/model/confirmable.rb
83
87
  - lib/active_authentication/model/lockable.rb
88
+ - lib/active_authentication/model/magiclinkable.rb
84
89
  - lib/active_authentication/model/omniauthable.rb
85
90
  - lib/active_authentication/model/recoverable.rb
86
91
  - lib/active_authentication/model/registerable.rb
@@ -116,7 +121,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
116
121
  - !ruby/object:Gem::Version
117
122
  version: '0'
118
123
  requirements: []
119
- rubygems_version: 3.5.3
124
+ rubygems_version: 3.5.22
120
125
  signing_key:
121
126
  specification_version: 4
122
127
  summary: A pure Rails authentication solution