summaryrefslogtreecommitdiffstats
path: root/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ProjectAccessFactory.java
diff options
context:
space:
mode:
Diffstat (limited to 'gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ProjectAccessFactory.java')
-rw-r--r--gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ProjectAccessFactory.java110
1 files changed, 75 insertions, 35 deletions
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ProjectAccessFactory.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ProjectAccessFactory.java
index ca23ec2500..4cd6fa0739 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ProjectAccessFactory.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/project/ProjectAccessFactory.java
@@ -14,6 +14,10 @@
package com.google.gerrit.httpd.rpc.project;
+import static com.google.gerrit.server.permissions.GlobalPermission.ADMINISTRATE_SERVER;
+import static com.google.gerrit.server.permissions.RefPermission.CREATE_CHANGE;
+import static com.google.gerrit.server.permissions.RefPermission.READ;
+
import com.google.common.collect.Maps;
import com.google.gerrit.common.data.AccessSection;
import com.google.gerrit.common.data.GroupDescription;
@@ -24,21 +28,28 @@ 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.GlobalPermission;
+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.permissions.RefPermission;
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 +67,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 +103,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,23 +115,23 @@ 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();
}
}
- final RefControl metaConfigControl = pc.controlForRef(RefNames.REFS_CONFIG);
List<AccessSection> local = new ArrayList<>();
Set<String> ownerOf = new HashSet<>();
Map<AccountGroup.UUID, Boolean> visibleGroups = new HashMap<>();
+ PermissionBackend.ForProject perm = permissionBackend.user(user).project(projectName);
+ boolean checkReadConfig = check(perm, RefNames.REFS_CONFIG, READ);
for (AccessSection section : config.getAccessSections()) {
String name = section.getName();
@@ -122,20 +140,19 @@ class ProjectAccessFactory extends Handler<ProjectAccess> {
local.add(section);
ownerOf.add(name);
- } else if (metaConfigControl.isVisible()) {
+ } else if (checkReadConfig) {
local.add(section);
}
} else if (RefConfigSection.isValid(name)) {
- RefControl rc = pc.controlForRef(name);
- if (rc.isOwner()) {
+ if (pc.controlForRef(name).isOwner()) {
local.add(section);
ownerOf.add(name);
- } else if (metaConfigControl.isVisible()) {
+ } else if (checkReadConfig) {
local.add(section);
- } else if (rc.isVisible()) {
+ } else if (check(perm, name, READ)) {
// Filter the section to only add rules describing groups that
// are visible to the current-user. This includes any group the
// user is a member of, as well as groups they own or that
@@ -177,10 +194,9 @@ class ProjectAccessFactory extends Handler<ProjectAccess> {
}
}
- if (ownerOf.isEmpty() && pc.isOwnerAnyRef()) {
+ if (ownerOf.isEmpty() && isAdmin()) {
// Special case: If the section list is empty, this project has no current
- // access control information. Rely on what ProjectControl determines
- // is ownership, which probably means falling back to site administrators.
+ // access control information. Fall back to site administrators.
ownerOf.add(AccessSection.ALL);
}
@@ -193,19 +209,19 @@ class ProjectAccessFactory extends Handler<ProjectAccess> {
detail.setInheritsFrom(config.getProject().getParent(allProjectsName));
- if (projectName.equals(allProjectsName)) {
- if (pc.isOwner()) {
- ownerOf.add(AccessSection.GLOBAL_CAPABILITIES);
- }
+ if (projectName.equals(allProjectsName)
+ && permissionBackend.user(user).testOrFalse(ADMINISTRATE_SERVER)) {
+ ownerOf.add(AccessSection.GLOBAL_CAPABILITIES);
}
detail.setLocal(local);
detail.setOwnerOf(ownerOf);
detail.setCanUpload(
- metaConfigControl.isVisible() && (pc.isOwner() || metaConfigControl.canUpload()));
- detail.setConfigVisible(pc.isOwner() || metaConfigControl.isVisible());
+ pc.isOwner()
+ || (checkReadConfig && perm.ref(RefNames.REFS_CONFIG).testOrFalse(CREATE_CHANGE)));
+ detail.setConfigVisible(pc.isOwner() || checkReadConfig);
detail.setGroupInfo(buildGroupInfo(local));
- detail.setLabelTypes(pc.getLabelTypes());
+ detail.setLabelTypes(pc.getProjectState().getLabelTypes());
detail.setFileHistoryLinks(getConfigFileLogLinks(projectName.get()));
return detail;
}
@@ -235,9 +251,33 @@ 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;
+ }
+
+ private static boolean check(PermissionBackend.ForProject ctx, String ref, RefPermission perm)
+ throws PermissionBackendException {
+ try {
+ ctx.ref(ref).check(perm);
+ return true;
+ } catch (AuthException denied) {
+ return false;
+ }
+ }
+
+ private boolean isAdmin() throws PermissionBackendException {
+ try {
+ permissionBackend.user(user).check(GlobalPermission.ADMINISTRATE_SERVER);
+ return true;
+ } catch (AuthException e) {
+ return false;
+ }
}
}