diff --git a/lib/api.js b/lib/api.js index 277d085fa..9a317be86 100644 --- a/lib/api.js +++ b/lib/api.js @@ -4,6 +4,8 @@ const NetfluxSrv = require('chainpad-server'); const Decrees = require("./decrees"); const nThen = require("nthen"); +const Fs = require("fs"); +const Path = require("path"); module.exports.create = function (Env) { var log = Env.Log; @@ -19,6 +21,9 @@ nThen(function (w) { console.error(err); } })); +}).nThen(function (w) { + var fullPath = Path.join(Env.paths.block, 'placeholder.txt'); + Fs.writeFile(fullPath, 'PLACEHOLDER\n', w()); }).nThen(function () { // asynchronously create a historyKeeper and RPC together require('./historyKeeper.js').create(Env, function (err, historyKeeper) { diff --git a/lib/storage/blob.js b/lib/storage/blob.js index 4b17dc85c..7cf13dd59 100644 --- a/lib/storage/blob.js +++ b/lib/storage/blob.js @@ -495,6 +495,10 @@ BlobStore.create = function (config, _cb) { Fse.mkdirp(Path.join(Env.archivePath, Env.blobPath), w(function (e) { if (e) { CB(e); } })); + }).nThen(function (w) { + // XXX make a placeholder file in the root of the blob path + var fullPath = Path.join(Env.blobPath, 'placeholder.txt'); + Fse.writeFile(fullPath, 'PLACEHOLDER\n', w()); }).nThen(function () { var methods = { isFileId: isValidId, diff --git a/www/checkup/main.js b/www/checkup/main.js index 2c227df5d..e58976a8a 100644 --- a/www/checkup/main.js +++ b/www/checkup/main.js @@ -1113,6 +1113,54 @@ define([ }); }); + assert(function (cb, msg) { + var path = '/blob/placeholder.txt'; + var fullPath; + try { + fullPath = new URL(path, ApiConfig.fileHost || ApiConfig.httpUnsafeOrigin).href; + } catch (err) { + fullPath = path; + } + + msg.appendChild(h('span', [ + "A placeholder file was expected to be available at ", + code(fullPath), + ", but it was not found.", + " This commonly indicates a mismatch between the API server's ", + code('blobPath'), + " value and the path that the webserver or reverse proxy is attempting to serve.", + " This misconfiguration will cause errors with uploaded files and CryptPad's office editors (sheet, presentation, document).", + ])); + + Tools.common_xhr(fullPath, xhr => { + cb(xhr.status === 200 || xhr.status); + }); + }); + + assert(function (cb, msg) { + var path = '/block/placeholder.txt'; + var fullPath; + try { + fullPath = new URL(path, ApiConfig.fileHost || ApiConfig.httpUnsafeOrigin).href; + } catch (err) { + fullPath = path; + } + + msg.appendChild(h('span', [ + "A placeholder file was expected to be available at ", + code(fullPath), + ", but it was not found.", + " This commonly indicates a mismatch between the API server's ", + code('blockPath'), + " value and the path that the webserver or reverse proxy is attempting to serve.", + " This misconfiguration will cause errors with login, registration, and password change.", + ])); + + Tools.common_xhr(fullPath, xhr => { + cb(xhr.status === 200 || xhr.status); + }); + }); + var serverToken; Tools.common_xhr('/', function (xhr) { serverToken = xhr.getResponseHeader('server');