LCOV - code coverage report
Current view: top level - server/restapi/project - ProjectsCollection.java (source / functions) Hit Total Coverage
Test: _coverage_report.dat Lines: 38 41 92.7 %
Date: 2022-11-19 15:00:39 Functions: 9 9 100.0 %

          Line data    Source code
       1             : // Copyright (C) 2012 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.restapi.project;
      16             : 
      17             : import com.google.common.collect.ListMultimap;
      18             : import com.google.common.flogger.FluentLogger;
      19             : import com.google.gerrit.common.Nullable;
      20             : import com.google.gerrit.entities.Project;
      21             : import com.google.gerrit.extensions.registration.DynamicMap;
      22             : import com.google.gerrit.extensions.restapi.AuthException;
      23             : import com.google.gerrit.extensions.restapi.BadRequestException;
      24             : import com.google.gerrit.extensions.restapi.IdString;
      25             : import com.google.gerrit.extensions.restapi.NeedsParams;
      26             : import com.google.gerrit.extensions.restapi.ResourceConflictException;
      27             : import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
      28             : import com.google.gerrit.extensions.restapi.RestApiException;
      29             : import com.google.gerrit.extensions.restapi.RestCollection;
      30             : import com.google.gerrit.extensions.restapi.RestView;
      31             : import com.google.gerrit.extensions.restapi.TopLevelResource;
      32             : import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
      33             : import com.google.gerrit.json.OutputFormat;
      34             : import com.google.gerrit.server.CurrentUser;
      35             : import com.google.gerrit.server.ProjectUtil;
      36             : import com.google.gerrit.server.permissions.PermissionBackend;
      37             : import com.google.gerrit.server.permissions.PermissionBackendException;
      38             : import com.google.gerrit.server.permissions.ProjectPermission;
      39             : import com.google.gerrit.server.project.ProjectCache;
      40             : import com.google.gerrit.server.project.ProjectResource;
      41             : import com.google.gerrit.server.project.ProjectState;
      42             : import com.google.inject.Inject;
      43             : import com.google.inject.Provider;
      44             : import java.io.IOException;
      45             : import java.util.Optional;
      46             : 
      47             : public class ProjectsCollection
      48             :     implements RestCollection<TopLevelResource, ProjectResource>, NeedsParams {
      49         149 :   private static final FluentLogger logger = FluentLogger.forEnclosingClass();
      50             : 
      51             :   private final DynamicMap<RestView<ProjectResource>> views;
      52             :   private final Provider<ListProjects> list;
      53             :   private final Provider<QueryProjects> queryProjects;
      54             :   private final ProjectCache projectCache;
      55             :   private final PermissionBackend permissionBackend;
      56             :   private final Provider<CurrentUser> user;
      57             : 
      58             :   private boolean hasQuery;
      59             : 
      60             :   @Inject
      61             :   public ProjectsCollection(
      62             :       DynamicMap<RestView<ProjectResource>> views,
      63             :       Provider<ListProjects> list,
      64             :       Provider<QueryProjects> queryProjects,
      65             :       ProjectCache projectCache,
      66             :       PermissionBackend permissionBackend,
      67         149 :       Provider<CurrentUser> user) {
      68         149 :     this.views = views;
      69         149 :     this.list = list;
      70         149 :     this.queryProjects = queryProjects;
      71         149 :     this.projectCache = projectCache;
      72         149 :     this.permissionBackend = permissionBackend;
      73         149 :     this.user = user;
      74         149 :   }
      75             : 
      76             :   @Override
      77             :   public void setParams(ListMultimap<String, String> params) throws BadRequestException {
      78             :     // The --query option is defined in QueryProjects
      79           3 :     this.hasQuery = params.containsKey("query");
      80           3 :   }
      81             : 
      82             :   @Override
      83             :   public RestView<TopLevelResource> list() {
      84           3 :     if (hasQuery) {
      85           0 :       return queryProjects.get();
      86             :     }
      87           3 :     return list.get().setFormat(OutputFormat.JSON);
      88             :   }
      89             : 
      90             :   @Override
      91             :   public ProjectResource parse(TopLevelResource parent, IdString id)
      92             :       throws RestApiException, IOException, PermissionBackendException {
      93          15 :     ProjectResource rsrc = _parse(id.get(), true);
      94          15 :     if (rsrc == null) {
      95           6 :       throw new ResourceNotFoundException(id);
      96             :     }
      97          15 :     return rsrc;
      98             :   }
      99             : 
     100             :   /**
     101             :    * Parses a project ID from a request body and returns the project.
     102             :    *
     103             :    * @param id ID of the project, can be a project name
     104             :    * @return the project
     105             :    * @throws RestApiException thrown if the project ID cannot be resolved or if the project is not
     106             :    *     visible to the calling user
     107             :    * @throws IOException thrown when there is an error.
     108             :    */
     109             :   public ProjectResource parse(String id)
     110             :       throws RestApiException, IOException, PermissionBackendException {
     111         144 :     return parse(id, true);
     112             :   }
     113             : 
     114             :   /**
     115             :    * Parses a project ID from a request body and returns the project.
     116             :    *
     117             :    * @param id ID of the project, can be a project name
     118             :    * @param checkAccess if true, check the project is accessible by the current user
     119             :    * @return the project
     120             :    * @throws RestApiException thrown if the project ID cannot be resolved or if the project is not
     121             :    *     visible to the calling user and checkVisibility is true.
     122             :    * @throws IOException thrown when there is an error.
     123             :    */
     124             :   public ProjectResource parse(String id, boolean checkAccess)
     125             :       throws RestApiException, IOException, PermissionBackendException {
     126         144 :     ProjectResource rsrc = _parse(id, checkAccess);
     127         144 :     if (rsrc == null) {
     128         143 :       throw new UnprocessableEntityException(String.format("Project Not Found: %s", id));
     129             :     }
     130         144 :     return rsrc;
     131             :   }
     132             : 
     133             :   @Nullable
     134             :   private ProjectResource _parse(String id, boolean checkAccess)
     135             :       throws PermissionBackendException, ResourceConflictException {
     136         144 :     id = ProjectUtil.sanitizeProjectName(id);
     137             : 
     138         144 :     Project.NameKey nameKey = Project.nameKey(id);
     139         144 :     Optional<ProjectState> state = projectCache.get(nameKey);
     140         144 :     if (!state.isPresent()) {
     141         143 :       return null;
     142             :     }
     143             : 
     144         144 :     logger.atFine().log("Project %s has state %s", nameKey, state.get().getProject().getState());
     145             : 
     146         144 :     if (checkAccess) {
     147             :       // Hidden projects(permitsRead = false) should only be accessible by the project owners.
     148             :       // WRITE_CONFIG is checked here because it's only allowed to project owners (ACCESS may also
     149             :       // be allowed for other users). Allowing project owners to access here will help them to view
     150             :       // and update the config of hidden projects easily.
     151         144 :       if (state.get().statePermitsRead()) {
     152             :         try {
     153         144 :           permissionBackend.currentUser().project(nameKey).check(ProjectPermission.ACCESS);
     154           4 :         } catch (AuthException e) {
     155           4 :           return null;
     156         144 :         }
     157             :       } else {
     158             :         try {
     159           2 :           permissionBackend.currentUser().project(nameKey).check(ProjectPermission.WRITE_CONFIG);
     160           0 :         } catch (AuthException e) {
     161           0 :           state.get().checkStatePermitsRead();
     162           2 :         }
     163             :       }
     164             :     }
     165         144 :     return new ProjectResource(state.get(), user.get());
     166             :   }
     167             : 
     168             :   @Override
     169             :   public DynamicMap<RestView<ProjectResource>> views() {
     170          14 :     return views;
     171             :   }
     172             : }

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