Convert reading project access to use PermissionBackend

Reading the access sections for a project requires ACCESS
permission, as the handlers filter references and groups
depending on the caller.

Change-Id: Ie5a3d58b5456593db6e6ac9725bb981bcef8b3a8
This commit is contained in:
Shawn Pearce 2017-02-23 12:07:36 -08:00 committed by David Pursehouse
parent 17ab8ce41e
commit 5bff3ab86b
4 changed files with 46 additions and 28 deletions

View File

@ -24,6 +24,7 @@ import com.google.gerrit.server.config.AllProjectsName;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.server.git.MetaDataUpdate;
import com.google.gerrit.server.git.ProjectConfig;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.project.NoSuchProjectException;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectControl;
@ -89,7 +90,8 @@ class ChangeProjectAccess extends ProjectAccessHandler<ProjectAccess> {
ProjectConfig config,
MetaDataUpdate md,
boolean parentProjectUpdate)
throws IOException, NoSuchProjectException, ConfigInvalidException {
throws IOException, NoSuchProjectException, ConfigInvalidException,
PermissionBackendException {
RevCommit commit = config.commit(md);
gitRefUpdated.fire(

View File

@ -24,21 +24,27 @@ import com.google.gerrit.common.data.ProjectAccess;
import com.google.gerrit.common.data.RefConfigSection;
import com.google.gerrit.common.data.WebLinkInfoCommon;
import com.google.gerrit.common.errors.NoSuchGroupException;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.httpd.rpc.Handler;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.WebLinks;
import com.google.gerrit.server.account.GroupBackend;
import com.google.gerrit.server.account.GroupControl;
import com.google.gerrit.server.config.AllProjectsName;
import com.google.gerrit.server.git.MetaDataUpdate;
import com.google.gerrit.server.git.ProjectConfig;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.permissions.ProjectPermission;
import com.google.gerrit.server.project.NoSuchProjectException;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectControl;
import com.google.gerrit.server.project.RefControl;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.assistedinject.Assisted;
import java.io.IOException;
import java.util.ArrayList;
@ -56,27 +62,32 @@ class ProjectAccessFactory extends Handler<ProjectAccess> {
private final GroupBackend groupBackend;
private final ProjectCache projectCache;
private final ProjectControl.Factory projectControlFactory;
private final PermissionBackend permissionBackend;
private final Provider<CurrentUser> user;
private final ProjectControl.GenericFactory projectControlFactory;
private final GroupControl.Factory groupControlFactory;
private final MetaDataUpdate.Server metaDataUpdateFactory;
private final AllProjectsName allProjectsName;
private final Project.NameKey projectName;
private ProjectControl pc;
private WebLinks webLinks;
@Inject
ProjectAccessFactory(
final GroupBackend groupBackend,
final ProjectCache projectCache,
final ProjectControl.Factory projectControlFactory,
final GroupControl.Factory groupControlFactory,
final MetaDataUpdate.Server metaDataUpdateFactory,
final AllProjectsName allProjectsName,
final WebLinks webLinks,
GroupBackend groupBackend,
ProjectCache projectCache,
PermissionBackend permissionBackend,
Provider<CurrentUser> user,
ProjectControl.GenericFactory projectControlFactory,
GroupControl.Factory groupControlFactory,
MetaDataUpdate.Server metaDataUpdateFactory,
AllProjectsName allProjectsName,
WebLinks webLinks,
@Assisted final Project.NameKey name) {
this.groupBackend = groupBackend;
this.projectCache = projectCache;
this.permissionBackend = permissionBackend;
this.user = user;
this.projectControlFactory = projectControlFactory;
this.groupControlFactory = groupControlFactory;
this.metaDataUpdateFactory = metaDataUpdateFactory;
@ -87,8 +98,10 @@ class ProjectAccessFactory extends Handler<ProjectAccess> {
}
@Override
public ProjectAccess call() throws NoSuchProjectException, IOException, ConfigInvalidException {
pc = open();
public ProjectAccess call()
throws NoSuchProjectException, IOException, ConfigInvalidException,
PermissionBackendException {
ProjectControl pc = checkProjectControl();
// Load the current configuration from the repository, ensuring its the most
// recent version available. If it differs from what was in the project
@ -97,16 +110,15 @@ class ProjectAccessFactory extends Handler<ProjectAccess> {
ProjectConfig config;
try (MetaDataUpdate md = metaDataUpdateFactory.create(projectName)) {
config = ProjectConfig.read(md);
if (config.updateGroupNames(groupBackend)) {
md.setMessage("Update group names\n");
config.commit(md);
projectCache.evict(config.getProject());
pc = open();
pc = checkProjectControl();
} else if (config.getRevision() != null
&& !config.getRevision().equals(pc.getProjectState().getConfig().getRevision())) {
projectCache.evict(config.getProject());
pc = open();
pc = checkProjectControl();
}
}
@ -235,9 +247,14 @@ class ProjectAccessFactory extends Handler<ProjectAccess> {
return Maps.filterEntries(infos, in -> in.getValue() != null);
}
private ProjectControl open() throws NoSuchProjectException {
return projectControlFactory.validateFor( //
projectName, //
ProjectControl.OWNER | ProjectControl.VISIBLE);
private ProjectControl checkProjectControl()
throws NoSuchProjectException, IOException, PermissionBackendException {
ProjectControl pc = projectControlFactory.controlFor(projectName, user.get());
try {
permissionBackend.user(user).project(projectName).check(ProjectPermission.ACCESS);
} catch (AuthException e) {
throw new NoSuchProjectException(projectName);
}
return pc;
}
}

View File

@ -183,7 +183,7 @@ public abstract class ProjectAccessHandler<T> extends Handler<T> {
MetaDataUpdate md,
boolean parentProjectUpdate)
throws IOException, NoSuchProjectException, ConfigInvalidException, OrmException,
PermissionDeniedException;
PermissionDeniedException, PermissionBackendException;
private void replace(ProjectConfig config, Set<String> toDelete, AccessSection section)
throws NoSuchGroupException {

View File

@ -95,7 +95,7 @@ public class GetAccess implements RestReadView<ProjectResource> {
public ProjectAccessInfo apply(Project.NameKey nameKey)
throws ResourceNotFoundException, ResourceConflictException, IOException {
try {
return this.apply(new ProjectResource(projectControlFactory.controlFor(nameKey, self.get())));
return apply(new ProjectResource(projectControlFactory.controlFor(nameKey, self.get())));
} catch (NoSuchProjectException e) {
throw new ResourceNotFoundException(nameKey.get());
}
@ -111,7 +111,7 @@ public class GetAccess implements RestReadView<ProjectResource> {
Project.NameKey projectName = rsrc.getNameKey();
ProjectAccessInfo info = new ProjectAccessInfo();
ProjectConfig config;
ProjectControl pc = open(projectName);
ProjectControl pc = createProjectControl(projectName);
RefControl metaConfigControl = pc.controlForRef(RefNames.REFS_CONFIG);
try (MetaDataUpdate md = metaDataUpdateFactory.create(projectName)) {
config = ProjectConfig.read(md);
@ -120,11 +120,11 @@ public class GetAccess implements RestReadView<ProjectResource> {
md.setMessage("Update group names\n");
config.commit(md);
projectCache.evict(config.getProject());
pc = open(projectName);
pc = createProjectControl(projectName);
} else if (config.getRevision() != null
&& !config.getRevision().equals(pc.getProjectState().getConfig().getRevision())) {
projectCache.evict(config.getProject());
pc = open(projectName);
pc = createProjectControl(projectName);
}
} catch (ConfigInvalidException e) {
throw new ResourceConflictException(e.getMessage());
@ -252,11 +252,10 @@ public class GetAccess implements RestReadView<ProjectResource> {
return accessSectionInfo;
}
private ProjectControl open(Project.NameKey projectName)
throws ResourceNotFoundException, IOException {
private ProjectControl createProjectControl(Project.NameKey projectName)
throws IOException, ResourceNotFoundException {
try {
return projectControlFactory.validateFor(
projectName, ProjectControl.OWNER | ProjectControl.VISIBLE, self.get());
return projectControlFactory.controlFor(projectName, self.get());
} catch (NoSuchProjectException e) {
throw new ResourceNotFoundException(projectName.get());
}