Merge branch 'staging' into restricted-registration

pull/1/head
ansuz 4 years ago
commit 9fbd10fa8e

@ -1,6 +1,6 @@
--- ---
name: Bug report name: Bug report
about: Create a report to help us improve about: Report a bug in the software
title: '' title: ''
labels: '' labels: ''
assignees: '' assignees: ''

@ -0,0 +1,57 @@
---
name: Initial instance configuration
about: Difficulty configuring a CryptPad instance
title: CONFIG
labels: configuration
assignees: ''
---
We receive many issues from people that have tried to set up a new CryptPad instance that does not load any of the interactive editors or which mostly works but has particular problems with the sheet editor.
Before you create an issue:
## See your instance's checkup page
If your instance is able to at least partially load some pages then you should be able to access the diagnostic page `http(s)://<your-domain>/checkup/`. It will perform some automated tests of your instance's configuration and will provide hints indicating:
1. what is incorrect about your configuration
2. what to change in order to correct the problem
## Write down the exact steps you followed to configure your instance
0. Provide the URL of the guide you followed
1. Confirm that your system has the necessary pre-requisites
* Did you fetch the source code with `git` as recommended?
* Have you installed the recommend version of Nodejs (12.14.0) using [NVM](https://github.com/nvm-sh/nvm)?
* Have you installed `bower` using `npm`?
* Have you fetched the latest source code? Run `git branch` and confirm that it returns either `main` or [the latest of our releases](github.com/xwiki-labs/cryptpad/releases/latest).
2. Did you copy `cryptpad/config/config.example.js` to `cryptpad/config/config.js`, read the comments, and edit the fields which are described as being necessary for a production environment?
3. Did you restart the application server (`server.js`) after making configuration changes?
4. Are you running NGINX as a reverse proxy as we recommend?
5. Have you generated an SSL certificate that is valid for both the domains that are required by the sandboxing system?
6. Do the domains in your NGINX conf match those in `cryptpad/config/config.js`?
## Review the steps you took
If the answer to any of the above questions is _No_ then that is the most likely cause of your difficulty.
Identifying the problem on your own reduces the time we spend answering GitHub issues and leaves more time to fix actual bugs and develop new features.
## Confirm that the problem stems from your instance and not from your browser
Not all browsers support CryptPad correctly, and various browser extensions interfere with its intended behaviour.
https://CryptPad.fr is a good reference point that you can use to confirm that your browser can load a correctly configured instance. If you can't load CryptPad.fr then the problem may be with your browser, its configuration, or one of its active extensions.
## Create a detailed report
If you believe you've done all of those steps correctly then proceed with creating an issue with the following:
0. A concise description of the problem you're experiencing and why you believe it stems from a bug in the software and not a configuration issue
1. The list of all the steps you wrote down when following our instructions above
2. A link to your instance so we can easily load your `/checkup/` page for ourselves
3. A list of any errors visible in your browser's console on whichever page is not behaving as expected
4. A list of any further steps you've taken to debug the problem on your own
Finally, remove the text of this issue template and leave only the content you've written.

@ -94,7 +94,7 @@ define([
var imprintUrl = AppConfig.imprint && (typeof(AppConfig.imprint) === "boolean" ? var imprintUrl = AppConfig.imprint && (typeof(AppConfig.imprint) === "boolean" ?
'/imprint.html' : AppConfig.imprint); '/imprint.html' : AppConfig.imprint);
Pages.versionString = "v4.4.0"; Pages.versionString = "v4.5.0";
// used for the about menu // used for the about menu

@ -7,8 +7,13 @@ define([
], function (Config, h, Msg, Pages, LocalStore) { ], function (Config, h, Msg, Pages, LocalStore) {
return function () { return function () {
var adminEmail = Config.adminEmail && Config.adminEmail !== 'i.did.not.read.my.config@cryptpad.fr'; var developerEmail = "contact@cryptpad.fr";
var adminEmail = Config.adminEmail && [
'i.did.not.read.my.config@cryptpad.fr',
developerEmail
].indexOf(Config.adminEmail) === -1;
var adminMailbox = Config.supportMailbox && LocalStore.isLoggedIn(); var adminMailbox = Config.supportMailbox && LocalStore.isLoggedIn();
return h('div#cp-main', [ return h('div#cp-main', [
Pages.infopageTopbar(), Pages.infopageTopbar(),
h('div.container.cp-container', [ h('div.container.cp-container', [
@ -110,7 +115,7 @@ define([
) )
), ),
h('div.col-12.col-sm-6.col-md-3.col-lg-3', h('div.col-12.col-sm-6.col-md-3.col-lg-3',
h('a.card', {href : "mailto:contact@cryptpad.fr"}, h('a.card', {href : "mailto:" + developerEmail},
h('div.card-body', h('div.card-body',
h('p', [ h('p', [
h('img', { h('img', {

@ -1,6 +1,12 @@
.cursor_main() { .cursor_main() {
// CodeMirror // CodeMirror
.cp-codemirror-cursor { .cp-codemirror-cursor {
&:before {
content: "";
display: inline-block;
}
cursor: default; cursor: default;
background-color: red; background-color: red;
background-clip: padding-box; background-clip: padding-box;
@ -8,8 +14,8 @@
border: 2px solid red; border: 2px solid red;
border-right-color: transparent !important; border-right-color: transparent !important;
border-left-color: transparent !important; border-left-color: transparent !important;
margin-left: -3px; display: inline-block;
margin-right: -3px; margin: -2px -3px;
} }
.cp-codemirror-selection { .cp-codemirror-selection {
background-color: rgba(255,0,0,0.3); background-color: rgba(255,0,0,0.3);

2
package-lock.json generated

@ -1,6 +1,6 @@
{ {
"name": "cryptpad", "name": "cryptpad",
"version": "4.4.0", "version": "4.5.0",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {

@ -1,7 +1,7 @@
{ {
"name": "cryptpad", "name": "cryptpad",
"description": "realtime collaborative visual editor with zero knowlege server", "description": "realtime collaborative visual editor with zero knowlege server",
"version": "4.4.0", "version": "4.5.0",
"license": "AGPL-3.0+", "license": "AGPL-3.0+",
"repository": { "repository": {
"type": "git", "type": "git",

@ -1,7 +1,6 @@
@import (reference) "../include/colortheme-all.less"; @import (reference) "../../customize/src/less2/include/colortheme-all.less";
@import (reference) "../include/font.less"; @import (reference) "../../customize/src/less2/include/font.less";
//@import (reference) "../include/forms.less"; @import (reference) "../../customize/src/less2/include/alertify.less";
@import (reference) "../include/alertify.less";
html, body { html, body {
.font_main(); .font_main();
@ -55,9 +54,16 @@ html, body {
word-break: break-word; word-break: break-word;
padding: 5px; padding: 5px;
//font-size: 16px; //font-size: 16px;
border: 1px solid red; &.cp-danger {
border: 1px solid @cp_alerts-danger-bg;
background-color: @cp_alerts-danger-bg; background-color: @cp_alerts-danger-bg;
color: @cp_alerts-danger-text; color: @cp_alerts-danger-text;
}
&.cp-warning {
border: 1px solid @cp_alerts-warning-bg;
background-color: @cp_alerts-warning-bg;
color: @cp_alerts-warning-text;
}
code { code {
word-break: keep-all; word-break: keep-all;
font-style: italic; font-style: italic;

@ -15,7 +15,7 @@ define([
'/bower_components/tweetnacl/nacl-fast.min.js', '/bower_components/tweetnacl/nacl-fast.min.js',
'css!/bower_components/components-font-awesome/css/font-awesome.min.css', 'css!/bower_components/components-font-awesome/css/font-awesome.min.css',
'less!/customize/src/less2/pages/page-checkup.less', 'less!/checkup/app-checkup.less',
], 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) { NetConfig) {
@ -26,7 +26,7 @@ define([
}; };
var assert = function (f, msg) { var assert = function (f, msg) {
Assert(f, msg || h('span.advisory-text')); Assert(f, msg || h('span.advisory-text.cp-danger'));
}; };
var CONFIG_PATH = function () { var CONFIG_PATH = function () {
@ -420,10 +420,7 @@ define([
dataType: 'text', dataType: 'text',
complete: function (xhr) { complete: function (xhr) {
var allHeaders = xhr.getAllResponseHeaders(); var allHeaders = xhr.getAllResponseHeaders();
console.error(allHeaders);
var headers = {}; var headers = {};
var duplicated = allHeaders.split('\n').some(function (header) { var duplicated = allHeaders.split('\n').some(function (header) {
var duplicate; var duplicate;
header.replace(/([^:]+):(.*)/, function (all, type, value) { header.replace(/([^:]+):(.*)/, function (all, type, value) {
@ -436,8 +433,6 @@ define([
return duplicate; return duplicate;
}); });
if (duplicated) { return void cb(false); }
var expect = { var expect = {
'cross-origin-resource-policy': 'cross-origin', 'cross-origin-resource-policy': 'cross-origin',
}; };
@ -448,7 +443,8 @@ define([
} }
}); });
cb(!incorrect); if (duplicated || incorrect) { console.error(allHeaders); }
cb(!duplicated && !incorrect);
}, },
}); });
}; };
@ -467,6 +463,59 @@ define([
checkAPIHeaders(url, cb); checkAPIHeaders(url, cb);
}); });
var setWarningClass = function (msg) {
$(msg).removeClass('cp-danger').addClass('cp-warning');
};
assert(function (cb, msg) {
var email = ApiConfig.adminEmail;
if (typeof(email) === 'string' && email && email !== 'i.did.not.read.my.config@cryptpad.fr') {
return void cb(true);
}
setWarningClass(msg);
msg.appendChild(h('span', [
'This instance does not provide a valid ',
h('code', 'adminEmail'),
' which can make it difficult to contact its adminstrator to report vulnerabilities or abusive content.',
' This can be configured in ', CONFIG_PATH(), '. ',
RESTART_WARNING(),
]));
cb(email);
});
assert(function (cb, msg) {
var support = ApiConfig.supportMailbox;
setWarningClass(msg);
msg.appendChild(h('span', [
"This instance's encrypted support ticket functionality has not been enabled. This can make it difficult for its users to safely report issues that concern sensitive information. ",
"This can be configured via the ",
h('code', 'supportMailbox'),
" attribute in ",
CONFIG_PATH(),
". ",
RESTART_WARNING(),
]));
cb(support && typeof(support) === 'string' && support.length === 44);
});
assert(function (cb, msg) {
var adminKeys = ApiConfig.adminKeys;
if (Array.isArray(adminKeys) && adminKeys.length >= 1 && typeof(adminKeys[0]) === 'string' && adminKeys[0].length === 44) {
return void cb(true);
}
setWarningClass(msg);
msg.appendChild(h('span', [
"This instance has not been configured to support web administration. This can be enabled by adding a registered user's public signing key to the ",
h('code', 'adminKeys'),
' array in ',
CONFIG_PATH(),
'. ',
RESTART_WARNING(),
]));
cb(false);
});
var row = function (cells) { var row = function (cells) {
return h('tr', cells.map(function (cell) { return h('tr', cells.map(function (cell) {
return h('td', cell); return h('td', cell);

@ -789,7 +789,6 @@ define([
])).click(common.prepareFeedback(type)); ])).click(common.prepareFeedback(type));
break; break;
case 'storeindrive': case 'storeindrive':
Messages.toolbar_storeInDrive = "Store in CryptDrive"; // XXX
button = $(h('button.cp-toolbar-storeindrive', { button = $(h('button.cp-toolbar-storeindrive', {
style: 'display:none;' style: 'display:none;'
}, [ }, [

@ -431,7 +431,7 @@ define([
else if ($this.hasClass("cp-app-code-context-download")) { else if ($this.hasClass("cp-app-code-context-download")) {
if ($mt.is('pre.mermaid') || $mt.is('pre.markmap')) { if ($mt.is('pre.mermaid') || $mt.is('pre.markmap')) {
(function () { (function () {
var name = 'image.svg'; // XXX var name = Messages.mediatag_defaultImageName + '.svg';
var svg = $mt.find('svg')[0].cloneNode(true); var svg = $mt.find('svg')[0].cloneNode(true);
$(svg).attr('xmlns', 'http://www.w3.org/2000/svg').attr('width', $mt.width()).attr('height', $mt.height()); $(svg).attr('xmlns', 'http://www.w3.org/2000/svg').attr('width', $mt.width()).attr('height', $mt.height());
$(svg).find('foreignObject').each(function (i, el) { $(svg).find('foreignObject').each(function (i, el) {
@ -454,7 +454,7 @@ define([
} }
if ($mt.is('pre.mathjax')) { if ($mt.is('pre.mathjax')) {
(function () { (function () {
var name = 'image.png'; // XXX var name = Messages.mediatag_defaultImageName + '.png';
var svg = $mt.find('> span > svg')[0]; var svg = $mt.find('> span > svg')[0];
var clone = svg.cloneNode(true); var clone = svg.cloneNode(true);
var html = clone.outerHTML; var html = clone.outerHTML;

@ -2668,16 +2668,22 @@ define([
} }
// Only execute the following code the first time we call onReady
if (!firstReady) {
setMyId();
oldHashes = JSON.parse(JSON.stringify(content.hashes));
initializing = false;
return void setEditable(!readOnly);
}
firstReady = false;
var useNewDefault = content.version && content.version >= 2; var useNewDefault = content.version && content.version >= 2;
openRtChannel(function () { openRtChannel(function () {
setMyId(); setMyId();
oldHashes = JSON.parse(JSON.stringify(content.hashes)); oldHashes = JSON.parse(JSON.stringify(content.hashes));
initializing = false; initializing = false;
// Only execute the following code the first time we call onReady
if (!firstReady) { return void setEditable(!readOnly); }
firstReady = false;
common.openPadChat(APP.onLocal); common.openPadChat(APP.onLocal);
if (!readOnly) { if (!readOnly) {
@ -2790,10 +2796,8 @@ define([
checkNewCheckpoint(); checkNewCheckpoint();
}); });
}; };
var isModified = editor.asc_isDocumentModified || function () { var editing = editor.asc_isDocumentModified ? editor.asc_isDocumentModified() : editor.isDocumentModify;
return editor.isDocumentModify; if (editing) {
};
if (isModified()) {
setEditable(false); setEditable(false);
APP.unsavedLocks = myLocks; APP.unsavedLocks = myLocks;
APP.onStrictSaveChanges = function () { APP.onStrictSaveChanges = function () {
@ -2838,10 +2842,12 @@ define([
common.gotoURL(); common.gotoURL();
}); });
} }
setEditable(true); //setEditable(true);
try { getEditor().asc_setViewMode(false); } catch (e) {}
offline = false; offline = false;
} else { } else {
setEditable(false); try { getEditor().asc_setViewMode(true); } catch (e) {}
//setEditable(false);
offline = true; offline = true;
UI.findOKButton().click(); UI.findOKButton().click();
UIElements.disconnectAlert(); UIElements.disconnectAlert();

File diff suppressed because one or more lines are too long

@ -129,8 +129,8 @@ define([
var l = privateData.plan ? ApiConfig.premiumUploadSize : false; var l = privateData.plan ? ApiConfig.premiumUploadSize : false;
l = l || ApiConfig.maxUploadSize || "?"; l = l || ApiConfig.maxUploadSize || "?";
var maxSizeStr = Util.bytesToMegabytes(l); var maxSizeStr = Util.bytesToMegabytes(l);
// XXX blob.byteLength is wrong: we should use the lenght of the encrypted content (see whiteboard) var estimate = FileCrypto.computeEncryptedSize((blob && blob.byteLength) || 0, metadata);
if (blob && blob.byteLength && typeof(l) === "number" && blob.byteLength > l) { if (blob && blob.byteLength && typeof(estimate) === 'number' && typeof(l) === "number" && estimate > l) {
$pv.text(Messages.error); $pv.text(Messages.error);
queue.inProgress = false; queue.inProgress = false;
queue.next(); queue.next();

@ -626,7 +626,6 @@ define([
}, },
isNewFile: isNewFile, isNewFile: isNewFile,
isDeleted: isDeleted, isDeleted: isDeleted,
password: password,
channel: secret.channel, channel: secret.channel,
enableSF: localStorage.CryptPad_SF === "1", // TODO to remove when enabled by default enableSF: localStorage.CryptPad_SF === "1", // TODO to remove when enabled by default
devMode: localStorage.CryptPad_dev === "1", devMode: localStorage.CryptPad_dev === "1",
@ -651,6 +650,7 @@ define([
if (isSafe) { if (isSafe) {
additionalPriv.hashes = hashes; additionalPriv.hashes = hashes;
additionalPriv.password = password;
} }
for (var k in additionalPriv) { metaObj.priv[k] = additionalPriv[k]; } for (var k in additionalPriv) { metaObj.priv[k] = additionalPriv[k]; }

@ -1226,5 +1226,7 @@
"calendar": "Kalender", "calendar": "Kalender",
"calendar_before": "vorher", "calendar_before": "vorher",
"calendar_weekNumber": "Woche {0}", "calendar_weekNumber": "Woche {0}",
"oo_cantMigrate": "Diese Tabelle überschreitet die maximale Größe für hochgeladene Dateien und kann nicht migriert werden." "oo_cantMigrate": "Diese Tabelle überschreitet die maximale Größe für hochgeladene Dateien und kann nicht migriert werden.",
"toolbar_storeInDrive": "In CryptDrive speichern",
"genericCopySuccess": "In die Zwischenablage kopiert"
} }

@ -1226,5 +1226,8 @@
"pad_goToAnchor": "Aller à cette ancre", "pad_goToAnchor": "Aller à cette ancre",
"settings_padOpenLinkLabel": "Activer l'ouverture directe des liens", "settings_padOpenLinkLabel": "Activer l'ouverture directe des liens",
"settings_padOpenLinkHint": "Cette option permet d'ouvrir les liens dans un document texte sans fenêtre daperçu", "settings_padOpenLinkHint": "Cette option permet d'ouvrir les liens dans un document texte sans fenêtre daperçu",
"settings_padOpenLinkTitle": "Ouvrir les lien avec un seul clic" "settings_padOpenLinkTitle": "Ouvrir les lien avec un seul clic",
"toolbar_storeInDrive": "Stocker dans CryptDrive",
"genericCopySuccess": "Copié dans le presse-papiers",
"mediatag_defaultImageName": "image"
} }

@ -1226,5 +1226,8 @@
"settings_notifCalendarCheckbox": "Enable calendar notifications", "settings_notifCalendarCheckbox": "Enable calendar notifications",
"calendar_notifications": "Reminders", "calendar_notifications": "Reminders",
"calendar_addNotification": "Add reminder", "calendar_addNotification": "Add reminder",
"calendar_noNotification": "None" "calendar_noNotification": "None",
"toolbar_storeInDrive": "Store in CryptDrive",
"genericCopySuccess": "Copied to clipboard",
"mediatag_defaultImageName": "image"
} }

@ -513,7 +513,7 @@ define([
var privateData = metadataMgr.getPrivateData(); var privateData = metadataMgr.getPrivateData();
var url = Hash.getPublicSigningKeyString(privateData.origin, data.name, data.edPublic); var url = Hash.getPublicSigningKeyString(privateData.origin, data.name, data.edPublic);
var success = Clipboard.copy(url); var success = Clipboard.copy(url);
if (success) { UI.log(Messages.shareSuccess); } if (success) { UI.log(Messages.genericCopySuccess); }
}; };
}; };

Loading…
Cancel
Save