@Nullable
    public String ensureBuiltinRole(String roleName, String description, Set<String> expectedPermissions) {
        Role previousRole = null;
        try {
            previousRole = roleService.load(roleName);
            if (!previousRole.isReadOnly() || !expectedPermissions.equals(previousRole.getPermissions())) {
                final String msg = "Invalid role '" + roleName + "', fixing it.";
                LOG.debug(msg);
                throw new IllegalArgumentException(msg); // jump to fix code
            }
        } catch (NotFoundException | IllegalArgumentException | NoSuchElementException ignored) {
            LOG.info("{} role is missing or invalid, re-adding it as a built-in role.", roleName);
            final RoleImpl fixedRole = new RoleImpl();
            // copy the mongodb id over, in order to update the role instead of reading it
            if (previousRole != null) {
                fixedRole._id = previousRole.getId();
            }
            fixedRole.setReadOnly(true);
            fixedRole.setName(roleName);
            fixedRole.setDescription(description);
            fixedRole.setPermissions(expectedPermissions);

            try {
                final Role savedRole = roleService.save(fixedRole);
                return savedRole.getId();
            } catch (DuplicateKeyException | ValidationException e) {
                LOG.error("Unable to save fixed '" + roleName + "' role, please restart Graylog to fix this.", e);
            }
        }

        if (previousRole == null) {
            LOG.error("Unable to access fixed '" + roleName + "' role, please restart Graylog to fix this.");
            return null;
        }

        return previousRole.getId();
    }
@Test
    public void ensureBuiltinRoleWithInvalidPermissions() throws Exception {
        final Role existingRole = mock(Role.class);

        when(existingRole.getId()).thenReturn("new-id");
        when(existingRole.isReadOnly()).thenReturn(true);
        when(existingRole.getPermissions()).thenReturn(ImmutableSet.of("a")); // The existing role has wrong permissions

        when(roleService.load("test-role")).thenReturn(existingRole);
        when(roleService.save(any(Role.class))).thenReturn(existingRole);

        assertThat(migrationHelpers.ensureBuiltinRole("test-role", "description", ImmutableSet.of("a", "b")))
                .isEqualTo("new-id");

        final ArgumentCaptor<Role> roleArg = ArgumentCaptor.forClass(Role.class);

        verify(roleService, times(1)).save(roleArg.capture());

        assertThat(roleArg.getValue()).satisfies(role -> {
            assertThat(role.getName()).describedAs("role name").isEqualTo("test-role");
            assertThat(role.getDescription()).describedAs("role description").isEqualTo("description");
            assertThat(role.isReadOnly()).describedAs("role is read-only").isTrue();
            assertThat(role.getPermissions()).describedAs("role permissions").containsOnly("a", "b");
        });
    }