LCOV - code coverage report
Current view: top level - sshd/commands - SetMembersCommand.java (source / functions) Hit Total Coverage
Test: _coverage_report.dat Lines: 6 49 12.2 %
Date: 2022-11-19 15:00:39 Functions: 1 8 12.5 %

          Line data    Source code
       1             : // Copyright (C) 2013 The Android Open Source Project
       2             : //
       3             : // Licensed under the Apache License, Version 2.0 (the "License");
       4             : // you may not use this file except in compliance with the License.
       5             : // You may obtain a copy of the License at
       6             : //
       7             : // http://www.apache.org/licenses/LICENSE-2.0
       8             : //
       9             : // Unless required by applicable law or agreed to in writing, software
      10             : // distributed under the License is distributed on an "AS IS" BASIS,
      11             : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             : // See the License for the specific language governing permissions and
      13             : // limitations under the License.
      14             : 
      15             : package com.google.gerrit.sshd.commands;
      16             : 
      17             : import static java.util.stream.Collectors.joining;
      18             : import static java.util.stream.Collectors.toList;
      19             : 
      20             : import com.google.common.base.MoreObjects;
      21             : import com.google.common.collect.Streams;
      22             : import com.google.gerrit.entities.Account;
      23             : import com.google.gerrit.entities.AccountGroup;
      24             : import com.google.gerrit.entities.InternalGroup;
      25             : import com.google.gerrit.extensions.restapi.IdString;
      26             : import com.google.gerrit.extensions.restapi.RestApiException;
      27             : import com.google.gerrit.extensions.restapi.TopLevelResource;
      28             : import com.google.gerrit.server.account.AccountCache;
      29             : import com.google.gerrit.server.account.AccountState;
      30             : import com.google.gerrit.server.account.GroupCache;
      31             : import com.google.gerrit.server.group.GroupResource;
      32             : import com.google.gerrit.server.restapi.group.AddMembers;
      33             : import com.google.gerrit.server.restapi.group.AddSubgroups;
      34             : import com.google.gerrit.server.restapi.group.DeleteMembers;
      35             : import com.google.gerrit.server.restapi.group.DeleteSubgroups;
      36             : import com.google.gerrit.server.restapi.group.GroupsCollection;
      37             : import com.google.gerrit.sshd.CommandMetaData;
      38             : import com.google.gerrit.sshd.SshCommand;
      39             : import com.google.inject.Inject;
      40             : import java.io.IOException;
      41             : import java.io.UnsupportedEncodingException;
      42             : import java.util.ArrayList;
      43             : import java.util.List;
      44             : import java.util.Optional;
      45             : import org.kohsuke.args4j.Argument;
      46             : import org.kohsuke.args4j.Option;
      47             : 
      48             : @CommandMetaData(
      49             :     name = "set-members",
      50             :     description = "Modify members of specific group or number of groups")
      51           1 : public class SetMembersCommand extends SshCommand {
      52             : 
      53           1 :   @Option(
      54             :       name = "--add",
      55             :       aliases = {"-a"},
      56             :       metaVar = "USER",
      57             :       usage = "users that should be added as group member")
      58             :   private List<Account.Id> accountsToAdd = new ArrayList<>();
      59             : 
      60           1 :   @Option(
      61             :       name = "--remove",
      62             :       aliases = {"-r"},
      63             :       metaVar = "USER",
      64             :       usage = "users that should be removed from the group")
      65             :   private List<Account.Id> accountsToRemove = new ArrayList<>();
      66             : 
      67           1 :   @Option(
      68             :       name = "--include",
      69             :       aliases = {"-i"},
      70             :       metaVar = "GROUP",
      71             :       usage = "group that should be included as group member")
      72             :   private List<AccountGroup.UUID> groupsToInclude = new ArrayList<>();
      73             : 
      74           1 :   @Option(
      75             :       name = "--exclude",
      76             :       aliases = {"-e"},
      77             :       metaVar = "GROUP",
      78             :       usage = "group that should be excluded from the group")
      79             :   private List<AccountGroup.UUID> groupsToRemove = new ArrayList<>();
      80             : 
      81           1 :   @Argument(
      82             :       index = 0,
      83             :       required = true,
      84             :       multiValued = true,
      85             :       metaVar = "GROUP",
      86             :       usage = "groups to modify")
      87             :   private List<AccountGroup.UUID> groups = new ArrayList<>();
      88             : 
      89             :   @Inject private AddMembers addMembers;
      90             : 
      91             :   @Inject private DeleteMembers deleteMembers;
      92             : 
      93             :   @Inject private AddSubgroups addSubgroups;
      94             : 
      95             :   @Inject private DeleteSubgroups deleteSubgroups;
      96             : 
      97             :   @Inject private GroupsCollection groupsCollection;
      98             : 
      99             :   @Inject private GroupCache groupCache;
     100             : 
     101             :   @Inject private AccountCache accountCache;
     102             : 
     103             :   @Override
     104             :   protected void run() throws UnloggedFailure, Failure, Exception {
     105           0 :     enableGracefulStop();
     106             :     try {
     107           0 :       for (AccountGroup.UUID groupUuid : groups) {
     108           0 :         GroupResource resource =
     109           0 :             groupsCollection.parse(TopLevelResource.INSTANCE, IdString.fromUrl(groupUuid.get()));
     110           0 :         if (!accountsToRemove.isEmpty()) {
     111           0 :           deleteMembers.apply(resource, fromMembers(accountsToRemove));
     112           0 :           reportMembersAction("removed from", resource, accountsToRemove);
     113             :         }
     114           0 :         if (!groupsToRemove.isEmpty()) {
     115           0 :           deleteSubgroups.apply(resource, fromGroups(groupsToRemove));
     116           0 :           reportGroupsAction("excluded from", resource, groupsToRemove);
     117             :         }
     118           0 :         if (!accountsToAdd.isEmpty()) {
     119           0 :           addMembers.apply(resource, fromMembers(accountsToAdd));
     120           0 :           reportMembersAction("added to", resource, accountsToAdd);
     121             :         }
     122           0 :         if (!groupsToInclude.isEmpty()) {
     123           0 :           addSubgroups.apply(resource, fromGroups(groupsToInclude));
     124           0 :           reportGroupsAction("included to", resource, groupsToInclude);
     125             :         }
     126           0 :       }
     127           0 :     } catch (RestApiException e) {
     128           0 :       throw die(e.getMessage());
     129           0 :     }
     130           0 :   }
     131             : 
     132             :   private void reportMembersAction(
     133             :       String action, GroupResource group, List<Account.Id> accountIdList)
     134             :       throws UnsupportedEncodingException, IOException {
     135           0 :     String names =
     136           0 :         accountIdList.stream()
     137           0 :             .map(
     138             :                 accountId -> {
     139           0 :                   Optional<AccountState> accountState = accountCache.get(accountId);
     140           0 :                   if (!accountState.isPresent()) {
     141           0 :                     return "n/a";
     142             :                   }
     143           0 :                   return MoreObjects.firstNonNull(
     144           0 :                       accountState.get().account().preferredEmail(), "n/a");
     145             :                 })
     146           0 :             .collect(joining(", "));
     147           0 :     out.write(
     148           0 :         String.format("Members %s group %s: %s\n", action, group.getName(), names).getBytes(ENC));
     149           0 :   }
     150             : 
     151             :   private void reportGroupsAction(
     152             :       String action, GroupResource group, List<AccountGroup.UUID> groupUuidList)
     153             :       throws UnsupportedEncodingException, IOException {
     154           0 :     String names =
     155           0 :         groupUuidList.stream()
     156           0 :             .map(uuid -> groupCache.get(uuid).map(InternalGroup::getName))
     157           0 :             .flatMap(Streams::stream)
     158           0 :             .collect(joining(", "));
     159           0 :     out.write(
     160           0 :         String.format("Groups %s group %s: %s\n", action, group.getName(), names).getBytes(ENC));
     161           0 :   }
     162             : 
     163             :   private AddSubgroups.Input fromGroups(List<AccountGroup.UUID> accounts) {
     164           0 :     return AddSubgroups.Input.fromGroups(accounts.stream().map(Object::toString).collect(toList()));
     165             :   }
     166             : 
     167             :   private AddMembers.Input fromMembers(List<Account.Id> accounts) {
     168           0 :     return AddMembers.Input.fromMembers(accounts.stream().map(Object::toString).collect(toList()));
     169             :   }
     170             : }

Generated by: LCOV version 1.16+git.20220603.dfeb750