aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/src
diff options
context:
space:
mode:
Diffstat (limited to 'packages/meshbay-hub/src')
-rw-r--r--packages/meshbay-hub/src/meshbay_hub/static/group-settings.js19
1 files changed, 17 insertions, 2 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/group-settings.js b/packages/meshbay-hub/src/meshbay_hub/static/group-settings.js
index 4d67348..16f6901 100644
--- a/packages/meshbay-hub/src/meshbay_hub/static/group-settings.js
+++ b/packages/meshbay-hub/src/meshbay_hub/static/group-settings.js
@@ -727,11 +727,23 @@ function GroupSettingsPanel({ groupId, group, token, transportRef, gekRef,
* wrapped for them; if the hub removal then fails, they are a member on paper
* with no key. The other order would leave them able to reach a node that
* still serves them.
+ *
+ * **A node that refuses does not cancel the hub half.** It used to: the node
+ * call threw, the whole removal ended there, and the person stayed a member
+ * everywhere — the list here (the hub answers it), the owner's other
+ * sessions, the administrator's view — with nothing said about which half
+ * had failed. Someone invited to the wrong group hit it every time, because
+ * a node holds no member row for an invitation nobody has redeemed and
+ * answered "no such member in that group" to the only button offering to
+ * take them back out. The hub half only ever removes access, so it is not
+ * the half to skip when the other is in doubt; what the node said is
+ * reported once the removal has been done, rather than in place of it.
*/
const removeMember = useCallback(async (member) => {
const transport = transportRef && transportRef.current;
setError('');
setRemoving(member.user_id);
+ let nodeError = '';
try {
if (platform.node.available) {
try {
@@ -747,14 +759,17 @@ function GroupSettingsPanel({ groupId, group, token, transportRef, gekRef,
const signFn = (sk && window.MeshBayKeys)
? (transcript) => window.MeshBayKeys.signBytes(sk, transcript)
: null;
- await transport.revokeMember(member.user_id, signFn);
+ try {
+ await transport.revokeMember(member.user_id, signFn);
+ } catch (err) { nodeError = err.message; }
}
await hubFetch(`/v1/groups/${groupId}/members/${member.username}`, {
method: 'DELETE', token,
});
loadMembers();
+ if (nodeError) setError(nodeError);
} catch (err) {
- setError(err.message);
+ setError(nodeError ? `${nodeError} — ${err.message}` : err.message);
} finally {
setRemoving('');
}