display instance info on the home page
* implements /api/instance * updates recommended NGINX config * adds a test on /checkup/
This commit is contained in:
parent
bbd914b88d
commit
8adeeb21ec
9 changed files with 114 additions and 9 deletions
|
@ -5,7 +5,8 @@ define([
|
||||||
'/customize/messages.js',
|
'/customize/messages.js',
|
||||||
'jquery',
|
'jquery',
|
||||||
'/api/config',
|
'/api/config',
|
||||||
], function (h, Language, AppConfig, Msg, $, ApiConfig) {
|
'optional!/api/instance',
|
||||||
|
], function (h, Language, AppConfig, Msg, $, ApiConfig, Instance) {
|
||||||
var Pages = {};
|
var Pages = {};
|
||||||
|
|
||||||
Pages.setHTML = function (e, html) {
|
Pages.setHTML = function (e, html) {
|
||||||
|
@ -138,6 +139,21 @@ define([
|
||||||
});
|
});
|
||||||
var value = AppConfig.hostDescription;
|
var value = AppConfig.hostDescription;
|
||||||
Pages.hostDescription = (value && (value[l] || value.default)) || Msg.home_host;
|
Pages.hostDescription = (value && (value[l] || value.default)) || Msg.home_host;
|
||||||
|
|
||||||
|
Pages.Instance = {};
|
||||||
|
Object.keys(Instance).forEach(function (k) {
|
||||||
|
var value = Instance[k];
|
||||||
|
var result = Pages.Instance[k] = value[l] || value.default || undefined;
|
||||||
|
});
|
||||||
|
|
||||||
|
var name;
|
||||||
|
try {
|
||||||
|
name = Pages.Instance.name || new URL('/', ApiConfig.httpUnsafeOrigin).host;
|
||||||
|
} catch (err) {
|
||||||
|
name = 'CryptPad';
|
||||||
|
}
|
||||||
|
Pages.Instance.name = name;
|
||||||
|
Pages.Instance.description = Pages.Instance.description || Msg.main_catch_phrase;
|
||||||
}());
|
}());
|
||||||
|
|
||||||
// used for the about menu
|
// used for the about menu
|
||||||
|
|
|
@ -11,7 +11,8 @@ define([
|
||||||
'/customize/messages.js',
|
'/customize/messages.js',
|
||||||
'/customize/application_config.js',
|
'/customize/application_config.js',
|
||||||
'/common/outer/local-store.js',
|
'/common/outer/local-store.js',
|
||||||
'/customize/pages.js'
|
'/customize/pages.js',
|
||||||
|
//'json!/api/instance',
|
||||||
], function ($, Config, h, Feedback, UI, Hash, Constants, Util, TextFit, Msg, AppConfig, LocalStore, Pages) {
|
], function ($, Config, h, Feedback, UI, Hash, Constants, Util, TextFit, Msg, AppConfig, LocalStore, Pages) {
|
||||||
var urlArgs = Config.requireConf.urlArgs;
|
var urlArgs = Config.requireConf.urlArgs;
|
||||||
|
|
||||||
|
@ -177,6 +178,19 @@ define([
|
||||||
]));
|
]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// instance location
|
||||||
|
var locationBlock;
|
||||||
|
|
||||||
|
if (Pages.Instance.location) {
|
||||||
|
locationBlock = h('div.cp-instance-location', [
|
||||||
|
h('i.fa.fa-map-pin', {'aria-hidden': 'true'}),
|
||||||
|
'Encrypted data is hosted in: ', // XXX translate
|
||||||
|
Pages.Instance.location,
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
locationBlock = h('div', h('br')); // XXX
|
||||||
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
h('div#cp-main', [
|
h('div#cp-main', [
|
||||||
Pages.infopageTopbar(),
|
Pages.infopageTopbar(),
|
||||||
|
@ -188,12 +202,9 @@ define([
|
||||||
'aria-hidden': 'true',
|
'aria-hidden': 'true',
|
||||||
alt: ''
|
alt: ''
|
||||||
}),
|
}),
|
||||||
h('h1', 'CryptPad.fr'), // XXX use instance name
|
h('h1', Pages.Instance.name),
|
||||||
UI.setHTML(h('span.tag-line'), Msg.main_catch_phrase), // XXX Use instance description
|
UI.setHTML(h('span.tag-line'), Pages.Instance.description),
|
||||||
h('div.cp-instance-location', [
|
locationBlock,
|
||||||
h('i.fa.fa-map-pin', {'aria-hidden': 'true'}),
|
|
||||||
'Encrypted data is hosted in: France (OVH)' // XXX Use instance location
|
|
||||||
]),
|
|
||||||
termsLink,
|
termsLink,
|
||||||
privacyLink,
|
privacyLink,
|
||||||
imprintLink
|
imprintLink
|
||||||
|
|
|
@ -183,7 +183,7 @@ server {
|
||||||
# /api/config is loaded once per page load and is used to retrieve
|
# /api/config is loaded once per page load and is used to retrieve
|
||||||
# the caching variable which is applied to every other resource
|
# the caching variable which is applied to every other resource
|
||||||
# which is loaded during that session.
|
# which is loaded during that session.
|
||||||
location ~ ^/api/(config|broadcast).*$ {
|
location ~ ^/api/.*$ {
|
||||||
proxy_pass http://localhost:3000;
|
proxy_pass http://localhost:3000;
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
proxy_set_header Host $host;
|
proxy_set_header Host $host;
|
||||||
|
|
21
server.js
21
server.js
|
@ -261,6 +261,27 @@ var serveBroadcast = makeRouteCache(function (host) {
|
||||||
app.get('/api/config', serveConfig);
|
app.get('/api/config', serveConfig);
|
||||||
app.get('/api/broadcast', serveBroadcast);
|
app.get('/api/broadcast', serveBroadcast);
|
||||||
|
|
||||||
|
var define = function (obj) {
|
||||||
|
return `define(function (){
|
||||||
|
return ${JSON.stringify(obj, null, '\t')};
|
||||||
|
});`
|
||||||
|
};
|
||||||
|
|
||||||
|
app.get('/api/instance', function (req, res) { // XXX use caching?
|
||||||
|
res.setHeader('Content-Type', 'text/javascript');
|
||||||
|
res.send(define({
|
||||||
|
name: {
|
||||||
|
default: Env.instanceName,
|
||||||
|
},
|
||||||
|
description: {
|
||||||
|
default: Env.instanceDescription,
|
||||||
|
},
|
||||||
|
location: {
|
||||||
|
default: Env.instanceJurisdiction,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
var four04_path = Path.resolve(__dirname + '/customize.dist/404.html');
|
var four04_path = Path.resolve(__dirname + '/customize.dist/404.html');
|
||||||
var fivehundred_path = Path.resolve(__dirname + '/customize.dist/500.html');
|
var fivehundred_path = Path.resolve(__dirname + '/customize.dist/500.html');
|
||||||
var custom_four04_path = Path.resolve(__dirname + '/customize/404.html');
|
var custom_four04_path = Path.resolve(__dirname + '/customize/404.html');
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
var first = true;
|
var first = true;
|
||||||
window.addEventListener('error', function (ev) {
|
window.addEventListener('error', function (ev) {
|
||||||
|
if (window.CHECKUP_MAIN_LOADED) { return; }
|
||||||
if (!ev) { return; }
|
if (!ev) { return; }
|
||||||
var srcElement = ev.srcElement;
|
var srcElement = ev.srcElement;
|
||||||
if (!srcElement) { return; }
|
if (!srcElement) { return; }
|
||||||
|
|
|
@ -22,6 +22,8 @@ define([
|
||||||
], function ($, ApiConfig, Assertions, h, Messages, DomReady,
|
], function ($, ApiConfig, Assertions, h, Messages, DomReady,
|
||||||
nThen, SFCommonO, Login, Hash, Util, Pinpad,
|
nThen, SFCommonO, Login, Hash, Util, Pinpad,
|
||||||
NetConfig, Pages, Tools, AppConfig) {
|
NetConfig, Pages, Tools, AppConfig) {
|
||||||
|
window.CHECKUP_MAIN_LOADED = true;
|
||||||
|
|
||||||
var Assert = Assertions();
|
var Assert = Assertions();
|
||||||
var trimSlashes = function (s) {
|
var trimSlashes = function (s) {
|
||||||
if (typeof(s) !== 'string') { return s; }
|
if (typeof(s) !== 'string') { return s; }
|
||||||
|
@ -1364,6 +1366,25 @@ define([
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
assert(function (cb, msg) {
|
||||||
|
var url = '/api/instance';
|
||||||
|
msg.appendChild(h('span', [
|
||||||
|
link(url, url),
|
||||||
|
" did not load as expected. This is most likely caused by a missing directive in your reverse proxy or an outdated version of the API server.",
|
||||||
|
]));
|
||||||
|
|
||||||
|
require([
|
||||||
|
`optional!${url}`,
|
||||||
|
], function (Instance) {
|
||||||
|
// if the URL fails to load then an empty object will be returned
|
||||||
|
// this can be interpreted as a failure, even though the rest of the platform should still work
|
||||||
|
if (!Object.keys(Instance).length) {
|
||||||
|
return void cb(Instance);
|
||||||
|
}
|
||||||
|
cb(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
var serverToken;
|
var serverToken;
|
||||||
Tools.common_xhr('/', function (xhr) {
|
Tools.common_xhr('/', function (xhr) {
|
||||||
serverToken = xhr.getResponseHeader('server');
|
serverToken = xhr.getResponseHeader('server');
|
||||||
|
|
|
@ -8,6 +8,7 @@ define([
|
||||||
// json plugin
|
// json plugin
|
||||||
text: '/bower_components/requirejs-plugins/lib/text',
|
text: '/bower_components/requirejs-plugins/lib/text',
|
||||||
json: '/bower_components/requirejs-plugins/src/json',
|
json: '/bower_components/requirejs-plugins/src/json',
|
||||||
|
optional: '/lib/optional/optional',
|
||||||
// jquery declares itself as literally "jquery" so it cannot be pulled by path :(
|
// jquery declares itself as literally "jquery" so it cannot be pulled by path :(
|
||||||
"jquery": "/bower_components/jquery/dist/jquery.min",
|
"jquery": "/bower_components/jquery/dist/jquery.min",
|
||||||
"mermaid": "/lib/mermaid/mermaid.min",
|
"mermaid": "/lib/mermaid/mermaid.min",
|
||||||
|
|
|
@ -10,4 +10,5 @@ This file is intended to be used as a log of what third-party source we have ven
|
||||||
* [pdfjs](https://mozilla.github.io/pdf.js/) with some minor modifications to prevent CSP errors
|
* [pdfjs](https://mozilla.github.io/pdf.js/) with some minor modifications to prevent CSP errors
|
||||||
* [mermaid 9.0.0](https://github.com/mermaid-js/mermaid/releases/tag/8.13.4) extends our markdown integration to support a variety of diagram types
|
* [mermaid 9.0.0](https://github.com/mermaid-js/mermaid/releases/tag/8.13.4) extends our markdown integration to support a variety of diagram types
|
||||||
* [Fabricjs 4.6.0](https://github.com/fabricjs/fabric.js) and [Fabric-history](https://github.com/lyzerk/fabric-history) for the whiteboard app
|
* [Fabricjs 4.6.0](https://github.com/fabricjs/fabric.js) and [Fabric-history](https://github.com/lyzerk/fabric-history) for the whiteboard app
|
||||||
|
* [Requirejs optional module plugin](https://stackoverflow.com/a/27422370)
|
||||||
|
|
||||||
|
|
33
www/lib/optional/optional.js
Normal file
33
www/lib/optional/optional.js
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
define("optional", [], {
|
||||||
|
load : function (moduleName, parentRequire, onload, config){
|
||||||
|
|
||||||
|
var onLoadSuccess = function(moduleInstance){
|
||||||
|
// Module successfully loaded, call the onload callback so that
|
||||||
|
// requirejs can work its internal magic.
|
||||||
|
onload(moduleInstance);
|
||||||
|
}
|
||||||
|
|
||||||
|
var onLoadFailure = function(err){
|
||||||
|
// optional module failed to load.
|
||||||
|
var failedId = err.requireModules && err.requireModules[0];
|
||||||
|
console.warn("Could not load optional module: " + failedId);
|
||||||
|
|
||||||
|
// Undefine the module to cleanup internal stuff in requireJS
|
||||||
|
requirejs.undef(failedId);
|
||||||
|
|
||||||
|
// Now define the module instance as a simple empty object
|
||||||
|
// (NOTE: you can return any other value you want here)
|
||||||
|
define(failedId, [], function(){return {};});
|
||||||
|
|
||||||
|
// Now require the module make sure that requireJS thinks
|
||||||
|
// that is it loaded. Since we've just defined it, requirejs
|
||||||
|
// will not attempt to download any more script files and
|
||||||
|
// will just call the onLoadSuccess handler immediately
|
||||||
|
parentRequire([failedId], onLoadSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
parentRequire([moduleName], onLoadSuccess, onLoadFailure, {
|
||||||
|
accept: 'application/json',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
Loading…
Reference in a new issue