diff options
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub/api')
| -rw-r--r-- | packages/meshbay-hub/src/meshbay_hub/api/invite_links.py | 27 |
1 files changed, 17 insertions, 10 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/api/invite_links.py b/packages/meshbay-hub/src/meshbay_hub/api/invite_links.py index d44576b..f33dc6e 100644 --- a/packages/meshbay-hub/src/meshbay_hub/api/invite_links.py +++ b/packages/meshbay-hub/src/meshbay_hub/api/invite_links.py @@ -43,7 +43,9 @@ MAX_OUTSTANDING_PER_GROUP = 20 # A node's invitation lifetime is the operator's setting (7 days by default); # the ticket follows it, up to this. MAX_LIFETIME = timedelta(days=30) -# How long a redeemed link stays in the owner's list, saying who used it. +# How long a spent link is kept before it is forgotten. The owner is not shown +# it — the person is in the group — but while the row is here, a reload or a +# second tab of the invitation page still answers the account that used it. KEEP_REDEEMED = timedelta(days=30) _TICKET = re.compile(r"^[A-Za-z0-9_-]{22}$") # secrets.token_urlsafe(16) @@ -205,14 +207,21 @@ async def list_invite_links( current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): - """The owner's view: who each link was for, masked, and whether it was used.""" + """ + The owner's view: the links nobody has used yet, masked. + + A redeemed one is left out. The person it let in has a row of their own in + the members list, so keeping the link there too says the same thing twice + and pushes down the links that still wait for somebody — which are the ones + the owner can act on, by cancelling them. + """ await _owned_group(db, group_id, current_user) rows = (await db.execute( - select(GroupInviteLink, User.username) - .outerjoin(User, User.id == GroupInviteLink.redeemed_by) - .where(GroupInviteLink.group_id == group_id) + select(GroupInviteLink) + .where(GroupInviteLink.group_id == group_id, + GroupInviteLink.redeemed_by.is_(None)) .order_by(GroupInviteLink.created_at.desc()) - .limit(200))).all() + .limit(200))).scalars().all() now = datetime.now(UTC) return {"links": [{ "link_id": r.id, @@ -220,10 +229,8 @@ async def list_invite_links( "node_invite_id": r.node_invite_id, "created_at": _aware(r.created_at).isoformat(), "expires_at": _aware(r.expires_at).isoformat(), - "status": ("redeemed" if r.redeemed_by - else "expired" if _aware(r.expires_at) <= now else "pending"), - "redeemed_by": name, - } for r, name in rows]} + "status": "expired" if _aware(r.expires_at) <= now else "pending", + } for r in rows]} @router.delete("/{group_id}/invite-links/{link_id}") |