From fb92ea1ae7cb3d77fbbea3132b49b29f0a38320e Mon Sep 17 00:00:00 2001 From: veg Date: Mon, 21 Sep 2026 09:41:31 +0000 Subject: [PATCH] refactor: extract guest session helpers The __party_guest_$user session name was spelled out in cmd_join, cmd_leave, cmd_status, cmd_role, and _disconnect_user. Add guest_session_name to print it consistently. Add ensure_guest_session for the has-session/new-session snippet duplicated in cmd_join and cmd_role. Add caller_present_on for the client-or-guest-session OR duplicated in cmd_leave and cmd_status. --- party | 85 +++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 50 insertions(+), 35 deletions(-) diff --git a/party b/party index f8a08a3..0c21411 100755 --- a/party +++ b/party @@ -398,6 +398,42 @@ party_conn_state() { fi } +# Guest sessions +# -------------- + +# Print the caller's guest session name for a given user: the fixed +# session __party_guest_ that join/leave/status/role/kick/detach +# all target. +guest_session_name() { + printf '__party_guest_%s\n' "$1" +} + +# Ensure the caller's guest session exists on , creating it off +# if needed. Leaves the session name in `guest` for the +# caller. +# +# Reusing by name is an accepted insider risk, not a defended one: any +# write-capable invitee can pre-create a session called +# __party_guest_$USER (and even group it to the party), so on a shared +# server no session name is unforgeable. We trust invitees by design, +# that's the whole model. A read-only invitee (-r) can't create +# sessions, so it's not exposed. See README §Trust model. +ensure_guest_session() { + _eg_sock="$1" _eg_host_sess="$2" + guest=$(guest_session_name "$USER") + "$PARTY_TMUX" -S "$_eg_sock" has-session -t "$guest" 2>/dev/null \ + || "$PARTY_TMUX" -S "$_eg_sock" new-session -d -t "$_eg_host_sess" -s "$guest" +} + +# Boolean: does the caller have any presence on the party at , +# either an attached client or an owned guest session? Only meaningful +# when party_conn_state is `ok`; callers gate on that themselves. +caller_present_on() { + "$PARTY_TMUX" -S "$1" list-clients -F '#{client_user}' 2>/dev/null \ + | grep -qx "$USER" \ + || "$PARTY_TMUX" -S "$1" has-session -t "$(guest_session_name "$USER")" 2>/dev/null +} + # FS perms # -------- # @@ -1267,17 +1303,7 @@ EOF # An active guest session survives a client detach, so create it # only if it isn't already there, a plain new-session on re-join # would hit "duplicate session" and abort under set -e. - # - # Reusing by name is an accepted insider risk, not a defended one: - # any write-capable invitee can pre-create a session called - # __party_guest_$USER (and even group it to the party), so on a - # shared server no session name is unforgeable. We trust invitees - # by design, that's the whole model. A read-only invitee (-r) - # can't create sessions, so it's not exposed. See README §Trust - # model. - guest="__party_guest_$USER" - "$PARTY_TMUX" -S "$RR_SOCKET" has-session -t "$guest" 2>/dev/null \ - || "$PARTY_TMUX" -S "$RR_SOCKET" new-session -d -t "$RR_PARTY_NAME" -s "$guest" + ensure_guest_session "$RR_SOCKET" "$RR_PARTY_NAME" set -- attach-session -t "$guest" fi @@ -1314,17 +1340,13 @@ cmd_leave() { found=0 for rec in $(roster_list); do roster_read "$rec" || continue - # Presence checks below (has-session, list-clients) are only - # meaningful on a server that accepted our connection: for an - # unauthorized caller has-session answers rc 0 for ANY target, - # which made leave "succeed" against parties we never joined. + # Presence checks inside caller_present_on (has-session, + # list-clients) are only meaningful on a server that accepted + # our connection: for an unauthorized caller has-session answers + # rc 0 for ANY target, which made leave "succeed" against + # parties we never joined. [ "$(party_conn_state "$RR_SOCKET")" = ok ] || continue - attached=0 - "$PARTY_TMUX" -S "$RR_SOCKET" has-session -t "__party_guest_$USER" 2>/dev/null \ - && attached=1 - "$PARTY_TMUX" -S "$RR_SOCKET" list-clients -F '#{client_user}' 2>/dev/null \ - | grep -qx "$USER" && attached=1 - [ "$attached" = 1 ] || continue + caller_present_on "$RR_SOCKET" || continue _disconnect_user "$USER" found=$((found+1)) done @@ -1512,7 +1534,7 @@ cmd_mute() { _set_user_access mute -r Muted "$@"; } # their guest session if present. Used by both cmd_kick and cmd_detach. _disconnect_user() { user="$1" - "$PARTY_TMUX" -S "$RR_SOCKET" kill-session -t "__party_guest_$user" 2>/dev/null || true + "$PARTY_TMUX" -S "$RR_SOCKET" kill-session -t "$(guest_session_name "$user")" 2>/dev/null || true "$PARTY_TMUX" -S "$RR_SOCKET" list-clients -F '#{client_name} #{client_user}' 2>/dev/null \ | while read -r cname cuser; do [ "$cuser" = "$user" ] || continue @@ -1674,14 +1696,10 @@ cmd_status() { [ "$state" = ok ] || continue # Joined covers two cases. Passive: we have a client attached to # the host's session, list-clients sees it. Active: we have our - # own __party_guest_$USER session, which survives a client detach - # (party leave will still find and clean it up). OR the two so a - # detached active guest still reports as joined. - if "$PARTY_TMUX" -S "$RR_SOCKET" list-clients -F '#{client_user}' \ - 2>/dev/null | grep -qx "$USER" \ - || "$PARTY_TMUX" -S "$RR_SOCKET" has-session \ - -t "__party_guest_$USER" 2>/dev/null - then + # own guest session, which survives a client detach (party leave + # will still find and clean it up). caller_present_on ORs the + # two so a detached active guest still reports as joined. + if caller_present_on "$RR_SOCKET"; then joined="$joined $RR_PARTY_NAME" fi done @@ -1739,15 +1757,12 @@ EOF done fi [ -n "$sock" ] || { echo "party role: not attached to any party." >&2; exit 1; } - guest="__party_guest_$USER" + guest=$(guest_session_name "$USER") # active and switch may switch a client INTO the guest session; create # it on demand. passive and the no-arg print path don't need it. case "$sub" in - active|switch) - "$PARTY_TMUX" -S "$sock" has-session -t "$guest" 2>/dev/null \ - || "$PARTY_TMUX" -S "$sock" new-session -d -t "$host_sess" -s "$guest" - ;; + active|switch) ensure_guest_session "$sock" "$host_sess" ;; esac "$PARTY_TMUX" -S "$sock" list-clients \