Skip to content

Demoting the last owner to Viewer or Dashboard leaves a team with no owner #8580

Closed

Description

@cstns

changeUserRole in forge/db/controllers/Team.js:116 guards the last owner only when the new role is exactly Member:

if (oldRole === Roles.Owner && role === Roles.Member) {
    const ownerCount = await team.ownerCount(transaction)
    if (ownerCount === 1) {
        throw new Error('Cannot remove last owner')
    }

Demote the sole owner to Viewer (10) or Dashboard (5) and the check is never reached.

Reproduced on a local platform with a fresh team whose only member was its owner:

  • PUT /api/v1/teams/:id/members/:userId with {"role": 30} gives 403 Invalid request, so the guard works
  • the same call with {"role": 10} gives 200 {"status": "okay"}
  • the team now has 0 owners

After that the team can't be recovered by anyone who isn't a platform admin. As the demoted user I get 403 on promoting myself back, deleting the team, renaming it, and inviting anyone who could become an owner. There's no path back through the UI or the API.

Might be worth running the owner count check on any demotion away from Owner rather than only on the one to Member.

Metadata

Metadata

Assignees

Labels

area:apiWork on the platform APItype:bugSomething isn't working

Type

No type

Projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions