Merge changes I5aaf20ee,Ib9312e97
* changes:
Resolve "self" even if inactive
Add query test that resolving "self" fails for anonymous users
diff --git a/Documentation/rest-api-accounts.txt b/Documentation/rest-api-accounts.txt
index 8078922..c326b66 100644
--- a/Documentation/rest-api-accounts.txt
+++ b/Documentation/rest-api-accounts.txt
@@ -2153,8 +2153,8 @@
link:config-gerrit.txt#accounts.visibility[visible] to the calling user are not
considered.
-In all cases _except_ a bare account ID, inactive accounts are not considered.
-Inactive accounts may only be referenced by bare ID.
+In all cases _except_ a bare account ID and `self`/`me`, inactive accounts are
+not considered. Inactive accounts should only be referenced by bare ID.
If the input is a bare account ID, this will always resolve to exactly
one account if there is a visible account with that ID, and zero accounts
diff --git a/java/com/google/gerrit/server/account/AccountResolver.java b/java/com/google/gerrit/server/account/AccountResolver.java
index 3dea6a9..9b4952b 100644
--- a/java/com/google/gerrit/server/account/AccountResolver.java
+++ b/java/com/google/gerrit/server/account/AccountResolver.java
@@ -68,7 +68,7 @@
* </ol>
*
* <p>The result never includes accounts that are not visible to the calling user. It also never
- * includes inactive accounts, with one specific exception noted in method Javadoc.
+ * includes inactive accounts, with a small number of specific exceptions noted in method Javadoc.
*/
@Singleton
public class AccountResolver {
@@ -252,6 +252,11 @@
private class BySelf extends StringSearcher {
@Override
+ public boolean callerShouldFilterOutInactiveCandidates() {
+ return false;
+ }
+
+ @Override
public boolean callerMayAssumeCandidatesAreVisible() {
return true;
}
@@ -279,8 +284,6 @@
private class ByExactAccountId extends AccountIdSearcher {
@Override
public boolean callerShouldFilterOutInactiveCandidates() {
- // The only case where we *don't* enforce that the account is active is when passing an exact
- // numeric account ID.
return false;
}
@@ -497,9 +500,9 @@
*
* <ul>
* <li>The strings {@code "self"} and {@code "me"}, if the current user is an {@link
- * IdentifiedUser}.
- * <li>A bare account ID ({@code "18419"}). In this case, and <strong>only</strong> this case,
- * may return exactly one inactive account. This case short-circuits if the input matches.
+ * IdentifiedUser}. In this case, may return exactly one inactive account.
+ * <li>A bare account ID ({@code "18419"}). In this case, may return exactly one inactive
+ * account. This case short-circuits if the input matches.
* <li>An account ID in parentheses following a full name ({@code "Full Name (18419)"}). This
* case short-circuits if the input matches.
* <li>A username ({@code "username"}).
diff --git a/javatests/com/google/gerrit/acceptance/server/account/AccountResolverIT.java b/javatests/com/google/gerrit/acceptance/server/account/AccountResolverIT.java
index 63fda12..d99fa72 100644
--- a/javatests/com/google/gerrit/acceptance/server/account/AccountResolverIT.java
+++ b/javatests/com/google/gerrit/acceptance/server/account/AccountResolverIT.java
@@ -105,6 +105,19 @@
}
@Test
+ public void bySelfInactive() throws Exception {
+ gApi.accounts().id(user.id.get()).setActive(false);
+
+ requestScopeOperations.setApiUser(user.id);
+ assertThat(gApi.accounts().id("self").getActive()).isFalse();
+
+ Result result = resolveAsResult("self");
+ assertThat(result.asIdSet()).containsExactly(user.id);
+ assertThat(result.isSelf()).isTrue();
+ assertThat(result.asUniqueUser()).isSameAs(self.get());
+ }
+
+ @Test
public void byExactAccountId() throws Exception {
Account.Id existingId = accountOperations.newAccount().create();
Account.Id idWithExistingIdAsFullname =
diff --git a/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java b/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
index 524b399..da62b7c 100644
--- a/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
+++ b/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
@@ -64,6 +64,7 @@
import com.google.gerrit.extensions.common.ChangeInput;
import com.google.gerrit.extensions.common.ChangeMessageInfo;
import com.google.gerrit.extensions.common.CommentInfo;
+import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.index.FieldDef;
@@ -3095,6 +3096,44 @@
assertQuery("project:repo+foo", change);
}
+ @Test
+ public void selfFailsForAnonymousUser() throws Exception {
+ for (String query : ImmutableList.of("assignee:self", "starredby:self", "is:starred")) {
+ assertQuery(query);
+ RequestContext oldContext = requestContext.setContext(anonymousUserProvider::get);
+
+ try {
+ requestContext.setContext(anonymousUserProvider::get);
+ assertThatAuthException(query)
+ .hasMessageThat()
+ .isEqualTo("Must be signed-in to use this operator");
+ } finally {
+ requestContext.setContext(oldContext);
+ }
+ }
+ }
+
+ @Test
+ public void selfSucceedsForInactiveAccount() throws Exception {
+ Account.Id user2 =
+ accountManager.authenticate(AuthRequest.forUser("anotheruser")).getAccountId();
+
+ TestRepository<Repo> repo = createProject("repo");
+ Change change = insert(repo, newChange(repo));
+ AssigneeInput ain = new AssigneeInput();
+ ain.assignee = user2.toString();
+ gApi.changes().id(change.getId().get()).setAssignee(ain);
+
+ RequestContext adminContext = requestContext.setContext(newRequestContext(user2));
+ assertQuery("assignee:self", change);
+
+ requestContext.setContext(adminContext);
+ gApi.accounts().id(user2.get()).setActive(false);
+
+ requestContext.setContext(newRequestContext(user2));
+ assertQuery("assignee:self", change);
+ }
+
protected ChangeInserter newChange(TestRepository<Repo> repo) throws Exception {
return newChange(repo, null, null, null, null, false);
}
@@ -3224,6 +3263,15 @@
}
}
+ protected ThrowableSubject assertThatAuthException(Object query) throws Exception {
+ try {
+ newQuery(query).get();
+ throw new AssertionError("expected AuthException for query: " + query);
+ } catch (AuthException e) {
+ return assertThat(e);
+ }
+ }
+
protected TestRepository<Repo> createProject(String name) throws Exception {
gApi.projects().create(name).get();
return new TestRepository<>(repoManager.openRepository(new Project.NameKey(name)));