rails_simple_auth 1.0.1 → 1.0.3
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +43 -0
- data/README.md +271 -14
- data/app/controllers/rails_simple_auth/confirmations_controller.rb +25 -17
- data/app/controllers/rails_simple_auth/omniauth_callbacks_controller.rb +6 -4
- data/app/controllers/rails_simple_auth/passwords_controller.rb +13 -12
- data/app/controllers/rails_simple_auth/registrations_controller.rb +6 -4
- data/app/controllers/rails_simple_auth/sessions_controller.rb +28 -17
- data/app/mailers/rails_simple_auth/auth_mailer.rb +13 -7
- data/app/views/rails_simple_auth/confirmations/new.html.erb +2 -2
- data/app/views/rails_simple_auth/passwords/new.html.erb +2 -2
- data/app/views/rails_simple_auth/registrations/new.html.erb +5 -5
- data/app/views/rails_simple_auth/sessions/magic_link_form.html.erb +2 -2
- data/app/views/rails_simple_auth/sessions/new.html.erb +2 -2
- data/lib/generators/rails_simple_auth/css/css_generator.rb +20 -20
- data/lib/generators/rails_simple_auth/install/install_generator.rb +32 -32
- data/lib/generators/rails_simple_auth/install/templates/initializer.rb +3 -3
- data/lib/generators/rails_simple_auth/install/templates/migration.rb +2 -2
- data/lib/generators/rails_simple_auth/temporary_users/USAGE +21 -0
- data/lib/generators/rails_simple_auth/temporary_users/templates/add_temporary_to_users.rb.erb +8 -0
- data/lib/generators/rails_simple_auth/temporary_users/temporary_users_generator.rb +40 -0
- data/lib/generators/rails_simple_auth/views/views_generator.rb +8 -8
- data/lib/rails_simple_auth/configuration.rb +21 -7
- data/lib/rails_simple_auth/controllers/concerns/authentication.rb +17 -18
- data/lib/rails_simple_auth/controllers/concerns/session_management.rb +24 -0
- data/lib/rails_simple_auth/engine.rb +1 -1
- data/lib/rails_simple_auth/models/concerns/authenticatable.rb +13 -5
- data/lib/rails_simple_auth/models/concerns/confirmable.rb +42 -3
- data/lib/rails_simple_auth/models/concerns/oauth_connectable.rb +5 -5
- data/lib/rails_simple_auth/models/concerns/temporary_user.rb +114 -0
- data/lib/rails_simple_auth/models/session.rb +2 -4
- data/lib/rails_simple_auth/routes.rb +15 -15
- data/lib/rails_simple_auth/version.rb +1 -1
- data/lib/rails_simple_auth.rb +14 -12
- metadata +20 -13
|
@@ -8,13 +8,17 @@ module RailsSimpleAuth
|
|
|
8
8
|
|
|
9
9
|
unless Rails.env.local?
|
|
10
10
|
rate_limit to: 5, within: 15.minutes, by: -> { client_ip }, only: :create,
|
|
11
|
-
with: -> { redirect_to new_session_path, alert:
|
|
11
|
+
with: -> { redirect_to new_session_path, alert: 'Too many login attempts. Please try again later.' }
|
|
12
12
|
|
|
13
|
-
rate_limit to: 3, within: 10.minutes, by: -> { params[:
|
|
14
|
-
with:
|
|
13
|
+
rate_limit to: 3, within: 10.minutes, by: -> { params[:email].to_s.downcase }, only: :request_magic_link,
|
|
14
|
+
with: lambda {
|
|
15
|
+
redirect_to new_session_path, alert: 'Too many magic link requests. Please try again later.'
|
|
16
|
+
}
|
|
15
17
|
|
|
16
18
|
rate_limit to: 5, within: 15.minutes, by: -> { client_ip }, only: :magic_link_login,
|
|
17
|
-
with:
|
|
19
|
+
with: lambda {
|
|
20
|
+
redirect_to new_session_path, alert: 'Too many magic link attempts. Please try again later.'
|
|
21
|
+
}
|
|
18
22
|
end
|
|
19
23
|
|
|
20
24
|
def new
|
|
@@ -22,20 +26,20 @@ module RailsSimpleAuth
|
|
|
22
26
|
end
|
|
23
27
|
|
|
24
28
|
def create
|
|
25
|
-
user = user_class.
|
|
29
|
+
user = user_class.find_by(email: params[:email]) || user_class.new(password: SecureRandom.hex(32))
|
|
26
30
|
|
|
27
31
|
if user.authenticate(params[:password]) && user.persisted?
|
|
28
32
|
if confirmation_required_for?(user)
|
|
29
|
-
@error_message =
|
|
30
|
-
@previous_email = params[:
|
|
33
|
+
@error_message = 'Please confirm your email before signing in.'
|
|
34
|
+
@previous_email = params[:email]
|
|
31
35
|
render :new, status: :unprocessable_content
|
|
32
36
|
else
|
|
33
37
|
sign_in_and_redirect(user)
|
|
34
38
|
end
|
|
35
39
|
else
|
|
36
|
-
Rails.logger.warn("Failed login attempt for email: #{params[:
|
|
37
|
-
@error_message =
|
|
38
|
-
@previous_email = params[:
|
|
40
|
+
Rails.logger.warn("Failed login attempt for email: #{params[:email]} from IP: #{client_ip}")
|
|
41
|
+
@error_message = 'Invalid email or password'
|
|
42
|
+
@previous_email = params[:email]
|
|
39
43
|
render :new, status: :unprocessable_content
|
|
40
44
|
end
|
|
41
45
|
end
|
|
@@ -44,7 +48,7 @@ module RailsSimpleAuth
|
|
|
44
48
|
user = current_user
|
|
45
49
|
destroy_current_session
|
|
46
50
|
run_after_sign_out_callback(user) if user
|
|
47
|
-
redirect_to resolve_path(:after_sign_out_path), notice:
|
|
51
|
+
redirect_to resolve_path(:after_sign_out_path), notice: 'Signed out successfully.'
|
|
48
52
|
end
|
|
49
53
|
|
|
50
54
|
def magic_link_form
|
|
@@ -52,24 +56,30 @@ module RailsSimpleAuth
|
|
|
52
56
|
end
|
|
53
57
|
|
|
54
58
|
def request_magic_link
|
|
55
|
-
user = user_class.
|
|
59
|
+
user = user_class.find_by(email: params[:email])
|
|
56
60
|
|
|
57
|
-
if user
|
|
61
|
+
if user.respond_to?(:generate_magic_link_token)
|
|
58
62
|
token = user.generate_magic_link_token
|
|
59
63
|
RailsSimpleAuth.configuration.mailer.magic_link(user, token).deliver_later
|
|
60
64
|
end
|
|
61
65
|
|
|
62
|
-
redirect_to new_session_path, notice:
|
|
66
|
+
redirect_to new_session_path, notice: 'If an account exists with that email, a magic link has been sent.'
|
|
63
67
|
end
|
|
64
68
|
|
|
65
69
|
def magic_link_login
|
|
66
70
|
user = user_class.find_signed(params[:token], purpose: :magic_link)
|
|
67
71
|
|
|
68
72
|
if user
|
|
69
|
-
|
|
73
|
+
# Auto-confirm unconfirmed users via magic link (email ownership verified)
|
|
74
|
+
if user.respond_to?(:confirm!) && user.respond_to?(:unconfirmed?) && user.unconfirmed? && !user.confirm!
|
|
75
|
+
# Confirmation failed (e.g., email already taken during reconfirmation)
|
|
76
|
+
error_message = user.errors.full_messages.first || 'Could not confirm email.'
|
|
77
|
+
redirect_to new_session_path, alert: error_message
|
|
78
|
+
return
|
|
79
|
+
end
|
|
70
80
|
sign_in_and_redirect(user)
|
|
71
81
|
else
|
|
72
|
-
redirect_to new_session_path, alert:
|
|
82
|
+
redirect_to new_session_path, alert: 'Invalid or expired magic link.'
|
|
73
83
|
end
|
|
74
84
|
end
|
|
75
85
|
|
|
@@ -82,9 +92,10 @@ module RailsSimpleAuth
|
|
|
82
92
|
end
|
|
83
93
|
|
|
84
94
|
def sign_in_and_redirect(user)
|
|
95
|
+
destroy_temporary_user_session(user)
|
|
85
96
|
create_session_for(user)
|
|
86
97
|
run_after_sign_in_callback(user)
|
|
87
|
-
redirect_to stored_location_or_default, notice:
|
|
98
|
+
redirect_to stored_location_or_default, notice: 'Signed in successfully.'
|
|
88
99
|
end
|
|
89
100
|
end
|
|
90
101
|
end
|
|
@@ -1,17 +1,23 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module RailsSimpleAuth
|
|
4
|
-
class AuthMailer <
|
|
4
|
+
class AuthMailer < ApplicationMailer
|
|
5
5
|
default from: -> { RailsSimpleAuth.configuration.mailer_sender }
|
|
6
6
|
|
|
7
|
+
# Use the mailers folder for templates instead of auth_mailer
|
|
8
|
+
self.mailer_name = 'rails_simple_auth/mailers'
|
|
9
|
+
|
|
7
10
|
def confirmation(user, token)
|
|
8
11
|
@user = user
|
|
9
12
|
@token = token
|
|
10
13
|
@confirmation_url = main_app.confirmation_url(token: token)
|
|
11
14
|
|
|
15
|
+
# Use confirmable_email for reconfirmation (email change) scenarios
|
|
16
|
+
recipient = user.respond_to?(:confirmable_email) ? user.confirmable_email : user.email
|
|
17
|
+
|
|
12
18
|
mail(
|
|
13
|
-
to:
|
|
14
|
-
subject:
|
|
19
|
+
to: recipient,
|
|
20
|
+
subject: 'Confirm your email'
|
|
15
21
|
)
|
|
16
22
|
end
|
|
17
23
|
|
|
@@ -21,8 +27,8 @@ module RailsSimpleAuth
|
|
|
21
27
|
@magic_link_url = main_app.magic_link_url(token: token)
|
|
22
28
|
|
|
23
29
|
mail(
|
|
24
|
-
to: user.
|
|
25
|
-
subject:
|
|
30
|
+
to: user.email,
|
|
31
|
+
subject: 'Sign in to your account'
|
|
26
32
|
)
|
|
27
33
|
end
|
|
28
34
|
|
|
@@ -32,8 +38,8 @@ module RailsSimpleAuth
|
|
|
32
38
|
@password_reset_url = main_app.edit_password_url(token: token)
|
|
33
39
|
|
|
34
40
|
mail(
|
|
35
|
-
to: user.
|
|
36
|
-
subject:
|
|
41
|
+
to: user.email,
|
|
42
|
+
subject: 'Reset your password'
|
|
37
43
|
)
|
|
38
44
|
end
|
|
39
45
|
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
|
|
9
9
|
<%= form_with url: main_app.confirmations_path, class: "rsa-auth-form__form" do |form| %>
|
|
10
10
|
<div class="rsa-auth-form__group">
|
|
11
|
-
<%= form.label :
|
|
12
|
-
<%= form.email_field :
|
|
11
|
+
<%= form.label :email, "Email", class: "rsa-auth-form__label" %>
|
|
12
|
+
<%= form.email_field :email,
|
|
13
13
|
class: "rsa-auth-form__input",
|
|
14
14
|
required: true,
|
|
15
15
|
autofocus: true %>
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
|
|
9
9
|
<%= form_with url: main_app.passwords_path, class: "rsa-auth-form__form" do |form| %>
|
|
10
10
|
<div class="rsa-auth-form__group">
|
|
11
|
-
<%= form.label :
|
|
12
|
-
<%= form.email_field :
|
|
11
|
+
<%= form.label :email, "Email", class: "rsa-auth-form__label" %>
|
|
12
|
+
<%= form.email_field :email,
|
|
13
13
|
class: "rsa-auth-form__input",
|
|
14
14
|
required: true,
|
|
15
15
|
autofocus: true %>
|
|
@@ -4,13 +4,13 @@
|
|
|
4
4
|
|
|
5
5
|
<%= form_with model: @user, url: main_app.sign_up_path, class: "rsa-auth-form__form" do |form| %>
|
|
6
6
|
<div class="rsa-auth-form__group">
|
|
7
|
-
<%= form.label :
|
|
8
|
-
<%= form.email_field :
|
|
9
|
-
class: "rsa-auth-form__input #{@user.errors[:
|
|
7
|
+
<%= form.label :email, "Email", class: "rsa-auth-form__label" %>
|
|
8
|
+
<%= form.email_field :email,
|
|
9
|
+
class: "rsa-auth-form__input #{@user.errors[:email].any? ? 'rsa-auth-form__input--error' : ''}",
|
|
10
10
|
required: true,
|
|
11
11
|
autofocus: true %>
|
|
12
|
-
<% if @user.errors[:
|
|
13
|
-
<p class="rsa-auth-form__error"><%= @user.errors[:
|
|
12
|
+
<% if @user.errors[:email].any? %>
|
|
13
|
+
<p class="rsa-auth-form__error"><%= @user.errors[:email].first %></p>
|
|
14
14
|
<% end %>
|
|
15
15
|
</div>
|
|
16
16
|
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
|
|
9
9
|
<%= form_with url: main_app.request_magic_link_path, class: "rsa-auth-form__form" do |form| %>
|
|
10
10
|
<div class="rsa-auth-form__group">
|
|
11
|
-
<%= form.label :
|
|
12
|
-
<%= form.email_field :
|
|
11
|
+
<%= form.label :email, "Email", class: "rsa-auth-form__label" %>
|
|
12
|
+
<%= form.email_field :email,
|
|
13
13
|
class: "rsa-auth-form__input",
|
|
14
14
|
required: true,
|
|
15
15
|
autofocus: true %>
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
<%= form_with url: main_app.session_path, class: "rsa-auth-form__form" do |form| %>
|
|
6
6
|
<div class="rsa-auth-form__group">
|
|
7
|
-
<%= form.label :
|
|
8
|
-
<%= form.email_field :
|
|
7
|
+
<%= form.label :email, "Email", class: "rsa-auth-form__label" %>
|
|
8
|
+
<%= form.email_field :email,
|
|
9
9
|
class: "rsa-auth-form__input #{@error_message.present? ? 'rsa-auth-form__input--error' : ''}",
|
|
10
10
|
required: true,
|
|
11
11
|
autofocus: true,
|
|
@@ -1,35 +1,35 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
3
|
+
require 'rails/generators'
|
|
4
4
|
|
|
5
5
|
module RailsSimpleAuth
|
|
6
6
|
module Generators
|
|
7
7
|
class CssGenerator < Rails::Generators::Base
|
|
8
|
-
source_root File.expand_path(
|
|
8
|
+
source_root File.expand_path('templates', __dir__)
|
|
9
9
|
|
|
10
|
-
class_option :path, type: :string, default:
|
|
11
|
-
|
|
10
|
+
class_option :path, type: :string, default: 'app/assets/stylesheets',
|
|
11
|
+
desc: 'Path to copy CSS to'
|
|
12
12
|
|
|
13
13
|
def copy_css
|
|
14
|
-
template
|
|
14
|
+
template 'rails_simple_auth.css', "#{options[:path]}/rails_simple_auth.css"
|
|
15
15
|
|
|
16
|
-
say
|
|
16
|
+
say ''
|
|
17
17
|
say "CSS copied to #{options[:path]}/rails_simple_auth.css", :green
|
|
18
|
-
say
|
|
19
|
-
say
|
|
20
|
-
say
|
|
21
|
-
say
|
|
18
|
+
say ''
|
|
19
|
+
say 'To use this CSS:'
|
|
20
|
+
say ''
|
|
21
|
+
say ' 1. Include in your application.css or layout:'
|
|
22
22
|
say " <%= stylesheet_link_tag 'rails_simple_auth' %>"
|
|
23
|
-
say
|
|
24
|
-
say
|
|
25
|
-
say
|
|
26
|
-
say
|
|
27
|
-
say
|
|
28
|
-
say
|
|
29
|
-
say
|
|
30
|
-
say
|
|
31
|
-
say
|
|
32
|
-
say
|
|
23
|
+
say ''
|
|
24
|
+
say ' 2. Customize by overriding CSS variables in your own stylesheet:'
|
|
25
|
+
say ''
|
|
26
|
+
say ' :root {'
|
|
27
|
+
say ' --rsa-color-primary: #your-brand-color;'
|
|
28
|
+
say ' --rsa-color-background-form: #your-form-bg;'
|
|
29
|
+
say ' }'
|
|
30
|
+
say ''
|
|
31
|
+
say ' 3. Or edit rails_simple_auth.css directly.'
|
|
32
|
+
say ''
|
|
33
33
|
end
|
|
34
34
|
end
|
|
35
35
|
end
|
|
@@ -1,64 +1,64 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
4
|
-
require
|
|
3
|
+
require 'rails/generators'
|
|
4
|
+
require 'rails/generators/active_record'
|
|
5
5
|
|
|
6
6
|
module RailsSimpleAuth
|
|
7
7
|
module Generators
|
|
8
8
|
class InstallGenerator < Rails::Generators::Base
|
|
9
9
|
include Rails::Generators::Migration
|
|
10
10
|
|
|
11
|
-
source_root File.expand_path(
|
|
11
|
+
source_root File.expand_path('templates', __dir__)
|
|
12
12
|
|
|
13
|
-
class_option :user_model, type: :string, default:
|
|
14
|
-
|
|
13
|
+
class_option :user_model, type: :string, default: 'User',
|
|
14
|
+
desc: 'Name of your User model'
|
|
15
15
|
class_option :skip_migration, type: :boolean, default: false,
|
|
16
|
-
|
|
16
|
+
desc: 'Skip generating migration'
|
|
17
17
|
|
|
18
18
|
def self.next_migration_number(dirname)
|
|
19
19
|
ActiveRecord::Generators::Base.next_migration_number(dirname)
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
def create_initializer
|
|
23
|
-
template
|
|
23
|
+
template 'initializer.rb', 'config/initializers/rails_simple_auth.rb'
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
def create_migration
|
|
27
27
|
return if options[:skip_migration]
|
|
28
28
|
|
|
29
|
-
migration_template
|
|
29
|
+
migration_template 'migration.rb', 'db/migrate/add_rails_simple_auth.rb'
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
def add_routes
|
|
33
|
-
route
|
|
33
|
+
route 'rails_simple_auth_routes'
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
def show_instructions
|
|
37
|
-
say
|
|
38
|
-
say
|
|
39
|
-
say
|
|
40
|
-
say
|
|
41
|
-
say
|
|
42
|
-
say
|
|
37
|
+
say ''
|
|
38
|
+
say 'RailsSimpleAuth installed successfully!', :green
|
|
39
|
+
say ''
|
|
40
|
+
say 'Next steps:'
|
|
41
|
+
say ' 1. Review and edit the migration: db/migrate/xxx_add_rails_simple_auth.rb'
|
|
42
|
+
say ' 2. Run: rails db:migrate'
|
|
43
43
|
say " 3. Add concerns to your #{options[:user_model]} model:"
|
|
44
|
-
say
|
|
44
|
+
say ''
|
|
45
45
|
say " class #{options[:user_model]} < ApplicationRecord"
|
|
46
|
-
say
|
|
47
|
-
say
|
|
48
|
-
say
|
|
49
|
-
say
|
|
50
|
-
say
|
|
51
|
-
say
|
|
52
|
-
say
|
|
53
|
-
say
|
|
54
|
-
say
|
|
55
|
-
say
|
|
56
|
-
say
|
|
57
|
-
say
|
|
58
|
-
say
|
|
59
|
-
say
|
|
60
|
-
say
|
|
61
|
-
say
|
|
46
|
+
say ' include RailsSimpleAuth::Models::Concerns::Authenticatable'
|
|
47
|
+
say ' include RailsSimpleAuth::Models::Concerns::Confirmable # optional'
|
|
48
|
+
say ' include RailsSimpleAuth::Models::Concerns::MagicLinkable # optional'
|
|
49
|
+
say ' include RailsSimpleAuth::Models::Concerns::OAuthConnectable # optional'
|
|
50
|
+
say ' end'
|
|
51
|
+
say ''
|
|
52
|
+
say ' 4. Add before_action to protect routes:'
|
|
53
|
+
say ''
|
|
54
|
+
say ' class ApplicationController < ActionController::Base'
|
|
55
|
+
say ' before_action :require_authentication'
|
|
56
|
+
say ' end'
|
|
57
|
+
say ''
|
|
58
|
+
say 'Optional generators:'
|
|
59
|
+
say ' rails generate rails_simple_auth:views # Copy views for customization'
|
|
60
|
+
say ' rails generate rails_simple_auth:css # Copy CSS for styling'
|
|
61
|
+
say ''
|
|
62
62
|
end
|
|
63
63
|
end
|
|
64
64
|
end
|
|
@@ -58,14 +58,14 @@ RailsSimpleAuth.configure do |config|
|
|
|
58
58
|
# ============================================================================
|
|
59
59
|
|
|
60
60
|
# Layout to use for auth pages (default: "application")
|
|
61
|
-
config.layout =
|
|
61
|
+
config.layout = 'application'
|
|
62
62
|
|
|
63
63
|
# ============================================================================
|
|
64
64
|
# Mailer
|
|
65
65
|
# ============================================================================
|
|
66
66
|
|
|
67
67
|
# From address for auth emails
|
|
68
|
-
config.mailer_sender = ENV.fetch(
|
|
68
|
+
config.mailer_sender = ENV.fetch('MAILER_FROM', 'noreply@example.com')
|
|
69
69
|
|
|
70
70
|
# Custom mailer class (must implement confirmation, magic_link, password_reset methods)
|
|
71
71
|
# config.mailer_class = "RailsSimpleAuth::AuthMailer"
|
|
@@ -75,7 +75,7 @@ RailsSimpleAuth.configure do |config|
|
|
|
75
75
|
# ============================================================================
|
|
76
76
|
|
|
77
77
|
# Your user model class name
|
|
78
|
-
config.user_class_name =
|
|
78
|
+
config.user_class_name = '<%= options[:user_model] %>'
|
|
79
79
|
|
|
80
80
|
# Custom session model (if you want to use your own)
|
|
81
81
|
# config.session_class_name = "RailsSimpleAuth::Session"
|
|
@@ -11,7 +11,7 @@ class AddRailsSimpleAuth < ActiveRecord::Migration[8.0]
|
|
|
11
11
|
# Uncomment and modify as needed:
|
|
12
12
|
|
|
13
13
|
# Required fields for authentication
|
|
14
|
-
# add_column :users, :
|
|
14
|
+
# add_column :users, :email, :string, null: false
|
|
15
15
|
# add_column :users, :password_digest, :string, null: false
|
|
16
16
|
|
|
17
17
|
# Email confirmation (optional - if using Confirmable concern)
|
|
@@ -22,7 +22,7 @@ class AddRailsSimpleAuth < ActiveRecord::Migration[8.0]
|
|
|
22
22
|
# add_column :users, :admin, :boolean, default: false
|
|
23
23
|
|
|
24
24
|
# Indexes
|
|
25
|
-
# add_index :users, :
|
|
25
|
+
# add_index :users, :email, unique: true
|
|
26
26
|
# add_index :users, :confirmed_at
|
|
27
27
|
|
|
28
28
|
# ============================================================================
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
Description:
|
|
2
|
+
Creates a migration to add temporary user support to your User model.
|
|
3
|
+
Temporary users allow guest/demo user flows where visitors can try
|
|
4
|
+
your app without signing up, then convert to permanent accounts.
|
|
5
|
+
|
|
6
|
+
Example:
|
|
7
|
+
bin/rails generate rails_simple_auth:temporary_users
|
|
8
|
+
|
|
9
|
+
This will create:
|
|
10
|
+
db/migrate/YYYYMMDDHHMMSS_add_temporary_to_users.rb
|
|
11
|
+
|
|
12
|
+
After running the migration, include the concern in your User model:
|
|
13
|
+
include RailsSimpleAuth::Models::Concerns::TemporaryUser
|
|
14
|
+
|
|
15
|
+
And enable in your initializer:
|
|
16
|
+
config.temporary_users_enabled = true
|
|
17
|
+
|
|
18
|
+
The concern provides:
|
|
19
|
+
- temporary? / permanent? methods
|
|
20
|
+
- temporary / permanent / temporary_expired scopes
|
|
21
|
+
- convert_to_permanent!(email:, password:) for account conversion
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class AddTemporaryToUsers < ActiveRecord::Migration[<%= Rails::VERSION::MAJOR %>.<%= Rails::VERSION::MINOR %>]
|
|
4
|
+
def change
|
|
5
|
+
add_column :users, :temporary, :boolean, default: false, null: false
|
|
6
|
+
add_index :users, [:temporary, :created_at], name: "index_users_on_temporary_and_created_at"
|
|
7
|
+
end
|
|
8
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails/generators'
|
|
4
|
+
require 'rails/generators/active_record'
|
|
5
|
+
|
|
6
|
+
module RailsSimpleAuth
|
|
7
|
+
module Generators
|
|
8
|
+
class TemporaryUsersGenerator < Rails::Generators::Base
|
|
9
|
+
include Rails::Generators::Migration
|
|
10
|
+
|
|
11
|
+
source_root File.expand_path('templates', __dir__)
|
|
12
|
+
|
|
13
|
+
desc 'Creates a migration to add temporary user support to your User model'
|
|
14
|
+
|
|
15
|
+
def self.next_migration_number(dirname)
|
|
16
|
+
ActiveRecord::Generators::Base.next_migration_number(dirname)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def create_migration_file
|
|
20
|
+
migration_template 'add_temporary_to_users.rb.erb',
|
|
21
|
+
'db/migrate/add_temporary_to_users.rb'
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def show_instructions
|
|
25
|
+
say ''
|
|
26
|
+
say 'Temporary users migration created!', :green
|
|
27
|
+
say ''
|
|
28
|
+
say 'Next steps:', :yellow
|
|
29
|
+
say ' 1. Run: bin/rails db:migrate'
|
|
30
|
+
say ''
|
|
31
|
+
say ' 2. Include the concern in your User model:'
|
|
32
|
+
say ' include RailsSimpleAuth::Models::Concerns::TemporaryUser'
|
|
33
|
+
say ''
|
|
34
|
+
say ' 3. Enable in your initializer:'
|
|
35
|
+
say ' config.temporary_users_enabled = true'
|
|
36
|
+
say ''
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
3
|
+
require 'rails/generators'
|
|
4
4
|
|
|
5
5
|
module RailsSimpleAuth
|
|
6
6
|
module Generators
|
|
7
7
|
class ViewsGenerator < Rails::Generators::Base
|
|
8
|
-
source_root File.expand_path(
|
|
8
|
+
source_root File.expand_path('../../../../app/views/rails_simple_auth', __dir__)
|
|
9
9
|
|
|
10
10
|
class_option :only, type: :array, default: [],
|
|
11
|
-
|
|
11
|
+
desc: 'Only copy specific view directories (sessions, registrations, passwords, confirmations, mailers)'
|
|
12
12
|
|
|
13
13
|
def copy_views
|
|
14
14
|
view_directories.each do |dir|
|
|
15
15
|
directory dir, "app/views/rails_simple_auth/#{dir}"
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
-
say
|
|
19
|
-
say
|
|
20
|
-
say
|
|
21
|
-
say
|
|
18
|
+
say ''
|
|
19
|
+
say 'Views copied to app/views/rails_simple_auth/', :green
|
|
20
|
+
say ''
|
|
21
|
+
say 'You can now customize these views. Rails will use your local copies'
|
|
22
22
|
say "instead of the gem's views."
|
|
23
|
-
say
|
|
23
|
+
say ''
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
private
|
|
@@ -10,14 +10,17 @@ module RailsSimpleAuth
|
|
|
10
10
|
:mailer_sender, :mailer_class,
|
|
11
11
|
:user_class_name, :session_class_name,
|
|
12
12
|
:password_minimum_length,
|
|
13
|
-
:after_sign_in_callback, :after_sign_out_callback, :after_sign_up_callback, :after_confirmation_callback
|
|
13
|
+
:after_sign_in_callback, :after_sign_out_callback, :after_sign_up_callback, :after_confirmation_callback,
|
|
14
|
+
:temporary_users_enabled
|
|
15
|
+
|
|
16
|
+
attr_reader :temporary_user_cleanup_days
|
|
14
17
|
|
|
15
18
|
def initialize
|
|
16
19
|
@magic_link_enabled = true
|
|
17
20
|
@email_confirmation_enabled = true
|
|
18
21
|
@oauth_enabled = false
|
|
19
22
|
@oauth_providers = []
|
|
20
|
-
@oauth_link_existing_accounts = true
|
|
23
|
+
@oauth_link_existing_accounts = true # Allow OAuth to link to existing email accounts
|
|
21
24
|
|
|
22
25
|
@magic_link_expiry = 15.minutes
|
|
23
26
|
@password_reset_expiry = 15.minutes
|
|
@@ -37,14 +40,14 @@ module RailsSimpleAuth
|
|
|
37
40
|
@after_sign_up_path = :root_path
|
|
38
41
|
@after_confirmation_path = :new_session_path
|
|
39
42
|
|
|
40
|
-
@layout =
|
|
43
|
+
@layout = 'rails_simple_auth'
|
|
41
44
|
@app_name = nil
|
|
42
45
|
|
|
43
|
-
@mailer_sender =
|
|
44
|
-
@mailer_class =
|
|
46
|
+
@mailer_sender = 'noreply@example.com'
|
|
47
|
+
@mailer_class = 'RailsSimpleAuth::AuthMailer'
|
|
45
48
|
|
|
46
|
-
@user_class_name =
|
|
47
|
-
@session_class_name =
|
|
49
|
+
@user_class_name = 'User'
|
|
50
|
+
@session_class_name = 'RailsSimpleAuth::Session'
|
|
48
51
|
|
|
49
52
|
@password_minimum_length = 8
|
|
50
53
|
|
|
@@ -52,6 +55,9 @@ module RailsSimpleAuth
|
|
|
52
55
|
@after_sign_out_callback = nil
|
|
53
56
|
@after_sign_up_callback = nil
|
|
54
57
|
@after_confirmation_callback = nil
|
|
58
|
+
|
|
59
|
+
@temporary_users_enabled = false
|
|
60
|
+
@temporary_user_cleanup_days = 7
|
|
55
61
|
end
|
|
56
62
|
|
|
57
63
|
def user_class
|
|
@@ -93,5 +99,13 @@ module RailsSimpleAuth
|
|
|
93
99
|
def rate_limit_for(action)
|
|
94
100
|
rate_limits&.dig(action.to_sym)
|
|
95
101
|
end
|
|
102
|
+
|
|
103
|
+
def temporary_user_cleanup_days=(value)
|
|
104
|
+
unless value.is_a?(Integer) && value.positive?
|
|
105
|
+
raise ConfigurationError, 'temporary_user_cleanup_days must be a positive integer'
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
@temporary_user_cleanup_days = value
|
|
109
|
+
end
|
|
96
110
|
end
|
|
97
111
|
end
|