Allow removing inactive users from groups

When attempting to remove an inactive user from a group, Gerrit resolves
the member input against active accounts only. This makes the delete
request fail with 422 even though the account is already a group member
and should be removable.

Resolve member deletion inputs with inactive accounts included, so group
cleanup does not depend on the member's active status.

Bug: Issue 522635656
Release-Notes: Allow removing inactive users from groups
Change-Id: I2a1bdfa9356ccdd7c77b0f6f8000a7cd6e40f5dc
diff --git a/java/com/google/gerrit/server/restapi/group/DeleteMembers.java b/java/com/google/gerrit/server/restapi/group/DeleteMembers.java
index a4d28c2..b30ed8f 100644
--- a/java/com/google/gerrit/server/restapi/group/DeleteMembers.java
+++ b/java/com/google/gerrit/server/restapi/group/DeleteMembers.java
@@ -76,7 +76,8 @@
       if (Strings.isNullOrEmpty(nameOrEmail)) {
         continue;
       }
-      membersToRemove.add(accountResolver.resolve(nameOrEmail).asUnique().account().id());
+      membersToRemove.add(
+          accountResolver.resolveIncludeInactive(nameOrEmail).asUnique().account().id());
     }
     AccountGroup.UUID groupUuid = internalGroup.getGroupUUID();
     try {
diff --git a/javatests/com/google/gerrit/acceptance/api/group/GroupsIT.java b/javatests/com/google/gerrit/acceptance/api/group/GroupsIT.java
index 289e642..9661202 100644
--- a/javatests/com/google/gerrit/acceptance/api/group/GroupsIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/group/GroupsIT.java
@@ -217,6 +217,37 @@
   }
 
   @Test
+  public void removeInactiveMemberByUserName() throws Exception {
+    String inactiveMemberUserName = name("inactiveUser");
+    Account.Id inactiveAccountId =
+        accountOperations.newAccount().username(inactiveMemberUserName).inactive().create();
+    AccountGroup.UUID group = groupOperations.newGroup().addMember(inactiveAccountId).create();
+
+    gApi.groups().id(group.get()).removeMembers(inactiveMemberUserName);
+
+    ImmutableSet<Account.Id> members = groupOperations.group(group).get().members();
+    assertThat(members).isEmpty();
+  }
+
+  @Test
+  public void removeInactiveMemberByEmail() throws Exception {
+    String inactiveMemberEmail = "inactiveUser@example.com";
+    Account.Id inactiveAccountId =
+        accountOperations
+            .newAccount()
+            .username(name("inactiveUser"))
+            .inactive()
+            .preferredEmail(inactiveMemberEmail)
+            .create();
+    AccountGroup.UUID group = groupOperations.newGroup().addMember(inactiveAccountId).create();
+
+    gApi.groups().id(group.get()).removeMembers(inactiveMemberEmail);
+
+    ImmutableSet<Account.Id> members = groupOperations.group(group).get().members();
+    assertThat(members).isEmpty();
+  }
+
+  @Test
   public void addExternalGroups() throws Exception {
     AccountGroup.UUID group1 = groupOperations.newGroup().create();
     AccountGroup.UUID group2 = groupOperations.newGroup().create();