Merge branch 'admin-network-pane' into staging

pull/1/head
ansuz 4 years ago
commit 0a7e692989

@ -122,28 +122,6 @@ module.exports = {
], ],
*/ */
/* We're very proud that CryptPad is available to the public as free software!
* We do, however, still need to pay our bills as we develop the platform.
*
* By default CryptPad will prompt users to consider donating to
* our OpenCollective campaign. We publish the state of our finances periodically
* so you can decide for yourself whether our expenses are reasonable.
*
* You can disable any solicitations for donations by setting 'removeDonateButton' to true,
* but we'd appreciate it if you didn't!
*/
//removeDonateButton: false,
/*
* By default, CryptPad contacts one of our servers once a day.
* This check-in will also send some very basic information about your instance including its
* version and the adminEmail so we can reach you if we are aware of a serious problem.
* We will never sell it or send you marketing mail.
*
* If you want to block this check-in and remain set 'blockDailyCheck' to true.
*/
//blockDailyCheck: false,
/* ===================== /* =====================
* STORAGE * STORAGE
* ===================== */ * ===================== */

@ -10,6 +10,7 @@ module.exports.create = function (Env) {
nThen(function (w) { nThen(function (w) {
Decrees.load(Env, w(function (err) { Decrees.load(Env, w(function (err) {
Env.flushCache();
if (err) { if (err) {
log.error('DECREES_LOADING', { log.error('DECREES_LOADING', {
error: err.code || err, error: err.code || err,

@ -317,6 +317,15 @@ var instanceStatus = function (Env, Server, cb) {
maxUploadSize: Env.maxUploadSize, maxUploadSize: Env.maxUploadSize,
premiumUploadSize: Env.premiumUploadSize, premiumUploadSize: Env.premiumUploadSize,
consentToContact: Env.consentToContact,
listMyInstance: Env.listMyInstance,
provideAggregateStatistics: Env.provideAggregateStatistics,
removeDonateButton: Env.removeDonateButton,
blockDailyCheck: Env.blockDailyCheck,
updateAvailable: Env.updateAvailable,
}); });
}; };

@ -4,9 +4,9 @@ const Quota = module.exports;
//const Util = require("../common-util"); //const Util = require("../common-util");
const Keys = require("../keys"); const Keys = require("../keys");
const Package = require('../../package.json');
const Https = require("https"); const Https = require("https");
const Util = require("../common-util"); const Util = require("../common-util");
const Stats = require("../stats");
var validLimitFields = ['limit', 'plan', 'note', 'users', 'origin']; var validLimitFields = ['limit', 'plan', 'note', 'users', 'origin'];
@ -51,24 +51,66 @@ Quota.applyCustomLimits = function (Env) {
// console.log(Env.limits); // console.log(Env.limits);
}; };
var isRemoteVersionNewer = function (local, remote) {
try {
local = local.split('.').map(Number);
remote = remote.split('.').map(Number);
for (var i = 0; i < 3; i++) {
if (remote[i] < local[i]) { return false; }
if (remote[i] > local[i]) { return true; }
}
} catch (err) {
// if anything goes wrong just fall through and return false
// false negatives are better than false positives
}
return false;
};
/* /*
Env = { var Assert = require("assert");
myDomain, [
mySubdomain, // remote versions
adminEmail, ['4.5.0', '4.5.0', false], // equal semver should not prompt
Package.version, ['4.5.0', '4.5.1', true], // patch versions should prompt
['4.5.0', '4.6.0', true], // minor versions should prompt
['4.5.0', '5.0.0', true], // major versions should prompt
// local
['5.3.1', '4.9.0', false], // newer major should not prompt
['4.7.0', '4.6.0', false], // newer minor should not prompt
['4.7.0', '4.6.1', false], // newer patch should not prompt if other values are greater
].forEach(function (x) {
var result = isRemoteVersionNewer(x[0], x[1]);
Assert.equal(result, x[2]);
});
*/
// check if the remote endpoint reported an available server version
// which is newer than your current version (Env.version)
// if so, set Env.updateAvailable to the URL of its release notes
var checkUpdateAvailability = function (Env, json) {
if (!(json && typeof(json.updateAvailable) === 'string' && typeof(json.version) === 'string')) { return; }
// expects {updateAvailable: 'https://github.com/xwiki-labs/cryptpad/releases/4.7.0', version: '4.7.0'}
// the version string is provided explicitly even though it could be parsed from GitHub's URL
// this will allow old instances to understand responses of arbitrary URLs
// as long as we keep using semver for 'version'
if (!isRemoteVersionNewer(Env.version, json.version)) {
Env.updateAvailable = undefined;
return;
}
Env.updateAvailable = json.updateAvailable;
Env.Log.info('AN_UPDATE_IS_AVAILABLE', {
version: json.version,
updateAvailable: json.updateAvaiable,
});
}; };
*/
var queryAccountServer = function (Env, cb) { var queryAccountServer = function (Env, cb) {
var done = Util.once(Util.mkAsync(cb)); var done = Util.once(Util.mkAsync(cb));
var body = JSON.stringify({ var rawBody = Stats.instanceData(Env);
domain: Env.myDomain, Env.Log.info("SERVER_TELEMETRY", rawBody);
subdomain: Env.mySubdomain || null, var body = JSON.stringify(rawBody);
adminEmail: Env.adminEmail,
version: Package.version
});
var options = { var options = {
host: 'accounts.cryptpad.fr', host: 'accounts.cryptpad.fr',
path: '/api/getauthorized', path: '/api/getauthorized',
@ -92,6 +134,7 @@ var queryAccountServer = function (Env, cb) {
response.on('end', function () { response.on('end', function () {
try { try {
var json = JSON.parse(str); var json = JSON.parse(str);
checkUpdateAvailability(Env, json);
// don't overwrite the limits with junk data // don't overwrite the limits with junk data
if (json && json.message === 'EINVAL') { return void cb(); } if (json && json.message === 'EINVAL') { return void cb(); }
done(void 0, json); done(void 0, json);

@ -34,6 +34,13 @@ SET_MAINTENANCE
SET_ADMIN_EMAIL SET_ADMIN_EMAIL
SET_SUPPORT_MAILBOX SET_SUPPORT_MAILBOX
// COMMUNITY PARTICIPATION AND GOVERNANCE
CONSENT_TO_CONTACT
LIST_MY_INSTANCE
PROVIDE_AGGREGATE_STATISTICS
REMOVE_DONATE_BUTTON
BLOCK_DAILY_CHECK
NOT IMPLEMENTED: NOT IMPLEMENTED:
// RESTRICTED REGISTRATION // RESTRICTED REGISTRATION
@ -89,6 +96,21 @@ commands.DISABLE_INTEGRATED_EVICTION = makeBooleanSetter('disableIntegratedEvict
// CryptPad_AsyncStore.rpc.send('ADMIN', [ 'ADMIN_DECREE', ['DISABLE_INTEGRATED_TASKS', [true]]], console.log) // CryptPad_AsyncStore.rpc.send('ADMIN', [ 'ADMIN_DECREE', ['DISABLE_INTEGRATED_TASKS', [true]]], console.log)
commands.DISABLE_INTEGRATED_TASKS = makeBooleanSetter('disableIntegratedTasks'); commands.DISABLE_INTEGRATED_TASKS = makeBooleanSetter('disableIntegratedTasks');
// CryptPad_AsyncStore.rpc.send('ADMIN', [ 'ADMIN_DECREE', ['CONSENT_TO_CONTACT', [true]]], console.log)
commands.CONSENT_TO_CONTACT = makeBooleanSetter('consentToContact');
// CryptPad_AsyncStore.rpc.send('ADMIN', [ 'ADMIN_DECREE', ['LIST_MY_INSTANCE', [true]]], console.log)
commands.LIST_MY_INSTANCE = makeBooleanSetter('listMyInstance');
// CryptPad_AsyncStore.rpc.send('ADMIN', [ 'ADMIN_DECREE', ['PROVIDE_AGGREGATE_STATISTICS', [true]]], console.log)
commands.PROVIDE_AGGREGATE_STATISTICS = makeBooleanSetter('provideAggregateStatistics');
// CryptPad_AsyncStore.rpc.send('ADMIN', [ 'ADMIN_DECREE', ['REMOVE_DONATE_BUTTON', [true]]], console.log)
commands.REMOVE_DONATE_BUTTON = makeBooleanSetter('removeDonateButton');
// CryptPad_AsyncStore.rpc.send('ADMIN', [ 'ADMIN_DECREE', ['BLOCK_DAILY_CHECK', [true]]], console.log)
commands.BLOCK_DAILY_CHECK = makeBooleanSetter('blockDailyCheck');
/* /*
var isNonNegativeNumber = function (n) { var isNonNegativeNumber = function (n) {
return !(typeof(n) !== 'number' || isNaN(n) || n < 0); return !(typeof(n) !== 'number' || isNaN(n) || n < 0);

@ -10,10 +10,21 @@ const Core = require("./commands/core");
const Quota = require("./commands/quota"); const Quota = require("./commands/quota");
const Util = require("./common-util"); const Util = require("./common-util");
const Package = require("../package.json");
module.exports.create = function (config) { var canonicalizeOrigin = function (s) {
if (typeof(s) === 'undefined') { return; }
return (s || '').trim().replace(/\/+$/, '');
};
module.exports.create = function (config) {
const Env = { const Env = {
version: Package.version,
httpUnsafeOrigin: canonicalizeOrigin(config.httpUnsafeOrigin),
httpSafeOrigin: canonicalizeOrigin(config.httpSafeOrigin),
removeDonateButton: config.removeDonateButton,
OFFLINE_MODE: false, OFFLINE_MODE: false,
FRESH_KEY: '', FRESH_KEY: '',
FRESH_MODE: true, FRESH_MODE: true,
@ -97,6 +108,11 @@ module.exports.create = function (config) {
allowSubscriptions: config.allowSubscriptions === true, allowSubscriptions: config.allowSubscriptions === true,
blockDailyCheck: config.blockDailyCheck === true, blockDailyCheck: config.blockDailyCheck === true,
consentToContact: false,
listMyInstance: false,
provideAggregateStatistics: false,
updateAvailable: undefined,
myDomain: config.myDomain, myDomain: config.myDomain,
mySubdomain: config.mySubdomain, // only exists for the accounts integration mySubdomain: config.mySubdomain, // only exists for the accounts integration
customLimits: {}, customLimits: {},

@ -0,0 +1,65 @@
/*jshint esversion: 6 */
const Stats = module.exports;
Stats.instanceData = function (Env) {
var data = {
version: Env.version,
domain: Env.myDomain,
subdomain: Env.mySubdomain,
httpUnsafeOrigin: Env.httpUnsafeOrigin,
httpSafeOrigin: Env.httpSafeOrigin,
adminEmail: Env.adminEmail,
consentToContact: Boolean(Env.consentToContact),
};
/* We reserve the right to choose not to include instances
in our public directory at our discretion.
The following details will be included in your telemetry
as factors that may contribute to that decision.
These values are publicly available via /api/config
posting them to our server just makes it easier for us.
*/
if (Env.listMyInstance) {
// clearly indicate that you want to be listed
data.listMyInstance = Env.listMyInstance;
// you should have enabled your admin panel
data.adminKeys = Env.admins.length > 0;
// we expect that you enable your support mailbox
data.supportMailbox = Boolean(Env.supportMailbox);
// do you allow registration?
data.restrictRegistration = Boolean(Env.restrictRegistration);
// have you removed the donate button?
data.removeDonateButton = Boolean(Env.removeDonateButton);
// after how long do you consider a document to be inactive?
data.inactiveTime = Env.inactiveTime;
// how much storage do you offer to registered users?
data.defaultStorageLimit = Env.defaultStorageLimit;
// what size file upload do you permit
data.maxUploadSize = Env.maxUploadSize;
// how long do you retain inactive accounts?
data.accountRetentionTime = Env.accountRetentionTime;
// how long do you retain archived data?
//data.archiveRetentionTime = Env.archiveRetentionTime,
}
// we won't consider instances for public listings
// unless they opt to provide more info about themselves
if (!Env.provideAggregateStatistics) { return data; }
return data;
};

@ -4,7 +4,6 @@
var Express = require('express'); var Express = require('express');
var Http = require('http'); var Http = require('http');
var Fs = require('fs'); var Fs = require('fs');
var Package = require('./package.json');
var Path = require("path"); var Path = require("path");
var nThen = require("nthen"); var nThen = require("nthen");
var Util = require("./lib/common-util"); var Util = require("./lib/common-util");
@ -16,10 +15,6 @@ var Env = require("./lib/env").create(config);
var app = Express(); var app = Express();
var canonicalizeOrigin = function (s) {
return (s || '').trim().replace(/\/+$/, '');
};
var fancyURL = function (domain, path) { var fancyURL = function (domain, path) {
try { try {
if (domain && path) { return new URL(path, domain).href; } if (domain && path) { return new URL(path, domain).href; }
@ -30,15 +25,10 @@ var fancyURL = function (domain, path) {
(function () { (function () {
// you absolutely must provide an 'httpUnsafeOrigin' // you absolutely must provide an 'httpUnsafeOrigin'
if (typeof(config.httpUnsafeOrigin) !== 'string') { if (typeof(Env.httpUnsafeOrigin) !== 'string') {
throw new Error("No 'httpUnsafeOrigin' provided"); throw new Error("No 'httpUnsafeOrigin' provided");
} }
config.httpUnsafeOrigin = canonicalizeOrigin(config.httpUnsafeOrigin);
if (typeof(config.httpSafeOrigin) === 'string') {
config.httpSafeOrigin = canonicalizeOrigin(config.httpSafeOrigin);
}
// fall back to listening on a local address // fall back to listening on a local address
// if httpAddress is not a string // if httpAddress is not a string
if (typeof(config.httpAddress) !== 'string') { if (typeof(config.httpAddress) !== 'string') {
@ -50,7 +40,7 @@ var fancyURL = function (domain, path) {
config.httpPort = 3000; config.httpPort = 3000;
} }
if (typeof(config.httpSafeOrigin) !== 'string') { if (typeof(Env.httpSafeOrigin) !== 'string') {
Env.NO_SANDBOX = true; Env.NO_SANDBOX = true;
if (typeof(config.httpSafePort) !== 'number') { if (typeof(config.httpSafePort) !== 'number') {
config.httpSafePort = config.httpPort + 1; config.httpSafePort = config.httpPort + 1;
@ -76,7 +66,7 @@ var setHeaders = (function () {
} }
// next define the base Content Security Policy (CSP) headers // next define the base Content Security Policy (CSP) headers
if (typeof(config.contentSecurity) === 'string') { if (typeof(config.contentSecurity) === 'string') { // XXX deprecate this
headers['Content-Security-Policy'] = config.contentSecurity; headers['Content-Security-Policy'] = config.contentSecurity;
if (!/;$/.test(headers['Content-Security-Policy'])) { headers['Content-Security-Policy'] += ';' } if (!/;$/.test(headers['Content-Security-Policy'])) { headers['Content-Security-Policy'] += ';' }
if (headers['Content-Security-Policy'].indexOf('frame-ancestors') === -1) { if (headers['Content-Security-Policy'].indexOf('frame-ancestors') === -1) {
@ -87,14 +77,14 @@ var setHeaders = (function () {
} }
} else { } else {
// use the default CSP headers constructed with your domain // use the default CSP headers constructed with your domain
headers['Content-Security-Policy'] = Default.contentSecurity(config.httpUnsafeOrigin); headers['Content-Security-Policy'] = Default.contentSecurity(Env.httpUnsafeOrigin);
} }
const padHeaders = Util.clone(headers); const padHeaders = Util.clone(headers);
if (typeof(config.padContentSecurity) === 'string') { if (typeof(config.padContentSecurity) === 'string') {
padHeaders['Content-Security-Policy'] = config.padContentSecurity; padHeaders['Content-Security-Policy'] = config.padContentSecurity;
} else { } else {
padHeaders['Content-Security-Policy'] = Default.padContentSecurity(config.httpUnsafeOrigin); padHeaders['Content-Security-Policy'] = Default.padContentSecurity(Env.httpUnsafeOrigin);
} }
if (Object.keys(headers).length) { if (Object.keys(headers).length) {
return function (req, res) { return function (req, res) {
@ -151,7 +141,7 @@ app.head(/^\/common\/feedback\.html/, function (req, res, next) {
app.use('/blob', function (req, res, next) { app.use('/blob', function (req, res, next) {
if (req.method === 'HEAD') { if (req.method === 'HEAD') {
Express.static(Path.join(__dirname, (config.blobPath || './blob')), { Express.static(Path.join(__dirname, Env.paths.blob), {
setHeaders: function (res, path, stat) { setHeaders: function (res, path, stat) {
res.set('Access-Control-Allow-Origin', '*'); res.set('Access-Control-Allow-Origin', '*');
res.set('Access-Control-Allow-Headers', 'Content-Length'); res.set('Access-Control-Allow-Headers', 'Content-Length');
@ -191,13 +181,13 @@ var mainPagePattern = new RegExp('^\/(' + mainPages.join('|') + ').html$');
app.get(mainPagePattern, Express.static(__dirname + '/customize')); app.get(mainPagePattern, Express.static(__dirname + '/customize'));
app.get(mainPagePattern, Express.static(__dirname + '/customize.dist')); app.get(mainPagePattern, Express.static(__dirname + '/customize.dist'));
app.use("/blob", Express.static(Path.join(__dirname, (config.blobPath || './blob')), { app.use("/blob", Express.static(Path.join(__dirname, Env.paths.blob), {
maxAge: Env.DEV_MODE? "0d": "365d" maxAge: Env.DEV_MODE? "0d": "365d"
})); }));
app.use("/datastore", Express.static(Path.join(__dirname, (config.filePath || './datastore')), { app.use("/datastore", Express.static(Path.join(__dirname, Env.paths.data), {
maxAge: "0d" maxAge: "0d"
})); }));
app.use("/block", Express.static(Path.join(__dirname, (config.blockPath || '/block')), { app.use("/block", Express.static(Path.join(__dirname, Env.paths.block), {
maxAge: "0d", maxAge: "0d",
})); }));
@ -252,12 +242,12 @@ var serveConfig = makeRouteCache(function (host) {
'var obj = ' + JSON.stringify({ 'var obj = ' + JSON.stringify({
requireConf: { requireConf: {
waitSeconds: 600, waitSeconds: 600,
urlArgs: 'ver=' + Package.version + cacheString(), urlArgs: 'ver=' + Env.version + cacheString(),
}, },
removeDonateButton: (config.removeDonateButton === true), removeDonateButton: (Env.removeDonateButton === true),
allowSubscriptions: (config.allowSubscriptions === true), allowSubscriptions: (Env.allowSubscriptions === true),
websocketPath: config.externalWebsocketURL, websocketPath: config.externalWebsocketURL,
httpUnsafeOrigin: config.httpUnsafeOrigin, httpUnsafeOrigin: Env.httpUnsafeOrigin,
adminEmail: Env.adminEmail, adminEmail: Env.adminEmail,
adminKeys: Env.admins, adminKeys: Env.admins,
inactiveTime: Env.inactiveTime, inactiveTime: Env.inactiveTime,
@ -265,10 +255,10 @@ var serveConfig = makeRouteCache(function (host) {
defaultStorageLimit: Env.defaultStorageLimit, defaultStorageLimit: Env.defaultStorageLimit,
maxUploadSize: Env.maxUploadSize, maxUploadSize: Env.maxUploadSize,
premiumUploadSize: Env.premiumUploadSize, premiumUploadSize: Env.premiumUploadSize,
restrictRegistration: Env.restrictRegistration, // FIXME see the race condition in env.js restrictRegistration: Env.restrictRegistration,
}, null, '\t'), }, null, '\t'),
'obj.httpSafeOrigin = ' + (function () { 'obj.httpSafeOrigin = ' + (function () {
if (config.httpSafeOrigin) { return '"' + config.httpSafeOrigin + '"'; } if (Env.httpSafeOrigin) { return '"' + Env.httpSafeOrigin + '"'; }
if (config.httpSafePort) { if (config.httpSafePort) {
return "(function () { return window.location.origin.replace(/\:[0-9]+$/, ':" + return "(function () { return window.location.origin.replace(/\:[0-9]+$/, ':" +
config.httpSafePort + "'); }())"; config.httpSafePort + "'); }())";
@ -332,16 +322,16 @@ nThen(function (w) {
var ps = port === 80? '': ':' + port; var ps = port === 80? '': ':' + port;
var roughAddress = 'http://' + hostName + ps; var roughAddress = 'http://' + hostName + ps;
var betterAddress = fancyURL(config.httpUnsafeOrigin); var betterAddress = fancyURL(Env.httpUnsafeOrigin);
if (betterAddress) { if (betterAddress) {
console.log('Serving content for %s via %s.\n', betterAddress, roughAddress); console.log('Serving content for %s via %s.\n', betterAddress, roughAddress);
} else { } else {
console.log('Serving content via %s.\n', roughAddress); console.log('Serving content via %s.\n', roughAddress);
} }
if (!Array.isArray(config.adminKeys)) { if (!Env.admins.length) {
console.log("Your instance is not correctly configured for safe use in production.\nSee %s for more information.\n", console.log("Your instance is not correctly configured for safe use in production.\nSee %s for more information.\n",
fancyURL(config.httpUnsafeOrigin, '/checkup/') || 'https://your-domain.com/checkup/' fancyURL(Env.httpUnsafeOrigin, '/checkup/') || 'https://your-domain.com/checkup/'
); );
} }
}); });

@ -85,15 +85,27 @@ define([
'performance': [ // Msg.admin_cat_performance 'performance': [ // Msg.admin_cat_performance
'cp-admin-refresh-performance', 'cp-admin-refresh-performance',
'cp-admin-performance-profiling', 'cp-admin-performance-profiling',
] ],
'network': [ // Msg.admin_cat_network
'cp-admin-update-available',
'cp-admin-checkup',
'cp-admin-block-daily-check',
//'cp-admin-provide-aggregate-statistics',
'cp-admin-list-my-instance',
'cp-admin-consent-to-contact',
'cp-admin-remove-donate-button',
],
}; };
var create = {}; var create = {};
var keyToCamlCase = function (key) {
return key.replace(/-([a-z])/g, function (g) { return g[1].toUpperCase(); });
};
var makeBlock = function (key, addButton) { // Title, Hint, maybeButton var makeBlock = function (key, addButton) { // Title, Hint, maybeButton
// Convert to camlCase for translation keys // Convert to camlCase for translation keys
var safeKey = key.replace(/-([a-z])/g, function (g) { return g[1].toUpperCase(); }); var safeKey = keyToCamlCase(key);
var $div = $('<div>', {'class': 'cp-admin-' + key + ' cp-sidebarlayout-element'}); var $div = $('<div>', {'class': 'cp-admin-' + key + ' cp-sidebarlayout-element'});
$('<label>').text(Messages['admin_'+safeKey+'Title'] || key).appendTo($div); $('<label>').text(Messages['admin_'+safeKey+'Title'] || key).appendTo($div);
$('<span>', {'class': 'cp-sidebarlayout-description'}) $('<span>', {'class': 'cp-sidebarlayout-description'})
@ -260,7 +272,7 @@ define([
var $div = makeBlock(key); // Msg.admin_registrationHint, .admin_registrationTitle, .admin_registrationButton var $div = makeBlock(key); // Msg.admin_registrationHint, .admin_registrationTitle, .admin_registrationButton
var state = APP.instanceStatus.restrictRegistration; var state = APP.instanceStatus.restrictRegistration;
var $cbox = $(UI.createCheckbox('cp-settings-userfeedback', var $cbox = $(UI.createCheckbox('cp-settings-' + key,
Messages.admin_registrationTitle, Messages.admin_registrationTitle,
state, { label: { class: 'noTitle' } })); state, { label: { class: 'noTitle' } }));
var spinner = UI.makeSpinner($cbox); var spinner = UI.makeSpinner($cbox);
@ -289,6 +301,55 @@ define([
return $div; return $div;
}; };
var makeAdminCheckbox = function (data) {
return function () {
var state = data.getState();
var key = data.key;
var $div = makeBlock(key);
var labelKey = 'admin_' + keyToCamlCase(key) + 'Label';
var titleKey = 'admin_' + keyToCamlCase(key) + 'Title';
var $cbox = $(UI.createCheckbox('cp-admin-' + key,
Messages[labelKey] || Messages[titleKey],
state, { label: { class: 'noTitle' } }));
var spinner = UI.makeSpinner($cbox);
var $checkbox = $cbox.find('input').on('change', function() {
spinner.spin();
var val = $checkbox.is(':checked') || false;
$checkbox.attr('disabled', 'disabled');
data.query(val, function (state) {
spinner.done();
$checkbox[0].checked = state;
$checkbox.removeAttr('disabled');
});
});
$cbox.appendTo($div);
return $div;
};
};
// Msg.admin_registrationHint, .admin_registrationTitle, .admin_registrationButton
create['registration'] = makeAdminCheckbox({
key: 'registration',
getState: function () {
return APP.instanceStatus.restrictRegistration;
},
query: function (val, setState) {
sFrameChan.query('Q_ADMIN_RPC', {
cmd: 'ADMIN_DECREE',
data: ['RESTRICT_REGISTRATION', [val]]
}, function (e, response) {
if (e || response.error) {
UI.warn(Messages.error);
console.error(e, response);
}
APP.updateStatus(function () {
setState(APP.instanceStatus.restrictRegistration);
});
});
},
});
create['email'] = function () { create['email'] = function () {
var key = 'email'; var key = 'email';
var $div = makeBlock(key, true); // Msg.admin_emailHint, Msg.admin_emailTitle, Msg.admin_emailButton var $div = makeBlock(key, true); // Msg.admin_emailHint, Msg.admin_emailTitle, Msg.admin_emailButton
@ -1663,6 +1724,135 @@ define([
return $div; return $div;
}; };
create['update-available'] = function () { // Messages.admin_updateAvailableTitle.admin_updateAvailableHint.admin_updateAvailableLabel.admin_updateAvailableButton
if (!APP.instanceStatus.updateAvailable) { return; }
var $div = makeBlock('update-available', true);
var updateURL = 'https://github.com/xwiki-labs/cryptpad/releases/latest';
if (typeof(APP.instanceStatus.updateAvailable) === 'string') {
updateURL = APP.instanceStatus.updateAvailable;
}
$div.find('button').click(function () {
common.openURL(updateURL);
});
return $div;
};
create['checkup'] = function () {
var $div = makeBlock('checkup', true); // Messages.admin_checkupButton.admin_checkupHint.admin_checkupTitle
$div.find('button').click(function () {
common.openURL('/checkup/');
});
return $div;
};
create['consent-to-contact'] = makeAdminCheckbox({ // Messages.admin_consentToContactTitle.admin_consentToContactHint.admin_consentToContactLabel
key: 'consent-to-contact',
getState: function () {
return APP.instanceStatus.consentToContact;
},
query: function (val, setState) {
sFrameChan.query('Q_ADMIN_RPC', {
cmd: 'ADMIN_DECREE',
data: ['CONSENT_TO_CONTACT', [val]]
}, function (e, response) {
if (e || response.error) {
UI.warn(Messages.error);
console.error(e, response);
}
APP.updateStatus(function () {
setState(APP.instanceStatus.consentToContact);
});
});
},
});
create['list-my-instance'] = makeAdminCheckbox({ // Messages.admin_listMyInstanceTitle.admin_listMyInstanceHint.admin_listMyInstanceLabel
key: 'list-my-instance',
getState: function () {
return APP.instanceStatus.listMyInstance;
},
query: function (val, setState) {
sFrameChan.query('Q_ADMIN_RPC', {
cmd: 'ADMIN_DECREE',
data: ['LIST_MY_INSTANCE', [val]]
}, function (e, response) {
if (e || response.error) {
UI.warn(Messages.error);
console.error(e, response);
}
APP.updateStatus(function () {
setState(APP.instanceStatus.listMyInstance);
});
});
},
});
create['provide-aggregate-statistics'] = makeAdminCheckbox({ // Messages.admin_provideAggregateStatisticsTitle.admin_provideAggregateStatisticsHint.admin_provideAggregateStatisticsLabel
key: 'provide-aggregate-statistics',
getState: function () {
return APP.instanceStatus.provideAggregateStatistics;
},
query: function (val, setState) {
sFrameChan.query('Q_ADMIN_RPC', {
cmd: 'ADMIN_DECREE',
data: ['PROVIDE_AGGREGATE_STATISTICS', [val]]
}, function (e, response) {
if (e || response.error) {
UI.warn(Messages.error);
console.error(e, response);
}
APP.updateStatus(function () {
setState(APP.instanceStatus.provideAggregateStatistics);
});
});
},
});
create['remove-donate-button'] = makeAdminCheckbox({ // Messages.admin_removeDonateButtonTitle.admin_removeDonateButtonHint.admin_removeDonateButtonLabel
key: 'remove-donate-button',
getState: function () {
return APP.instanceStatus.removeDonateButton;
},
query: function (val, setState) {
sFrameChan.query('Q_ADMIN_RPC', {
cmd: 'ADMIN_DECREE',
data: ['REMOVE_DONATE_BUTTON', [val]]
}, function (e, response) {
if (e || response.error) {
UI.warn(Messages.error);
console.error(e, response);
}
APP.updateStatus(function () {
setState(APP.instanceStatus.removeDonateButton);
});
});
},
});
create['block-daily-check'] = makeAdminCheckbox({ // Messages.admin_blockDailyCheckTitle.admin_blockDailyCheckHint.admin_blockDailyCheckLabel
key: 'block-daily-check',
getState: function () {
return APP.instanceStatus.blockDailyCheck;
},
query: function (val, setState) {
sFrameChan.query('Q_ADMIN_RPC', {
cmd: 'ADMIN_DECREE',
data: ['BLOCK_DAILY_CHECK', [val]]
}, function (e, response) {
if (e || response.error) {
UI.warn(Messages.error);
console.error(e, response);
}
APP.updateStatus(function () {
setState(APP.instanceStatus.blockDailyCheck);
});
});
},
});
var hideCategories = function () { var hideCategories = function () {
APP.$rightside.find('> div').hide(); APP.$rightside.find('> div').hide();
}; };
@ -1680,6 +1870,7 @@ define([
support: 'fa fa-life-ring', support: 'fa fa-life-ring',
broadcast: 'fa fa-bullhorn', broadcast: 'fa fa-bullhorn',
performance: 'fa fa-heartbeat', performance: 'fa fa-heartbeat',
network: 'fa fa-sitemap', // or fa-university ?
}; };
var createLeftside = function () { var createLeftside = function () {

Loading…
Cancel
Save