Skip to content

Commit 964ae8e

Browse files
authored
Change unconfirmed user login behaviour (mastodon#11375)
Allow access to account settings, 2FA, authorized applications, and account deletions to unconfirmed and pending users, as well as users who had their accounts disabled. Suspended users cannot update their e-mail or password or delete their account. Display account status on account settings page, for example, when an account is frozen, limited, unconfirmed or pending review. After sign up, login users straight away and show a simple page that tells them the status of their account with links to account settings and logout, to reduce onboarding friction and allow users to correct wrongly typed e-mail addresses. Move the final sign-up step of SSO integrations to be the same as above to reduce code duplication.
1 parent fea903f commit 964ae8e

35 files changed

Lines changed: 298 additions & 148 deletions

app/controllers/about_controller.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ class AboutController < ApplicationController
77
before_action :set_instance_presenter
88
before_action :set_expires_in
99

10-
skip_before_action :check_user_permissions, only: [:more, :terms]
10+
skip_before_action :require_functional!, only: [:more, :terms]
1111

1212
def show; end
1313

app/controllers/api/base_controller.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ class Api::BaseController < ApplicationController
77
include RateLimitHeaders
88

99
skip_before_action :store_current_location
10-
skip_before_action :check_user_permissions
10+
skip_before_action :require_functional!
1111

1212
before_action :set_cache_headers
1313

app/controllers/application_controller.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class ApplicationController < ActionController::Base
2525
rescue_from Mastodon::NotPermittedError, with: :forbidden
2626

2727
before_action :store_current_location, except: :raise_not_found, unless: :devise_controller?
28-
before_action :check_user_permissions, if: :user_signed_in?
28+
before_action :require_functional!, if: :user_signed_in?
2929

3030
def raise_not_found
3131
raise ActionController::RoutingError, "No route matches #{params[:unmatched_route]}"
@@ -57,8 +57,8 @@ def require_staff!
5757
forbidden unless current_user&.staff?
5858
end
5959

60-
def check_user_permissions
61-
forbidden if current_user.disabled? || current_user.account.suspended?
60+
def require_functional!
61+
redirect_to edit_user_registration_path unless current_user.functional?
6262
end
6363

6464
def after_sign_out_path_for(_resource_or_scope)

app/controllers/auth/confirmations_controller.rb

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,34 +4,15 @@ class Auth::ConfirmationsController < Devise::ConfirmationsController
44
layout 'auth'
55

66
before_action :set_body_classes
7-
before_action :set_user, only: [:finish_signup]
87

9-
def finish_signup
10-
return unless request.patch? && params[:user]
11-
12-
if @user.update(user_params)
13-
@user.skip_reconfirmation!
14-
bypass_sign_in(@user)
15-
redirect_to root_path, notice: I18n.t('devise.confirmations.send_instructions')
16-
else
17-
@show_errors = true
18-
end
19-
end
8+
skip_before_action :require_functional!
209

2110
private
2211

23-
def set_user
24-
@user = current_user
25-
end
26-
2712
def set_body_classes
2813
@body_classes = 'lighter'
2914
end
3015

31-
def user_params
32-
params.require(:user).permit(:email)
33-
end
34-
3516
def after_confirmation_path_for(_resource_name, user)
3617
if user.created_by_application && truthy_param?(:redirect_to_app)
3718
user.created_by_application.redirect_uri

app/controllers/auth/omniauth_callbacks_controller.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ def after_sign_in_path_for(resource)
2727
if resource.email_verified?
2828
root_path
2929
else
30-
finish_signup_path
30+
auth_setup_path(missing_email: '1')
3131
end
3232
end
3333
end

app/controllers/auth/registrations_controller.rb

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ class Auth::RegistrationsController < Devise::RegistrationsController
99
before_action :set_sessions, only: [:edit, :update]
1010
before_action :set_instance_presenter, only: [:new, :create, :update]
1111
before_action :set_body_classes, only: [:new, :create, :edit, :update]
12+
before_action :require_not_suspended!, only: [:update]
13+
14+
skip_before_action :require_functional!, only: [:edit, :update]
1215

1316
def new
1417
super(&:build_invite_request)
@@ -43,7 +46,7 @@ def configure_sign_up_params
4346
end
4447

4548
def after_sign_up_path_for(_resource)
46-
new_user_session_path
49+
auth_setup_path
4750
end
4851

4952
def after_sign_in_path_for(_resource)
@@ -102,4 +105,8 @@ def determine_layout
102105
def set_sessions
103106
@sessions = current_user.session_activations
104107
end
108+
109+
def require_not_suspended!
110+
forbidden if current_account.suspended?
111+
end
105112
end

app/controllers/auth/sessions_controller.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@ class Auth::SessionsController < Devise::SessionsController
66
layout 'auth'
77

88
skip_before_action :require_no_authentication, only: [:create]
9-
skip_before_action :check_user_permissions, only: [:destroy]
9+
skip_before_action :require_functional!
10+
1011
prepend_before_action :authenticate_with_two_factor, if: :two_factor_enabled?, only: [:create]
12+
1113
before_action :set_instance_presenter, only: [:new]
1214
before_action :set_body_classes
1315

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# frozen_string_literal: true
2+
3+
class Auth::SetupController < ApplicationController
4+
layout 'auth'
5+
6+
before_action :authenticate_user!
7+
before_action :require_unconfirmed_or_pending!
8+
before_action :set_body_classes
9+
before_action :set_user
10+
11+
skip_before_action :require_functional!
12+
13+
def show
14+
flash.now[:notice] = begin
15+
if @user.pending?
16+
I18n.t('devise.registrations.signed_up_but_pending')
17+
else
18+
I18n.t('devise.registrations.signed_up_but_unconfirmed')
19+
end
20+
end
21+
end
22+
23+
def update
24+
# This allows updating the e-mail without entering a password as is required
25+
# on the account settings page; however, we only allow this for accounts
26+
# that were not confirmed yet
27+
28+
if @user.update(user_params)
29+
redirect_to auth_setup_path, notice: I18n.t('devise.confirmations.send_instructions')
30+
else
31+
render :show
32+
end
33+
end
34+
35+
helper_method :missing_email?
36+
37+
private
38+
39+
def require_unconfirmed_or_pending!
40+
redirect_to root_path if current_user.confirmed? && current_user.approved?
41+
end
42+
43+
def set_user
44+
@user = current_user
45+
end
46+
47+
def set_body_classes
48+
@body_classes = 'lighter'
49+
end
50+
51+
def user_params
52+
params.require(:user).permit(:email)
53+
end
54+
55+
def missing_email?
56+
truthy_param?(:missing_email)
57+
end
58+
end

app/controllers/oauth/authorized_applications_controller.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ class Oauth::AuthorizedApplicationsController < Doorkeeper::AuthorizedApplicatio
77
before_action :authenticate_resource_owner!
88
before_action :set_body_classes
99

10+
skip_before_action :require_functional!
11+
1012
include Localized
1113

1214
def destroy

app/controllers/settings/deletes_controller.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ class Settings::DeletesController < Settings::BaseController
55

66
before_action :check_enabled_deletion
77
before_action :authenticate_user!
8+
before_action :require_not_suspended!
9+
10+
skip_before_action :require_functional!
811

912
def show
1013
@confirmation = Form::DeleteConfirmation.new
@@ -29,4 +32,8 @@ def check_enabled_deletion
2932
def delete_params
3033
params.require(:form_delete_confirmation).permit(:password)
3134
end
35+
36+
def require_not_suspended!
37+
forbidden if current_account.suspended?
38+
end
3239
end

0 commit comments

Comments
 (0)