diff --git a/packages/api/src/admin/roles.spec.ts b/packages/api/src/admin/roles.spec.ts index 5fe7fda091..3015345d69 100644 --- a/packages/api/src/admin/roles.spec.ts +++ b/packages/api/src/admin/roles.spec.ts @@ -1086,6 +1086,42 @@ describe('createAdminRolesHandlers', () => { expect(deps.updateUser).not.toHaveBeenCalled(); }); + it('returns 400 when removing the last admin user', async () => { + const deps = createDeps({ + getRoleByName: jest.fn().mockResolvedValue(mockRole({ name: SystemRoles.ADMIN })), + findUser: jest.fn().mockResolvedValue(mockUser({ role: SystemRoles.ADMIN })), + countUsersByRole: jest.fn().mockResolvedValue(1), + }); + const handlers = createAdminRolesHandlers(deps); + const { req, res, status, json } = createReqRes({ + params: { name: SystemRoles.ADMIN, userId: validUserId }, + }); + + await handlers.removeRoleMember(req, res); + + expect(status).toHaveBeenCalledWith(400); + expect(json).toHaveBeenCalledWith({ error: 'Cannot remove the last admin user' }); + expect(deps.updateUser).not.toHaveBeenCalled(); + }); + + it('allows removing an admin when multiple admins exist', async () => { + const deps = createDeps({ + getRoleByName: jest.fn().mockResolvedValue(mockRole({ name: SystemRoles.ADMIN })), + findUser: jest.fn().mockResolvedValue(mockUser({ role: SystemRoles.ADMIN })), + countUsersByRole: jest.fn().mockResolvedValue(3), + }); + const handlers = createAdminRolesHandlers(deps); + const { req, res, status, json } = createReqRes({ + params: { name: SystemRoles.ADMIN, userId: validUserId }, + }); + + await handlers.removeRoleMember(req, res); + + expect(status).toHaveBeenCalledWith(200); + expect(json).toHaveBeenCalledWith({ success: true }); + expect(deps.updateUser).toHaveBeenCalledWith(validUserId, { role: SystemRoles.USER }); + }); + it('returns 500 on unexpected error', async () => { const deps = createDeps({ getRoleByName: jest.fn().mockResolvedValue(mockRole()), diff --git a/packages/api/src/admin/roles.ts b/packages/api/src/admin/roles.ts index 0477d9a7d7..753c481d9f 100644 --- a/packages/api/src/admin/roles.ts +++ b/packages/api/src/admin/roles.ts @@ -337,6 +337,13 @@ export function createAdminRolesHandlers(deps: AdminRolesDeps) { return res.status(400).json({ error: 'User is not a member of this role' }); } + if (name === SystemRoles.ADMIN) { + const adminCount = await countUsersByRole(SystemRoles.ADMIN); + if (adminCount <= 1) { + return res.status(400).json({ error: 'Cannot remove the last admin user' }); + } + } + await updateUser(userId, { role: SystemRoles.USER }); return res.status(200).json({ success: true }); } catch (error) {