LCOV - code coverage report
Current view: top level - server/account - GroupControl.java (source / functions) Hit Total Coverage
Test: _coverage_report.dat Lines: 78 90 86.7 %
Date: 2022-11-19 15:00:39 Functions: 20 20 100.0 %

          Line data    Source code
       1             : // Copyright (C) 2009 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.server.account;
      16             : 
      17             : import com.google.common.flogger.FluentLogger;
      18             : import com.google.gerrit.entities.Account;
      19             : import com.google.gerrit.entities.AccountGroup;
      20             : import com.google.gerrit.entities.GroupDescription;
      21             : import com.google.gerrit.exceptions.NoSuchGroupException;
      22             : import com.google.gerrit.server.CurrentUser;
      23             : import com.google.gerrit.server.permissions.GlobalPermission;
      24             : import com.google.gerrit.server.permissions.PermissionBackend;
      25             : import com.google.gerrit.server.permissions.PermissionBackendException;
      26             : import com.google.inject.Inject;
      27             : import com.google.inject.Provider;
      28             : import com.google.inject.Singleton;
      29             : 
      30             : /** Access control management for a group of accounts managed in Gerrit. */
      31             : public class GroupControl {
      32          55 :   private static final FluentLogger logger = FluentLogger.forEnclosingClass();
      33             : 
      34             :   @Singleton
      35             :   public static class GenericFactory {
      36             :     private final PermissionBackend permissionBackend;
      37             :     private final GroupBackend groupBackend;
      38             : 
      39             :     @Inject
      40         150 :     GenericFactory(PermissionBackend permissionBackend, GroupBackend gb) {
      41         150 :       this.permissionBackend = permissionBackend;
      42         150 :       groupBackend = gb;
      43         150 :     }
      44             : 
      45             :     public GroupControl controlFor(CurrentUser who, AccountGroup.UUID groupId)
      46             :         throws NoSuchGroupException {
      47          44 :       GroupDescription.Basic group = groupBackend.get(groupId);
      48          44 :       if (group == null) {
      49           1 :         throw new NoSuchGroupException(groupId);
      50             :       }
      51          44 :       return new GroupControl(who, group, permissionBackend, groupBackend);
      52             :     }
      53             :   }
      54             : 
      55             :   public static class Factory {
      56             :     private final PermissionBackend permissionBackend;
      57             :     private final Provider<CurrentUser> user;
      58             :     private final GroupBackend groupBackend;
      59             : 
      60             :     @Inject
      61         151 :     Factory(PermissionBackend permissionBackend, Provider<CurrentUser> cu, GroupBackend gb) {
      62         151 :       this.permissionBackend = permissionBackend;
      63         151 :       user = cu;
      64         151 :       groupBackend = gb;
      65         151 :     }
      66             : 
      67             :     public GroupControl controlFor(AccountGroup.UUID groupId) throws NoSuchGroupException {
      68           4 :       final GroupDescription.Basic group = groupBackend.get(groupId);
      69           4 :       if (group == null) {
      70           0 :         throw new NoSuchGroupException(groupId);
      71             :       }
      72           4 :       return controlFor(group);
      73             :     }
      74             : 
      75             :     public GroupControl controlFor(GroupDescription.Basic group) {
      76          38 :       return new GroupControl(user.get(), group, permissionBackend, groupBackend);
      77             :     }
      78             : 
      79             :     public GroupControl validateFor(AccountGroup.UUID groupUUID) throws NoSuchGroupException {
      80           2 :       final GroupControl c = controlFor(groupUUID);
      81           2 :       if (!c.isVisible()) {
      82           0 :         throw new NoSuchGroupException(groupUUID);
      83             :       }
      84           2 :       return c;
      85             :     }
      86             :   }
      87             : 
      88             :   private final CurrentUser user;
      89             :   private final GroupDescription.Basic group;
      90             :   private Boolean isOwner;
      91             :   private final PermissionBackend.WithUser perm;
      92             :   private final GroupBackend groupBackend;
      93             : 
      94             :   GroupControl(
      95             :       CurrentUser who,
      96             :       GroupDescription.Basic gd,
      97             :       PermissionBackend permissionBackend,
      98          55 :       GroupBackend gb) {
      99          55 :     user = who;
     100          55 :     group = gd;
     101          55 :     this.perm = permissionBackend.user(user);
     102          55 :     groupBackend = gb;
     103          55 :   }
     104             : 
     105             :   public GroupDescription.Basic getGroup() {
     106          20 :     return group;
     107             :   }
     108             : 
     109             :   public CurrentUser getUser() {
     110          47 :     return user;
     111             :   }
     112             : 
     113             :   /** Can this user see this group exists? */
     114             :   public boolean isVisible() {
     115          38 :     if (user.isInternalUser()) {
     116           3 :       logger.atFine().log(
     117             :           "group %s is visible to internal user %s",
     118           3 :           group.getGroupUUID().get(), user.getLoggableName());
     119           3 :       return true;
     120             :     }
     121             : 
     122          37 :     if (groupBackend.isVisibleToAll(group.getGroupUUID())) {
     123           7 :       logger.atFine().log(
     124             :           "group %s is visible to user %s (group is visible to all users)",
     125           7 :           group.getGroupUUID().get(), user.getLoggableName());
     126           7 :       return true;
     127             :     }
     128             : 
     129          34 :     if (user.getEffectiveGroups().contains(group.getGroupUUID())) {
     130          31 :       logger.atFine().log(
     131             :           "group %s is visible to user %s (user is member of the group)",
     132          31 :           group.getGroupUUID().get(), user.getLoggableName());
     133          31 :       return true;
     134             :     }
     135             : 
     136          22 :     if (isOwner()) {
     137          19 :       logger.atFine().log(
     138             :           "group %s is visible to user %s (user is owner of the group)",
     139          19 :           group.getGroupUUID().get(), user.getLoggableName());
     140          19 :       return true;
     141             :     }
     142             : 
     143             :     // The check for canAdministrateServer may seem redundant, but it's needed to make external
     144             :     // groups visible to server administrators.
     145           7 :     if (canAdministrateServer()) {
     146           0 :       logger.atFine().log(
     147             :           "group %s is visible to user %s (user is admin)",
     148           0 :           group.getGroupUUID().get(), user.getLoggableName());
     149           0 :       return true;
     150             :     }
     151             : 
     152           7 :     logger.atFine().log(
     153           7 :         "group %s is not visible to user %s", group.getGroupUUID().get(), user.getLoggableName());
     154           7 :     return false;
     155             :   }
     156             : 
     157             :   public boolean isOwner() {
     158          47 :     if (isOwner != null) {
     159          12 :       return isOwner;
     160             :     }
     161             : 
     162             :     // Keep this logic in sync with DefaultRefFilter#isGroupOwner(...).
     163          47 :     if (group instanceof GroupDescription.Internal) {
     164          47 :       AccountGroup.UUID ownerUUID = ((GroupDescription.Internal) group).getOwnerGroupUUID();
     165          47 :       if (getUser().getEffectiveGroups().contains(ownerUUID)) {
     166          35 :         logger.atFine().log(
     167          35 :             "user %s is owner of group %s", user.getLoggableName(), group.getGroupUUID().get());
     168          35 :         isOwner = true;
     169          26 :       } else if (canAdministrateServer()) {
     170          21 :         logger.atFine().log(
     171             :             "user %s is owner of group %s (user is admin)",
     172          21 :             user.getLoggableName(), group.getGroupUUID().get());
     173          21 :         isOwner = true;
     174             :       } else {
     175          13 :         logger.atFine().log(
     176             :             "user %s is not an owner of group %s",
     177          13 :             user.getLoggableName(), group.getGroupUUID().get());
     178          13 :         isOwner = false;
     179             :       }
     180          47 :     } else {
     181           0 :       logger.atFine().log(
     182             :           "user %s is not an owner of external group %s",
     183           0 :           user.getLoggableName(), group.getGroupUUID().get());
     184           0 :       isOwner = false;
     185             :     }
     186          47 :     return isOwner;
     187             :   }
     188             : 
     189             :   private boolean canAdministrateServer() {
     190             :     try {
     191          26 :       return perm.test(GlobalPermission.ADMINISTRATE_SERVER);
     192           0 :     } catch (PermissionBackendException e) {
     193           0 :       logger.atFine().log(
     194             :           "Failed to check %s global capability for user %s",
     195           0 :           GlobalPermission.ADMINISTRATE_SERVER, user.getLoggableName());
     196           0 :       return false;
     197             :     }
     198             :   }
     199             : 
     200             :   public boolean canAddMember() {
     201          13 :     return isOwner();
     202             :   }
     203             : 
     204             :   public boolean canRemoveMember() {
     205           6 :     return isOwner();
     206             :   }
     207             : 
     208             :   public boolean canSeeMember(Account.Id id) {
     209          14 :     if (user.isIdentifiedUser() && user.getAccountId().equals(id)) {
     210          10 :       return true;
     211             :     }
     212          12 :     return canSeeMembers();
     213             :   }
     214             : 
     215             :   public boolean canAddGroup() {
     216           4 :     return isOwner();
     217             :   }
     218             : 
     219             :   public boolean canRemoveGroup() {
     220           4 :     return isOwner();
     221             :   }
     222             : 
     223             :   public boolean canSeeGroup() {
     224          12 :     return canSeeMembers();
     225             :   }
     226             : 
     227             :   private boolean canSeeMembers() {
     228          14 :     if (group instanceof GroupDescription.Internal) {
     229          14 :       return ((GroupDescription.Internal) group).isVisibleToAll() || isOwner();
     230             :     }
     231           1 :     return canAdministrateServer();
     232             :   }
     233             : }

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