Merge branch 'soon' of github.com:xwiki-labs/cryptpad into soon

pull/1/head
yflory 5 years ago
commit 62f133dc63

@ -1,4 +1,43 @@
# Elasmotherium release notes # FalklandWolf release (3.5.0)
## Goals
This release features work that we've been planning for a long time centered around sharing collections of documents in a more granular way.
This is our first release since David Benqué joined our team, so in addition to these team-centric updates we also worked on integrating some UI/UX improvements.
## Update notes
Updating to 3.5.0 from 3.4.0 is simple.
1. stop your server
2. pull the latest code via git
3. run `bower update`
4. restart your server
## Features
* We restyled some elements throughout the platform:
* our tooltips have a sleeker flat design
* the quota bar which appears in the drive, teams, and settings pages has also been improved
* we've begun improving the look and feel of various popup dialogs
* We've added support for password-change for owned uploaded files and owned shared folders:
* changing passwords for encrypted files means that the original file will be removed from the server and a new file will be encrypted with a new key and uploaded to a new location on the server. References to the original file will be broken. This includes links, media-tags embedded within pads, and items in other users' drives or shared folders to which you do not have access.
* the process is very similar for shared folders stored in users' CryptDrives, except that users will have the opportunity to enter the new password when they visit the platform.
* We're very happy to finally introduce the notion of _read-only shared folders_. While we've had the capacity to make shared folders read-only for some time, it was only in the same sense as pads were read-only.
* This is to say that while a viewer cannot modify the document, any links to encrypted documents within that document would confer their natural editing rights to viewers, making it possible to accidentally leak access when a single pad was shared.
* Our new read-only shared folders encrypt the editing keys for the documents they contain, such that only those with the ability to change the folder structure itself have the inherent capacity to edit the documents contained within. We think this is more intuitive than the alternative, but it took a lot of work to make it happen!
* Unfortunately, older shared folders created before this release will already contain the cryptographic keys which confer editing rights. Pads which are added to shared folders from this release onward will have the keys for their editing rights encrypted. We'll offer the ability for owners to migrate these shared folders in an upcoming release once we've added the ability to selectively trim document history.
* Similarly, we've introduced the notion of _viewers_ in teams. Viewers are listed in the team roster and have the ability to view the contents of the team's drive, but not to edit them or add new documents.
* Unfortunately, the notion of viewers is also complicated by the fact that documents added to team drives or shared folders in team drives did not have their editing keys encrypted. The first team member to open the team drive since we've deployed this release will run a migration that will encrypt the keys saved within the team drive, however, the encryption keys will remain in the drive's history until we develop a means of selectively trimming history.
## Bug fixes
* We discovered and fixed some bugs in the serverside code responsible for handling some aspects of file upload related to starting a new upload after having cancelled a previous session.
* We also identified a regression in Our _slides_ app related to the rendering of `<br>` tags, such as you might create with a `****` sequence in the corresponding markdown. This was introduced with some overly broad CSS that was intended to style our notifications page. We've since made the notifications styles more specific such that they can't interfere with other applications.
* We've become aware of some mysterious behaviour in Firefox that seems to cause some tabs or functionality to reconnect to the server after going offline while other aspects of the platform did not. Until now we've always assumed that users were connected or not, and this partial connection has revealed some bugs in our implementation. Consequently, we've begun adding some measures to detect odd behaviour if it occurs. We expect to have determined the cause of this behaviour and to have proposed a solution by our next release.
# Elasmotherium release (3.4.0)
## Goals ## Goals

@ -14,6 +14,7 @@ var map = {
'ru': 'Русский', 'ru': 'Русский',
//'te': 'తెలుగు', //'te': 'తెలుగు',
'zh': '繁體中文', 'zh': '繁體中文',
//'nl': 'Nederlands'
}; };
var messages = {}; var messages = {};

