diff --git a/static/js/channel.js b/static/js/channel.js index d7e70c62c1..7f728096c4 100644 --- a/static/js/channel.js +++ b/static/js/channel.js @@ -1,7 +1,9 @@ import $ from "jquery"; import * as blueslip from "./blueslip"; +import {page_params} from "./page_params"; import * as reload_state from "./reload_state"; +import * as setup from "./setup"; const pending_requests = []; @@ -52,7 +54,28 @@ function call(args, idempotent) { return; } - if (xhr.status === 403) { + if (xhr.status === 401) { + if ( + setup.password_change_in_progress || + setup.xhr_password_changes.get(xhr) !== setup.password_changes + ) { + // The backend for handling password change API requests + // will replace the user's session; this results in a + // brief race where any API request will fail with a 401 + // error after the old session is deactivated but before + // the new one has been propagated to the browser. So we + // skip our normal HTTP 401 error handling if we're in the + // process of executing a password change. + return; + } + + // We got logged out somehow, perhaps from another window + // changing the user's password, or a session timeout. We + // could display an error message, but jumping right to + // the login page conveys the same information with a + // smoother relogin experience. + window.location.replace(page_params.login_page); + } else if (xhr.status === 403) { try { if ( JSON.parse(xhr.responseText).code === "CSRF_FAILED" && diff --git a/static/js/setup.js b/static/js/setup.js index edddc4bca7..7ccf4bb863 100644 --- a/static/js/setup.js +++ b/static/js/setup.js @@ -8,7 +8,7 @@ import * as util from "./util"; // Miscellaneous early setup. export let password_change_in_progress = false; export let password_changes = 0; -const xhr_password_changes = new WeakMap(); +export const xhr_password_changes = new WeakMap(); export function set_password_change_in_progress(value) { password_change_in_progress = value; @@ -55,29 +55,6 @@ $(() => { xhr_password_changes.set(xhr, password_changes); }); - // For some reason, jQuery wants this to be attached to an element. - $(document).ajaxError((event, xhr) => { - if (password_change_in_progress || xhr_password_changes.get(xhr) !== password_changes) { - // The backend for handling password change API requests - // will replace the user's session; this results in a - // brief race where any API request will fail with a 401 - // error after the old session is deactivated but before - // the new one has been propagated to the browser. So we - // skip our normal HTTP 401 error handling if we're in the - // process of executing a password change. - return; - } - - if (xhr.status === 401) { - // We got logged out somehow, perhaps from another window - // changing the user's password, or a session timeout. We - // could display an error message, but jumping right to - // the login page conveys the same information with a - // smoother re-login experience. - window.location.replace(page_params.login_page); - } - }); - $.fn.expectOne = function () { if (blueslip && this.length !== 1) { blueslip.error("Expected one element in jQuery set, " + this.length + " found"); diff --git a/tools/test-js-with-node b/tools/test-js-with-node index 89d1d82d91..9c29b2feaa 100755 --- a/tools/test-js-with-node +++ b/tools/test-js-with-node @@ -45,6 +45,7 @@ EXEMPT_FILES = { "static/js/billing/upgrade.js", "static/js/blueslip.ts", "static/js/blueslip_stacktrace.ts", + "static/js/channel.js", "static/js/click_handlers.js", "static/js/compose_actions.js", "static/js/compose_closed_ui.js",