Skip to content

Commit cb3ca8f

Browse files
authored
Merge pull request #1759 from basecamp/split-signin-and-signup
Split sign in and sign up
2 parents 3c6203d + fd06e5d commit cb3ca8f

24 files changed

+190
-95
lines changed

Gemfile.saas.lock

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
GIT
22
remote: https://github.com/basecamp/fizzy-saas
3-
revision: 7f392bbbf9f5170d334b6ee2f6d240569bd157ed
3+
revision: f80da3c2faf34b94d65a41a501f19e8dba379012
44
specs:
55
fizzy-saas (0.1.0)
66
prometheus-client-mmap
@@ -52,7 +52,7 @@ GIT
5252

5353
GIT
5454
remote: https://github.com/rails/rails.git
55-
revision: 4f7ab01bb5d6be78c7447dbb230c55027d08ae34
55+
revision: 690ec8898318b8f50714e86676353ebe1551261e
5656
branch: main
5757
specs:
5858
actioncable (8.2.0.alpha)
@@ -423,7 +423,7 @@ GEM
423423
rake-compiler-dock (1.9.1)
424424
rb_sys (0.9.117)
425425
rake-compiler-dock (= 1.9.1)
426-
rdoc (6.15.1)
426+
rdoc (6.16.1)
427427
erb
428428
psych (>= 4.0.0)
429429
tsort
@@ -479,10 +479,10 @@ GEM
479479
rexml (~> 3.2, >= 3.2.5)
480480
rubyzip (>= 1.2.2, < 4.0)
481481
websocket (~> 1.0)
482-
sentry-rails (6.1.1)
482+
sentry-rails (6.2.0)
483483
railties (>= 5.2.0)
484-
sentry-ruby (~> 6.1.1)
485-
sentry-ruby (6.1.1)
484+
sentry-ruby (~> 6.2.0)
485+
sentry-ruby (6.2.0)
486486
bigdecimal
487487
concurrent-ruby (~> 1.0, >= 1.0.2)
488488
sniffer (0.5.0)

app/controllers/sessions/magic_links_controller.rb

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ def show
99
end
1010

1111
def create
12-
if identity = MagicLink.consume(code)
13-
start_new_session_for identity
14-
redirect_to after_authentication_url
12+
if magic_link = MagicLink.consume(code)
13+
start_new_session_for magic_link.identity
14+
redirect_to after_sign_in_url(magic_link)
1515
else
1616
redirect_to session_magic_link_path, alert: "Try another code."
1717
end
@@ -21,4 +21,12 @@ def create
2121
def code
2222
params.expect(:code)
2323
end
24+
25+
def after_sign_in_url(magic_link)
26+
if magic_link.for_sign_up?
27+
new_signup_completion_path
28+
else
29+
after_authentication_url
30+
end
31+
end
2432
end
Lines changed: 4 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,4 @@
11
class SessionsController < ApplicationController
2-
# FIXME: Remove this before launch!
3-
unless Rails.env.local?
4-
http_basic_authenticate_with \
5-
name: Rails.application.credentials.account_signup_http_basic_auth.name,
6-
password: Rails.application.credentials.account_signup_http_basic_auth.password,
7-
realm: "Fizzy Signup",
8-
only: :create, unless: -> { Identity.exists?(email_address: email_address) }
9-
end
10-
112
disallow_account_scope
123
require_unauthenticated_access except: :destroy
134
rate_limit to: 10, within: 3.minutes, only: :create, with: -> { redirect_to new_session_path, alert: "Try again later." }
@@ -19,10 +10,11 @@ def new
1910

2011
def create
2112
if identity = Identity.find_by_email_address(email_address)
22-
handle_existing_user(identity)
23-
elsif
24-
handle_new_signup
13+
magic_link = identity.send_magic_link
14+
flash[:magic_link_code] = magic_link&.code if Rails.env.development?
2515
end
16+
17+
redirect_to session_magic_link_path
2618
end
2719