@ -0,0 +1,13 @@
/*
* You can override the translation text using this file.
* The recommended method is to make a copy of this file (/customize.dist/translations/messages.{LANG}.js)
in a 'customize' directory (/customize/translations/messages.{LANG}.js).
* If you want to check all the existing translation keys, you can open the internal language file
but you should not change it directly (/common/translations/messages.{LANG}.js)
*/
define(['/common/translations/messages.nl.js'], function (Messages) {
// Replace the existing keys in your copied file here:
// Messages.button_newpad = "New Rich Text Document";
return Messages;
});

@ -534,7 +534,7 @@ define([
APP.hideDuplicateOwned = Util.find(priv, ['settings', 'drive', 'hideDuplicate']); APP.hideDuplicateOwned = Util.find(priv, ['settings', 'drive', 'hideDuplicate']);
APP.closed = false; APP.closed = false;
var $readOnly = $('#cp-app-drive-edition-state'); var $readOnly = $(h('div#cp-app-drive-edition-state.cp-app-drive-content-info-box', Messages.readonly));
var updateObject = driveConfig.updateObject; var updateObject = driveConfig.updateObject;
var updateSharedFolders = driveConfig.updateSharedFolders; var updateSharedFolders = driveConfig.updateSharedFolders;
@ -1917,7 +1917,9 @@ define([
var $files = $('<span>', { var $files = $('<span>', {
'class': 'cp-app-drive-element-files cp-app-drive-element-list' 'class': 'cp-app-drive-element-files cp-app-drive-element-list'
}).text(files); }).text(files);
if (getViewMode() === 'grid') {
$span.attr('title', key); $span.attr('title', key);
}
$span.append($name).append($state).append($subfolders).append($files); $span.append($name).append($state).append($subfolders).append($files);
}; };
@ -2167,6 +2169,7 @@ define([
var createInfoBox = function (path) { var createInfoBox = function (path) {
if (APP.readOnly || $content.data('readOnlyFolder')) { return; }
var $box = $('<div>', {'class': 'cp-app-drive-content-info-box'}); var $box = $('<div>', {'class': 'cp-app-drive-content-info-box'});
var msg; var msg;
switch (path[0]) { switch (path[0]) {
@ -3360,13 +3363,11 @@ define([
var readOnlyFolder = false; var readOnlyFolder = false;
if (APP.readOnly) { if (APP.readOnly) {
// Read-only drive (team?) // Read-only drive (team?)
$readOnly.show(); $content.prepend($readOnly.clone());
} else if (folders[sfId] && folders[sfId].readOnly) { } else if (sfId && folders[sfId] && folders[sfId].readOnly) {
// If readonly shared folder... // If readonly shared folder...
$readOnly.show(); $content.prepend($readOnly.clone());
readOnlyFolder = true; readOnlyFolder = true;
} else {
$readOnly.hide();
} }
$content.data('readOnlyFolder', readOnlyFolder); $content.data('readOnlyFolder', readOnlyFolder);

@ -1035,6 +1035,10 @@ define([
team.userObject.setReadOnly(!secret.keys.secondaryKey, secret.keys.secondaryKey); team.userObject.setReadOnly(!secret.keys.secondaryKey, secret.keys.secondaryKey);
} }
if (!secret.keys.secondaryKey && team.rpc) {
team.rpc.destroy();
}
// Upgrade the shared folders // Upgrade the shared folders
var folders = Util.find(team, ['proxy', 'drive', 'sharedFolders']); var folders = Util.find(team, ['proxy', 'drive', 'sharedFolders']);
Object.keys(folders || {}).forEach(function (sfId) { Object.keys(folders || {}).forEach(function (sfId) {

@ -115,9 +115,13 @@ define([
}; };
exp.deprecateSharedFolder = function (id) { exp.deprecateSharedFolder = function (id) {
if (readOnly) { return; }
var data = files[SHARED_FOLDERS][id]; var data = files[SHARED_FOLDERS][id];
if (!data) { return; } if (!data) { return; }
var ro = !data.href || exp.cryptor.decrypt(data.href).indexOf('#') === -1;
if (!ro) {
files[SHARED_FOLDERS_TEMP][id] = JSON.parse(JSON.stringify(data)); files[SHARED_FOLDERS_TEMP][id] = JSON.parse(JSON.stringify(data));
}
var paths = exp.findFile(Number(id)); var paths = exp.findFile(Number(id));
exp.delete(paths, null, true); exp.delete(paths, null, true);
delete files[SHARED_FOLDERS][id]; delete files[SHARED_FOLDERS][id];

@ -1233,5 +1233,14 @@
"driveOfflineError": "Die Verbindung zu CryptPad ist verloren gegangen. Änderungen an diesem Pad werden nicht in deinem CryptDrive gespeichert. Bitte schließe alle CryptPad-Tabs und versuche es in einem neuen Fenster erneut. ", "driveOfflineError": "Die Verbindung zu CryptPad ist verloren gegangen. Änderungen an diesem Pad werden nicht in deinem CryptDrive gespeichert. Bitte schließe alle CryptPad-Tabs und versuche es in einem neuen Fenster erneut. ",
"storageStatus": "Speicher:<br /><b>{0}</b> von <b>{1}</b> belegt", "storageStatus": "Speicher:<br /><b>{0}</b> von <b>{1}</b> belegt",
"teams_table": "Rollen", "teams_table": "Rollen",
"teams_table_generic": "Rollen und Berechtigungen" "teams_table_generic": "Rollen und Berechtigungen",
"teams_table_generic_view": "Ansehen: Zugriff auf Ordner und Pads (nur Lesen)",
"teams_table_generic_edit": "Bearbeiten: Erstellen, Ändern und Löschen von Ordnern und Pads",
"teams_table_generic_admin": "Mitglieder verwalten: Einladen und Entfernen von Mitgliedern, Ändern von Benutzerrollen bis maximal Admin",
"teams_table_generic_own": "Team verwalten: Ändern von Namen und Avatar des Teams, Hinzufügen oder Entfernen von Eigentümerschaften des Teams, Löschung des Teams",
"teams_table_specific": "Ausnahmen",
"teams_table_specificHint": "Dies sind ältere geteilte Ordner, wo Benutzer noch Bearbeitungsrechte haben. Für hier erstellte oder hierhin kopierte Pads gelten Standard-Berechtigungen.",
"teams_table_admins": "Mitglieder verwalten",
"teams_table_owners": "Team verwalten",
"teams_table_role": "Rolle"
} }

@ -17,7 +17,7 @@
<div id="cp-app-drive-content-container"> <div id="cp-app-drive-content-container">
<div id="cp-app-drive-toolbar"></div> <div id="cp-app-drive-toolbar"></div>
<div id="cp-app-drive-connection-state" style="display: none"></div> <div id="cp-app-drive-connection-state" style="display: none"></div>
<div id="cp-app-drive-edition-state" style="display: none"></div> <div id="cp-app-drive-edition-state" class="cp-app-drive-content-info-box" style="display: none"></div>
<div id="cp-app-drive-content" tabindex="2"></div> <div id="cp-app-drive-content" tabindex="2"></div>
</div> </div>
</div> </div>

@ -58,6 +58,14 @@ define([
APP.newSharedFolder = null; APP.newSharedFolder = null;
} }
} }
if (newObj && newObj.deprecated) {
delete folders[fId];
delete drive.sharedFolders[fId];
if (manager && manager.folders) {
delete manager.folders[fId];
}
return;
}
folders[fId] = folders[fId] || {}; folders[fId] = folders[fId] || {};
copyObjectValue(folders[fId], newObj); copyObjectValue(folders[fId], newObj);
folders[fId].readOnly = !secret.keys.secondaryKey; folders[fId].readOnly = !secret.keys.secondaryKey;
@ -69,6 +77,16 @@ define([
manager.folders[fId].userObject.setReadOnly(readOnly, secret.keys.secondaryKey); manager.folders[fId].userObject.setReadOnly(readOnly, secret.keys.secondaryKey);
})); }));
}); });
// Remove from memory folders that have been deleted from the drive remotely
oldIds.forEach(function (fId) {
if (!drive.sharedFolders[fId]) {
delete folders[fId];
delete drive.sharedFolders[fId];
if (manager && manager.folders) {
delete manager.folders[fId];
}
}
});
}).nThen(function () { }).nThen(function () {
cb(); cb();
}); });
@ -117,7 +135,6 @@ define([
SFCommon.create(waitFor(function (c) { common = c; })); SFCommon.create(waitFor(function (c) { common = c; }));
}).nThen(function (waitFor) { }).nThen(function (waitFor) {
$('#cp-app-drive-connection-state').text(Messages.disconnected); $('#cp-app-drive-connection-state').text(Messages.disconnected);
$('#cp-app-drive-edition-state').text(Messages.readonly);
var privReady = Util.once(waitFor()); var privReady = Util.once(waitFor());
var metadataMgr = common.getMetadataMgr(); var metadataMgr = common.getMetadataMgr();
if (JSON.stringify(metadataMgr.getPrivateData()) !== '{}') { if (JSON.stringify(metadataMgr.getPrivateData()) !== '{}') {

@ -152,6 +152,9 @@ define([
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
save(); save();
if (!$input.val()) { return; }
if (!$(el).closest('.kanban-item').is(':last-child')) { return; }
$(el).closest('.kanban-board').find('.kanban-title-button.fa-plus').click();
return; return;
} }
if (e.which === 27) { if (e.which === 27) {
@ -301,6 +304,8 @@ define([
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
save(); save();
if (!$input.val()) { return; }
$(el).closest('.kanban-board').find('.kanban-title-button.fa-plus').click();
return; return;
} }
if (e.which === 27) { if (e.which === 27) {

@ -80,6 +80,16 @@ define([
manager.folders[fId].userObject.setReadOnly(readOnly, secret.keys.secondaryKey); manager.folders[fId].userObject.setReadOnly(readOnly, secret.keys.secondaryKey);
})); }));
}); });
// Remove from memory folders that have been deleted from the drive remotely
oldIds.forEach(function (fId) {
if (!drive.sharedFolders[fId]) {
delete folders[fId];
delete drive.sharedFolders[fId];
if (manager && manager.folders) {
delete manager.folders[fId];
}
}
});
}).nThen(function () { }).nThen(function () {
cb(); cb();
}); });
@ -287,7 +297,7 @@ define([
// Provide secondaryKey // Provide secondaryKey
var teamData = (privateData.teams || {})[id] || {}; var teamData = (privateData.teams || {})[id] || {};
driveAPP.readOnly = !teamData.secondaryKey; driveAPP.readOnly = !teamData.hasSecondaryKey;
var drive = DriveUI.create(common, { var drive = DriveUI.create(common, {
proxy: proxy, proxy: proxy,
folders: folders, folders: folders,
@ -475,7 +485,6 @@ define([
h('div#cp-app-drive-content-container', [ h('div#cp-app-drive-content-container', [
h('div#cp-app-drive-toolbar'), h('div#cp-app-drive-toolbar'),
h('div#cp-app-drive-connection-state', {style: "display: none;"}, Messages.disconnected), h('div#cp-app-drive-connection-state', {style: "display: none;"}, Messages.disconnected),
h('div#cp-app-drive-edition-state', {style: "display: none;"}, Messages.readonly),
h('div#cp-app-drive-content', {tabindex:2}) h('div#cp-app-drive-content', {tabindex:2})
]) ])
]) ])
@ -745,7 +754,7 @@ define([
}); });
var pending = Object.keys(roster).filter(function (k) { var pending = Object.keys(roster).filter(function (k) {
if (!roster[k].pending) { return; } if (!roster[k].pending) { return; }
return roster[k].role === "MEMBER" || !roster[k].role; return roster[k].role === "VIEWER" || !roster[k].role;
}).map(function (k) { }).map(function (k) {
return makeMember(common, roster[k], me); return makeMember(common, roster[k], me);
}); });

Loading…
Cancel
Save