Add SSH command to set group members

Add a new SSH command that allows to
- add users to groups
- remove users from groups
- include groups into groups
- exclude groups from groups

That change is based on previous work of Edwin Kempin:
https://gerrit-review.googlesource.com/#/c/30009

Bug: issue 1095
Change-Id: I9a80bc52f5a9847d4e8b4d848149167844eadd19
This commit is contained in:
David Ostrovsky
2013-06-11 01:01:28 +02:00
parent 2180d654bb
commit 4adb97e1a6
5 changed files with 251 additions and 0 deletions

View File

@@ -39,6 +39,7 @@ public class MasterCommandModule extends CommandModule {
// deprecated alias to review command
alias(gerrit, "approve", ReviewCommand.class);
command(gerrit, SetAccountCommand.class);
command(gerrit, SetMembersCommand.class);
command(gerrit, SetProjectCommand.class);
command(gerrit, "test-submit").toProvider(new DispatchCommandProvider(testSubmit));

View File

@@ -0,0 +1,164 @@
// Copyright (C) 2013 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.sshd.commands;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Objects;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.gerrit.extensions.restapi.IdString;
import com.google.gerrit.extensions.restapi.TopLevelResource;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.server.account.AccountCache;
import com.google.gerrit.server.account.GroupCache;
import com.google.gerrit.server.group.AddIncludedGroups;
import com.google.gerrit.server.group.AddMembers;
import com.google.gerrit.server.group.DeleteIncludedGroups;
import com.google.gerrit.server.group.DeleteMembers;
import com.google.gerrit.server.group.GroupResource;
import com.google.gerrit.server.group.GroupsCollection;
import com.google.gerrit.sshd.CommandMetaData;
import com.google.gerrit.sshd.SshCommand;
import com.google.inject.Inject;
import com.google.inject.Provider;
import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.Option;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.List;
@CommandMetaData(name = "set-members", descr = "Modifies members of specific group or number of groups")
public class SetMembersCommand extends SshCommand {
@Option(name = "--add", aliases = {"-a"}, metaVar = "USER", usage = "users that should be added as group member")
private List<Account.Id> accountsToAdd = Lists.newArrayList();
@Option(name = "--remove", aliases = {"-r"}, metaVar = "USER", usage = "users that should be removed from the group")
private List<Account.Id> accountsToRemove = Lists.newArrayList();
@Option(name = "--include", aliases = {"-i"}, metaVar = "GROUP", usage = "group that should be included as group member")
private List<AccountGroup.UUID> groupsToInclude = Lists.newArrayList();
@Option(name = "--exclude", aliases = {"-e"}, metaVar = "GROUP", usage = "group that should be excluded from the group")
private List<AccountGroup.UUID> groupsToRemove = Lists.newArrayList();
@Argument(index = 0, required = true, multiValued = true, metaVar = "GROUP", usage = "groups to modify")
private List<AccountGroup.UUID> groups = Lists.newArrayList();
@Inject
private Provider<AddMembers> addMembers;
@Inject
private Provider<DeleteMembers> deleteMembers;
@Inject
private Provider<AddIncludedGroups> addIncludedGroups;
@Inject
private Provider<DeleteIncludedGroups> deleteIncludedGroups;
@Inject
private GroupsCollection groupsCollection;
@Inject
private GroupCache groupCache;
@Inject
private AccountCache accountCache;
@Override
protected void run() throws UnloggedFailure, Failure, Exception {
for (AccountGroup.UUID groupUuid : groups) {
GroupResource resource =
groupsCollection.parse(TopLevelResource.INSTANCE,
IdString.fromUrl(groupUuid.get()));
if (!accountsToRemove.isEmpty()) {
deleteMembers.get().apply(resource, fromMembers(accountsToRemove));
reportMembersAction("removed from", resource, accountsToRemove);
}
if (!groupsToRemove.isEmpty()) {
deleteIncludedGroups.get().apply(resource, fromGroups(groupsToRemove));
reportGroupsAction("excluded from", resource, groupsToRemove);
}
if (!accountsToAdd.isEmpty()) {
addMembers.get().apply(resource, fromMembers(accountsToAdd));
reportMembersAction("added to", resource, accountsToAdd);
}
if (!groupsToInclude.isEmpty()) {
addIncludedGroups.get().apply(resource, fromGroups(groupsToInclude));
reportGroupsAction("included to", resource, groupsToInclude);
}
}
}
private void reportMembersAction(String action, GroupResource group,
List<Account.Id> accountIdList) throws UnsupportedEncodingException,
IOException {
out.write(String.format(
"Members %s group %s: %s\n",
action,
group.getName(),
Joiner.on(", ").join(
Iterables.transform(accountIdList,
new Function<Account.Id, String>() {
@Override
public String apply(Account.Id accountId) {
return Objects.firstNonNull(accountCache.get(accountId)
.getAccount().getPreferredEmail(), "n/a");
}
}))).getBytes(ENC));
}
private void reportGroupsAction(String action, GroupResource group,
List<AccountGroup.UUID> groupUuidList)
throws UnsupportedEncodingException, IOException {
out.write(String.format(
"Groups %s group %s: %s\n",
action,
group.getName(),
Joiner.on(", ").join(
Iterables.transform(groupUuidList,
new Function<AccountGroup.UUID, String>() {
@Override
public String apply(AccountGroup.UUID uuid) {
return groupCache.get(uuid).getName();
}
}))).getBytes(ENC));
}
private AddIncludedGroups.Input fromGroups(List<AccountGroup.UUID> accounts) {
return AddIncludedGroups.Input.fromGroups(Lists.newArrayList(Iterables
.transform(accounts, new Function<AccountGroup.UUID, String>() {
@Override
public String apply(AccountGroup.UUID uuid) {
return uuid.toString();
}
})));
}
private AddMembers.Input fromMembers(List<Account.Id> accounts) {
return AddMembers.Input.fromMembers(Lists.newArrayList(Iterables.transform(
accounts, new Function<Account.Id, String>() {
@Override
public String apply(Account.Id id) {
return id.toString();
}
})));
}
}