0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-02-24 23:48:13 -05:00

🐛 Fixed re-authenticate modal not showing when saving in editor

closes https://github.com/TryGhost/Team/issues/865

Ghost now returns a forbidden error rather than an unauthorized error when saving whilst logged out so the session invalidation was not being triggered.

- added forbidden check to ajax service to trigger session invalidation
- added automatic retry of save in editor when re-authenticating
- fixed re-population of user and proxy services when re-authenticating, it's not needed at that point because nothing has been cleared
This commit is contained in:
Kevin Ansfield 2021-07-14 12:27:51 +01:00
parent 53d76da054
commit 8630be5a87
4 changed files with 28 additions and 9 deletions

View file

@ -1,4 +1,3 @@
import $ from 'jquery';
import ModalComponent from 'ghost-admin/components/modal-base';
import ValidationEngine from 'ghost-admin/mixins/validation-engine';
import {htmlSafe} from '@ember/template';
@ -43,7 +42,8 @@ export default ModalComponent.extend(ValidationEngine, {
_passwordConfirm() {
// Manually trigger events for input fields, ensuring legacy compatibility with
// browsers and password managers that don't send proper events on autofill
$('#login').find('input').trigger('change');
const inputs = document.querySelectorAll('#login input');
inputs.forEach(input => input.dispatchEvent(new Event('change')));
this.set('authenticationError', null);

View file

@ -284,6 +284,15 @@ export default Controller.extend({
},
toggleReAuthenticateModal() {
if (this.showReAuthenticateModal) {
// closing, re-attempt save if needed
if (this._reauthSave) {
this.saveTask.perform(this._reauthSaveOptions);
}
this._reauthSave = false;
this._reauthSaveOptions = null;
}
this.toggleProperty('showReAuthenticateModal');
},
@ -490,6 +499,12 @@ export default Controller.extend({
return post;
} catch (error) {
if (this.showReAuthenticateModal) {
this._reauthSave = true;
this._reauthSaveOptions = options;
return;
}
this.set('post.status', prevStatus);
if (error === undefined && this.post.errors.length === 0) {

View file

@ -1,7 +1,7 @@
import AjaxService from 'ember-ajax/services/ajax';
import config from 'ghost-admin/config/environment';
import moment from 'moment';
import {AjaxError, isAjaxError} from 'ember-ajax/errors';
import {AjaxError, isAjaxError, isForbiddenError} from 'ember-ajax/errors';
import {captureMessage} from '@sentry/browser';
import {get} from '@ember/object';
import {isArray as isEmberArray} from '@ember/array';
@ -279,15 +279,19 @@ let ajaxService = AjaxService.extend({
let isGhostRequest = GHOST_REQUEST.test(request.url);
let isAuthenticated = this.get('session.isAuthenticated');
let isUnauthorized = this.isUnauthorizedError(status, headers, payload);
let isForbidden = isForbiddenError(status, headers, payload);
// used when reporting connection errors, helps distinguish CDN
if (isGhostRequest) {
this._responseServer = headers.server;
}
if (isAuthenticated && isGhostRequest && isUnauthorized) {
if (isAuthenticated && isGhostRequest && (isUnauthorized || (isForbidden && payload.errors?.[0].message === 'Authorization failed'))) {
this.skipSessionDeletion = true;
this.session.invalidate();
// skip showing alert message. Wouldn't be shown if fully logged out,
// is unneeded when showing re-authenticate modal
return;
}
return this._super(...arguments);

View file

@ -56,6 +56,11 @@ export default class SessionService extends ESASessionService {
}
async handleAuthentication() {
if (this.skipAuthSuccessHandler) {
this.skipAuthSuccessHandler = false;
return;
}
try {
await this.populateUser();
} catch (err) {
@ -64,11 +69,6 @@ export default class SessionService extends ESASessionService {
await this.postAuthPreparation();
if (this.skipAuthSuccessHandler) {
this.skipAuthSuccessHandler = false;
return;
}
super.handleAuthentication('home');
}