Remove the non-permission check #isHidden from ProjectControl
PermissionBackend is supposed to only contain permission related checks. Apparently, this #isHidden is a project state check rather than a permission check. Thus it should be removed from the ProjectControl, which is part of the DefaultPermissionBackend. Before removing this, "ACCESS" permission checks for hidden projects will only succeed for the project owners. After removing, they may also succeed for other users, e.g. internal user. The existing checks for "ACCESS" could be divided into two categories base on whether it's helpful for users to change the configuration of the project state or not. For the helpful case, this commit preserves the current behavior of the "ACCESS" check on hidden projects by checking the "READ_CONFIG" permission which will only succeed for the project owners. For the other case, this commit rejects directly even for project owners if the project is hidden. Change-Id: I20743e6380129eea7cb942d8d9ccad314e29d187
This commit is contained in:
@@ -184,7 +184,7 @@ public class GitOverHttpServlet extends GitServlet {
|
|||||||
try {
|
try {
|
||||||
Project.NameKey nameKey = new Project.NameKey(projectName);
|
Project.NameKey nameKey = new Project.NameKey(projectName);
|
||||||
ProjectState state = projectCache.checkedGet(nameKey);
|
ProjectState state = projectCache.checkedGet(nameKey);
|
||||||
if (state == null) {
|
if (state == null || !state.statePermitsRead()) {
|
||||||
throw new RepositoryNotFoundException(nameKey.get());
|
throw new RepositoryNotFoundException(nameKey.get());
|
||||||
}
|
}
|
||||||
req.setAttribute(ATT_STATE, state);
|
req.setAttribute(ATT_STATE, state);
|
||||||
|
@@ -259,8 +259,14 @@ class ProjectAccessFactory extends Handler<ProjectAccess> {
|
|||||||
throws NoSuchProjectException, IOException, PermissionBackendException,
|
throws NoSuchProjectException, IOException, PermissionBackendException,
|
||||||
ResourceConflictException {
|
ResourceConflictException {
|
||||||
ProjectState state = projectCache.checkedGet(projectName);
|
ProjectState state = projectCache.checkedGet(projectName);
|
||||||
|
// Hidden projects(permitsRead = false) should only be accessible by the project owners.
|
||||||
|
// READ_CONFIG is checked here because it's only allowed to project owners(ACCESS may also
|
||||||
|
// be allowed for other users). Allowing project owners to access here will help them to view
|
||||||
|
// and update the config of hidden projects easily.
|
||||||
|
ProjectPermission permissionToCheck =
|
||||||
|
state.statePermitsRead() ? ProjectPermission.ACCESS : ProjectPermission.READ_CONFIG;
|
||||||
try {
|
try {
|
||||||
permissionBackend.currentUser().project(projectName).check(ProjectPermission.ACCESS);
|
permissionBackend.currentUser().project(projectName).check(permissionToCheck);
|
||||||
} catch (AuthException e) {
|
} catch (AuthException e) {
|
||||||
throw new NoSuchProjectException(projectName);
|
throw new NoSuchProjectException(projectName);
|
||||||
}
|
}
|
||||||
|
@@ -79,7 +79,13 @@ public class ProjectHandler extends OptionHandler<ProjectState> {
|
|||||||
if (state == null) {
|
if (state == null) {
|
||||||
throw new CmdLineException(owner, String.format("project %s not found", nameWithoutSuffix));
|
throw new CmdLineException(owner, String.format("project %s not found", nameWithoutSuffix));
|
||||||
}
|
}
|
||||||
permissionBackend.currentUser().project(nameKey).check(ProjectPermission.ACCESS);
|
// Hidden projects(permitsRead = false) should only be accessible by the project owners.
|
||||||
|
// READ_CONFIG is checked here because it's only allowed to project owners(ACCESS may also
|
||||||
|
// be allowed for other users). Allowing project owners to access here will help them to view
|
||||||
|
// and update the config of hidden projects easily.
|
||||||
|
ProjectPermission permissionToCheck =
|
||||||
|
state.statePermitsRead() ? ProjectPermission.ACCESS : ProjectPermission.READ_CONFIG;
|
||||||
|
permissionBackend.currentUser().project(nameKey).check(permissionToCheck);
|
||||||
} catch (AuthException e) {
|
} catch (AuthException e) {
|
||||||
throw new CmdLineException(owner, new NoSuchProjectException(nameKey).getMessage());
|
throw new CmdLineException(owner, new NoSuchProjectException(nameKey).getMessage());
|
||||||
} catch (PermissionBackendException | IOException e) {
|
} catch (PermissionBackendException | IOException e) {
|
||||||
|
@@ -150,6 +150,11 @@ public class EventBroker implements EventDispatcher {
|
|||||||
|
|
||||||
protected boolean isVisibleTo(Project.NameKey project, CurrentUser user) {
|
protected boolean isVisibleTo(Project.NameKey project, CurrentUser user) {
|
||||||
try {
|
try {
|
||||||
|
ProjectState state = projectCache.get(project);
|
||||||
|
if (state == null || !state.statePermitsRead()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
permissionBackend.user(user).project(project).check(ProjectPermission.ACCESS);
|
permissionBackend.user(user).project(project).check(ProjectPermission.ACCESS);
|
||||||
return true;
|
return true;
|
||||||
} catch (AuthException | PermissionBackendException e) {
|
} catch (AuthException | PermissionBackendException e) {
|
||||||
|
@@ -202,11 +202,6 @@ class ProjectControl {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns whether the project is hidden. */
|
|
||||||
private boolean isHidden() {
|
|
||||||
return getProject().getState().equals(com.google.gerrit.extensions.client.ProjectState.HIDDEN);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean canAddRefs() {
|
private boolean canAddRefs() {
|
||||||
return (canPerformOnAnyRef(Permission.CREATE) || isAdmin());
|
return (canPerformOnAnyRef(Permission.CREATE) || isAdmin());
|
||||||
}
|
}
|
||||||
@@ -400,8 +395,7 @@ class ProjectControl {
|
|||||||
private boolean can(ProjectPermission perm) throws PermissionBackendException {
|
private boolean can(ProjectPermission perm) throws PermissionBackendException {
|
||||||
switch (perm) {
|
switch (perm) {
|
||||||
case ACCESS:
|
case ACCESS:
|
||||||
return (!isHidden() && (user.isInternalUser() || canPerformOnAnyRef(Permission.READ)))
|
return user.isInternalUser() || isOwner() || canPerformOnAnyRef(Permission.READ);
|
||||||
|| isOwner();
|
|
||||||
|
|
||||||
case READ:
|
case READ:
|
||||||
return allRefsAreVisible(Collections.emptySet());
|
return allRefsAreVisible(Collections.emptySet());
|
||||||
|
@@ -53,7 +53,7 @@ public class ChildProjects {
|
|||||||
|
|
||||||
/** Gets all child projects recursively. */
|
/** Gets all child projects recursively. */
|
||||||
public List<ProjectInfo> list(Project.NameKey parent) throws PermissionBackendException {
|
public List<ProjectInfo> list(Project.NameKey parent) throws PermissionBackendException {
|
||||||
Map<Project.NameKey, Project> projects = readAllProjects();
|
Map<Project.NameKey, Project> projects = readAllReadableProjects();
|
||||||
Multimap<Project.NameKey, Project.NameKey> children = parentToChildren(projects);
|
Multimap<Project.NameKey, Project.NameKey> children = parentToChildren(projects);
|
||||||
PermissionBackend.WithUser perm = permissionBackend.currentUser();
|
PermissionBackend.WithUser perm = permissionBackend.currentUser();
|
||||||
|
|
||||||
@@ -62,11 +62,11 @@ public class ChildProjects {
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<Project.NameKey, Project> readAllProjects() {
|
private Map<Project.NameKey, Project> readAllReadableProjects() {
|
||||||
Map<Project.NameKey, Project> projects = new HashMap<>();
|
Map<Project.NameKey, Project> projects = new HashMap<>();
|
||||||
for (Project.NameKey name : projectCache.all()) {
|
for (Project.NameKey name : projectCache.all()) {
|
||||||
ProjectState c = projectCache.get(name);
|
ProjectState c = projectCache.get(name);
|
||||||
if (c != null) {
|
if (c != null && c.statePermitsRead()) {
|
||||||
projects.put(c.getNameKey(), c.getProject());
|
projects.put(c.getNameKey(), c.getProject());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -44,17 +44,17 @@ public class SuggestParentCandidates {
|
|||||||
public List<Project.NameKey> getNameKeys() throws PermissionBackendException {
|
public List<Project.NameKey> getNameKeys() throws PermissionBackendException {
|
||||||
return permissionBackend
|
return permissionBackend
|
||||||
.currentUser()
|
.currentUser()
|
||||||
.filter(ProjectPermission.ACCESS, parents())
|
.filter(ProjectPermission.ACCESS, readableParents())
|
||||||
.stream()
|
.stream()
|
||||||
.sorted()
|
.sorted()
|
||||||
.collect(toList());
|
.collect(toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
private Set<Project.NameKey> parents() {
|
private Set<Project.NameKey> readableParents() {
|
||||||
Set<Project.NameKey> parents = new HashSet<>();
|
Set<Project.NameKey> parents = new HashSet<>();
|
||||||
for (Project.NameKey p : projectCache.all()) {
|
for (Project.NameKey p : projectCache.all()) {
|
||||||
ProjectState ps = projectCache.get(p);
|
ProjectState ps = projectCache.get(p);
|
||||||
if (ps != null) {
|
if (ps != null && ps.statePermitsRead()) {
|
||||||
Project.NameKey parent = ps.getProject().getParent();
|
Project.NameKey parent = ps.getProject().getParent();
|
||||||
if (parent != null) {
|
if (parent != null) {
|
||||||
parents.add(parent);
|
parents.add(parent);
|
||||||
|
@@ -28,6 +28,8 @@ import com.google.gerrit.server.permissions.GlobalPermission;
|
|||||||
import com.google.gerrit.server.permissions.PermissionBackend;
|
import com.google.gerrit.server.permissions.PermissionBackend;
|
||||||
import com.google.gerrit.server.permissions.PermissionBackendException;
|
import com.google.gerrit.server.permissions.PermissionBackendException;
|
||||||
import com.google.gerrit.server.permissions.ProjectPermission;
|
import com.google.gerrit.server.permissions.ProjectPermission;
|
||||||
|
import com.google.gerrit.server.project.ProjectCache;
|
||||||
|
import com.google.gerrit.server.project.ProjectState;
|
||||||
import com.google.gerrit.server.util.IdGenerator;
|
import com.google.gerrit.server.util.IdGenerator;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import com.google.inject.Provider;
|
import com.google.inject.Provider;
|
||||||
@@ -46,13 +48,18 @@ public class ListTasks implements RestReadView<ConfigResource> {
|
|||||||
private final PermissionBackend permissionBackend;
|
private final PermissionBackend permissionBackend;
|
||||||
private final WorkQueue workQueue;
|
private final WorkQueue workQueue;
|
||||||
private final Provider<CurrentUser> self;
|
private final Provider<CurrentUser> self;
|
||||||
|
private final ProjectCache projectCache;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public ListTasks(
|
public ListTasks(
|
||||||
PermissionBackend permissionBackend, WorkQueue workQueue, Provider<CurrentUser> self) {
|
PermissionBackend permissionBackend,
|
||||||
|
WorkQueue workQueue,
|
||||||
|
Provider<CurrentUser> self,
|
||||||
|
ProjectCache projectCache) {
|
||||||
this.permissionBackend = permissionBackend;
|
this.permissionBackend = permissionBackend;
|
||||||
this.workQueue = workQueue;
|
this.workQueue = workQueue;
|
||||||
this.self = self;
|
this.self = self;
|
||||||
|
this.projectCache = projectCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -77,15 +84,18 @@ public class ListTasks implements RestReadView<ConfigResource> {
|
|||||||
if (task.projectName != null) {
|
if (task.projectName != null) {
|
||||||
Boolean visible = visibilityCache.get(task.projectName);
|
Boolean visible = visibilityCache.get(task.projectName);
|
||||||
if (visible == null) {
|
if (visible == null) {
|
||||||
|
Project.NameKey nameKey = new Project.NameKey(task.projectName);
|
||||||
|
ProjectState state = projectCache.get(nameKey);
|
||||||
|
if (state == null || !state.statePermitsRead()) {
|
||||||
|
visible = false;
|
||||||
|
} else {
|
||||||
try {
|
try {
|
||||||
permissionBackend
|
permissionBackend.user(user).project(nameKey).check(ProjectPermission.ACCESS);
|
||||||
.user(user)
|
|
||||||
.project(new Project.NameKey(task.projectName))
|
|
||||||
.check(ProjectPermission.ACCESS);
|
|
||||||
visible = true;
|
visible = true;
|
||||||
} catch (AuthException e) {
|
} catch (AuthException e) {
|
||||||
visible = false;
|
visible = false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
visibilityCache.put(task.projectName, visible);
|
visibilityCache.put(task.projectName, visible);
|
||||||
}
|
}
|
||||||
if (visible) {
|
if (visible) {
|
||||||
|
@@ -18,8 +18,10 @@ import com.google.gerrit.extensions.registration.DynamicMap;
|
|||||||
import com.google.gerrit.extensions.restapi.AuthException;
|
import com.google.gerrit.extensions.restapi.AuthException;
|
||||||
import com.google.gerrit.extensions.restapi.ChildCollection;
|
import com.google.gerrit.extensions.restapi.ChildCollection;
|
||||||
import com.google.gerrit.extensions.restapi.IdString;
|
import com.google.gerrit.extensions.restapi.IdString;
|
||||||
|
import com.google.gerrit.extensions.restapi.ResourceConflictException;
|
||||||
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
|
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
|
||||||
import com.google.gerrit.extensions.restapi.RestView;
|
import com.google.gerrit.extensions.restapi.RestView;
|
||||||
|
import com.google.gerrit.reviewdb.client.Project;
|
||||||
import com.google.gerrit.server.CurrentUser;
|
import com.google.gerrit.server.CurrentUser;
|
||||||
import com.google.gerrit.server.config.ConfigResource;
|
import com.google.gerrit.server.config.ConfigResource;
|
||||||
import com.google.gerrit.server.config.TaskResource;
|
import com.google.gerrit.server.config.TaskResource;
|
||||||
@@ -30,6 +32,8 @@ import com.google.gerrit.server.permissions.GlobalPermission;
|
|||||||
import com.google.gerrit.server.permissions.PermissionBackend;
|
import com.google.gerrit.server.permissions.PermissionBackend;
|
||||||
import com.google.gerrit.server.permissions.PermissionBackendException;
|
import com.google.gerrit.server.permissions.PermissionBackendException;
|
||||||
import com.google.gerrit.server.permissions.ProjectPermission;
|
import com.google.gerrit.server.permissions.ProjectPermission;
|
||||||
|
import com.google.gerrit.server.project.ProjectCache;
|
||||||
|
import com.google.gerrit.server.project.ProjectState;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import com.google.inject.Provider;
|
import com.google.inject.Provider;
|
||||||
import com.google.inject.Singleton;
|
import com.google.inject.Singleton;
|
||||||
@@ -41,6 +45,7 @@ public class TasksCollection implements ChildCollection<ConfigResource, TaskReso
|
|||||||
private final WorkQueue workQueue;
|
private final WorkQueue workQueue;
|
||||||
private final Provider<CurrentUser> self;
|
private final Provider<CurrentUser> self;
|
||||||
private final PermissionBackend permissionBackend;
|
private final PermissionBackend permissionBackend;
|
||||||
|
private final ProjectCache projectCache;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
TasksCollection(
|
TasksCollection(
|
||||||
@@ -48,12 +53,14 @@ public class TasksCollection implements ChildCollection<ConfigResource, TaskReso
|
|||||||
ListTasks list,
|
ListTasks list,
|
||||||
WorkQueue workQueue,
|
WorkQueue workQueue,
|
||||||
Provider<CurrentUser> self,
|
Provider<CurrentUser> self,
|
||||||
PermissionBackend permissionBackend) {
|
PermissionBackend permissionBackend,
|
||||||
|
ProjectCache projectCache) {
|
||||||
this.views = views;
|
this.views = views;
|
||||||
this.list = list;
|
this.list = list;
|
||||||
this.workQueue = workQueue;
|
this.workQueue = workQueue;
|
||||||
this.self = self;
|
this.self = self;
|
||||||
this.permissionBackend = permissionBackend;
|
this.permissionBackend = permissionBackend;
|
||||||
|
this.projectCache = projectCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -63,7 +70,8 @@ public class TasksCollection implements ChildCollection<ConfigResource, TaskReso
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TaskResource parse(ConfigResource parent, IdString id)
|
public TaskResource parse(ConfigResource parent, IdString id)
|
||||||
throws ResourceNotFoundException, AuthException, PermissionBackendException {
|
throws ResourceNotFoundException, AuthException, PermissionBackendException,
|
||||||
|
ResourceConflictException {
|
||||||
CurrentUser user = self.get();
|
CurrentUser user = self.get();
|
||||||
if (!user.isIdentifiedUser()) {
|
if (!user.isIdentifiedUser()) {
|
||||||
throw new AuthException("Authentication required");
|
throw new AuthException("Authentication required");
|
||||||
@@ -78,11 +86,16 @@ public class TasksCollection implements ChildCollection<ConfigResource, TaskReso
|
|||||||
|
|
||||||
Task<?> task = workQueue.getTask(taskId);
|
Task<?> task = workQueue.getTask(taskId);
|
||||||
if (task instanceof ProjectTask) {
|
if (task instanceof ProjectTask) {
|
||||||
|
Project.NameKey nameKey = ((ProjectTask<?>) task).getProjectNameKey();
|
||||||
|
ProjectState state = projectCache.get(nameKey);
|
||||||
|
if (state == null) {
|
||||||
|
throw new ResourceNotFoundException(String.format("project %s not found", nameKey));
|
||||||
|
}
|
||||||
|
|
||||||
|
state.checkStatePermitsRead();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
permissionBackend
|
permissionBackend.user(user).project(nameKey).check(ProjectPermission.ACCESS);
|
||||||
.user(user)
|
|
||||||
.project(((ProjectTask<?>) task).getProjectNameKey())
|
|
||||||
.check(ProjectPermission.ACCESS);
|
|
||||||
return new TaskResource(task);
|
return new TaskResource(task);
|
||||||
} catch (AuthException e) {
|
} catch (AuthException e) {
|
||||||
// Fall through and try view queue permission.
|
// Fall through and try view queue permission.
|
||||||
|
@@ -80,7 +80,9 @@ public class ListChildProjects implements RestReadView<ProjectResource> {
|
|||||||
Map<Project.NameKey, Project> children = new HashMap<>();
|
Map<Project.NameKey, Project> children = new HashMap<>();
|
||||||
for (Project.NameKey name : projectCache.all()) {
|
for (Project.NameKey name : projectCache.all()) {
|
||||||
ProjectState c = projectCache.get(name);
|
ProjectState c = projectCache.get(name);
|
||||||
if (c != null && parent.equals(c.getProject().getParent(allProjects))) {
|
if (c != null
|
||||||
|
&& parent.equals(c.getProject().getParent(allProjects))
|
||||||
|
&& c.statePermitsRead()) {
|
||||||
children.put(c.getNameKey(), c.getProject());
|
children.put(c.getNameKey(), c.getProject());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -88,8 +88,11 @@ public class ListDashboards implements RestReadView<ProjectResource> {
|
|||||||
private Collection<ProjectState> tree(ProjectResource rsrc) throws PermissionBackendException {
|
private Collection<ProjectState> tree(ProjectResource rsrc) throws PermissionBackendException {
|
||||||
Map<Project.NameKey, ProjectState> tree = new LinkedHashMap<>();
|
Map<Project.NameKey, ProjectState> tree = new LinkedHashMap<>();
|
||||||
for (ProjectState ps : rsrc.getProjectState().tree()) {
|
for (ProjectState ps : rsrc.getProjectState().tree()) {
|
||||||
|
if (ps.statePermitsRead()) {
|
||||||
tree.put(ps.getNameKey(), ps);
|
tree.put(ps.getNameKey(), ps);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
tree.keySet()
|
tree.keySet()
|
||||||
.retainAll(permissionBackend.currentUser().filter(ProjectPermission.ACCESS, tree.keySet()));
|
.retainAll(permissionBackend.currentUser().filter(ProjectPermission.ACCESS, tree.keySet()));
|
||||||
return tree.values();
|
return tree.values();
|
||||||
|
@@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
package com.google.gerrit.server.restapi.project;
|
package com.google.gerrit.server.restapi.project;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static com.google.gerrit.extensions.client.ProjectState.HIDDEN;
|
import static com.google.gerrit.extensions.client.ProjectState.HIDDEN;
|
||||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
import static java.util.stream.Collectors.toList;
|
import static java.util.stream.Collectors.toList;
|
||||||
@@ -521,11 +522,28 @@ public class ListProjects implements RestReadView<TopLevelResource> {
|
|||||||
if (type == FilterType.PARENT_CANDIDATES) {
|
if (type == FilterType.PARENT_CANDIDATES) {
|
||||||
matches = parentsOf(matches);
|
matches = parentsOf(matches);
|
||||||
}
|
}
|
||||||
// TODO(dborowitz): Streamified PermissionBackend#filter.
|
|
||||||
return perm.filter(ProjectPermission.ACCESS, matches.collect(toList()))
|
List<Project.NameKey> results = new ArrayList<>();
|
||||||
.stream()
|
List<Project.NameKey> projectNameKeys = matches.sorted().collect(toList());
|
||||||
.sorted()
|
for (Project.NameKey nameKey : projectNameKeys) {
|
||||||
.collect(toList());
|
ProjectState state = projectCache.get(nameKey);
|
||||||
|
checkNotNull(state, "Failed to load project %s", nameKey);
|
||||||
|
|
||||||
|
// Hidden projects(permitsRead = false) should only be accessible by the project owners.
|
||||||
|
// READ_CONFIG is checked here because it's only allowed to project owners(ACCESS may also
|
||||||
|
// be allowed for other users). Allowing project owners to access here will help them to view
|
||||||
|
// and update the config of hidden projects easily.
|
||||||
|
ProjectPermission permissionToCheck =
|
||||||
|
state.statePermitsRead() ? ProjectPermission.ACCESS : ProjectPermission.READ_CONFIG;
|
||||||
|
try {
|
||||||
|
perm.project(nameKey).check(permissionToCheck);
|
||||||
|
results.add(nameKey);
|
||||||
|
} catch (AuthException e) {
|
||||||
|
// Not added to results.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Stream<Project.NameKey> parentsOf(Stream<Project.NameKey> matches) {
|
private Stream<Project.NameKey> parentsOf(Stream<Project.NameKey> matches) {
|
||||||
@@ -551,13 +569,19 @@ public class ListProjects implements RestReadView<TopLevelResource> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean isParentAccessible(
|
private boolean isParentAccessible(
|
||||||
Map<Project.NameKey, Boolean> checked, PermissionBackend.WithUser perm, ProjectState p)
|
Map<Project.NameKey, Boolean> checked, PermissionBackend.WithUser perm, ProjectState state)
|
||||||
throws PermissionBackendException {
|
throws PermissionBackendException {
|
||||||
Project.NameKey name = p.getNameKey();
|
Project.NameKey name = state.getNameKey();
|
||||||
Boolean b = checked.get(name);
|
Boolean b = checked.get(name);
|
||||||
if (b == null) {
|
if (b == null) {
|
||||||
try {
|
try {
|
||||||
perm.project(name).check(ProjectPermission.ACCESS);
|
// Hidden projects(permitsRead = false) should only be accessible by the project owners.
|
||||||
|
// READ_CONFIG is checked here because it's only allowed to project owners(ACCESS may also
|
||||||
|
// be allowed for other users). Allowing project owners to access here will help them to view
|
||||||
|
// and update the config of hidden projects easily.
|
||||||
|
ProjectPermission permissionToCheck =
|
||||||
|
state.statePermitsRead() ? ProjectPermission.ACCESS : ProjectPermission.READ_CONFIG;
|
||||||
|
perm.project(name).check(permissionToCheck);
|
||||||
b = true;
|
b = true;
|
||||||
} catch (AuthException denied) {
|
} catch (AuthException denied) {
|
||||||
b = false;
|
b = false;
|
||||||
|
@@ -150,8 +150,14 @@ public class ProjectsCollection
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (checkAccess) {
|
if (checkAccess) {
|
||||||
|
// Hidden projects(permitsRead = false) should only be accessible by the project owners.
|
||||||
|
// READ_CONFIG is checked here because it's only allowed to project owners(ACCESS may also
|
||||||
|
// be allowed for other users). Allowing project owners to access here will help them to view
|
||||||
|
// and update the config of hidden projects easily.
|
||||||
|
ProjectPermission permissionToCheck =
|
||||||
|
state.statePermitsRead() ? ProjectPermission.ACCESS : ProjectPermission.READ_CONFIG;
|
||||||
try {
|
try {
|
||||||
permissionBackend.currentUser().project(nameKey).check(ProjectPermission.ACCESS);
|
permissionBackend.currentUser().project(nameKey).check(permissionToCheck);
|
||||||
} catch (AuthException e) {
|
} catch (AuthException e) {
|
||||||
return null; // Pretend like not found on access denied.
|
return null; // Pretend like not found on access denied.
|
||||||
}
|
}
|
||||||
|
@@ -20,6 +20,7 @@ import static com.google.gerrit.common.data.GlobalCapability.MAINTAIN_SERVER;
|
|||||||
import com.google.gerrit.extensions.annotations.RequiresAnyCapability;
|
import com.google.gerrit.extensions.annotations.RequiresAnyCapability;
|
||||||
import com.google.gerrit.extensions.restapi.AuthException;
|
import com.google.gerrit.extensions.restapi.AuthException;
|
||||||
import com.google.gerrit.extensions.restapi.IdString;
|
import com.google.gerrit.extensions.restapi.IdString;
|
||||||
|
import com.google.gerrit.extensions.restapi.ResourceConflictException;
|
||||||
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
|
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
|
||||||
import com.google.gerrit.server.config.ConfigResource;
|
import com.google.gerrit.server.config.ConfigResource;
|
||||||
import com.google.gerrit.server.config.TaskResource;
|
import com.google.gerrit.server.config.TaskResource;
|
||||||
@@ -51,7 +52,10 @@ final class KillCommand extends SshCommand {
|
|||||||
try {
|
try {
|
||||||
TaskResource taskRsrc = tasksCollection.parse(cfgRsrc, IdString.fromDecoded(id));
|
TaskResource taskRsrc = tasksCollection.parse(cfgRsrc, IdString.fromDecoded(id));
|
||||||
deleteTask.apply(taskRsrc, null);
|
deleteTask.apply(taskRsrc, null);
|
||||||
} catch (AuthException | ResourceNotFoundException | PermissionBackendException e) {
|
} catch (AuthException
|
||||||
|
| ResourceNotFoundException
|
||||||
|
| ResourceConflictException
|
||||||
|
| PermissionBackendException e) {
|
||||||
stderr.print("kill: " + id + ": No such task\n");
|
stderr.print("kill: " + id + ": No such task\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Submodule plugins/replication updated: dc1e7ff434...9b08f32446
Reference in New Issue
Block a user