aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-node/src
diff options
context:
space:
mode:
Diffstat (limited to 'packages/meshbay-node/src')
-rw-r--r--packages/meshbay-node/src/meshbay_node/roster.py18
-rw-r--r--packages/meshbay-node/src/meshbay_node/transport/webrtc/admin.py7
-rw-r--r--packages/meshbay-node/src/meshbay_node/transport/webrtc/admission.py5
-rw-r--r--packages/meshbay-node/src/meshbay_node/transport/webrtc/handshake.py1
4 files changed, 28 insertions, 3 deletions
diff --git a/packages/meshbay-node/src/meshbay_node/roster.py b/packages/meshbay-node/src/meshbay_node/roster.py
index eb8c031..07b9ea6 100644
--- a/packages/meshbay-node/src/meshbay_node/roster.py
+++ b/packages/meshbay-node/src/meshbay_node/roster.py
@@ -398,6 +398,24 @@ class Roster:
(user_id,)) as cur:
return [dict(r) for r in await cur.fetchall()]
+ async def name_identity(self, user_id: str, username: str) -> bool:
+ """
+ Give a nameless account the name its hub token carries.
+
+ Only an empty name is filled: an invitation names the person the
+ operator meant, and that stays. Links, devices and open groups pin an
+ account with no name, which left the audit log showing a bare id.
+ """
+ assert self._db
+ if not username:
+ return False
+ cur = await self._db.execute(
+ "UPDATE identities SET username = ? "
+ "WHERE user_id = ? AND username = ''",
+ (username, user_id))
+ await self._db.commit()
+ return cur.rowcount > 0
+
async def revoke_device(self, user_id: str, pk_ed25519: str) -> bool:
"""
Retire one device, leaving the account's others alone.
diff --git a/packages/meshbay-node/src/meshbay_node/transport/webrtc/admin.py b/packages/meshbay-node/src/meshbay_node/transport/webrtc/admin.py
index 9a6cbd1..48734ab 100644
--- a/packages/meshbay-node/src/meshbay_node/transport/webrtc/admin.py
+++ b/packages/meshbay-node/src/meshbay_node/transport/webrtc/admin.py
@@ -157,6 +157,13 @@ class AdminMixin:
if ident and not self._device_confirmed:
self._pinned_pk = ident["pk_ed25519"]
+ async def _name_identity(self) -> None:
+ """Record the token's username for an account the roster has unnamed."""
+ roster = self._ctx.get("roster")
+ if roster is None or not self._user_id or not self._username:
+ return
+ await roster.name_identity(self._user_id, self._username)
+
def _is_node_admin(self) -> bool:
"""
Whether the **account** on this connection is the one the node belongs to.
diff --git a/packages/meshbay-node/src/meshbay_node/transport/webrtc/admission.py b/packages/meshbay-node/src/meshbay_node/transport/webrtc/admission.py
index 20ebc79..fd9c756 100644
--- a/packages/meshbay-node/src/meshbay_node/transport/webrtc/admission.py
+++ b/packages/meshbay-node/src/meshbay_node/transport/webrtc/admission.py
@@ -380,9 +380,8 @@ class AdmissionMixin:
return
await self._pin_and_admit(
- # The name comes from the invitation, not from the token: the hub does
- # not put a username claim in a JWT, so pinning from the session alone
- # left the roster nameless and `member revoke <name>` unable to match.
+ # The invitation's name first: it is the person the operator meant.
+ # The token's name covers an invitation that carries none.
roster, user_id, invite["username"] or username, pk_ed_b64, pk_x_b64,
group_id=invite["group_id"], role=invite["role"],
approved_by=invite["created_by"],
diff --git a/packages/meshbay-node/src/meshbay_node/transport/webrtc/handshake.py b/packages/meshbay-node/src/meshbay_node/transport/webrtc/handshake.py
index 7822186..f3f4aee 100644
--- a/packages/meshbay-node/src/meshbay_node/transport/webrtc/handshake.py
+++ b/packages/meshbay-node/src/meshbay_node/transport/webrtc/handshake.py
@@ -212,6 +212,7 @@ class HandshakeMixin:
self._group_id = self._pending_group
self._username = self._pending_username
self._spawn(self._load_pinned_pk())
+ self._spawn(self._name_identity())
self._register_peer()