chore: Auto reload frontend of client is out of date (#1270)
* Move editor version to header Add editor version check for API endpoints * fix: Editor update auto-reload Bump RME * fix: Only redirect if editor header exists * lint
This commit is contained in:
parent
82749ffbd8
commit
e0b33ee576
@ -1,6 +1,5 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import { action, set, observable, computed } from 'mobx';
|
import { action, set, observable, computed } from 'mobx';
|
||||||
import pkg from 'rich-markdown-editor/package.json';
|
|
||||||
import addDays from 'date-fns/add_days';
|
import addDays from 'date-fns/add_days';
|
||||||
import invariant from 'invariant';
|
import invariant from 'invariant';
|
||||||
import { client } from 'utils/ApiClient';
|
import { client } from 'utils/ApiClient';
|
||||||
@ -180,7 +179,6 @@ export default class Document extends BaseModel {
|
|||||||
try {
|
try {
|
||||||
if (isCreating) {
|
if (isCreating) {
|
||||||
return await this.store.create({
|
return await this.store.create({
|
||||||
editorVersion: pkg.version,
|
|
||||||
parentDocumentId: this.parentDocumentId,
|
parentDocumentId: this.parentDocumentId,
|
||||||
collectionId: this.collectionId,
|
collectionId: this.collectionId,
|
||||||
title: this.title,
|
title: this.title,
|
||||||
@ -194,7 +192,6 @@ export default class Document extends BaseModel {
|
|||||||
title: this.title,
|
title: this.title,
|
||||||
text: this.text,
|
text: this.text,
|
||||||
lastRevision: this.revision,
|
lastRevision: this.revision,
|
||||||
editorVersion: pkg.version,
|
|
||||||
...options,
|
...options,
|
||||||
});
|
});
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
// @flow
|
// @flow
|
||||||
|
import pkg from 'rich-markdown-editor/package.json';
|
||||||
import { map, trim } from 'lodash';
|
import { map, trim } from 'lodash';
|
||||||
import invariant from 'invariant';
|
import invariant from 'invariant';
|
||||||
import stores from 'stores';
|
import stores from 'stores';
|
||||||
@ -41,6 +42,7 @@ class ApiClient {
|
|||||||
Accept: 'application/json',
|
Accept: 'application/json',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'cache-control': 'no-cache',
|
'cache-control': 'no-cache',
|
||||||
|
'x-editor-version': pkg.version,
|
||||||
pragma: 'no-cache',
|
pragma: 'no-cache',
|
||||||
});
|
});
|
||||||
if (stores.auth.authenticated) {
|
if (stores.auth.authenticated) {
|
||||||
@ -100,6 +102,11 @@ class ApiClient {
|
|||||||
// we're trying to parse an error so JSON may not be valid
|
// we're trying to parse an error so JSON may not be valid
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (response.status === 400 && error.error === 'editor_update_required') {
|
||||||
|
window.location.reload(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
throw error;
|
throw error;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -692,12 +692,13 @@ router.post('documents.create', auth(), async ctx => {
|
|||||||
const {
|
const {
|
||||||
title = '',
|
title = '',
|
||||||
text = '',
|
text = '',
|
||||||
editorVersion,
|
|
||||||
publish,
|
publish,
|
||||||
collectionId,
|
collectionId,
|
||||||
parentDocumentId,
|
parentDocumentId,
|
||||||
index,
|
index,
|
||||||
} = ctx.body;
|
} = ctx.body;
|
||||||
|
const editorVersion = ctx.headers['x-editor-version'];
|
||||||
|
|
||||||
ctx.assertUuid(collectionId, 'collectionId must be an uuid');
|
ctx.assertUuid(collectionId, 'collectionId must be an uuid');
|
||||||
if (parentDocumentId) {
|
if (parentDocumentId) {
|
||||||
ctx.assertUuid(parentDocumentId, 'parentDocumentId must be an uuid');
|
ctx.assertUuid(parentDocumentId, 'parentDocumentId must be an uuid');
|
||||||
@ -787,10 +788,11 @@ router.post('documents.update', auth(), async ctx => {
|
|||||||
publish,
|
publish,
|
||||||
autosave,
|
autosave,
|
||||||
done,
|
done,
|
||||||
editorVersion,
|
|
||||||
lastRevision,
|
lastRevision,
|
||||||
append,
|
append,
|
||||||
} = ctx.body;
|
} = ctx.body;
|
||||||
|
const editorVersion = ctx.headers['x-editor-version'];
|
||||||
|
|
||||||
ctx.assertPresent(id, 'id is required');
|
ctx.assertPresent(id, 'id is required');
|
||||||
ctx.assertPresent(title || text, 'title or text is required');
|
ctx.assertPresent(title || text, 'title or text is required');
|
||||||
if (append) ctx.assertPresent(text, 'Text is required while appending');
|
if (append) ctx.assertPresent(text, 'Text is required while appending');
|
||||||
|
@ -25,6 +25,7 @@ import validation from '../middlewares/validation';
|
|||||||
import methodOverride from '../middlewares/methodOverride';
|
import methodOverride from '../middlewares/methodOverride';
|
||||||
import cache from './middlewares/cache';
|
import cache from './middlewares/cache';
|
||||||
import apiWrapper from './middlewares/apiWrapper';
|
import apiWrapper from './middlewares/apiWrapper';
|
||||||
|
import editor from './middlewares/editor';
|
||||||
|
|
||||||
const api = new Koa();
|
const api = new Koa();
|
||||||
const router = new Router();
|
const router = new Router();
|
||||||
@ -36,6 +37,7 @@ api.use(methodOverride());
|
|||||||
api.use(cache());
|
api.use(cache());
|
||||||
api.use(validation());
|
api.use(validation());
|
||||||
api.use(apiWrapper());
|
api.use(apiWrapper());
|
||||||
|
api.use(editor());
|
||||||
|
|
||||||
// routes
|
// routes
|
||||||
router.use('/', auth.routes());
|
router.use('/', auth.routes());
|
||||||
|
17
server/api/middlewares/editor.js
Normal file
17
server/api/middlewares/editor.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// @flow
|
||||||
|
import { type Context } from 'koa';
|
||||||
|
import pkg from 'rich-markdown-editor/package.json';
|
||||||
|
import { EditorUpdateError } from '../../errors';
|
||||||
|
|
||||||
|
export default function editor() {
|
||||||
|
return async function editorMiddleware(ctx: Context, next: () => Promise<*>) {
|
||||||
|
const editorVersion = ctx.headers['x-editor-version'];
|
||||||
|
|
||||||
|
// As the client can only ever be behind the server there's no need for a
|
||||||
|
// more strict check of version infront/behind here
|
||||||
|
if (editorVersion && editorVersion !== pkg.version) {
|
||||||
|
throw new EditorUpdateError();
|
||||||
|
}
|
||||||
|
return next();
|
||||||
|
};
|
||||||
|
}
|
@ -45,3 +45,9 @@ export function ParamRequiredError(
|
|||||||
export function ValidationError(message: string = 'Validation failed') {
|
export function ValidationError(message: string = 'Validation failed') {
|
||||||
return httpErrors(400, message, { id: 'validation_error' });
|
return httpErrors(400, message, { id: 'validation_error' });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function EditorUpdateError(
|
||||||
|
message: string = 'The client editor is out of date and must be reloaded'
|
||||||
|
) {
|
||||||
|
return httpErrors(400, message, { id: 'editor_update_required' });
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user