GetState: Allow admins to get the account state of other users

Originally we didn't allow this because we thought that not all metadata
that we want to return can be computed on behalf of another user (see
commit message of change Id8928cdbd). It's unclear if this is really the
case, but if it's the case we can simply skip the metadata or include it
with value null. Getting the rest of the account state data may still be
useful for admins to investigate issues, even if some of the metadata is
skipped.

Release-Notes: Allow admins to get the account state of other users
Bug: Google b/330836100
Change-Id: Icfed1ad7e83d812685f988f1f25be7d2bd731e57
Signed-off-by: Edwin Kempin <ekempin@google.com>
diff --git a/java/com/google/gerrit/server/restapi/account/GetState.java b/java/com/google/gerrit/server/restapi/account/GetState.java
index b18e61c..797b888 100644
--- a/java/com/google/gerrit/server/restapi/account/GetState.java
+++ b/java/com/google/gerrit/server/restapi/account/GetState.java
@@ -27,6 +27,7 @@
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.account.AccountResource;
 import com.google.gerrit.server.account.AccountStateProvider;
+import com.google.gerrit.server.permissions.GlobalPermission;
 import com.google.gerrit.server.permissions.PermissionBackend;
 import com.google.gerrit.server.permissions.PermissionBackendException;
 import com.google.gerrit.server.plugincontext.PluginSetContext;
@@ -80,7 +81,12 @@
     }
 
     if (!rsrc.getUser().hasSameAccountId(self.get())) {
-      throw new AuthException("not allowed to get account state of other user");
+      try {
+        permissionBackend.currentUser().check(GlobalPermission.ADMINISTRATE_SERVER);
+      } catch (AuthException e) {
+        throw new AuthException(
+            String.format("cannot get account state of other user: %s", e.getMessage()));
+      }
     }
 
     AccountStateInfo accountState = new AccountStateInfo();
diff --git a/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java b/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java
index 94e163b..a390a00 100644
--- a/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java
@@ -3530,10 +3530,19 @@
   }
 
   @Test
-  public void cannotGetAccountStateOfOtherUser() throws Exception {
+  public void nonAdminCannotGetAccountStateOfOtherUser() throws Exception {
+    requestScopeOperations.setApiUser(user.id());
     AuthException thrown =
-        assertThrows(AuthException.class, () -> gApi.accounts().id(user.id().get()).state());
-    assertThat(thrown).hasMessageThat().isEqualTo("not allowed to get account state of other user");
+        assertThrows(AuthException.class, () -> gApi.accounts().id(admin.id().get()).state());
+    assertThat(thrown)
+        .hasMessageThat()
+        .isEqualTo("cannot get account state of other user: administrate server not permitted");
+  }
+
+  @Test
+  public void adminCanGetAccountStateOfOtherUser() throws Exception {
+    AccountStateInfo state = gApi.accounts().id(user.id().get()).state();
+    assertThat(state.account._accountId).isEqualTo(user.id().get());
   }
 
   @Test