LCOV - code coverage report
Current view: top level - server/permissions - GlobalPermission.java (source / functions) Hit Total Coverage
Test: _coverage_report.dat Lines: 54 64 84.4 %
Date: 2022-11-19 15:00:39 Functions: 6 6 100.0 %

          Line data    Source code
       1             : // Copyright (C) 2017 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.permissions;
      16             : 
      17             : import static com.google.gerrit.server.permissions.DefaultPermissionMappings.globalPermission;
      18             : 
      19             : import com.google.common.flogger.FluentLogger;
      20             : import com.google.gerrit.common.Nullable;
      21             : import com.google.gerrit.common.data.GlobalCapability;
      22             : import com.google.gerrit.extensions.annotations.CapabilityScope;
      23             : import com.google.gerrit.extensions.annotations.RequiresAnyCapability;
      24             : import com.google.gerrit.extensions.annotations.RequiresCapability;
      25             : import com.google.gerrit.extensions.api.access.GerritPermission;
      26             : import com.google.gerrit.extensions.api.access.GlobalOrPluginPermission;
      27             : import com.google.gerrit.extensions.api.access.PluginPermission;
      28             : import com.google.gerrit.extensions.registration.PluginName;
      29             : import java.lang.annotation.Annotation;
      30             : import java.util.Collections;
      31             : import java.util.LinkedHashSet;
      32             : import java.util.Optional;
      33             : import java.util.Set;
      34             : 
      35             : /**
      36             :  * Global server permissions built into Gerrit.
      37             :  *
      38             :  * <p>See also {@link GlobalCapability} which lists the equivalent strings used in the
      39             :  * refs/meta/config settings in All-Projects.
      40             :  */
      41         150 : public enum GlobalPermission implements GlobalOrPluginPermission {
      42         150 :   ACCESS_DATABASE,
      43         150 :   ADMINISTRATE_SERVER,
      44         150 :   CREATE_ACCOUNT,
      45         150 :   CREATE_GROUP,
      46         150 :   CREATE_PROJECT,
      47         150 :   EMAIL_REVIEWERS,
      48         150 :   FLUSH_CACHES,
      49         150 :   KILL_TASK,
      50         150 :   MAINTAIN_SERVER,
      51         150 :   MODIFY_ACCOUNT,
      52         150 :   READ_AS,
      53         150 :   RUN_AS,
      54         150 :   RUN_GC,
      55         150 :   STREAM_EVENTS,
      56         150 :   VIEW_ACCESS,
      57         150 :   VIEW_ALL_ACCOUNTS,
      58         150 :   VIEW_CACHES,
      59         150 :   VIEW_CONNECTIONS,
      60         150 :   VIEW_PLUGINS,
      61         150 :   VIEW_QUEUE;
      62             : 
      63         150 :   private static final FluentLogger logger = FluentLogger.forEnclosingClass();
      64             : 
      65             :   /**
      66             :    * Extracts the {@code @RequiresCapability} or {@code @RequiresAnyCapability} annotation.
      67             :    *
      68             :    * @param pluginName name of the declaring plugin. May be {@code null} or {@code "gerrit"} for
      69             :    *     classes originating from the core server.
      70             :    * @param clazz target class to extract annotation from.
      71             :    * @return empty set if no annotations were found, or a collection of permissions, any of which
      72             :    *     are suitable to enable access.
      73             :    * @throws PermissionBackendException the annotation could not be parsed.
      74             :    */
      75             :   public static Set<GlobalOrPluginPermission> fromAnnotation(
      76             :       @Nullable String pluginName, Class<?> clazz) throws PermissionBackendException {
      77         149 :     RequiresCapability rc = findAnnotation(clazz, RequiresCapability.class);
      78         149 :     RequiresAnyCapability rac = findAnnotation(clazz, RequiresAnyCapability.class);
      79         149 :     if (rc != null && rac != null) {
      80           0 :       logger.atSevere().log(
      81             :           "Class %s uses both @%s and @%s",
      82           0 :           clazz.getName(),
      83           0 :           RequiresCapability.class.getSimpleName(),
      84           0 :           RequiresAnyCapability.class.getSimpleName());
      85           0 :       throw new PermissionBackendException("cannot extract permission");
      86         149 :     } else if (rc != null) {
      87         148 :       return Collections.singleton(
      88         148 :           resolve(
      89             :               pluginName,
      90         148 :               rc.value(),
      91         148 :               rc.scope(),
      92         148 :               rc.fallBackToAdmin(),
      93             :               clazz,
      94             :               RequiresCapability.class));
      95          79 :     } else if (rac != null) {
      96           2 :       Set<GlobalOrPluginPermission> r = new LinkedHashSet<>();
      97           2 :       for (String capability : rac.value()) {
      98           2 :         r.add(
      99           2 :             resolve(
     100             :                 pluginName,
     101             :                 capability,
     102           2 :                 rac.scope(),
     103           2 :                 rac.fallBackToAdmin(),
     104             :                 clazz,
     105             :                 RequiresAnyCapability.class));
     106             :       }
     107           2 :       return Collections.unmodifiableSet(r);
     108             :     } else {
     109          79 :       return Collections.emptySet();
     110             :     }
     111             :   }
     112             : 
     113             :   public static Set<GlobalOrPluginPermission> fromAnnotation(Class<?> clazz)
     114             :       throws PermissionBackendException {
     115         148 :     return fromAnnotation(null, clazz);
     116             :   }
     117             : 
     118             :   private static GlobalOrPluginPermission resolve(
     119             :       @Nullable String pluginName,
     120             :       String capability,
     121             :       CapabilityScope scope,
     122             :       boolean fallBackToAdmin,
     123             :       Class<?> clazz,
     124             :       Class<?> annotationClass)
     125             :       throws PermissionBackendException {
     126         148 :     if (pluginName != null
     127          25 :         && !PluginName.GERRIT.equals(pluginName)
     128             :         && (scope == CapabilityScope.PLUGIN || scope == CapabilityScope.CONTEXT)) {
     129           1 :       return new PluginPermission(pluginName, capability, fallBackToAdmin);
     130             :     }
     131             : 
     132         148 :     if (scope == CapabilityScope.PLUGIN) {
     133           0 :       logger.atSevere().log(
     134             :           "Class %s uses @%s(scope=%s), but is not within a plugin",
     135           0 :           clazz.getName(), annotationClass.getSimpleName(), scope.name());
     136           0 :       throw new PermissionBackendException("cannot extract permission");
     137             :     }
     138             : 
     139         148 :     Optional<GlobalPermission> perm = globalPermission(capability);
     140         148 :     if (!perm.isPresent()) {
     141           0 :       logger.atSevere().log("Class %s requires unknown capability %s", clazz.getName(), capability);
     142           0 :       throw new PermissionBackendException("cannot extract permission");
     143             :     }
     144         148 :     return perm.get();
     145             :   }
     146             : 
     147             :   @Nullable
     148             :   private static <T extends Annotation> T findAnnotation(Class<?> clazz, Class<T> annotation) {
     149         149 :     for (; clazz != null; clazz = clazz.getSuperclass()) {
     150         149 :       T t = clazz.getAnnotation(annotation);
     151         149 :       if (t != null) {
     152         148 :         return t;
     153             :       }
     154             :     }
     155         149 :     return null;
     156             :   }
     157             : 
     158             :   @Override
     159             :   public String describeForException() {
     160          25 :     return GerritPermission.describeEnumValue(this);
     161             :   }
     162             : }

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