2820
def destroy
@@ -34,16 +26,4 @@ def destroy
3426
def email_address
3527
params.expect(:email_address)
3628
end
37-
38-
def handle_existing_user(identity)
39-
magic_link = identity.send_magic_link
40-
flash[:magic_link_code] = magic_link&.code if Rails.env.development?
41-
redirect_to session_magic_link_path
42-
end
43-
44-
def handle_new_signup
45-
Signup.new(email_address: email_address).create_identity
46-
session[:return_to_after_authenticating] = new_signup_completion_path
47-
redirect_to session_magic_link_path
48-
end
4929
end

app/controllers/signup/completions_controller.rb renamed to app/controllers/signups/completions_controller.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
class Signup::CompletionsController < ApplicationController
1+
class Signups::CompletionsController < ApplicationController
22
layout "public"
33

44
disallow_account_scope
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
class SignupsController < ApplicationController
2+
# FIXME: Remove this before launch!
3+
unless Rails.env.local?
4+
http_basic_authenticate_with \
5+
name: Rails.application.credentials.account_signup_http_basic_auth.name,
6+
password: Rails.application.credentials.account_signup_http_basic_auth.password,
7+
realm: "Fizzy Signup"
8+
end
9+
10+
disallow_account_scope
11+
allow_unauthenticated_access
12+
rate_limit to: 10, within: 3.minutes, only: :create, with: -> { redirect_to new_signup_path, alert: "Try again later." }
13+
before_action :redirect_authenticated_user
14+
15+
layout "public"
16+
17+
def new
18+
@signup = Signup.new
19+
end
20+
21+
def create
22+
Signup.new(signup_params).create_identity
23+
redirect_to session_magic_link_path
24+
end
25+
26+
private
27+
def redirect_authenticated_user
28+
redirect_to new_signup_completion_path if authenticated?
29+
end
30+
31+
def signup_params
32+
params.expect signup: :email_address
33+
end
34+
end

app/models/identity.rb

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@ class Identity < ApplicationRecord
1212

1313
normalizes :email_address, with: ->(value) { value.strip.downcase.presence }
1414

15-
def send_magic_link
16-
magic_links.create!.tap do |magic_link|
15+
def send_magic_link(**attributes)
16+
attributes[:purpose] = attributes.delete(:for) if attributes.key?(:for)
17+
18+
magic_links.create!(attributes).tap do |magic_link|
1719
MagicLinkMailer.sign_in_instructions(magic_link).deliver_later
1820
end
1921
end

app/models/magic_link.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ class MagicLink < ApplicationRecord
44

55
belongs_to :identity
66

7+
enum :purpose, %w[ sign_in sign_up ], prefix: :for, default: :sign_in
8+
79
scope :active, -> { where(expires_at: Time.current...) }
810
scope :stale, -> { where(expires_at: ..Time.current) }
911

@@ -24,7 +26,7 @@ def cleanup
2426

2527
def consume
2628
destroy
27-
identity
29+
self
2830
end
2931

3032
private

app/models/signup.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ def initialize(...)
1818

1919
def create_identity
2020
@identity = Identity.find_or_create_by!(email_address: email_address)
21-
@identity.send_magic_link
21+
@identity.send_magic_link for: :sign_up
2222
end
2323

2424
def complete

app/views/mailers/magic_link_mailer/sign_in_instructions.html.erb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
<% if @identity.users.any? %>
2+
<% if @magic_link.for_sign_in? %>
33
<h1 class="title">Fizzy verification code</h1>
44
<p class="subtitle">Please enter this 6-character verification code on the Fizzy sign-in page:</p>
55
<% else %>

app/views/mailers/magic_link_mailer/sign_in_instructions.text.erb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<% if @identity.users.any? %>
1+
<% if @magic_link.for_sign_in? %>
22
Please enter this 6-character verification code on the Fizzy sign-in page:
33
<% else %>
44
Please enter this 6-character verification code on the Fizzy sign-up page to create your new account:

0 commit comments

Comments
 (0)