Add REST endpoint to reindex a single group
This may become handy to fix single groups that are stale in the index. Change-Id: Iab3711f343fe1da9bba4979792edc83c76d75a09 Signed-off-by: Edwin Kempin <ekempin@google.com>
This commit is contained in:
@@ -791,6 +791,24 @@ newest audit event comes first.
|
||||
]
|
||||
----
|
||||
|
||||
[[index-group]]
|
||||
=== Index Group
|
||||
--
|
||||
'POST /groups/link:#group-id[\{group-id\}]/index'
|
||||
--
|
||||
|
||||
Adds or updates the internal group in the secondary index.
|
||||
|
||||
.Request
|
||||
----
|
||||
POST /groups/fdda826a0815859ab48d22a05a43472f0f55f89a/index HTTP/1.0
|
||||
----
|
||||
|
||||
.Response
|
||||
----
|
||||
HTTP/1.1 204 No Content
|
||||
----
|
||||
|
||||
[[group-member-endpoints]]
|
||||
== Group Member Endpoints
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ import org.junit.Test;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -481,6 +482,32 @@ public class GroupsIT extends AbstractDaemonTest {
|
||||
}
|
||||
}
|
||||
|
||||
// reindex is tested by {@link AbstractQueryGroupsTest#reindex}
|
||||
@Test
|
||||
public void reindexPermissions() throws Exception {
|
||||
TestAccount groupOwner = accounts.user2();
|
||||
GroupInput in = new GroupInput();
|
||||
in.name = name("group");
|
||||
in.members = Collections.singleton(groupOwner).stream()
|
||||
.map(u -> u.id.toString()).collect(toList());
|
||||
in.visibleToAll = true;
|
||||
GroupInfo group = gApi.groups().create(in).get();
|
||||
|
||||
// admin can reindex any group
|
||||
setApiUser(admin);
|
||||
gApi.groups().id(group.id).index();
|
||||
|
||||
// group owner can reindex own group (group is owned by itself)
|
||||
setApiUser(groupOwner);
|
||||
gApi.groups().id(group.id).index();
|
||||
|
||||
// user cannot reindex any group
|
||||
setApiUser(user);
|
||||
exception.expect(AuthException.class);
|
||||
exception.expectMessage("not allowed to index group");
|
||||
gApi.groups().id(group.id).index();
|
||||
}
|
||||
|
||||
private void assertAuditEvent(GroupAuditEventInfo info, Type expectedType,
|
||||
Account.Id expectedUser, Account.Id expectedMember) {
|
||||
assertThat(info.user._accountId).isEqualTo(expectedUser.get());
|
||||
|
||||
@@ -143,6 +143,15 @@ public interface GroupApi {
|
||||
*/
|
||||
List<? extends GroupAuditEventInfo> auditLog() throws RestApiException;
|
||||
|
||||
/**
|
||||
* Reindexes the group.
|
||||
*
|
||||
* Only supported for internal groups.
|
||||
*
|
||||
* @throws RestApiException
|
||||
*/
|
||||
void index() throws RestApiException;
|
||||
|
||||
/**
|
||||
* A default implementation which allows source compatibility
|
||||
* when adding new methods to the interface.
|
||||
@@ -239,5 +248,10 @@ public interface GroupApi {
|
||||
throws RestApiException {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void index() {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ import com.google.gerrit.server.group.GetName;
|
||||
import com.google.gerrit.server.group.GetOptions;
|
||||
import com.google.gerrit.server.group.GetOwner;
|
||||
import com.google.gerrit.server.group.GroupResource;
|
||||
import com.google.gerrit.server.group.Index;
|
||||
import com.google.gerrit.server.group.ListIncludedGroups;
|
||||
import com.google.gerrit.server.group.ListMembers;
|
||||
import com.google.gerrit.server.group.PutDescription;
|
||||
@@ -71,6 +72,7 @@ class GroupApiImpl implements GroupApi {
|
||||
private final DeleteIncludedGroups deleteGroups;
|
||||
private final GetAuditLog getAuditLog;
|
||||
private final GroupResource rsrc;
|
||||
private final Index index;
|
||||
|
||||
@AssistedInject
|
||||
GroupApiImpl(
|
||||
@@ -91,6 +93,7 @@ class GroupApiImpl implements GroupApi {
|
||||
AddIncludedGroups addGroups,
|
||||
DeleteIncludedGroups deleteGroups,
|
||||
GetAuditLog getAuditLog,
|
||||
Index index,
|
||||
@Assisted GroupResource rsrc) {
|
||||
this.getGroup = getGroup;
|
||||
this.getDetail = getDetail;
|
||||
@@ -109,6 +112,7 @@ class GroupApiImpl implements GroupApi {
|
||||
this.addGroups = addGroups;
|
||||
this.deleteGroups = deleteGroups;
|
||||
this.getAuditLog = getAuditLog;
|
||||
this.index = index;
|
||||
this.rsrc = rsrc;
|
||||
}
|
||||
|
||||
@@ -270,4 +274,13 @@ class GroupApiImpl implements GroupApi {
|
||||
throw new RestApiException("Cannot get audit log", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void index() throws RestApiException {
|
||||
try {
|
||||
index.apply(rsrc, new Index.Input());
|
||||
} catch (IOException e) {
|
||||
throw new RestApiException("Cannot index group", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
// Copyright (C) 2017 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.group;
|
||||
|
||||
import com.google.gerrit.common.data.GroupDescriptions;
|
||||
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.extensions.restapi.UnprocessableEntityException;
|
||||
import com.google.gerrit.reviewdb.client.AccountGroup;
|
||||
import com.google.gerrit.server.account.GroupCache;
|
||||
import com.google.gerrit.server.group.Index.Input;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@Singleton
|
||||
public class Index implements RestModifyView<GroupResource, Input> {
|
||||
public static class Input {
|
||||
}
|
||||
|
||||
private final GroupCache groupCache;
|
||||
|
||||
@Inject
|
||||
Index(GroupCache groupCache) {
|
||||
this.groupCache = groupCache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response<?> apply(GroupResource rsrc, Input input)
|
||||
throws IOException, AuthException, UnprocessableEntityException {
|
||||
if (!rsrc.getControl().isOwner()) {
|
||||
throw new AuthException("not allowed to index group");
|
||||
}
|
||||
|
||||
AccountGroup group = GroupDescriptions.toAccountGroup(rsrc.getGroup());
|
||||
if (group == null) {
|
||||
throw new UnprocessableEntityException(String
|
||||
.format("External Group Not Allowed: %s", rsrc.getGroupUUID().get()));
|
||||
}
|
||||
|
||||
// evicting the group from the cache, reindexes the account
|
||||
groupCache.evict(group);
|
||||
return Response.none();
|
||||
}
|
||||
}
|
||||
@@ -39,6 +39,7 @@ public class Module extends RestApiModule {
|
||||
get(GROUP_KIND).to(GetGroup.class);
|
||||
put(GROUP_KIND).to(PutGroup.class);
|
||||
get(GROUP_KIND, "detail").to(GetDetail.class);
|
||||
post(GROUP_KIND, "index").to(Index.class);
|
||||
post(GROUP_KIND, "members").to(AddMembers.class);
|
||||
post(GROUP_KIND, "members.add").to(AddMembers.class);
|
||||
post(GROUP_KIND, "members.delete").to(DeleteMembers.class);
|
||||
|
||||
@@ -59,6 +59,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;
|
||||
import java.util.Locale;
|
||||
@@ -300,6 +301,26 @@ public abstract class AbstractQueryGroupsTest extends GerritServerTests {
|
||||
assertQuery("uuid:" + group.id);
|
||||
}
|
||||
|
||||
// reindex permissions are tested by {@link GroupsIT#reindexPermissions}
|
||||
@Test
|
||||
public void reindex() throws Exception {
|
||||
GroupInfo group1 = createGroupWithDescription(name("group"), "barX");
|
||||
|
||||
// update group in the database so that group index is stale
|
||||
String newDescription = "barY";
|
||||
AccountGroup group =
|
||||
db.accountGroups().get(new AccountGroup.Id(group1.groupId));
|
||||
group.setDescription(newDescription);
|
||||
db.accountGroups().update(Collections.singleton(group));
|
||||
|
||||
assertQuery("description:" + group1.description, group1);
|
||||
assertQuery("description:" + newDescription);
|
||||
|
||||
gApi.groups().id(group1.id).index();
|
||||
assertQuery("description:" + group1.description);
|
||||
assertQuery("description:" + newDescription, group1);
|
||||
}
|
||||
|
||||
private Account.Id createAccount(String username, String fullName,
|
||||
String email, boolean active) throws Exception {
|
||||
try (ManualRequestContext ctx = oneOffRequestContext.open()) {
|
||||
|
||||
Reference in New Issue
Block a user