From e60414792d86a99c0f401f3c1bab92ee37835d39 Mon Sep 17 00:00:00 2001
From: Claire <claire.github-309c@sitedethib.com>
Date: Tue, 16 May 2023 18:03:52 +0200
Subject: [PATCH] Add polling and automatic redirection to `/start` on email
 confirmation (#25013)

---
 .../api/v1/emails/confirmations_controller.rb | 11 ++-
 app/javascript/packs/sign_up.js               | 15 ++++
 app/views/auth/setup/show.html.haml           |  2 +
 config/routes/api.rb                          |  1 +
 .../emails/confirmations_controller_spec.rb   | 68 +++++++++++++++++++
 5 files changed, 94 insertions(+), 3 deletions(-)
 create mode 100644 app/javascript/packs/sign_up.js

diff --git a/app/controllers/api/v1/emails/confirmations_controller.rb b/app/controllers/api/v1/emails/confirmations_controller.rb
index 32fb8e39fa..29ff897b91 100644
--- a/app/controllers/api/v1/emails/confirmations_controller.rb
+++ b/app/controllers/api/v1/emails/confirmations_controller.rb
@@ -1,9 +1,10 @@
 # frozen_string_literal: true
 
 class Api::V1::Emails::ConfirmationsController < Api::BaseController
-  before_action -> { doorkeeper_authorize! :write, :'write:accounts' }
-  before_action :require_user_owned_by_application!
-  before_action :require_user_not_confirmed!
+  before_action -> { authorize_if_got_token! :read, :'read:accounts' }, only: :check
+  before_action -> { doorkeeper_authorize! :write, :'write:accounts' }, except: :check
+  before_action :require_user_owned_by_application!, except: :check
+  before_action :require_user_not_confirmed!, except: :check
 
   def create
     current_user.update!(email: params[:email]) if params.key?(:email)
@@ -12,6 +13,10 @@ class Api::V1::Emails::ConfirmationsController < Api::BaseController
     render_empty
   end
 
+  def check
+    render json: current_user.confirmed?
+  end
+
   private
 
   def require_user_owned_by_application!
diff --git a/app/javascript/packs/sign_up.js b/app/javascript/packs/sign_up.js
new file mode 100644
index 0000000000..260e404eb7
--- /dev/null
+++ b/app/javascript/packs/sign_up.js
@@ -0,0 +1,15 @@
+import './public-path';
+import ready from '../mastodon/ready';
+import axios from 'axios';
+
+ready(() => {
+  setInterval(() => {
+    axios.get('/api/v1/emails/check_confirmation').then((response) => {
+      if (response.data) {
+        window.location = '/start';
+      }
+    }).catch(error => {
+      console.error(error);
+    });
+  }, 5000);
+});
diff --git a/app/views/auth/setup/show.html.haml b/app/views/auth/setup/show.html.haml
index 913b0c9132..64deca3345 100644
--- a/app/views/auth/setup/show.html.haml
+++ b/app/views/auth/setup/show.html.haml
@@ -1,6 +1,8 @@
 - content_for :page_title do
   = t('auth.setup.title')
 
+= javascript_pack_tag 'sign_up', crossorigin: 'anonymous'
+
 = simple_form_for(@user, url: auth_setup_path) do |f|
   = render 'auth/shared/progress', stage: 'confirm'
 
diff --git a/config/routes/api.rb b/config/routes/api.rb
index 91d5def821..19c583b3e1 100644
--- a/config/routes/api.rb
+++ b/config/routes/api.rb
@@ -109,6 +109,7 @@ namespace :api, format: false do
 
     namespace :emails do
       resources :confirmations, only: [:create]
+      get :check_confirmation, to: 'confirmations#check'
     end
 
     resource :instance, only: [:show] do
diff --git a/spec/controllers/api/v1/emails/confirmations_controller_spec.rb b/spec/controllers/api/v1/emails/confirmations_controller_spec.rb
index 2a0703ed9c..219b5075df 100644
--- a/spec/controllers/api/v1/emails/confirmations_controller_spec.rb
+++ b/spec/controllers/api/v1/emails/confirmations_controller_spec.rb
@@ -63,4 +63,72 @@ RSpec.describe Api::V1::Emails::ConfirmationsController do
       end
     end
   end
+
+  describe '#check' do
+    let(:scopes) { 'read' }
+
+    context 'with an oauth token' do
+      before do
+        allow(controller).to receive(:doorkeeper_token) { token }
+      end
+
+      context 'when the account is not confirmed' do
+        it 'returns http success' do
+          get :check
+          expect(response).to have_http_status(200)
+        end
+
+        it 'returns false' do
+          get :check
+          expect(body_as_json).to be false
+        end
+      end
+
+      context 'when the account is confirmed' do
+        let(:confirmed_at) { Time.now.utc }
+
+        it 'returns http success' do
+          get :check
+          expect(response).to have_http_status(200)
+        end
+
+        it 'returns true' do
+          get :check
+          expect(body_as_json).to be true
+        end
+      end
+    end
+
+    context 'with an authentication cookie' do
+      before do
+        sign_in user, scope: :user
+      end
+
+      context 'when the account is not confirmed' do
+        it 'returns http success' do
+          get :check
+          expect(response).to have_http_status(200)
+        end
+
+        it 'returns false' do
+          get :check
+          expect(body_as_json).to be false
+        end
+      end
+
+      context 'when the account is confirmed' do
+        let(:confirmed_at) { Time.now.utc }
+
+        it 'returns http success' do
+          get :check
+          expect(response).to have_http_status(200)
+        end
+
+        it 'returns true' do
+          get :check
+          expect(body_as_json).to be true
+        end
+      end
+    end
+  end
 end
-- 
GitLab