From bca1c086534cac6fcbbd2e187fa94b3be9253a5c Mon Sep 17 00:00:00 2001 From: yflory Date: Fri, 2 Jul 2021 18:46:03 +0200 Subject: [PATCH] Fix team pending owner issues --- www/common/outer/team.js | 162 +++++++++++++++++++++++---------------- www/teams/inner.js | 32 ++++---- 2 files changed, 113 insertions(+), 81 deletions(-) diff --git a/www/common/outer/team.js b/www/common/outer/team.js index 0ec224984..3dc39c6f3 100644 --- a/www/common/outer/team.js +++ b/www/common/outer/team.js @@ -986,47 +986,60 @@ define([ var state = team.roster.getState() || {}; var members = state.members || {}; - // Get pending owners - var md = team.listmap.metadata || {}; - if (Array.isArray(md.pending_owners)) { - // Get the members associated to the pending_owners' edPublic and mark them as such - md.pending_owners.forEach(function (ed) { - var member; - Object.keys(members).some(function (curve) { - if (members[curve].edPublic === ed) { - member = members[curve]; - return true; - } - }); - if (!member && teamData.owner) { - var removeOwnership = function (chan) { - ctx.Store.setPadMetadata(null, { - channel: chan, - command: 'RM_PENDING_OWNERS', - value: [ed], - }, function () {}); - }; - removeOwnership(teamData.channel); - removeOwnership(Util.find(teamData, ['keys', 'roster', 'channel'])); - removeOwnership(Util.find(teamData, ['keys', 'chat', 'channel'])); + var md; + nThen(function (waitFor) { + // Get pending owners + ctx.Store.getPadMetadata(null, { + channel: teamData.channel + }, waitFor(function (obj) { + if (obj && obj.error) { + md = team.listmap.metadata || {}; return; } - member.pendingOwner = true; - }); - } + md = obj; + })); + }).nThen(function () { + ctx.pending_owners = md.pending_owners; + if (Array.isArray(md.pending_owners)) { + // Get the members associated to the pending_owners' edPublic and mark them as such + md.pending_owners.forEach(function (ed) { + var member; + Object.keys(members).some(function (curve) { + if (members[curve].edPublic === ed) { + member = members[curve]; + return true; + } + }); + if (!member && teamData.owner) { + var removeOwnership = function (chan) { + ctx.Store.setPadMetadata(null, { + channel: chan, + command: 'RM_PENDING_OWNERS', + value: [ed], + }, function () {}); + }; + removeOwnership(teamData.channel); + removeOwnership(Util.find(teamData, ['keys', 'roster', 'channel'])); + removeOwnership(Util.find(teamData, ['keys', 'chat', 'channel'])); + return; + } + member.pendingOwner = true; + }); + } - // Add online status (using messenger data) - if (ctx.store.messenger) { - var chatData = team.getChatData(); - var online = ctx.store.messenger.getOnlineList(chatData.channel) || []; - online.forEach(function (curve) { - if (members[curve]) { - members[curve].online = true; - } - }); - } + // Add online status (using messenger data) + if (ctx.store.messenger) { + var chatData = team.getChatData(); + var online = ctx.store.messenger.getOnlineList(chatData.channel) || []; + online.forEach(function (curve) { + if (members[curve]) { + members[curve].online = true; + } + }); + } - cb(members); + cb(members); + }); }; // Return folders with edit rights available to everybody (decrypted pad href) @@ -1144,8 +1157,7 @@ define([ if (!teamData) { return void cb ({error: 'ENOENT'}); } var team = ctx.teams[teamId]; if (!team) { return void cb ({error: 'ENOENT'}); } - var md = team.listmap.metadata || {}; - var isPendingOwner = (md.pending_owners || []).indexOf(user.edPublic) !== -1; + var isPendingOwner = user.pendingOwner; nThen(function (waitFor) { var cmd = isPendingOwner ? 'RM_PENDING_OWNERS' : 'RM_OWNERS'; @@ -1364,42 +1376,60 @@ define([ var describeUser = function (ctx, data, cId, cb) { var teamId = data.teamId; if (!teamId) { return void cb({error: 'EINVAL'}); } + var teamData = Util.find(ctx, ['store', 'proxy', 'teams', teamId]); var team = ctx.teams[teamId]; - if (!team) { return void cb ({error: 'ENOENT'}); } + if (!teamData || !team) { return void cb ({error: 'ENOENT'}); } if (!team.roster) { return void cb({error: 'NO_ROSTER'}); } if (!data.curvePublic || !data.data) { return void cb({error: 'MISSING_DATA'}); } var state = team.roster.getState(); var user = state.members[data.curvePublic]; - // It it is an ownership revocation, we have to set it in pad metadata first - if (user.role === "OWNER" && data.data.role !== "OWNER") { - revokeOwnership(ctx, teamId, user, function (err) { - if (!err) { return void cb(); } - console.error(err); - return void cb({error: err}); - }); - return; - } + var md; + nThen(function (waitFor) { + // Get pending owners + ctx.Store.getPadMetadata(null, { + channel: teamData.channel + }, waitFor(function (obj) { + if (obj && obj.error) { + md = team.listmap.metadata || {}; + return; + } + md = obj; + })); + }).nThen(function () { + user.pendingOwner = Array.isArray(md.pending_owners) && + md.pending_owners.indexOf(user.edPublic) !== -1; - // Viewer to editor - if (user.role === "VIEWER" && data.data.role !== "VIEWER") { - changeEditRights(ctx, teamId, user, true, function (obj) { - return void cb(obj); - }); - } + // It it is an ownership revocation, we have to set it in pad metadata first + if (user.role === "OWNER" && data.data.role !== "OWNER") { + revokeOwnership(ctx, teamId, user, function (err) { + if (!err) { return void cb(); } + console.error(err); + return void cb({error: err}); + }); + return; + } - // Editor to viewer - if (user.role !== "VIEWER" && data.data.role === "VIEWER") { - changeEditRights(ctx, teamId, user, false, function (obj) { - return void cb(obj); - }); - } + // Viewer to editor + if (user.role === "VIEWER" && data.data.role !== "VIEWER") { + changeEditRights(ctx, teamId, user, true, function (obj) { + return void cb(obj); + }); + } - var obj = {}; - obj[data.curvePublic] = data.data; - team.roster.describe(obj, function (err) { - if (err) { return void cb({error: err}); } - cb(); + // Editor to viewer + if (user.role !== "VIEWER" && data.data.role === "VIEWER") { + changeEditRights(ctx, teamId, user, false, function (obj) { + return void cb(obj); + }); + } + + var obj = {}; + obj[data.curvePublic] = data.data; + team.roster.describe(obj, function (err) { + if (err) { return void cb({error: err}); } + cb(); + }); }); }; diff --git a/www/teams/inner.js b/www/teams/inner.js index 4b0532628..7a7cf9116 100644 --- a/www/teams/inner.js +++ b/www/teams/inner.js @@ -768,7 +768,7 @@ define([ $(demote).hide(); describeUser(common, data.curvePublic, { role: role - }, promote); + }, demote); }; if (isMe) { return void UI.confirm(Messages.team_demoteMeConfirm, function (yes) { @@ -901,22 +901,24 @@ define([ $header.append(invite); } - if (me && (me.role !== 'OWNER')) { - var leave = h('button.cp-online.btn.btn-danger', Messages.team_leaveButton); - $(leave).click(function () { - UI.confirm(Messages.team_leaveConfirm, function (yes) { - if (!yes) { return; } - APP.module.execCommand('LEAVE_TEAM', { - teamId: APP.team - }, function (obj) { - if (obj && obj.error) { - return void UI.warn(Messages.error); - } - }); + var leave = h('button.cp-online.btn.btn-danger', Messages.team_leaveButton); + $(leave).click(function () { + if (me && me.role === 'OWNER') { + Messages.team_leaveOwner = "Owners can't leave the team. You can demote yourself if there is at least one other owner."; // XXX + return void UI.alert(Messages.team_leaveOwner); + } + UI.confirm(Messages.team_leaveConfirm, function (yes) { + if (!yes) { return; } + APP.module.execCommand('LEAVE_TEAM', { + teamId: APP.team + }, function (obj) { + if (obj && obj.error) { + return void UI.warn(Messages.error); + } }); }); - $header.append(leave); - } + }); + $header.append(leave); var table = h('button.btn.btn-primary', Messages.teams_table); $(table).click(function (e) {