From 50e39f994502497b52c67e45fa0b4fdf0bab1279 Mon Sep 17 00:00:00 2001 From: yflory Date: Tue, 1 Oct 2019 11:33:42 +0200 Subject: [PATCH 01/10] Fix a race condition in teams --- www/common/outer/team.js | 12 +++++++++--- www/teams/inner.js | 5 +++-- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/www/common/outer/team.js b/www/common/outer/team.js index c5f053266..af232d01d 100644 --- a/www/common/outer/team.js +++ b/www/common/outer/team.js @@ -38,7 +38,9 @@ define([ // Also pin the onlyoffice channels if they exist if (n.rtChannel) { toPin.push(n.rtChannel); } if (n.lastVersion) { toPin.push(n.lastVersion); } - team.pin(toPin, function (obj) { console.error(obj); }); + team.pin(toPin, function (obj) { + if (obj && obj.error) { console.error(obj.error); } + }); } // Unpin the deleted pads (deleted <=> changed to undefined) if (p[0] === UserObject.FILES_DATA && typeof(o) === "object" && o.channel && !n) { @@ -51,7 +53,9 @@ define([ // Also unpin the onlyoffice channels if they exist if (o.rtChannel) { toUnpin.push(o.rtChannel); } if (o.lastVersion) { toUnpin.push(o.lastVersion); } - team.unpin(toUnpin, function (obj) { console.error(obj); }); + team.unpin(toUnpin, function (obj) { + if (obj && obj.error) { console.error(obj); } + }); } } } @@ -692,7 +696,7 @@ define([ return true; } }); - if ((!member || member.role !== 'OWNER') && teamData.owner) { + if (!member && teamData.owner) { var removeOwnership = function (chan) { ctx.Store.setPadMetadata(null, { channel: chan, @@ -764,6 +768,7 @@ define([ var onError = function (res) { var err = res && res.error; if (err) { + console.error(err); waitFor.abort(); return void cb({error:err}); } @@ -822,6 +827,7 @@ define([ var onError = function (res) { var err = res && res.error; if (err) { + console.error(err); waitFor.abort(); return void cb(err); } diff --git a/www/teams/inner.js b/www/teams/inner.js index d5c02741b..b1cbc6e6f 100644 --- a/www/teams/inner.js +++ b/www/teams/inner.js @@ -452,7 +452,8 @@ define([ // Name var name = h('span.cp-team-member-name', data.displayName); if (data.pendingOwner) { - $(name).append(h('em', " PENDING")); + $(name).append(h('em', " PENDING")); // XXX + // + XXX ability to demote yourself as owner if there is another owner } // Status var status = h('span.cp-team-member-status'+(data.online ? '.online' : '')); @@ -468,9 +469,9 @@ define([ title: Messages.team_rosterPromoteOwner }); $(promoteOwner).click(function () { - $(promoteOwner).hide(); UI.confirm(Messages.team_ownerConfirm, function (yes) { if (!yes) { return; } + $(promoteOwner).hide(); APP.module.execCommand('OFFER_OWNERSHIP', { teamId: APP.team, curvePublic: data.curvePublic From 22d5e417e4be5459976ba34b864adfe74328c51d Mon Sep 17 00:00:00 2001 From: yflory Date: Tue, 1 Oct 2019 11:46:52 +0200 Subject: [PATCH 02/10] Prevent infinite loop in the drive --- www/common/drive-ui.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/www/common/drive-ui.js b/www/common/drive-ui.js index d1b360bdf..e337bd386 100644 --- a/www/common/drive-ui.js +++ b/www/common/drive-ui.js @@ -3245,6 +3245,11 @@ define([ if (!isVirtual && typeof(root) === "undefined") { log(Messages.fm_unknownFolderError); debug("Unable to locate the selected directory: ", path); + if (path.length === 1 && path[0] === ROOT) { + // Somehow we can't display ROOT. We should abort now because we'll + // end up in an infinite loop + return void UI.warn(Messages.fm_error_cantPin); // Internal server error, please reload... + } var parentPath = path.slice(); parentPath.pop(); _displayDirectory(parentPath, true); From 590e6bd21152529fb19f24e8b527c16d3d46c5f7 Mon Sep 17 00:00:00 2001 From: yflory Date: Tue, 1 Oct 2019 11:57:21 +0200 Subject: [PATCH 03/10] Demote yourself --- www/common/translations/messages.json | 3 ++- www/teams/inner.js | 25 ++++++++++++++++++------- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/www/common/translations/messages.json b/www/common/translations/messages.json index 20525bc13..175a14d65 100644 --- a/www/common/translations/messages.json +++ b/www/common/translations/messages.json @@ -1212,5 +1212,6 @@ "team_deleteTitle": "Team deletion", "team_deleteHint": "Delete the team and all documents owned exclusively by the team.", "team_deleteButton": "Delete", - "team_deleteConfirm": "You are about to delete all of an entire team's data. This may impact other team members access to their data. This cannot be undone. Are you sure you want to proceed?" + "team_deleteConfirm": "You are about to delete all of an entire team's data. This may impact other team members access to their data. This cannot be undone. Are you sure you want to proceed?", + "team_demoteMeConfirm": "You are about to give up your rights. You will not be able to undo this action. Are you sure?" } diff --git a/www/teams/inner.js b/www/teams/inner.js index b1cbc6e6f..97af2c131 100644 --- a/www/teams/inner.js +++ b/www/teams/inner.js @@ -452,7 +452,9 @@ define([ // Name var name = h('span.cp-team-member-name', data.displayName); if (data.pendingOwner) { - $(name).append(h('em', " PENDING")); // XXX + $(name).append(h('em', { + title: Messages.team_pendingOwnerTitle + }, ' ' + Messages.team_pendingOwner)); // + XXX ability to demote yourself as owner if there is another owner } // Status @@ -501,16 +503,25 @@ define([ } // If I'm not a member and I have an equal or higher role than them, I can demote them // (if they're not already a MEMBER) - if (!isMe && myRole >= theirRole && theirRole > 0 && !data.pending) { + if (myRole >= theirRole && theirRole > 0 && !data.pending) { var demote = h('span.fa.fa-angle-double-down', { title: Messages.team_rosterDemote }); $(demote).click(function () { - var role = ROLES[theirRole - 1] || 'MEMBER'; - $(demote).hide(); - describeUser(common, data.curvePublic, { - role: role - }, promote); + var todo = function () { + var role = ROLES[theirRole - 1] || 'MEMBER'; + $(demote).hide(); + describeUser(common, data.curvePublic, { + role: role + }, promote); + }; + if (isMe) { + return void UI.confirm(Messages.team_demoteMeConfirm, function (yes) { + if (!yes) { return; } + todo(); + }); + } + todo(); }); $actions.append(demote); } From 572b9eb09be42684fead093a40e1623597136553 Mon Sep 17 00:00:00 2001 From: yflory Date: Tue, 1 Oct 2019 12:01:18 +0200 Subject: [PATCH 04/10] Fix merge conflict with weblate --- www/common/translations/messages.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/www/common/translations/messages.json b/www/common/translations/messages.json index 175a14d65..20525bc13 100644 --- a/www/common/translations/messages.json +++ b/www/common/translations/messages.json @@ -1212,6 +1212,5 @@ "team_deleteTitle": "Team deletion", "team_deleteHint": "Delete the team and all documents owned exclusively by the team.", "team_deleteButton": "Delete", - "team_deleteConfirm": "You are about to delete all of an entire team's data. This may impact other team members access to their data. This cannot be undone. Are you sure you want to proceed?", - "team_demoteMeConfirm": "You are about to give up your rights. You will not be able to undo this action. Are you sure?" + "team_deleteConfirm": "You are about to delete all of an entire team's data. This may impact other team members access to their data. This cannot be undone. Are you sure you want to proceed?" } From f33bc98c143512beed0e672554001cf0c09a9d4b Mon Sep 17 00:00:00 2001 From: Weblate Date: Tue, 1 Oct 2019 10:01:41 +0000 Subject: [PATCH 05/10] Translated using Weblate (English) Currently translated at 100.0% (1120 of 1120 strings) Translation: CryptPad/App Translate-URL: http://weblate.cryptpad.fr/projects/cryptpad/app/en/ Translated using Weblate (English) Currently translated at 100.0% (1119 of 1119 strings) Translation: CryptPad/App Translate-URL: http://weblate.cryptpad.fr/projects/cryptpad/app/en/ --- www/common/translations/messages.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/www/common/translations/messages.json b/www/common/translations/messages.json index 20525bc13..e5aef9818 100644 --- a/www/common/translations/messages.json +++ b/www/common/translations/messages.json @@ -1212,5 +1212,7 @@ "team_deleteTitle": "Team deletion", "team_deleteHint": "Delete the team and all documents owned exclusively by the team.", "team_deleteButton": "Delete", - "team_deleteConfirm": "You are about to delete all of an entire team's data. This may impact other team members access to their data. This cannot be undone. Are you sure you want to proceed?" + "team_deleteConfirm": "You are about to delete all of an entire team's data. This may impact other team members access to their data. This cannot be undone. Are you sure you want to proceed?", + "team_pendingOwner": "(pending)", + "team_pendingOwnerTitle": "This administrator has not accepted the ownership offer yet." } From 260b25079ce7b62aa29f4ea0d032121da798cdb4 Mon Sep 17 00:00:00 2001 From: Weblate Date: Tue, 1 Oct 2019 10:01:41 +0000 Subject: [PATCH 06/10] Translated using Weblate (French) Currently translated at 100.0% (1120 of 1120 strings) Translation: CryptPad/App Translate-URL: http://weblate.cryptpad.fr/projects/cryptpad/app/fr/ --- www/common/translations/messages.fr.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/www/common/translations/messages.fr.json b/www/common/translations/messages.fr.json index dbbadd86b..899f45e88 100644 --- a/www/common/translations/messages.fr.json +++ b/www/common/translations/messages.fr.json @@ -1212,5 +1212,7 @@ "team_deleteTitle": "Suppression de l'équipe", "team_deleteHint": "Supprimer l'équipe et tous les documents dont elle est exclusivement propriétaire.", "team_deleteButton": "Supprimer", - "team_deleteConfirm": "Vous êtes sur le point de supprimer les données d'une équipe entière. Cette action peut impacter l'accès à leur données pour d'autres membres de l'équipe. La suppression est irréversible. Êtes-vous sûr de vouloir continuer ?" + "team_deleteConfirm": "Vous êtes sur le point de supprimer les données d'une équipe entière. Cette action peut impacter l'accès à leur données pour d'autres membres de l'équipe. La suppression est irréversible. Êtes-vous sûr de vouloir continuer ?", + "team_pendingOwner": "(en attente)", + "team_pendingOwnerTitle": "Cet administrateur n'a pas encore accepté l'offre de devenir propriétaire de l'équipe." } From 24a474068b09609ae7acd6b9f05c5da8eb2062b2 Mon Sep 17 00:00:00 2001 From: Weblate Date: Tue, 1 Oct 2019 10:03:05 +0000 Subject: [PATCH 07/10] Translated using Weblate (English) Currently translated at 100.0% (1121 of 1121 strings) Translation: CryptPad/App Translate-URL: http://weblate.cryptpad.fr/projects/cryptpad/app/en/ --- www/common/translations/messages.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/www/common/translations/messages.json b/www/common/translations/messages.json index e5aef9818..feab1a206 100644 --- a/www/common/translations/messages.json +++ b/www/common/translations/messages.json @@ -1214,5 +1214,6 @@ "team_deleteButton": "Delete", "team_deleteConfirm": "You are about to delete all of an entire team's data. This may impact other team members access to their data. This cannot be undone. Are you sure you want to proceed?", "team_pendingOwner": "(pending)", - "team_pendingOwnerTitle": "This administrator has not accepted the ownership offer yet." + "team_pendingOwnerTitle": "This administrator has not accepted the ownership offer yet.", + "team_demoteMeConfirm": "You are about to give up your rights. You will not be able to undo this action. Are you sure?" } From 1f14f75e9530088873b71c78a3fa3ab988972a78 Mon Sep 17 00:00:00 2001 From: Weblate Date: Tue, 1 Oct 2019 10:03:05 +0000 Subject: [PATCH 08/10] Translated using Weblate (French) Currently translated at 100.0% (1121 of 1121 strings) Translation: CryptPad/App Translate-URL: http://weblate.cryptpad.fr/projects/cryptpad/app/fr/ --- www/common/translations/messages.fr.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/www/common/translations/messages.fr.json b/www/common/translations/messages.fr.json index 899f45e88..d585d6e02 100644 --- a/www/common/translations/messages.fr.json +++ b/www/common/translations/messages.fr.json @@ -1214,5 +1214,6 @@ "team_deleteButton": "Supprimer", "team_deleteConfirm": "Vous êtes sur le point de supprimer les données d'une équipe entière. Cette action peut impacter l'accès à leur données pour d'autres membres de l'équipe. La suppression est irréversible. Êtes-vous sûr de vouloir continuer ?", "team_pendingOwner": "(en attente)", - "team_pendingOwnerTitle": "Cet administrateur n'a pas encore accepté l'offre de devenir propriétaire de l'équipe." + "team_pendingOwnerTitle": "Cet administrateur n'a pas encore accepté l'offre de devenir propriétaire de l'équipe.", + "team_demoteMeConfirm": "Vous êtes sur le point de renoncer à vos droits. Vous ne serez pas en mesure d'annuler cette action. Continuer ?" } From b8f6b570194abc5ef4156e05321c6bdd8dc5f046 Mon Sep 17 00:00:00 2001 From: yflory Date: Tue, 1 Oct 2019 12:15:23 +0200 Subject: [PATCH 09/10] Demote yourself as owner only if there are no other owners --- www/teams/inner.js | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/www/teams/inner.js b/www/teams/inner.js index 97af2c131..024bb419d 100644 --- a/www/teams/inner.js +++ b/www/teams/inner.js @@ -444,8 +444,14 @@ define([ redrawRoster(common); }); }; - var makeMember = function (common, data, me) { + var makeMember = function (common, data, me, roster) { if (!data.curvePublic) { return; } + + var otherOwners = Object.keys(roster || {}).some(function (key) { + var user = roster[key]; + return user.role === "OWNER" && user.curvePublic !== me.curvePublic && !user.pendingOwner; + }); + // Avatar var avatar = h('span.cp-avatar.cp-team-member-avatar'); common.displayAvatar($(avatar), data.avatar, data.displayName); @@ -455,7 +461,6 @@ define([ $(name).append(h('em', { title: Messages.team_pendingOwnerTitle }, ' ' + Messages.team_pendingOwner)); - // + XXX ability to demote yourself as owner if there is another owner } // Status var status = h('span.cp-team-member-status'+(data.online ? '.online' : '')); @@ -523,7 +528,9 @@ define([ } todo(); }); - $actions.append(demote); + if (!(isMe && myRole === 2 && !otherOwners)) { + $actions.append(demote); + } } // If I'm not a member and I have an equal or higher role than them, I can remove them // Note: we can't remove owners, we have to demote them first @@ -579,7 +586,7 @@ define([ if (roster[k].pending) { return; } return roster[k].role === "OWNER" || roster[k].pendingOwner; }).map(function (k) { - return makeMember(common, roster[k], me); + return makeMember(common, roster[k], me, roster); }); var admins = Object.keys(roster).filter(function (k) { if (roster[k].pending) { return; } From 6abc8151d16d8f86dadbf9416c5b2a8133ad1721 Mon Sep 17 00:00:00 2001 From: yflory Date: Tue, 1 Oct 2019 12:15:50 +0200 Subject: [PATCH 10/10] lint compliance --- www/teams/inner.js | 1 - 1 file changed, 1 deletion(-) diff --git a/www/teams/inner.js b/www/teams/inner.js index 024bb419d..f1691ec4d 100644 --- a/www/teams/inner.js +++ b/www/teams/inner.js @@ -155,7 +155,6 @@ define([ if (obj && obj.error) { return void UI.warn(Messages.error); } - var val = obj.avatar; common.displayAvatar($avatar, obj.avatar, obj.name); $category.append($avatar); $avatar.append(obj.name);