@fontoxml/fontoxml-development-tools
Version:
Development tools for Fonto.
140 lines (125 loc) • 3.83 kB
JavaScript
/** @typedef {import('../../src/getAppConfig.js').DevCmsConfig} DevCmsConfig */
function sendJson(res, status, body) {
res.status(status)
.set('content-type', 'application/json; charset=utf-8')
.json(body);
}
/**
* @param {DevCmsConfig} config
*/
export default function configureDocumentLockPutRouteHandler(config) {
return (req, res) => {
const documentId = req.body.documentId;
const revisionId = req.body.revisionId;
const lock = req.body.lock;
const documentContext = req.body.documentContext || {};
req.cms.load(
documentId,
req.body.context.editSessionToken,
(error, content) => {
if (error) {
if (error.status === 404) {
res.status(404).end();
} else {
res.status(500).end();
}
return;
}
// Always check the revisionId
req.cms.getLatestRevisionId(
documentId,
req.body.context.editSessionToken,
(error, actualRevisionId) => {
if (error) {
res.status(500).send(error);
return;
}
const documentLoadLock = {
...config.documentLoadLock,
...config.documentLoadLockOverrides[documentId],
};
const currentState = {
lock: {
isLockAcquired:
documentContext.isLockAcquired !== undefined
? documentLoadLock.isLockAvailable &&
documentContext.isLockAcquired
: documentLoadLock.isLockAcquired,
isLockAvailable:
documentLoadLock.isLockAvailable,
reason: !documentLoadLock.isLockAvailable ? documentLoadLock.lockReason : undefined,
},
revisionId,
};
if (!currentState.lock.isLockAvailable) {
// Sending 403 here would cause the document to be considered inaccessible
// instead of merely having an unavailable lock.
sendJson(res, 412, currentState);
return;
}
if (revisionId !== actualRevisionId) {
sendJson(res, 412, currentState);
return;
}
// Store lock state on the client for simplicity
const newDocumentContext = {
...documentContext,
isLockAcquired: lock.isLockAcquired,
};
const shouldGenerateAdditionalRevisionId = lock.isLockAcquired
? config.additionalRevisionIdOn.lock
: config.additionalRevisionIdOn.unlock;
if (!shouldGenerateAdditionalRevisionId) {
sendJson(res, 200, {
documentContext: newDocumentContext,
lock: {
...currentState.lock,
isLockAcquired: lock.isLockAcquired,
},
revisionId: actualRevisionId,
});
} else {
const currentSession = req.getFontoSession(
req.body.context.editSessionToken,
);
req.cms.save(documentId, content, currentSession, (error) => {
if (error) {
res.status(500).send(error);
return;
}
// Retrieve the latest revision id (again) to return to the client.
req.cms.getLatestRevisionId(
documentId,
currentSession.editSessionToken,
(error, updatedRevisionId) => {
if (error) {
res.status(500).send(error);
return;
}
if (actualRevisionId === updatedRevisionId) {
const error = new Error(
`A new revision id was not generated as expected. The revision id remains: ${actualRevisionId}".`,
);
console.log('');
console.error(error);
res.status(500).send(error);
return;
}
sendJson(res, 200, {
documentContext: newDocumentContext,
lock: {
...currentState.lock,
isLockAcquired: lock.isLockAcquired,
},
revisionId: updatedRevisionId,
});
},
);
});
}
},
);
},
);
};
}