Fix log out from user menu not working on Safari (#31402)
This commit is contained in:
parent
2b1670da48
commit
c3e1d86d58
5 changed files with 102 additions and 34 deletions
|
@ -187,4 +187,15 @@ class Auth::SessionsController < Devise::SessionsController
|
||||||
def second_factor_attempts_key(user)
|
def second_factor_attempts_key(user)
|
||||||
"2fa_auth_attempts:#{user.id}:#{Time.now.utc.hour}"
|
"2fa_auth_attempts:#{user.id}:#{Time.now.utc.hour}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def respond_to_on_destroy
|
||||||
|
respond_to do |format|
|
||||||
|
format.json do
|
||||||
|
render json: {
|
||||||
|
redirect_to: after_sign_out_path_for(resource_name),
|
||||||
|
}, status: 200
|
||||||
|
end
|
||||||
|
format.all { super }
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -25,7 +25,7 @@ export const ConfirmLogOutModal: React.FC<BaseConfirmationModalProps> = ({
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
const onConfirm = useCallback(() => {
|
const onConfirm = useCallback(() => {
|
||||||
logOut();
|
void logOut();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -1,36 +1,20 @@
|
||||||
export const logOut = () => {
|
import api from 'mastodon/api';
|
||||||
const form = document.createElement('form');
|
|
||||||
|
|
||||||
const methodInput = document.createElement('input');
|
export async function logOut() {
|
||||||
methodInput.setAttribute('name', '_method');
|
try {
|
||||||
methodInput.setAttribute('value', 'delete');
|
const response = await api(false).delete<{ redirect_to?: string }>(
|
||||||
methodInput.setAttribute('type', 'hidden');
|
'/auth/sign_out',
|
||||||
form.appendChild(methodInput);
|
{ headers: { Accept: 'application/json' }, withCredentials: true },
|
||||||
|
);
|
||||||
|
|
||||||
const csrfToken = document.querySelector<HTMLMetaElement>(
|
if (response.status === 200 && response.data.redirect_to)
|
||||||
'meta[name=csrf-token]',
|
window.location.href = response.data.redirect_to;
|
||||||
);
|
else
|
||||||
|
console.error(
|
||||||
const csrfParam = document.querySelector<HTMLMetaElement>(
|
'Failed to log out, got an unexpected non-redirect response from the server',
|
||||||
'meta[name=csrf-param]',
|
response,
|
||||||
);
|
);
|
||||||
|
} catch (error) {
|
||||||
if (csrfParam && csrfToken) {
|
console.error('Failed to log out, response was an error', error);
|
||||||
const csrfInput = document.createElement('input');
|
|
||||||
csrfInput.setAttribute('name', csrfParam.content);
|
|
||||||
csrfInput.setAttribute('value', csrfToken.content);
|
|
||||||
csrfInput.setAttribute('type', 'hidden');
|
|
||||||
form.appendChild(csrfInput);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
const submitButton = document.createElement('input');
|
|
||||||
submitButton.setAttribute('type', 'submit');
|
|
||||||
form.appendChild(submitButton);
|
|
||||||
|
|
||||||
form.method = 'post';
|
|
||||||
form.action = '/auth/sign_out';
|
|
||||||
form.style.display = 'none';
|
|
||||||
|
|
||||||
document.body.appendChild(form);
|
|
||||||
submitButton.click();
|
|
||||||
};
|
|
||||||
|
|
30
spec/requests/log_out_spec.rb
Normal file
30
spec/requests/log_out_spec.rb
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
describe 'Log Out' do
|
||||||
|
include RoutingHelper
|
||||||
|
|
||||||
|
describe 'DELETE /auth/sign_out' do
|
||||||
|
let(:user) { Fabricate(:user) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
sign_in user
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'Logs out the user and redirect' do
|
||||||
|
delete '/auth/sign_out'
|
||||||
|
|
||||||
|
expect(response).to redirect_to('/auth/sign_in')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'Logs out the user and return a page to redirect to with a JSON request' do
|
||||||
|
delete '/auth/sign_out', headers: { 'HTTP_ACCEPT' => 'application/json' }
|
||||||
|
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
expect(response.media_type).to eq 'application/json'
|
||||||
|
|
||||||
|
expect(body_as_json[:redirect_to]).to eq '/auth/sign_in'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
43
spec/system/log_out_spec.rb
Normal file
43
spec/system/log_out_spec.rb
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
describe 'Log out' do
|
||||||
|
include ProfileStories
|
||||||
|
|
||||||
|
before do
|
||||||
|
as_a_logged_in_user
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'Logging out from the preferences' do
|
||||||
|
it 'logs the user out' do
|
||||||
|
visit settings_path
|
||||||
|
|
||||||
|
within '.sidebar' do
|
||||||
|
click_on 'Logout'
|
||||||
|
end
|
||||||
|
|
||||||
|
expect(page).to have_title(I18n.t('auth.login'))
|
||||||
|
expect(page).to have_current_path('/auth/sign_in')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'Logging out from the JS app', :js, :streaming do
|
||||||
|
it 'logs the user out' do
|
||||||
|
visit root_path
|
||||||
|
|
||||||
|
within '.navigation-bar' do
|
||||||
|
click_on 'Menu'
|
||||||
|
end
|
||||||
|
|
||||||
|
within '.dropdown-menu' do
|
||||||
|
click_on 'Logout'
|
||||||
|
end
|
||||||
|
|
||||||
|
click_on 'Log out'
|
||||||
|
|
||||||
|
expect(page).to have_title(I18n.t('auth.login'))
|
||||||
|
expect(page).to have_current_path('/auth/sign_in')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue