Skip to content

[FEATURE] Add Leave Room functionality for non-owner room members #2215

@nyxsky404

Description

@nyxsky404

Is your feature request related to a problem?

Once a user is invited to a collaboration room, there is no way for them to leave. The only destructive action available is `DELETE /api/rooms/[roomId]`, which removes the entire room and is restricted to the owner. Non-owner members are permanently in every room they are added to, with no way to exit.

This also means owners have no way to remove a specific member without deleting the entire room.

Current API surface

  • `POST /api/rooms/[roomId]/invite` — adds a member (owner only)
  • `DELETE /api/rooms/[roomId]` — deletes the entire room (owner only)
  • There is no endpoint to remove a single member.

Proposed solution

1. New API endpoint

Add `DELETE /api/rooms/[roomId]/members/[username]` with the following authorization logic:

  • A user may always remove themselves (leave the room).
  • The room owner may remove any non-owner member.
  • Owners cannot remove themselves (they must delete the room or transfer ownership instead).

```ts
// src/app/api/rooms/[roomId]/members/[username]/route.ts

export async function DELETE(req, { params }) {
const session = await getServerSession(authOptions);
if (!session?.githubLogin)
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });

const room = await getRoomById(params.roomId, session.githubLogin);
if (!room) return NextResponse.json({ error: 'Not found' }, { status: 404 });

const isSelf = normalizeRoomGithubUsername(params.username) ===
normalizeRoomGithubUsername(session.githubLogin);
const isOwner = room.is_owner;

if (!isSelf && !isOwner)
return NextResponse.json({ error: 'Forbidden' }, { status: 403 });

if (isSelf && isOwner)
return NextResponse.json(
{ error: 'Room owner cannot leave. Delete the room or transfer ownership.' },
{ status: 400 }
);

const { error } = await supabaseAdmin
.from('room_members')
.delete()
.eq('room_id', params.roomId)
.eq('github_username', normalizeRoomGithubUsername(params.username));

if (error) return NextResponse.json({ error: error.message }, { status: 500 });
return NextResponse.json({ success: true });
}
```

2. UI changes

  • `MembersPanel.tsx` — Add a "Remove" button next to each non-owner member (visible to the owner only).
  • `RoomClient.tsx` — Add a "Leave Room" button in the room header (visible to non-owner members only). On success, redirect to `/rooms`.

Files to modify

  • `src/app/api/rooms/[roomId]/members/[username]/route.ts` — new file
  • `src/lib/supabase-rooms.ts` — add `removeRoomMember(roomId, username)` helper
  • `src/components/rooms/MembersPanel.tsx` — "Remove member" button for owners
  • `src/app/rooms/[roomId]/RoomClient.tsx` — "Leave Room" button for non-owners

Acceptance criteria

  • Non-owner members can leave a room from the room view.
  • Leaving redirects the user to `/rooms` and the room no longer appears in their list.
  • Room owners can remove any non-owner member from `MembersPanel`.
  • Room owners cannot leave their own room (appropriate error message shown).
  • Removal uses username normalization (via `normalizeRoomGithubUsername`) consistent with the rest of the rooms feature.
  • The removed member's entry disappears from `MembersPanel` without a page reload.

Metadata

Metadata

Assignees

Labels

gssoc:assignedGSSoC: Issue assigned to a contributor

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions