Add REST endpoint to reindex a single account
This may become handy to fix single accounts that are stale in the index. Change-Id: If4c1787a26a564c19d1c4c1896afa89120ef4813 Signed-off-by: Edwin Kempin <ekempin@google.com>
This commit is contained in:
		| @@ -1941,6 +1941,24 @@ As response the contributor agreement name is returned. | ||||
|   "Individual" | ||||
| ---- | ||||
|  | ||||
| [[index-account]] | ||||
| === Index Account | ||||
| -- | ||||
| 'POST /accounts/link:#account-id[\{account-id\}]/index' | ||||
| -- | ||||
|  | ||||
| Adds or updates the account in the secondary index. | ||||
|  | ||||
| .Request | ||||
| ---- | ||||
|   POST /accounts/1000096/index HTTP/1.0 | ||||
| ---- | ||||
|  | ||||
| .Response | ||||
| ---- | ||||
|   HTTP/1.1 204 No Content | ||||
| ---- | ||||
|  | ||||
| [[ids]] | ||||
| == IDs | ||||
|  | ||||
|   | ||||
| @@ -675,6 +675,23 @@ public class AccountIT extends AbstractDaemonTest { | ||||
|     assertThat(info.get(1).seq).isEqualTo(3); | ||||
|   } | ||||
|  | ||||
|   // reindex is tested by {@link AbstractQueryAccountsTest#reindex} | ||||
|   @Test | ||||
|   public void reindexPermissions() throws Exception { | ||||
|     // admin can reindex any account | ||||
|     setApiUser(admin); | ||||
|     gApi.accounts().id(user.username).index(); | ||||
|  | ||||
|     // user can reindex own account | ||||
|     setApiUser(user); | ||||
|     gApi.accounts().self().index(); | ||||
|  | ||||
|     // user cannot reindex any account | ||||
|     exception.expect(AuthException.class); | ||||
|     exception.expectMessage("not allowed to index account"); | ||||
|     gApi.accounts().id(admin.username).index(); | ||||
|   } | ||||
|  | ||||
|   private void assertSequenceNumbers(List<SshKeyInfo> sshKeys) { | ||||
|     int seq = 1; | ||||
|     for (SshKeyInfo key : sshKeys) { | ||||
|   | ||||
| @@ -74,6 +74,8 @@ public interface AccountApi { | ||||
|   List<AgreementInfo> listAgreements() throws RestApiException; | ||||
|   void signAgreement(String agreementName) throws RestApiException; | ||||
|  | ||||
|   void index() throws RestApiException; | ||||
|  | ||||
|   /** | ||||
|    * A default implementation which allows source compatibility | ||||
|    * when adding new methods to the interface. | ||||
| @@ -211,5 +213,10 @@ public interface AccountApi { | ||||
|     public void signAgreement(String agreementName) throws RestApiException { | ||||
|       throw new NotImplementedException(); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void index() throws RestApiException { | ||||
|       throw new NotImplementedException(); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,56 @@ | ||||
| //Copyright (C) 2016 The Android Open Source Project | ||||
| // | ||||
| //Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| //you may not use this file except in compliance with the License. | ||||
| //You may obtain a copy of the License at | ||||
| // | ||||
| //http://www.apache.org/licenses/LICENSE-2.0 | ||||
| // | ||||
| //Unless required by applicable law or agreed to in writing, software | ||||
| //distributed under the License is distributed on an "AS IS" BASIS, | ||||
| //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| //See the License for the specific language governing permissions and | ||||
| //limitations under the License. | ||||
|  | ||||
| package com.google.gerrit.server.account; | ||||
|  | ||||
| import com.google.gerrit.extensions.restapi.AuthException; | ||||
| import com.google.gerrit.extensions.restapi.Response; | ||||
| import com.google.gerrit.extensions.restapi.RestModifyView; | ||||
| import com.google.gerrit.server.CurrentUser; | ||||
| import com.google.gerrit.server.account.Index.Input; | ||||
| import com.google.gwtorm.server.OrmException; | ||||
| import com.google.inject.Inject; | ||||
| import com.google.inject.Provider; | ||||
| import com.google.inject.Singleton; | ||||
|  | ||||
| import java.io.IOException; | ||||
|  | ||||
| @Singleton | ||||
| public class Index implements RestModifyView<AccountResource, Input> { | ||||
|   public static class Input { | ||||
|   } | ||||
|  | ||||
|   private final AccountCache accountCache; | ||||
|   private final Provider<CurrentUser> self; | ||||
|  | ||||
|   @Inject | ||||
|   Index(AccountCache accountCache, | ||||
|       Provider<CurrentUser> self) { | ||||
|     this.accountCache = accountCache; | ||||
|     this.self = self; | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public Response<?> apply(AccountResource rsrc, Input input) | ||||
|       throws IOException, AuthException, OrmException { | ||||
|     if (self.get() != rsrc.getUser() | ||||
|         && !self.get().getCapabilities().canModifyAccount()) { | ||||
|       throw new AuthException("not allowed to index account"); | ||||
|     } | ||||
|  | ||||
|     // evicting the account from the cache, reindexes the account | ||||
|     accountCache.evict(rsrc.getUser().getAccountId()); | ||||
|     return Response.none(); | ||||
|   } | ||||
| } | ||||
| @@ -40,6 +40,7 @@ public class Module extends RestApiModule { | ||||
|     put(ACCOUNT_KIND).to(PutAccount.class); | ||||
|     get(ACCOUNT_KIND).to(GetAccount.class); | ||||
|     get(ACCOUNT_KIND, "detail").to(GetDetail.class); | ||||
|     post(ACCOUNT_KIND, "index").to(Index.class); | ||||
|     get(ACCOUNT_KIND, "name").to(GetName.class); | ||||
|     put(ACCOUNT_KIND, "name").to(PutName.class); | ||||
|     delete(ACCOUNT_KIND, "name").to(PutName.class); | ||||
|   | ||||
| @@ -47,6 +47,7 @@ import com.google.gerrit.server.account.GetEditPreferences; | ||||
| import com.google.gerrit.server.account.GetPreferences; | ||||
| import com.google.gerrit.server.account.GetSshKeys; | ||||
| import com.google.gerrit.server.account.GetWatchedProjects; | ||||
| import com.google.gerrit.server.account.Index; | ||||
| import com.google.gerrit.server.account.PostWatchedProjects; | ||||
| import com.google.gerrit.server.account.PutAgreement; | ||||
| import com.google.gerrit.server.account.SetDiffPreferences; | ||||
| @@ -99,6 +100,7 @@ public class AccountApiImpl implements AccountApi { | ||||
|   private final SshKeys sshKeys; | ||||
|   private final GetAgreements getAgreements; | ||||
|   private final PutAgreement putAgreement; | ||||
|   private final Index index; | ||||
|  | ||||
|   @Inject | ||||
|   AccountApiImpl(AccountLoader.Factory ailf, | ||||
| @@ -126,6 +128,7 @@ public class AccountApiImpl implements AccountApi { | ||||
|       SshKeys sshKeys, | ||||
|       GetAgreements getAgreements, | ||||
|       PutAgreement putAgreement, | ||||
|       Index index, | ||||
|       @Assisted AccountResource account) { | ||||
|     this.account = account; | ||||
|     this.accountLoaderFactory = ailf; | ||||
| @@ -153,6 +156,7 @@ public class AccountApiImpl implements AccountApi { | ||||
|     this.gpgApiAdapter = gpgApiAdapter; | ||||
|     this.getAgreements = getAgreements; | ||||
|     this.putAgreement = putAgreement; | ||||
|     this.index = index; | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
| @@ -401,4 +405,12 @@ public class AccountApiImpl implements AccountApi { | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public void index() throws RestApiException { | ||||
|     try { | ||||
|       index.apply(account, new Index.Input()); | ||||
|     } catch (IOException | OrmException e) { | ||||
|       throw new RestApiException("Cannot index account", e); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -56,6 +56,7 @@ import org.junit.Test; | ||||
| import org.junit.rules.TestName; | ||||
|  | ||||
| import java.util.Arrays; | ||||
| import java.util.Collections; | ||||
| import java.util.Iterator; | ||||
| import java.util.List; | ||||
|  | ||||
| @@ -355,6 +356,25 @@ public abstract class AbstractQueryAccountsTest extends GerritServerTests { | ||||
|     assertQuery("username:" + user1.username, user1); | ||||
|   } | ||||
|  | ||||
|   // reindex permissions are tested by {@link AccountIT#reindexPermissions} | ||||
|   @Test | ||||
|   public void reindex() throws Exception { | ||||
|     AccountInfo user1 = newAccountWithFullName("tester", "Test Usre"); | ||||
|  | ||||
|     // update account in the database so that account index is stale | ||||
|     String newName = "Test User"; | ||||
|     Account account = db.accounts().get(new Account.Id(user1._accountId)); | ||||
|     account.setFullName(newName); | ||||
|     db.accounts().update(Collections.singleton(account)); | ||||
|  | ||||
|     assertQuery("name:" + quote(user1.name), user1); | ||||
|     assertQuery("name:" + quote(newName)); | ||||
|  | ||||
|     gApi.accounts().id(user1.username).index(); | ||||
|     assertQuery("name:" + quote(user1.name)); | ||||
|     assertQuery("name:" + quote(newName), user1); | ||||
|   } | ||||
|  | ||||
|   protected AccountInfo newAccount(String username) throws Exception { | ||||
|     return newAccountWithEmail(username, null); | ||||
|   } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Edwin Kempin
					Edwin Kempin