From a9fc8385778fb74f09138f248d5cb3d0370eaff6 Mon Sep 17 00:00:00 2001 From: MechaCat02 Date: Wed, 27 May 2026 22:00:13 +0200 Subject: [PATCH] fix(dashboard): redirect after a member removes themselves MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A member-with-app_admin who removes their own membership keeps a now- broken Members tab open until reload — `myRole` is only computed once in `loadApp`, and the next `/apps/{slug}` fetch would 403 anyway. After the DELETE succeeds, if the removed user is the caller, navigate back to /apps instead of refreshing the local member list. Co-Authored-By: Claude Opus 4.7 (1M context) --- dashboard/src/routes/apps/[slug]/+page.svelte | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/dashboard/src/routes/apps/[slug]/+page.svelte b/dashboard/src/routes/apps/[slug]/+page.svelte index 3f6e583..41fe007 100644 --- a/dashboard/src/routes/apps/[slug]/+page.svelte +++ b/dashboard/src/routes/apps/[slug]/+page.svelte @@ -16,6 +16,9 @@ import ConfirmModal from '$lib/ConfirmModal.svelte'; import ActionMenu from '$lib/ActionMenu.svelte'; import RoleChip from '$lib/RoleChip.svelte'; + import { currentUser } from '$lib/auth'; + + const me = $derived($currentUser); const SAMPLE_SOURCE = '#{\n statusCode: 200,\n body: #{ ok: true, echo: ctx.request.body }\n}'; @@ -308,8 +311,16 @@ removingMember = true; removeMemberError = null; try { + const removedSelf = !!me && memberToRemove.user_id === me.id; await api.appMembers.remove(app.id, memberToRemove.user_id); memberToRemove = null; + if (removedSelf) { + // We just revoked our own access to this app; the next + // fetch of /apps/{slug} would 403. Bounce back to the + // apps list rather than render a broken tab. + await goto(`${base}/apps`); + return; + } await loadMembers(app.id); } catch (e) { removeMemberError = e instanceof Error ? e.message : String(e);