query: Enable configurable result limit
Allow site administrators to configure the query limit for users
to be above the default hard-coded value of 500. Administrators
can add a global block to All-Projects project.config file with
group(s) that should have different limits:
[capability]
queryLimit = +0..1000 group Automated Tools
queryLimit = +0..100 group Registered Users
When applying a query limit to a user the largest value granted by any
of their groups is used.
This limit applies not only to the `gerrit query` command, but also
to the web UI results pagination size.
Bug: issue 934
Change-Id: I4e05448794de44bf51d3f0121358e456ab965c8b
Signed-off-by: Shawn O. Pearce <sop@google.com>
This commit is contained in:
@@ -24,6 +24,9 @@ import java.util.Set;
|
|||||||
|
|
||||||
/** Portion of a {@link Project} describing access rules. */
|
/** Portion of a {@link Project} describing access rules. */
|
||||||
public class AccessSection implements Comparable<AccessSection> {
|
public class AccessSection implements Comparable<AccessSection> {
|
||||||
|
/** Special name given to the global capabilities; not a valid reference. */
|
||||||
|
public static final String GLOBAL_CAPABILITIES = "GLOBAL_CAPABILITIES";
|
||||||
|
|
||||||
/** Pattern that matches all references in a project. */
|
/** Pattern that matches all references in a project. */
|
||||||
public static final String ALL = "refs/*";
|
public static final String ALL = "refs/*";
|
||||||
|
|
||||||
@@ -38,22 +41,22 @@ public class AccessSection implements Comparable<AccessSection> {
|
|||||||
return name.startsWith("refs/") || name.startsWith("^refs/");
|
return name.startsWith("refs/") || name.startsWith("^refs/");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String refPattern;
|
protected String name;
|
||||||
protected List<Permission> permissions;
|
protected List<Permission> permissions;
|
||||||
|
|
||||||
protected AccessSection() {
|
protected AccessSection() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public AccessSection(String refPattern) {
|
public AccessSection(String refPattern) {
|
||||||
setRefPattern(refPattern);
|
setName(refPattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getRefPattern() {
|
public String getName() {
|
||||||
return refPattern;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRefPattern(String refPattern) {
|
public void setName(String name) {
|
||||||
this.refPattern = refPattern;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Permission> getPermissions() {
|
public List<Permission> getPermissions() {
|
||||||
@@ -127,14 +130,14 @@ public class AccessSection implements Comparable<AccessSection> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String comparePattern() {
|
private String comparePattern() {
|
||||||
if (getRefPattern().startsWith(REGEX_PREFIX)) {
|
if (getName().startsWith(REGEX_PREFIX)) {
|
||||||
return getRefPattern().substring(REGEX_PREFIX.length());
|
return getName().substring(REGEX_PREFIX.length());
|
||||||
}
|
}
|
||||||
return getRefPattern();
|
return getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "AccessSection[" + getRefPattern() + "]";
|
return "AccessSection[" + getName() + "]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
// Copyright (C) 2011 The Android Open Source Project
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package com.google.gerrit.common.data;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/** Server wide capabilities. Represented as {@link Permission} objects. */
|
||||||
|
public class GlobalCapability {
|
||||||
|
public static final String QUERY_LIMIT = "queryLimit";
|
||||||
|
|
||||||
|
private static final List<String> NAMES_LC;
|
||||||
|
|
||||||
|
static {
|
||||||
|
NAMES_LC = new ArrayList<String>();
|
||||||
|
NAMES_LC.add(QUERY_LIMIT.toLowerCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return true if the name is recognized as a capability name. */
|
||||||
|
public static boolean isCapability(String varName) {
|
||||||
|
return NAMES_LC.contains(varName.toLowerCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return true if the capability should have a range attached. */
|
||||||
|
public static boolean hasRange(String varName) {
|
||||||
|
return QUERY_LIMIT.equalsIgnoreCase(varName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return the valid range for the capability if it has one, otherwise null. */
|
||||||
|
public static PermissionRange.WithDefaults getRange(String varName) {
|
||||||
|
if (QUERY_LIMIT.equalsIgnoreCase(varName)) {
|
||||||
|
return new PermissionRange.WithDefaults(
|
||||||
|
varName,
|
||||||
|
0, Integer.MAX_VALUE,
|
||||||
|
0, 500);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private GlobalCapability() {
|
||||||
|
// Utility class, do not create instances.
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,7 +14,50 @@
|
|||||||
|
|
||||||
package com.google.gerrit.common.data;
|
package com.google.gerrit.common.data;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class PermissionRange implements Comparable<PermissionRange> {
|
public class PermissionRange implements Comparable<PermissionRange> {
|
||||||
|
public static class WithDefaults extends PermissionRange {
|
||||||
|
protected int defaultMin;
|
||||||
|
protected int defaultMax;
|
||||||
|
|
||||||
|
protected WithDefaults() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public WithDefaults(String name, int min, int max, int defMin, int defMax) {
|
||||||
|
super(name, min, max);
|
||||||
|
setDefaultRange(defMin, defMax);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDefaultMin() {
|
||||||
|
return defaultMin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDefaultMax() {
|
||||||
|
return defaultMax;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDefaultRange(int min, int max) {
|
||||||
|
defaultMin = min;
|
||||||
|
defaultMax = max;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return all values between {@link #getMin()} and {@link #getMax()} */
|
||||||
|
public List<Integer> getValuesAsList() {
|
||||||
|
ArrayList<Integer> r = new ArrayList<Integer>(getRangeSize());
|
||||||
|
for (int i = min; i <= max; i++) {
|
||||||
|
r.add(i);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return number of values between {@link #getMin()} and {@link #getMax()} */
|
||||||
|
public int getRangeSize() {
|
||||||
|
return max - min;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected String name;
|
protected String name;
|
||||||
protected int min;
|
protected int min;
|
||||||
protected int max;
|
protected int max;
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ public class PermissionRule implements Comparable<PermissionRule> {
|
|||||||
int sp = src.indexOf(' ');
|
int sp = src.indexOf(' ');
|
||||||
String range = src.substring(0, sp);
|
String range = src.substring(0, sp);
|
||||||
|
|
||||||
if (range.matches("^([+-]\\d+)\\.\\.([+-]\\d)$")) {
|
if (range.matches("^([+-]?\\d+)\\.\\.([+-]?\\d+)$")) {
|
||||||
int dotdot = range.indexOf("..");
|
int dotdot = range.indexOf("..");
|
||||||
int min = parseInt(range.substring(0, dotdot));
|
int min = parseInt(range.substring(0, dotdot));
|
||||||
int max = parseInt(range.substring(dotdot + 2));
|
int max = parseInt(range.substring(dotdot + 2));
|
||||||
|
|||||||
@@ -52,8 +52,21 @@ public class ProjectAccess {
|
|||||||
local = as;
|
local = as;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public AccessSection getLocal(String name) {
|
||||||
|
for (AccessSection s : local) {
|
||||||
|
if (s.getName().equals(name)) {
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isOwnerOf(AccessSection section) {
|
public boolean isOwnerOf(AccessSection section) {
|
||||||
return getOwnerOf().contains(section.getRefPattern());
|
return isOwnerOf(section.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isOwnerOf(String name) {
|
||||||
|
return ownerOf.contains(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<String> getOwnerOf() {
|
public Set<String> getOwnerOf() {
|
||||||
|
|||||||
@@ -18,6 +18,10 @@ package com.google.gerrit.common.errors;
|
|||||||
public class InvalidQueryException extends Exception {
|
public class InvalidQueryException extends Exception {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public InvalidQueryException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
public InvalidQueryException(String message, String query) {
|
public InvalidQueryException(String message, String query) {
|
||||||
super("Invalid query: " + query + "\n\n" + message);
|
super("Invalid query: " + query + "\n\n" + message);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ public class AccessSectionEditor extends Composite implements
|
|||||||
private static final Binder uiBinder = GWT.create(Binder.class);
|
private static final Binder uiBinder = GWT.create(Binder.class);
|
||||||
|
|
||||||
@UiField
|
@UiField
|
||||||
ValueEditor<String> refPattern;
|
ValueEditor<String> name;
|
||||||
|
|
||||||
@UiField
|
@UiField
|
||||||
FlowPanel permissionContainer;
|
FlowPanel permissionContainer;
|
||||||
@@ -78,6 +78,11 @@ public class AccessSectionEditor extends Composite implements
|
|||||||
@UiField
|
@UiField
|
||||||
DivElement deleted;
|
DivElement deleted;
|
||||||
|
|
||||||
|
@UiField
|
||||||
|
SpanElement sectionType;
|
||||||
|
@UiField
|
||||||
|
SpanElement sectionName;
|
||||||
|
|
||||||
private final ProjectAccess projectAccess;
|
private final ProjectAccess projectAccess;
|
||||||
private AccessSection value;
|
private AccessSection value;
|
||||||
private boolean editing;
|
private boolean editing;
|
||||||
@@ -115,7 +120,18 @@ public class AccessSectionEditor extends Composite implements
|
|||||||
@UiHandler("deleteSection")
|
@UiHandler("deleteSection")
|
||||||
void onDeleteSection(ClickEvent event) {
|
void onDeleteSection(ClickEvent event) {
|
||||||
isDeleted = true;
|
isDeleted = true;
|
||||||
deletedName.setInnerText(refPattern.getValue());
|
|
||||||
|
if (name.isVisible() && AccessSection.isAccessSection(name.getValue())){
|
||||||
|
deletedName.setInnerText(Util.M.deletedReference(name.getValue()));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
String name = Util.C.sectionNames().get(value.getName());
|
||||||
|
if (name == null) {
|
||||||
|
name = value.getName();
|
||||||
|
}
|
||||||
|
deletedName.setInnerText(Util.M.deletedSection(name));
|
||||||
|
}
|
||||||
|
|
||||||
normal.getStyle().setDisplay(Display.NONE);
|
normal.getStyle().setDisplay(Display.NONE);
|
||||||
deleted.getStyle().setDisplay(Display.BLOCK);
|
deleted.getStyle().setDisplay(Display.BLOCK);
|
||||||
}
|
}
|
||||||
@@ -134,11 +150,11 @@ public class AccessSectionEditor extends Composite implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
void editRefPattern() {
|
void editRefPattern() {
|
||||||
refPattern.edit();
|
name.edit();
|
||||||
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
|
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
|
||||||
@Override
|
@Override
|
||||||
public void execute() {
|
public void execute() {
|
||||||
refPattern.setFocus(true);
|
name.setFocus(true);
|
||||||
}});
|
}});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,9 +173,29 @@ public class AccessSectionEditor extends Composite implements
|
|||||||
this.value = value;
|
this.value = value;
|
||||||
this.readOnly = !editing || !projectAccess.isOwnerOf(value);
|
this.readOnly = !editing || !projectAccess.isOwnerOf(value);
|
||||||
|
|
||||||
refPattern.setEnabled(!readOnly);
|
name.setEnabled(!readOnly);
|
||||||
deleteSection.setVisible(!readOnly);
|
deleteSection.setVisible(!readOnly);
|
||||||
|
|
||||||
|
if (AccessSection.isAccessSection(value.getName())) {
|
||||||
|
name.setVisible(true);
|
||||||
|
name.setIgnoreEditorValue(false);
|
||||||
|
sectionType.setInnerText(Util.C.sectionTypeReference());
|
||||||
|
|
||||||
|
} else {
|
||||||
|
name.setVisible(false);
|
||||||
|
name.setIgnoreEditorValue(true);
|
||||||
|
|
||||||
|
String name = Util.C.sectionNames().get(value.getName());
|
||||||
|
if (name != null) {
|
||||||
|
sectionType.setInnerText(name);
|
||||||
|
sectionName.getStyle().setDisplay(Display.NONE);
|
||||||
|
} else {
|
||||||
|
sectionType.setInnerText(Util.C.sectionTypeSection());
|
||||||
|
sectionName.setInnerText(value.getName());
|
||||||
|
sectionName.getStyle().clearDisplay();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (readOnly) {
|
if (readOnly) {
|
||||||
addContainer.getStyle().setDisplay(Display.NONE);
|
addContainer.getStyle().setDisplay(Display.NONE);
|
||||||
} else {
|
} else {
|
||||||
@@ -173,16 +209,24 @@ public class AccessSectionEditor extends Composite implements
|
|||||||
|
|
||||||
private void rebuildPermissionSelector() {
|
private void rebuildPermissionSelector() {
|
||||||
List<String> perms = new ArrayList<String>();
|
List<String> perms = new ArrayList<String>();
|
||||||
for (ApprovalType t : Gerrit.getConfig().getApprovalTypes()
|
|
||||||
.getApprovalTypes()) {
|
if (AccessSection.GLOBAL_CAPABILITIES.equals(value.getName())) {
|
||||||
String varName = Permission.LABEL + t.getCategory().getLabelName();
|
for (String varName : Util.C.capabilityNames().keySet()) {
|
||||||
if (value.getPermission(varName) == null) {
|
if (value.getPermission(varName) == null) {
|
||||||
perms.add(varName);
|
perms.add(varName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
} else if (AccessSection.isAccessSection(value.getName())) {
|
||||||
for (String varName : Util.C.permissionNames().keySet()) {
|
for (ApprovalType t : Gerrit.getConfig().getApprovalTypes().getApprovalTypes()) {
|
||||||
if (value.getPermission(varName) == null) {
|
String varName = Permission.LABEL + t.getCategory().getLabelName();
|
||||||
perms.add(varName);
|
if (value.getPermission(varName) == null) {
|
||||||
|
perms.add(varName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (String varName : Util.C.permissionNames().keySet()) {
|
||||||
|
if (value.getPermission(varName) == null) {
|
||||||
|
perms.add(varName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (perms.isEmpty()) {
|
if (perms.isEmpty()) {
|
||||||
|
|||||||
@@ -66,10 +66,10 @@ limitations under the License.
|
|||||||
background-color: selectionColor;
|
background-color: selectionColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
.refName {
|
.name {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
.refNameEdit {
|
.nameEdit {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,17 +107,20 @@ limitations under the License.
|
|||||||
<div ui:field='normal' class='{style.normal} {style.content}'>
|
<div ui:field='normal' class='{style.normal} {style.content}'>
|
||||||
<div class='{style.header}'>
|
<div class='{style.header}'>
|
||||||
<table class='{style.headerTable}'><tr>
|
<table class='{style.headerTable}'><tr>
|
||||||
<td class='{style.headerText}'><ui:msg>Reference:</ui:msg></td>
|
<td class='{style.headerText}'>
|
||||||
|
<span ui:field='sectionType'/>
|
||||||
|
</td>
|
||||||
<td width='100%'>
|
<td width='100%'>
|
||||||
<my:ValueEditor
|
<my:ValueEditor
|
||||||
ui:field='refPattern'
|
ui:field='name'
|
||||||
addStyleNames='{style.refName}'
|
addStyleNames='{style.name}'
|
||||||
editTitle='Edit reference pattern'>
|
editTitle='Edit reference pattern'>
|
||||||
<ui:attribute name='editTitle'/>
|
<ui:attribute name='editTitle'/>
|
||||||
<my:editor>
|
<my:editor>
|
||||||
<my:RefPatternBox styleName='{style.refNameEdit}'/>
|
<my:RefPatternBox styleName='{style.nameEdit}'/>
|
||||||
</my:editor>
|
</my:editor>
|
||||||
</my:ValueEditor>
|
</my:ValueEditor>
|
||||||
|
<span ui:field='sectionName' class='{style.name}'/>
|
||||||
</td>
|
</td>
|
||||||
</tr></table>
|
</tr></table>
|
||||||
|
|
||||||
@@ -144,7 +147,7 @@ limitations under the License.
|
|||||||
ui:field='deleted'
|
ui:field='deleted'
|
||||||
class='{style.deleted} {res.css.deleted}'
|
class='{style.deleted} {res.css.deleted}'
|
||||||
style='display: none'>
|
style='display: none'>
|
||||||
<ui:msg>Reference <span ui:field='deletedName'/> was deleted</ui:msg>
|
<span ui:field='deletedName'/>
|
||||||
<g:Anchor
|
<g:Anchor
|
||||||
ui:field='undoDelete'
|
ui:field='undoDelete'
|
||||||
href='javascript:void'
|
href='javascript:void'
|
||||||
|
|||||||
@@ -113,4 +113,10 @@ public interface AdminConstants extends Constants {
|
|||||||
String refErrorNoSpace();
|
String refErrorNoSpace();
|
||||||
String refErrorPrintable();
|
String refErrorPrintable();
|
||||||
String errorsMustBeFixed();
|
String errorsMustBeFixed();
|
||||||
|
|
||||||
|
Map<String, String> capabilityNames();
|
||||||
|
|
||||||
|
String sectionTypeReference();
|
||||||
|
String sectionTypeSection();
|
||||||
|
Map<String, String> sectionNames();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -116,3 +116,15 @@ refErrorDoubleSlash = References cannot contain '//'
|
|||||||
refErrorNoSpace = References cannot contain spaces
|
refErrorNoSpace = References cannot contain spaces
|
||||||
refErrorPrintable = References may contain only printable characters
|
refErrorPrintable = References may contain only printable characters
|
||||||
errorsMustBeFixed = Errors must be fixed before committing changes.
|
errorsMustBeFixed = Errors must be fixed before committing changes.
|
||||||
|
|
||||||
|
# Capability Names
|
||||||
|
capabilityNames = \
|
||||||
|
queryLimit
|
||||||
|
queryLimit = Query Limit
|
||||||
|
|
||||||
|
# Section Names
|
||||||
|
sectionTypeReference = Reference:
|
||||||
|
sectionTypeSection = Section:
|
||||||
|
sectionNames = \
|
||||||
|
GLOBAL_CAPABILITIES
|
||||||
|
GLOBAL_CAPABILITIES = Global Capabilities
|
||||||
|
|||||||
@@ -21,4 +21,7 @@ public interface AdminMessages extends Messages {
|
|||||||
String label(String name);
|
String label(String name);
|
||||||
String project(String name);
|
String project(String name);
|
||||||
String deletedGroup(int id);
|
String deletedGroup(int id);
|
||||||
|
|
||||||
|
String deletedReference(String name);
|
||||||
|
String deletedSection(String name);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,3 +2,5 @@ group = Group {0}
|
|||||||
label = Label {0}
|
label = Label {0}
|
||||||
project = Project {0}
|
project = Project {0}
|
||||||
deletedGroup = Deleted Group {0}
|
deletedGroup = Deleted Group {0}
|
||||||
|
deletedReference = Reference {0} was deleted
|
||||||
|
deletedSection = Section {0} was deleted
|
||||||
|
|||||||
@@ -19,8 +19,10 @@ import com.google.gerrit.client.rpc.GerritCallback;
|
|||||||
import com.google.gerrit.client.ui.SuggestUtil;
|
import com.google.gerrit.client.ui.SuggestUtil;
|
||||||
import com.google.gerrit.common.data.AccessSection;
|
import com.google.gerrit.common.data.AccessSection;
|
||||||
import com.google.gerrit.common.data.ApprovalType;
|
import com.google.gerrit.common.data.ApprovalType;
|
||||||
|
import com.google.gerrit.common.data.GlobalCapability;
|
||||||
import com.google.gerrit.common.data.GroupReference;
|
import com.google.gerrit.common.data.GroupReference;
|
||||||
import com.google.gerrit.common.data.Permission;
|
import com.google.gerrit.common.data.Permission;
|
||||||
|
import com.google.gerrit.common.data.PermissionRange;
|
||||||
import com.google.gerrit.common.data.PermissionRule;
|
import com.google.gerrit.common.data.PermissionRule;
|
||||||
import com.google.gwt.core.client.GWT;
|
import com.google.gwt.core.client.GWT;
|
||||||
import com.google.gwt.core.client.Scheduler;
|
import com.google.gwt.core.client.Scheduler;
|
||||||
@@ -98,7 +100,7 @@ public class PermissionEditor extends Composite implements Editor<Permission>,
|
|||||||
private final boolean readOnly;
|
private final boolean readOnly;
|
||||||
private final AccessSection section;
|
private final AccessSection section;
|
||||||
private Permission value;
|
private Permission value;
|
||||||
private ApprovalType rangeType;
|
private PermissionRange.WithDefaults validRange;
|
||||||
private boolean isDeleted;
|
private boolean isDeleted;
|
||||||
|
|
||||||
public PermissionEditor(boolean readOnly, AccessSection section) {
|
public PermissionEditor(boolean readOnly, AccessSection section) {
|
||||||
@@ -196,9 +198,9 @@ public class PermissionEditor extends Composite implements Editor<Permission>,
|
|||||||
if (ref.getUUID() != null) {
|
if (ref.getUUID() != null) {
|
||||||
if (value.getRule(ref) == null) {
|
if (value.getRule(ref) == null) {
|
||||||
PermissionRule newRule = value.getRule(ref, true);
|
PermissionRule newRule = value.getRule(ref, true);
|
||||||
if (rangeType != null) {
|
if (validRange != null) {
|
||||||
int min = rangeType.getMin().getValue();
|
int min = validRange.getDefaultMin();
|
||||||
int max = rangeType.getMax().getValue();
|
int max = validRange.getDefaultMax();
|
||||||
newRule.setRange(min, max);
|
newRule.setRange(min, max);
|
||||||
}
|
}
|
||||||
rules.getList().add(newRule);
|
rules.getList().add(newRule);
|
||||||
@@ -238,11 +240,20 @@ public class PermissionEditor extends Composite implements Editor<Permission>,
|
|||||||
@Override
|
@Override
|
||||||
public void setValue(Permission value) {
|
public void setValue(Permission value) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
|
|
||||||
if (value.isLabel()) {
|
if (value.isLabel()) {
|
||||||
rangeType =
|
ApprovalType at = Gerrit.getConfig().getApprovalTypes().byLabel(value.getLabel());
|
||||||
Gerrit.getConfig().getApprovalTypes().byLabel(value.getLabel());
|
if (at != null) {
|
||||||
|
validRange = new PermissionRange.WithDefaults(
|
||||||
|
value.getName(),
|
||||||
|
at.getMin().getValue(), at.getMax().getValue(),
|
||||||
|
at.getMin().getValue(), at.getMax().getValue());
|
||||||
|
}
|
||||||
|
} else if (GlobalCapability.isCapability(value.getName())) {
|
||||||
|
validRange = GlobalCapability.getRange(value.getName());
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
rangeType = null;
|
validRange = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value != null && Permission.OWNER.equals(value.getName())) {
|
if (value != null && Permission.OWNER.equals(value.getName())) {
|
||||||
@@ -279,7 +290,7 @@ public class PermissionEditor extends Composite implements Editor<Permission>,
|
|||||||
@Override
|
@Override
|
||||||
public PermissionRuleEditor create(int index) {
|
public PermissionRuleEditor create(int index) {
|
||||||
PermissionRuleEditor subEditor =
|
PermissionRuleEditor subEditor =
|
||||||
new PermissionRuleEditor(readOnly, section, value, rangeType);
|
new PermissionRuleEditor(readOnly, section, value, validRange);
|
||||||
ruleContainer.insert(subEditor, index);
|
ruleContainer.insert(subEditor, index);
|
||||||
return subEditor;
|
return subEditor;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,19 @@ import java.util.Map;
|
|||||||
class PermissionNameRenderer implements Renderer<String> {
|
class PermissionNameRenderer implements Renderer<String> {
|
||||||
static final PermissionNameRenderer INSTANCE = new PermissionNameRenderer();
|
static final PermissionNameRenderer INSTANCE = new PermissionNameRenderer();
|
||||||
|
|
||||||
private static Map<String, String> LC;
|
private static final Map<String, String> all;
|
||||||
|
|
||||||
|
static {
|
||||||
|
all = new HashMap<String, String>();
|
||||||
|
for (Map.Entry<String, String> e : Util.C.capabilityNames().entrySet()) {
|
||||||
|
all.put(e.getKey(), e.getValue());
|
||||||
|
all.put(e.getKey().toLowerCase(), e.getValue());
|
||||||
|
}
|
||||||
|
for (Map.Entry<String, String> e : Util.C.permissionNames().entrySet()) {
|
||||||
|
all.put(e.getKey(), e.getValue());
|
||||||
|
all.put(e.getKey().toLowerCase(), e.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String render(String varName) {
|
public String render(String varName) {
|
||||||
@@ -32,16 +44,9 @@ class PermissionNameRenderer implements Renderer<String> {
|
|||||||
return Util.M.label(new Permission(varName).getLabel());
|
return Util.M.label(new Permission(varName).getLabel());
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, String> m = Util.C.permissionNames();
|
String desc = all.get(varName);
|
||||||
String desc = m.get(varName);
|
|
||||||
if (desc == null) {
|
if (desc == null) {
|
||||||
if (LC == null) {
|
desc = all.get(varName.toLowerCase());
|
||||||
LC = new HashMap<String, String>();
|
|
||||||
for (Map.Entry<String, String> e : m.entrySet()) {
|
|
||||||
LC.put(e.getKey().toLowerCase(), e.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
desc = LC.get(varName.toLowerCase());
|
|
||||||
}
|
}
|
||||||
return desc != null ? desc : varName;
|
return desc != null ? desc : varName;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,9 +20,9 @@ import static com.google.gerrit.common.data.Permission.PUSH_TAG;
|
|||||||
import com.google.gerrit.client.Dispatcher;
|
import com.google.gerrit.client.Dispatcher;
|
||||||
import com.google.gerrit.client.ui.Hyperlink;
|
import com.google.gerrit.client.ui.Hyperlink;
|
||||||
import com.google.gerrit.common.data.AccessSection;
|
import com.google.gerrit.common.data.AccessSection;
|
||||||
import com.google.gerrit.common.data.ApprovalType;
|
|
||||||
import com.google.gerrit.common.data.GroupReference;
|
import com.google.gerrit.common.data.GroupReference;
|
||||||
import com.google.gerrit.common.data.Permission;
|
import com.google.gerrit.common.data.Permission;
|
||||||
|
import com.google.gerrit.common.data.PermissionRange;
|
||||||
import com.google.gerrit.common.data.PermissionRule;
|
import com.google.gerrit.common.data.PermissionRule;
|
||||||
import com.google.gwt.core.client.GWT;
|
import com.google.gwt.core.client.GWT;
|
||||||
import com.google.gwt.dom.client.DivElement;
|
import com.google.gwt.dom.client.DivElement;
|
||||||
@@ -30,7 +30,9 @@ import com.google.gwt.dom.client.SpanElement;
|
|||||||
import com.google.gwt.dom.client.Style.Display;
|
import com.google.gwt.dom.client.Style.Display;
|
||||||
import com.google.gwt.editor.client.Editor;
|
import com.google.gwt.editor.client.Editor;
|
||||||
import com.google.gwt.editor.client.EditorDelegate;
|
import com.google.gwt.editor.client.EditorDelegate;
|
||||||
|
import com.google.gwt.editor.client.IsEditor;
|
||||||
import com.google.gwt.editor.client.ValueAwareEditor;
|
import com.google.gwt.editor.client.ValueAwareEditor;
|
||||||
|
import com.google.gwt.editor.client.adapters.TakesValueEditor;
|
||||||
import com.google.gwt.event.dom.client.ClickEvent;
|
import com.google.gwt.event.dom.client.ClickEvent;
|
||||||
import com.google.gwt.text.shared.Renderer;
|
import com.google.gwt.text.shared.Renderer;
|
||||||
import com.google.gwt.uibinder.client.UiBinder;
|
import com.google.gwt.uibinder.client.UiBinder;
|
||||||
@@ -41,11 +43,13 @@ import com.google.gwt.user.client.ui.Anchor;
|
|||||||
import com.google.gwt.user.client.ui.CheckBox;
|
import com.google.gwt.user.client.ui.CheckBox;
|
||||||
import com.google.gwt.user.client.ui.Composite;
|
import com.google.gwt.user.client.ui.Composite;
|
||||||
import com.google.gwt.user.client.ui.HTMLPanel;
|
import com.google.gwt.user.client.ui.HTMLPanel;
|
||||||
|
import com.google.gwt.user.client.ui.IntegerBox;
|
||||||
import com.google.gwt.user.client.ui.UIObject;
|
import com.google.gwt.user.client.ui.UIObject;
|
||||||
import com.google.gwt.user.client.ui.ValueListBox;
|
import com.google.gwt.user.client.ui.ValueListBox;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class PermissionRuleEditor extends Composite implements
|
public class PermissionRuleEditor extends Composite implements
|
||||||
Editor<PermissionRule>, ValueAwareEditor<PermissionRule> {
|
Editor<PermissionRule>, ValueAwareEditor<PermissionRule> {
|
||||||
@@ -58,10 +62,10 @@ public class PermissionRuleEditor extends Composite implements
|
|||||||
ValueListBox<PermissionRule.Action> action;
|
ValueListBox<PermissionRule.Action> action;
|
||||||
|
|
||||||
@UiField(provided = true)
|
@UiField(provided = true)
|
||||||
ValueListBox<Integer> min;
|
RangeBox min;
|
||||||
|
|
||||||
@UiField(provided = true)
|
@UiField(provided = true)
|
||||||
ValueListBox<Integer> max;
|
RangeBox max;
|
||||||
|
|
||||||
@UiField
|
@UiField
|
||||||
CheckBox force;
|
CheckBox force;
|
||||||
@@ -87,18 +91,30 @@ public class PermissionRuleEditor extends Composite implements
|
|||||||
private boolean isDeleted;
|
private boolean isDeleted;
|
||||||
|
|
||||||
public PermissionRuleEditor(boolean readOnly, AccessSection section,
|
public PermissionRuleEditor(boolean readOnly, AccessSection section,
|
||||||
Permission permission, ApprovalType labelRange) {
|
Permission permission, PermissionRange.WithDefaults validRange) {
|
||||||
action = new ValueListBox<PermissionRule.Action>(actionRenderer);
|
action = new ValueListBox<PermissionRule.Action>(actionRenderer);
|
||||||
min = new ValueListBox<Integer>(rangeRenderer);
|
|
||||||
max = new ValueListBox<Integer>(rangeRenderer);
|
|
||||||
|
|
||||||
if (labelRange != null){
|
if (validRange != null && 10 < validRange.getRangeSize()) {
|
||||||
min.setValue((int) labelRange.getMin().getValue());
|
min = new RangeBox.Box();
|
||||||
max.setValue((int) labelRange.getMax().getValue());
|
max = new RangeBox.Box();
|
||||||
|
|
||||||
|
} else if (validRange != null) {
|
||||||
|
RangeBox.List minList = new RangeBox.List();
|
||||||
|
RangeBox.List maxList = new RangeBox.List();
|
||||||
|
List<Integer> valueList = validRange.getValuesAsList();
|
||||||
|
|
||||||
|
minList.list.setValue(validRange.getMin());
|
||||||
|
maxList.list.setValue(validRange.getMax());
|
||||||
|
|
||||||
|
minList.list.setAcceptableValues(valueList);
|
||||||
|
maxList.list.setAcceptableValues(valueList);
|
||||||
|
|
||||||
|
min = minList;
|
||||||
|
max = maxList;
|
||||||
|
|
||||||
min.setAcceptableValues(labelRange.getValuesAsList());
|
|
||||||
max.setAcceptableValues(labelRange.getValuesAsList());
|
|
||||||
} else {
|
} else {
|
||||||
|
min = new RangeBox.Box();
|
||||||
|
max = new RangeBox.Box();
|
||||||
action.setValue(PermissionRule.Action.ALLOW);
|
action.setValue(PermissionRule.Action.ALLOW);
|
||||||
action.setAcceptableValues(Arrays.asList(PermissionRule.Action.values()));
|
action.setAcceptableValues(Arrays.asList(PermissionRule.Action.values()));
|
||||||
}
|
}
|
||||||
@@ -108,16 +124,17 @@ public class PermissionRuleEditor extends Composite implements
|
|||||||
String name = permission.getName();
|
String name = permission.getName();
|
||||||
boolean canForce = PUSH.equals(name) || PUSH_TAG.equals(name);
|
boolean canForce = PUSH.equals(name) || PUSH_TAG.equals(name);
|
||||||
if (canForce) {
|
if (canForce) {
|
||||||
String ref = section.getRefPattern();
|
String ref = section.getName();
|
||||||
canForce = !ref.startsWith("refs/for/") && !ref.startsWith("^refs/for/");
|
canForce = !ref.startsWith("refs/for/") && !ref.startsWith("^refs/for/");
|
||||||
}
|
}
|
||||||
force.setVisible(canForce);
|
force.setVisible(canForce);
|
||||||
force.setEnabled(!readOnly);
|
force.setEnabled(!readOnly);
|
||||||
|
|
||||||
if (labelRange != null) {
|
if (validRange != null) {
|
||||||
|
min.setEnabled(!readOnly);
|
||||||
|
max.setEnabled(!readOnly);
|
||||||
action.getElement().getStyle().setDisplay(Display.NONE);
|
action.getElement().getStyle().setDisplay(Display.NONE);
|
||||||
DOM.setElementPropertyBoolean(min.getElement(), "disabled", readOnly);
|
|
||||||
DOM.setElementPropertyBoolean(max.getElement(), "disabled", readOnly);
|
|
||||||
} else {
|
} else {
|
||||||
rangeEditor.getStyle().setDisplay(Display.NONE);
|
rangeEditor.getStyle().setDisplay(Display.NONE);
|
||||||
DOM.setElementPropertyBoolean(action.getElement(), "disabled", readOnly);
|
DOM.setElementPropertyBoolean(action.getElement(), "disabled", readOnly);
|
||||||
@@ -188,23 +205,5 @@ public class PermissionRuleEditor extends Composite implements
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class RangeRenderer implements Renderer<Integer> {
|
|
||||||
@Override
|
|
||||||
public String render(Integer object) {
|
|
||||||
if (0 <= object) {
|
|
||||||
return "+" + object;
|
|
||||||
} else {
|
|
||||||
return String.valueOf(object);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void render(Integer object, Appendable appendable)
|
|
||||||
throws IOException {
|
|
||||||
appendable.append(render(object));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final ActionRenderer actionRenderer = new ActionRenderer();
|
private static final ActionRenderer actionRenderer = new ActionRenderer();
|
||||||
private static final RangeRenderer rangeRenderer = new RangeRenderer();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,8 +74,8 @@ limitations under the License.
|
|||||||
<div ui:field='normal' class='{style.normal}'>
|
<div ui:field='normal' class='{style.normal}'>
|
||||||
<g:ValueListBox ui:field='action' styleName='{style.actionList}'/>
|
<g:ValueListBox ui:field='action' styleName='{style.actionList}'/>
|
||||||
<span ui:field='rangeEditor'>
|
<span ui:field='rangeEditor'>
|
||||||
<g:ValueListBox ui:field='min' styleName='{style.minmax}'/>
|
<g:Widget ui:field='min' styleName='{style.minmax}'/>
|
||||||
<g:ValueListBox ui:field='max' styleName='{style.minmax}'/>
|
<g:Widget ui:field='max' styleName='{style.minmax}'/>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<q:Hyperlink ui:field='groupNameLink' styleName='{style.groupName}'/>
|
<q:Hyperlink ui:field='groupNameLink' styleName='{style.groupName}'/>
|
||||||
|
|||||||
@@ -80,6 +80,15 @@ public class ProjectAccessEditor extends Composite implements
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setValue(ProjectAccess value) {
|
public void setValue(ProjectAccess value) {
|
||||||
|
// If the owner can edit the Global Capabilities but they don't exist in this
|
||||||
|
// project, create an empty one at the beginning of the list making it
|
||||||
|
// possible to add permissions to it.
|
||||||
|
if (editing
|
||||||
|
&& value.isOwnerOf(AccessSection.GLOBAL_CAPABILITIES)
|
||||||
|
&& value.getLocal(AccessSection.GLOBAL_CAPABILITIES) == null) {
|
||||||
|
value.getLocal().add(0, new AccessSection(AccessSection.GLOBAL_CAPABILITIES));
|
||||||
|
}
|
||||||
|
|
||||||
this.value = value;
|
this.value = value;
|
||||||
|
|
||||||
Project.NameKey parent = value.getInheritsFrom();
|
Project.NameKey parent = value.getInheritsFrom();
|
||||||
@@ -102,7 +111,7 @@ public class ProjectAccessEditor extends Composite implements
|
|||||||
|
|
||||||
for (int i = 0; i < src.size(); i++) {
|
for (int i = 0; i < src.size(); i++) {
|
||||||
AccessSectionEditor e = (AccessSectionEditor) localContainer.getWidget(i);
|
AccessSectionEditor e = (AccessSectionEditor) localContainer.getWidget(i);
|
||||||
if (!e.isDeleted()) {
|
if (!e.isDeleted() && !src.get(i).getPermissions().isEmpty()) {
|
||||||
keep.add(src.get(i));
|
keep.add(src.get(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import com.google.gerrit.client.Gerrit;
|
|||||||
import com.google.gerrit.client.rpc.GerritCallback;
|
import com.google.gerrit.client.rpc.GerritCallback;
|
||||||
import com.google.gerrit.client.rpc.ScreenLoadCallback;
|
import com.google.gerrit.client.rpc.ScreenLoadCallback;
|
||||||
import com.google.gerrit.common.PageLinks;
|
import com.google.gerrit.common.PageLinks;
|
||||||
|
import com.google.gerrit.common.data.AccessSection;
|
||||||
import com.google.gerrit.common.data.ProjectAccess;
|
import com.google.gerrit.common.data.ProjectAccess;
|
||||||
import com.google.gerrit.reviewdb.Project;
|
import com.google.gerrit.reviewdb.Project;
|
||||||
import com.google.gwt.core.client.GWT;
|
import com.google.gwt.core.client.GWT;
|
||||||
|
|||||||
@@ -0,0 +1,90 @@
|
|||||||
|
// Copyright (C) 2011 The Android Open Source Project
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package com.google.gerrit.client.admin;
|
||||||
|
|
||||||
|
import com.google.gwt.editor.client.IsEditor;
|
||||||
|
import com.google.gwt.editor.client.adapters.TakesValueEditor;
|
||||||
|
import com.google.gwt.text.shared.Renderer;
|
||||||
|
import com.google.gwt.user.client.DOM;
|
||||||
|
import com.google.gwt.user.client.ui.Composite;
|
||||||
|
import com.google.gwt.user.client.ui.IntegerBox;
|
||||||
|
import com.google.gwt.user.client.ui.ValueListBox;
|
||||||
|
import com.google.gwt.user.client.ui.ValueBoxBase.TextAlignment;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
abstract class RangeBox extends Composite implements
|
||||||
|
IsEditor<TakesValueEditor<Integer>> {
|
||||||
|
static final RangeRenderer rangeRenderer = new RangeRenderer();
|
||||||
|
|
||||||
|
private static class RangeRenderer implements Renderer<Integer> {
|
||||||
|
@Override
|
||||||
|
public String render(Integer object) {
|
||||||
|
if (0 <= object) {
|
||||||
|
return "+" + object;
|
||||||
|
} else {
|
||||||
|
return String.valueOf(object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(Integer object, Appendable appendable)
|
||||||
|
throws IOException {
|
||||||
|
appendable.append(render(object));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class List extends RangeBox {
|
||||||
|
final ValueListBox<Integer> list;
|
||||||
|
|
||||||
|
List() {
|
||||||
|
list = new ValueListBox<Integer>(rangeRenderer);
|
||||||
|
initWidget(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void setEnabled(boolean on) {
|
||||||
|
DOM.setElementPropertyBoolean(list.getElement(), "disabled", !on);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TakesValueEditor<Integer> asEditor() {
|
||||||
|
return list.asEditor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Box extends RangeBox {
|
||||||
|
private final IntegerBox box;
|
||||||
|
|
||||||
|
Box() {
|
||||||
|
box = new IntegerBox();
|
||||||
|
box.setVisibleLength(10);
|
||||||
|
box.setAlignment(TextAlignment.RIGHT);
|
||||||
|
initWidget(box);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void setEnabled(boolean on) {
|
||||||
|
DOM.setElementPropertyBoolean(box.getElement(), "disabled", !on);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TakesValueEditor<Integer> asEditor() {
|
||||||
|
return box.asEditor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract void setEnabled(boolean on);
|
||||||
|
}
|
||||||
@@ -64,6 +64,8 @@ public class ValueEditor<T> extends Composite implements HasEditorErrors<T>,
|
|||||||
|
|
||||||
private ValueBoxBase<T> editChild;
|
private ValueBoxBase<T> editChild;
|
||||||
private ValueBoxEditor<T> editProxy;
|
private ValueBoxEditor<T> editProxy;
|
||||||
|
private boolean ignoreEditorValue;
|
||||||
|
private T value;
|
||||||
|
|
||||||
public ValueEditor() {
|
public ValueEditor() {
|
||||||
startHandlers = new StartEditHandlers();
|
startHandlers = new StartEditHandlers();
|
||||||
@@ -93,14 +95,19 @@ public class ValueEditor<T> extends Composite implements HasEditorErrors<T>,
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T getValue() {
|
public T getValue() {
|
||||||
return asEditor().getValue();
|
return ignoreEditorValue ? value : asEditor().getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setValue(T value) {
|
public void setValue(T value) {
|
||||||
|
this.value = value;
|
||||||
asEditor().setValue(value);
|
asEditor().setValue(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setIgnoreEditorValue(boolean off) {
|
||||||
|
ignoreEditorValue = off;
|
||||||
|
}
|
||||||
|
|
||||||
public void setEditTitle(String title) {
|
public void setEditTitle(String title) {
|
||||||
editIcon.setTitle(title);
|
editIcon.setTitle(title);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ package com.google.gerrit.httpd.rpc;
|
|||||||
import com.google.gerrit.common.data.AccountDashboardInfo;
|
import com.google.gerrit.common.data.AccountDashboardInfo;
|
||||||
import com.google.gerrit.common.data.ChangeInfo;
|
import com.google.gerrit.common.data.ChangeInfo;
|
||||||
import com.google.gerrit.common.data.ChangeListService;
|
import com.google.gerrit.common.data.ChangeListService;
|
||||||
|
import com.google.gerrit.common.data.GlobalCapability;
|
||||||
|
import com.google.gerrit.common.data.PermissionRange;
|
||||||
import com.google.gerrit.common.data.SingleListChangeInfo;
|
import com.google.gerrit.common.data.SingleListChangeInfo;
|
||||||
import com.google.gerrit.common.data.ToggleStarRequest;
|
import com.google.gerrit.common.data.ToggleStarRequest;
|
||||||
import com.google.gerrit.common.errors.InvalidQueryException;
|
import com.google.gerrit.common.errors.InvalidQueryException;
|
||||||
@@ -29,8 +31,10 @@ import com.google.gerrit.reviewdb.ReviewDb;
|
|||||||
import com.google.gerrit.reviewdb.StarredChange;
|
import com.google.gerrit.reviewdb.StarredChange;
|
||||||
import com.google.gerrit.server.CurrentUser;
|
import com.google.gerrit.server.CurrentUser;
|
||||||
import com.google.gerrit.server.account.AccountInfoCacheFactory;
|
import com.google.gerrit.server.account.AccountInfoCacheFactory;
|
||||||
|
import com.google.gerrit.server.account.CapabilityControl;
|
||||||
import com.google.gerrit.server.project.ChangeControl;
|
import com.google.gerrit.server.project.ChangeControl;
|
||||||
import com.google.gerrit.server.project.NoSuchChangeException;
|
import com.google.gerrit.server.project.NoSuchChangeException;
|
||||||
|
import com.google.gerrit.server.project.NoSuchProjectException;
|
||||||
import com.google.gerrit.server.query.Predicate;
|
import com.google.gerrit.server.query.Predicate;
|
||||||
import com.google.gerrit.server.query.QueryParseException;
|
import com.google.gerrit.server.query.QueryParseException;
|
||||||
import com.google.gerrit.server.query.change.ChangeData;
|
import com.google.gerrit.server.query.change.ChangeData;
|
||||||
@@ -79,15 +83,10 @@ public class ChangeListServiceImpl extends BaseServiceImplementation implements
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private static final int MAX_PER_PAGE = 100;
|
|
||||||
|
|
||||||
private static int safePageSize(final int pageSize) {
|
|
||||||
return 0 < pageSize && pageSize <= MAX_PER_PAGE ? pageSize : MAX_PER_PAGE;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final Provider<CurrentUser> currentUser;
|
private final Provider<CurrentUser> currentUser;
|
||||||
private final ChangeControl.Factory changeControlFactory;
|
private final ChangeControl.Factory changeControlFactory;
|
||||||
private final AccountInfoCacheFactory.Factory accountInfoCacheFactory;
|
private final AccountInfoCacheFactory.Factory accountInfoCacheFactory;
|
||||||
|
private final CapabilityControl.Factory capabilityControlFactory;
|
||||||
|
|
||||||
private final ChangeQueryBuilder.Factory queryBuilder;
|
private final ChangeQueryBuilder.Factory queryBuilder;
|
||||||
private final Provider<ChangeQueryRewriter> queryRewriter;
|
private final Provider<ChangeQueryRewriter> queryRewriter;
|
||||||
@@ -97,12 +96,14 @@ public class ChangeListServiceImpl extends BaseServiceImplementation implements
|
|||||||
final Provider<CurrentUser> currentUser,
|
final Provider<CurrentUser> currentUser,
|
||||||
final ChangeControl.Factory changeControlFactory,
|
final ChangeControl.Factory changeControlFactory,
|
||||||
final AccountInfoCacheFactory.Factory accountInfoCacheFactory,
|
final AccountInfoCacheFactory.Factory accountInfoCacheFactory,
|
||||||
|
final CapabilityControl.Factory capabilityControlFactory,
|
||||||
final ChangeQueryBuilder.Factory queryBuilder,
|
final ChangeQueryBuilder.Factory queryBuilder,
|
||||||
final Provider<ChangeQueryRewriter> queryRewriter) {
|
final Provider<ChangeQueryRewriter> queryRewriter) {
|
||||||
super(schema, currentUser);
|
super(schema, currentUser);
|
||||||
this.currentUser = currentUser;
|
this.currentUser = currentUser;
|
||||||
this.changeControlFactory = changeControlFactory;
|
this.changeControlFactory = changeControlFactory;
|
||||||
this.accountInfoCacheFactory = accountInfoCacheFactory;
|
this.accountInfoCacheFactory = accountInfoCacheFactory;
|
||||||
|
this.capabilityControlFactory = capabilityControlFactory;
|
||||||
this.queryBuilder = queryBuilder;
|
this.queryBuilder = queryBuilder;
|
||||||
this.queryRewriter = queryRewriter;
|
this.queryRewriter = queryRewriter;
|
||||||
}
|
}
|
||||||
@@ -118,25 +119,33 @@ public class ChangeListServiceImpl extends BaseServiceImplementation implements
|
|||||||
@Override
|
@Override
|
||||||
public void allQueryPrev(final String query, final String pos,
|
public void allQueryPrev(final String query, final String pos,
|
||||||
final int pageSize, final AsyncCallback<SingleListChangeInfo> callback) {
|
final int pageSize, final AsyncCallback<SingleListChangeInfo> callback) {
|
||||||
run(callback, new QueryPrev(pageSize, pos) {
|
try {
|
||||||
@Override
|
run(callback, new QueryPrev(pageSize, pos) {
|
||||||
ResultSet<Change> query(ReviewDb db, int lim, String key)
|
@Override
|
||||||
throws OrmException, InvalidQueryException {
|
ResultSet<Change> query(ReviewDb db, int lim, String key)
|
||||||
return searchQuery(db, query, lim, key, QUERY_PREV);
|
throws OrmException, InvalidQueryException {
|
||||||
}
|
return searchQuery(db, query, lim, key, QUERY_PREV);
|
||||||
});
|
}
|
||||||
|
});
|
||||||
|
} catch (InvalidQueryException e) {
|
||||||
|
callback.onFailure(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void allQueryNext(final String query, final String pos,
|
public void allQueryNext(final String query, final String pos,
|
||||||
final int pageSize, final AsyncCallback<SingleListChangeInfo> callback) {
|
final int pageSize, final AsyncCallback<SingleListChangeInfo> callback) {
|
||||||
run(callback, new QueryNext(pageSize, pos) {
|
try {
|
||||||
@Override
|
run(callback, new QueryNext(pageSize, pos) {
|
||||||
ResultSet<Change> query(ReviewDb db, int lim, String key)
|
@Override
|
||||||
throws OrmException, InvalidQueryException {
|
ResultSet<Change> query(ReviewDb db, int lim, String key)
|
||||||
return searchQuery(db, query, lim, key, QUERY_NEXT);
|
throws OrmException, InvalidQueryException {
|
||||||
}
|
return searchQuery(db, query, lim, key, QUERY_NEXT);
|
||||||
});
|
}
|
||||||
|
});
|
||||||
|
} catch (InvalidQueryException e) {
|
||||||
|
callback.onFailure(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@@ -290,6 +299,26 @@ public class ChangeListServiceImpl extends BaseServiceImplementation implements
|
|||||||
callback.onSuccess(currentUser.get().getStarredChanges());
|
callback.onSuccess(currentUser.get().getStarredChanges());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int safePageSize(final int pageSize) throws InvalidQueryException {
|
||||||
|
int maxLimit;
|
||||||
|
try {
|
||||||
|
PermissionRange range = capabilityControlFactory.controlFor()
|
||||||
|
.getRange(GlobalCapability.QUERY_LIMIT);
|
||||||
|
if (range != null) {
|
||||||
|
maxLimit = range.getMax();
|
||||||
|
} else {
|
||||||
|
maxLimit = GlobalCapability.getRange(GlobalCapability.QUERY_LIMIT)
|
||||||
|
.getDefaultMax();
|
||||||
|
}
|
||||||
|
} catch (NoSuchProjectException noConfig) {
|
||||||
|
maxLimit = 0;
|
||||||
|
}
|
||||||
|
if (maxLimit == 0) {
|
||||||
|
throw new InvalidQueryException("Search Disabled");
|
||||||
|
}
|
||||||
|
return 0 < pageSize && pageSize <= maxLimit ? pageSize : maxLimit;
|
||||||
|
}
|
||||||
|
|
||||||
private List<ChangeInfo> filter(final ResultSet<Change> rs,
|
private List<ChangeInfo> filter(final ResultSet<Change> rs,
|
||||||
final Set<Change.Id> starred, final AccountInfoCacheFactory accts) {
|
final Set<Change.Id> starred, final AccountInfoCacheFactory accts) {
|
||||||
final ArrayList<ChangeInfo> r = new ArrayList<ChangeInfo>();
|
final ArrayList<ChangeInfo> r = new ArrayList<ChangeInfo>();
|
||||||
@@ -309,7 +338,7 @@ public class ChangeListServiceImpl extends BaseServiceImplementation implements
|
|||||||
protected final int limit;
|
protected final int limit;
|
||||||
protected final int slim;
|
protected final int slim;
|
||||||
|
|
||||||
QueryNext(final int pageSize, final String pos) {
|
QueryNext(final int pageSize, final String pos) throws InvalidQueryException {
|
||||||
this.pos = pos;
|
this.pos = pos;
|
||||||
this.limit = safePageSize(pageSize);
|
this.limit = safePageSize(pageSize);
|
||||||
this.slim = limit + 1;
|
this.slim = limit + 1;
|
||||||
@@ -353,7 +382,7 @@ public class ChangeListServiceImpl extends BaseServiceImplementation implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
private abstract class QueryPrev extends QueryNext {
|
private abstract class QueryPrev extends QueryNext {
|
||||||
QueryPrev(int pageSize, String pos) {
|
QueryPrev(int pageSize, String pos) throws InvalidQueryException {
|
||||||
super(pageSize, pos);
|
super(pageSize, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -107,41 +107,48 @@ class ChangeProjectAccess extends Handler<ProjectAccess> {
|
|||||||
Set<String> toDelete = scanSectionNames(config);
|
Set<String> toDelete = scanSectionNames(config);
|
||||||
|
|
||||||
for (AccessSection section : mergeSections(sectionList)) {
|
for (AccessSection section : mergeSections(sectionList)) {
|
||||||
final String name = section.getRefPattern();
|
String name = section.getName();
|
||||||
if (!projectControl.controlForRef(name).isOwner()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (name.startsWith(AccessSection.REGEX_PREFIX)) {
|
if (AccessSection.GLOBAL_CAPABILITIES.equals(name)) {
|
||||||
if (!Repository.isValidRefName(RefControl.shortestExample(name))) {
|
if (!projectControl.isOwner()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
replace(config, toDelete, section);
|
||||||
|
|
||||||
|
} else if (AccessSection.isAccessSection(name)) {
|
||||||
|
if (!projectControl.controlForRef(name).isOwner()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name.startsWith(AccessSection.REGEX_PREFIX)) {
|
||||||
|
if (!Repository.isValidRefName(RefControl.shortestExample(name))) {
|
||||||
|
throw new InvalidNameException();
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (name.equals(AccessSection.ALL)) {
|
||||||
|
// This is a special case we have to allow, it fails below.
|
||||||
|
|
||||||
|
} else if (name.endsWith("/*")) {
|
||||||
|
String prefix = name.substring(0, name.length() - 2);
|
||||||
|
if (!Repository.isValidRefName(prefix)) {
|
||||||
|
throw new InvalidNameException();
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (!Repository.isValidRefName(name)) {
|
||||||
throw new InvalidNameException();
|
throw new InvalidNameException();
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (name.equals(AccessSection.ALL)) {
|
replace(config, toDelete, section);
|
||||||
// This is a special case we have to allow, it fails below.
|
|
||||||
|
|
||||||
} else if (name.endsWith("/*")) {
|
|
||||||
String prefix = name.substring(0, name.length() - 2);
|
|
||||||
if (!Repository.isValidRefName(prefix)) {
|
|
||||||
throw new InvalidNameException();
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (!Repository.isValidRefName(name)) {
|
|
||||||
throw new InvalidNameException();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Permission permission : section.getPermissions()) {
|
|
||||||
for (PermissionRule rule : permission.getRules()) {
|
|
||||||
lookupGroup(rule);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
config.replace(section);
|
|
||||||
toDelete.remove(section.getRefPattern());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (String name : toDelete) {
|
for (String name : toDelete) {
|
||||||
if (projectControl.controlForRef(name).isOwner()) {
|
if (AccessSection.GLOBAL_CAPABILITIES.equals(name)) {
|
||||||
|
if (projectControl.isOwner()) {
|
||||||
|
config.remove(config.getAccessSection(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (projectControl.controlForRef(name).isOwner()) {
|
||||||
config.remove(config.getAccessSection(name));
|
config.remove(config.getAccessSection(name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -167,6 +174,17 @@ class ChangeProjectAccess extends Handler<ProjectAccess> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void replace(ProjectConfig config, Set<String> toDelete,
|
||||||
|
AccessSection section) throws NoSuchGroupException {
|
||||||
|
for (Permission permission : section.getPermissions()) {
|
||||||
|
for (PermissionRule rule : permission.getRules()) {
|
||||||
|
lookupGroup(rule);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
config.replace(section);
|
||||||
|
toDelete.remove(section.getName());
|
||||||
|
}
|
||||||
|
|
||||||
private static List<AccessSection> mergeSections(List<AccessSection> src) {
|
private static List<AccessSection> mergeSections(List<AccessSection> src) {
|
||||||
Map<String, AccessSection> map = new LinkedHashMap<String, AccessSection>();
|
Map<String, AccessSection> map = new LinkedHashMap<String, AccessSection>();
|
||||||
for (AccessSection section : src) {
|
for (AccessSection section : src) {
|
||||||
@@ -174,11 +192,11 @@ class ChangeProjectAccess extends Handler<ProjectAccess> {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
AccessSection prior = map.get(section.getRefPattern());
|
AccessSection prior = map.get(section.getName());
|
||||||
if (prior != null) {
|
if (prior != null) {
|
||||||
prior.mergeFrom(section);
|
prior.mergeFrom(section);
|
||||||
} else {
|
} else {
|
||||||
map.put(section.getRefPattern(), section);
|
map.put(section.getName(), section);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new ArrayList<AccessSection>(map.values());
|
return new ArrayList<AccessSection>(map.values());
|
||||||
@@ -187,7 +205,7 @@ class ChangeProjectAccess extends Handler<ProjectAccess> {
|
|||||||
private static Set<String> scanSectionNames(ProjectConfig config) {
|
private static Set<String> scanSectionNames(ProjectConfig config) {
|
||||||
Set<String> names = new HashSet<String>();
|
Set<String> names = new HashSet<String>();
|
||||||
for (AccessSection section : config.getAccessSections()) {
|
for (AccessSection section : config.getAccessSections()) {
|
||||||
names.add(section.getRefPattern());
|
names.add(section.getName());
|
||||||
}
|
}
|
||||||
return names;
|
return names;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -115,46 +115,55 @@ class ProjectAccessFactory extends Handler<ProjectAccess> {
|
|||||||
new HashMap<AccountGroup.UUID, Boolean>();
|
new HashMap<AccountGroup.UUID, Boolean>();
|
||||||
|
|
||||||
for (AccessSection section : config.getAccessSections()) {
|
for (AccessSection section : config.getAccessSections()) {
|
||||||
RefControl rc = pc.controlForRef(section.getRefPattern());
|
String name = section.getName();
|
||||||
if (rc.isOwner()) {
|
if (AccessSection.GLOBAL_CAPABILITIES.equals(name)) {
|
||||||
local.add(section);
|
if (pc.isOwner()) {
|
||||||
ownerOf.add(section.getRefPattern());
|
local.add(section);
|
||||||
|
ownerOf.add(name);
|
||||||
|
}
|
||||||
|
|
||||||
} else if (rc.isVisible()) {
|
} else if (AccessSection.isAccessSection(name)) {
|
||||||
// Filter the section to only add rules describing groups that
|
RefControl rc = pc.controlForRef(name);
|
||||||
// are visible to the current-user. This includes any group the
|
if (rc.isOwner()) {
|
||||||
// user is a member of, as well as groups they own or that
|
local.add(section);
|
||||||
// are visible to all users.
|
ownerOf.add(name);
|
||||||
|
|
||||||
AccessSection dst = null;
|
} else if (rc.isVisible()) {
|
||||||
for (Permission srcPerm : section.getPermissions()) {
|
// Filter the section to only add rules describing groups that
|
||||||
Permission dstPerm = null;
|
// are visible to the current-user. This includes any group the
|
||||||
|
// user is a member of, as well as groups they own or that
|
||||||
|
// are visible to all users.
|
||||||
|
|
||||||
for (PermissionRule srcRule : srcPerm.getRules()) {
|
AccessSection dst = null;
|
||||||
AccountGroup.UUID group = srcRule.getGroup().getUUID();
|
for (Permission srcPerm : section.getPermissions()) {
|
||||||
if (group == null) {
|
Permission dstPerm = null;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Boolean canSeeGroup = visibleGroups.get(group);
|
for (PermissionRule srcRule : srcPerm.getRules()) {
|
||||||
if (canSeeGroup == null) {
|
AccountGroup.UUID group = srcRule.getGroup().getUUID();
|
||||||
try {
|
if (group == null) {
|
||||||
canSeeGroup = groupControlFactory.controlFor(group).isVisible();
|
continue;
|
||||||
} catch (NoSuchGroupException e) {
|
|
||||||
canSeeGroup = Boolean.FALSE;
|
|
||||||
}
|
}
|
||||||
visibleGroups.put(group, canSeeGroup);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (canSeeGroup) {
|
Boolean canSeeGroup = visibleGroups.get(group);
|
||||||
if (dstPerm == null) {
|
if (canSeeGroup == null) {
|
||||||
if (dst == null) {
|
try {
|
||||||
dst = new AccessSection(section.getRefPattern());
|
canSeeGroup = groupControlFactory.controlFor(group).isVisible();
|
||||||
local.add(dst);
|
} catch (NoSuchGroupException e) {
|
||||||
|
canSeeGroup = Boolean.FALSE;
|
||||||
}
|
}
|
||||||
dstPerm = dst.getPermission(srcPerm.getName(), true);
|
visibleGroups.put(group, canSeeGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (canSeeGroup) {
|
||||||
|
if (dstPerm == null) {
|
||||||
|
if (dst == null) {
|
||||||
|
dst = new AccessSection(name);
|
||||||
|
local.add(dst);
|
||||||
|
}
|
||||||
|
dstPerm = dst.getPermission(srcPerm.getName(), true);
|
||||||
|
}
|
||||||
|
dstPerm.add(srcRule);
|
||||||
}
|
}
|
||||||
dstPerm.add(srcRule);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -170,17 +179,22 @@ class ProjectAccessFactory extends Handler<ProjectAccess> {
|
|||||||
|
|
||||||
final ProjectAccess detail = new ProjectAccess();
|
final ProjectAccess detail = new ProjectAccess();
|
||||||
detail.setRevision(config.getRevision().name());
|
detail.setRevision(config.getRevision().name());
|
||||||
detail.setLocal(local);
|
|
||||||
detail.setOwnerOf(ownerOf);
|
|
||||||
|
|
||||||
if (projectName.equals(wildProject)) {
|
if (projectName.equals(wildProject)) {
|
||||||
|
if (pc.isOwner()) {
|
||||||
|
ownerOf.add(AccessSection.GLOBAL_CAPABILITIES);
|
||||||
|
}
|
||||||
detail.setInheritsFrom(null);
|
detail.setInheritsFrom(null);
|
||||||
|
|
||||||
} else if (config.getProject().getParent() != null) {
|
} else if (config.getProject().getParent() != null) {
|
||||||
detail.setInheritsFrom(config.getProject().getParent());
|
detail.setInheritsFrom(config.getProject().getParent());
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
detail.setInheritsFrom(wildProject);
|
detail.setInheritsFrom(wildProject);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
detail.setLocal(local);
|
||||||
|
detail.setOwnerOf(ownerOf);
|
||||||
return detail;
|
return detail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,135 @@
|
|||||||
|
// Copyright (C) 2011 The Android Open Source Project
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package com.google.gerrit.server.account;
|
||||||
|
|
||||||
|
import com.google.gerrit.common.data.AccessSection;
|
||||||
|
import com.google.gerrit.common.data.GlobalCapability;
|
||||||
|
import com.google.gerrit.common.data.Permission;
|
||||||
|
import com.google.gerrit.common.data.PermissionRange;
|
||||||
|
import com.google.gerrit.common.data.PermissionRule;
|
||||||
|
import com.google.gerrit.reviewdb.AccountGroup;
|
||||||
|
import com.google.gerrit.reviewdb.Project;
|
||||||
|
import com.google.gerrit.server.CurrentUser;
|
||||||
|
import com.google.gerrit.server.config.WildProjectName;
|
||||||
|
import com.google.gerrit.server.project.NoSuchProjectException;
|
||||||
|
import com.google.gerrit.server.project.ProjectCache;
|
||||||
|
import com.google.gerrit.server.project.ProjectState;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.Provider;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/** Access control management for server-wide capabilities. */
|
||||||
|
public class CapabilityControl {
|
||||||
|
public static class Factory {
|
||||||
|
private final Project.NameKey wildProject;
|
||||||
|
private final ProjectCache projectCache;
|
||||||
|
private final Provider<CurrentUser> user;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
Factory(@WildProjectName Project.NameKey wp, ProjectCache pc,
|
||||||
|
Provider<CurrentUser> cu) {
|
||||||
|
wildProject = wp;
|
||||||
|
projectCache = pc;
|
||||||
|
user = cu;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CapabilityControl controlFor() throws NoSuchProjectException {
|
||||||
|
final ProjectState p = projectCache.get(wildProject);
|
||||||
|
if (p == null) {
|
||||||
|
throw new NoSuchProjectException(wildProject);
|
||||||
|
}
|
||||||
|
return new CapabilityControl(p, user.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final ProjectState state;
|
||||||
|
private final CurrentUser user;
|
||||||
|
private Map<String, List<PermissionRule>> permissions;
|
||||||
|
|
||||||
|
private CapabilityControl(ProjectState p, CurrentUser currentUser) {
|
||||||
|
state = p;
|
||||||
|
user = currentUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Identity of the user the control will compute for. */
|
||||||
|
public CurrentUser getCurrentUser() {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** True if the user has this permission. Works only for non labels. */
|
||||||
|
public boolean canPerform(String permissionName) {
|
||||||
|
return !access(permissionName).isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The range of permitted values associated with a label permission. */
|
||||||
|
public PermissionRange getRange(String permission) {
|
||||||
|
if (GlobalCapability.hasRange(permission)) {
|
||||||
|
return toRange(permission, access(permission));
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static PermissionRange toRange(String permissionName,
|
||||||
|
List<PermissionRule> ruleList) {
|
||||||
|
int min = 0;
|
||||||
|
int max = 0;
|
||||||
|
for (PermissionRule rule : ruleList) {
|
||||||
|
min = Math.min(min, rule.getMin());
|
||||||
|
max = Math.max(max, rule.getMax());
|
||||||
|
}
|
||||||
|
return new PermissionRange(permissionName, min, max);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Rules for the given permission, or the empty list. */
|
||||||
|
private List<PermissionRule> access(String permissionName) {
|
||||||
|
List<PermissionRule> r = permissions().get(permissionName);
|
||||||
|
return r != null ? r : Collections.<PermissionRule> emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** All rules that pertain to this user. */
|
||||||
|
private Map<String, List<PermissionRule>> permissions() {
|
||||||
|
if (permissions == null) {
|
||||||
|
permissions = new HashMap<String, List<PermissionRule>>();
|
||||||
|
AccessSection section =
|
||||||
|
state.getConfig().getAccessSection(AccessSection.GLOBAL_CAPABILITIES);
|
||||||
|
for (Permission permission : section.getPermissions()) {
|
||||||
|
for (PermissionRule rule : permission.getRules()) {
|
||||||
|
if (matchGroup(rule.getGroup().getUUID())) {
|
||||||
|
if (!rule.getDeny()) {
|
||||||
|
List<PermissionRule> r = permissions.get(permission.getName());
|
||||||
|
if (r == null) {
|
||||||
|
r = new ArrayList<PermissionRule>(2);
|
||||||
|
permissions.put(permission.getName(), r);
|
||||||
|
}
|
||||||
|
r.add(rule);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return permissions;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean matchGroup(AccountGroup.UUID uuid) {
|
||||||
|
Set<AccountGroup.UUID> userGroups = getCurrentUser().getEffectiveGroups();
|
||||||
|
return userGroups.contains(uuid);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,6 +20,7 @@ import com.google.gerrit.reviewdb.ReviewDb;
|
|||||||
import com.google.gerrit.server.IdentifiedUser;
|
import com.google.gerrit.server.IdentifiedUser;
|
||||||
import com.google.gerrit.server.RequestCleanup;
|
import com.google.gerrit.server.RequestCleanup;
|
||||||
import com.google.gerrit.server.account.AccountResolver;
|
import com.google.gerrit.server.account.AccountResolver;
|
||||||
|
import com.google.gerrit.server.account.CapabilityControl;
|
||||||
import com.google.gerrit.server.account.GroupControl;
|
import com.google.gerrit.server.account.GroupControl;
|
||||||
import com.google.gerrit.server.account.PerformCreateGroup;
|
import com.google.gerrit.server.account.PerformCreateGroup;
|
||||||
import com.google.gerrit.server.git.CreateCodeReviewNotes;
|
import com.google.gerrit.server.git.CreateCodeReviewNotes;
|
||||||
@@ -56,6 +57,7 @@ public class GerritRequestModule extends FactoryModule {
|
|||||||
bind(AccountResolver.class);
|
bind(AccountResolver.class);
|
||||||
bind(ChangeQueryRewriter.class);
|
bind(ChangeQueryRewriter.class);
|
||||||
|
|
||||||
|
bind(CapabilityControl.Factory.class).in(SINGLETON);
|
||||||
bind(ChangeControl.Factory.class).in(SINGLETON);
|
bind(ChangeControl.Factory.class).in(SINGLETON);
|
||||||
bind(GroupControl.Factory.class).in(SINGLETON);
|
bind(GroupControl.Factory.class).in(SINGLETON);
|
||||||
bind(ProjectControl.Factory.class).in(SINGLETON);
|
bind(ProjectControl.Factory.class).in(SINGLETON);
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import static com.google.gerrit.common.data.AccessSection.isAccessSection;
|
|||||||
import static com.google.gerrit.common.data.Permission.isPermission;
|
import static com.google.gerrit.common.data.Permission.isPermission;
|
||||||
|
|
||||||
import com.google.gerrit.common.data.AccessSection;
|
import com.google.gerrit.common.data.AccessSection;
|
||||||
|
import com.google.gerrit.common.data.GlobalCapability;
|
||||||
import com.google.gerrit.common.data.GroupReference;
|
import com.google.gerrit.common.data.GroupReference;
|
||||||
import com.google.gerrit.common.data.Permission;
|
import com.google.gerrit.common.data.Permission;
|
||||||
import com.google.gerrit.common.data.PermissionRule;
|
import com.google.gerrit.common.data.PermissionRule;
|
||||||
@@ -54,6 +55,8 @@ public class ProjectConfig extends VersionedMetaData {
|
|||||||
private static final String KEY_INHERIT_FROM = "inheritFrom";
|
private static final String KEY_INHERIT_FROM = "inheritFrom";
|
||||||
private static final String KEY_GROUP_PERMISSIONS = "exclusiveGroupPermissions";
|
private static final String KEY_GROUP_PERMISSIONS = "exclusiveGroupPermissions";
|
||||||
|
|
||||||
|
private static final String CAPABILITY = "capability";
|
||||||
|
|
||||||
private static final String RECEIVE = "receive";
|
private static final String RECEIVE = "receive";
|
||||||
private static final String KEY_REQUIRE_SIGNED_OFF_BY = "requireSignedOffBy";
|
private static final String KEY_REQUIRE_SIGNED_OFF_BY = "requireSignedOffBy";
|
||||||
private static final String KEY_REQUIRE_CHANGE_ID = "requireChangeId";
|
private static final String KEY_REQUIRE_CHANGE_ID = "requireChangeId";
|
||||||
@@ -115,7 +118,7 @@ public class ProjectConfig extends VersionedMetaData {
|
|||||||
|
|
||||||
public void remove(AccessSection section) {
|
public void remove(AccessSection section) {
|
||||||
if (section != null) {
|
if (section != null) {
|
||||||
accessSections.remove(section.getRefPattern());
|
accessSections.remove(section.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,7 +129,7 @@ public class ProjectConfig extends VersionedMetaData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
accessSections.put(section.getRefPattern(), section);
|
accessSections.put(section.getName(), section);
|
||||||
}
|
}
|
||||||
|
|
||||||
public GroupReference resolve(AccountGroup group) {
|
public GroupReference resolve(AccountGroup group) {
|
||||||
@@ -234,38 +237,59 @@ public class ProjectConfig extends VersionedMetaData {
|
|||||||
for (String varName : rc.getNames(ACCESS, refName)) {
|
for (String varName : rc.getNames(ACCESS, refName)) {
|
||||||
if (isPermission(varName)) {
|
if (isPermission(varName)) {
|
||||||
Permission perm = as.getPermission(varName, true);
|
Permission perm = as.getPermission(varName, true);
|
||||||
|
loadPermissionRules(rc, ACCESS, refName, varName, groupsByName,
|
||||||
boolean useRange = perm.isLabel();
|
perm, perm.isLabel());
|
||||||
for (String ruleString : rc.getStringList(ACCESS, refName, varName)) {
|
|
||||||
PermissionRule rule;
|
|
||||||
try {
|
|
||||||
rule = PermissionRule.fromString(ruleString, useRange);
|
|
||||||
} catch (IllegalArgumentException notRule) {
|
|
||||||
error(new ValidationError(PROJECT_CONFIG, "Invalid rule in " + ACCESS
|
|
||||||
+ "." + refName + "." + varName + ": "
|
|
||||||
+ notRule.getMessage()));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
GroupReference ref = groupsByName.get(rule.getGroup().getName());
|
|
||||||
if (ref == null) {
|
|
||||||
// The group wasn't mentioned in the groups table, so there is
|
|
||||||
// no valid UUID for it. Pool the reference anyway so at least
|
|
||||||
// all rules in the same file share the same GroupReference.
|
|
||||||
//
|
|
||||||
ref = rule.getGroup();
|
|
||||||
groupsByName.put(ref.getName(), ref);
|
|
||||||
error(new ValidationError(PROJECT_CONFIG, "group \""
|
|
||||||
+ rule.getGroup().getName() + "\" not in " + GROUP_LIST));
|
|
||||||
}
|
|
||||||
|
|
||||||
rule.setGroup(ref);
|
|
||||||
perm.add(rule);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AccessSection capability = null;
|
||||||
|
for (String varName : rc.getNames(CAPABILITY)) {
|
||||||
|
if (GlobalCapability.isCapability(varName)) {
|
||||||
|
if (capability == null) {
|
||||||
|
capability = new AccessSection(AccessSection.GLOBAL_CAPABILITIES);
|
||||||
|
accessSections.put(AccessSection.GLOBAL_CAPABILITIES, capability);
|
||||||
|
}
|
||||||
|
Permission perm = capability.getPermission(varName, true);
|
||||||
|
loadPermissionRules(rc, CAPABILITY, null, varName, groupsByName, perm,
|
||||||
|
GlobalCapability.hasRange(varName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadPermissionRules(Config rc, String section,
|
||||||
|
String subsection, String varName,
|
||||||
|
Map<String, GroupReference> groupsByName, Permission perm,
|
||||||
|
boolean useRange) {
|
||||||
|
for (String ruleString : rc.getStringList(section, subsection, varName)) {
|
||||||
|
PermissionRule rule;
|
||||||
|
try {
|
||||||
|
rule = PermissionRule.fromString(ruleString, useRange);
|
||||||
|
} catch (IllegalArgumentException notRule) {
|
||||||
|
error(new ValidationError(PROJECT_CONFIG, "Invalid rule in "
|
||||||
|
+ section
|
||||||
|
+ (subsection != null ? "." + subsection : "")
|
||||||
|
+ "." + varName + ": "
|
||||||
|
+ notRule.getMessage()));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
GroupReference ref = groupsByName.get(rule.getGroup().getName());
|
||||||
|
if (ref == null) {
|
||||||
|
// The group wasn't mentioned in the groups table, so there is
|
||||||
|
// no valid UUID for it. Pool the reference anyway so at least
|
||||||
|
// all rules in the same file share the same GroupReference.
|
||||||
|
//
|
||||||
|
ref = rule.getGroup();
|
||||||
|
groupsByName.put(ref.getName(), ref);
|
||||||
|
error(new ValidationError(PROJECT_CONFIG,
|
||||||
|
"group \"" + ref.getName() + "\" not in " + GROUP_LIST));
|
||||||
|
}
|
||||||
|
|
||||||
|
rule.setGroup(ref);
|
||||||
|
perm.add(rule);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, GroupReference> readGroupList() throws IOException {
|
private Map<String, GroupReference> readGroupList() throws IOException {
|
||||||
@@ -321,8 +345,38 @@ public class ProjectConfig extends VersionedMetaData {
|
|||||||
set(rc, SUBMIT, null, KEY_MERGE_CONTENT, p.isUseContentMerge());
|
set(rc, SUBMIT, null, KEY_MERGE_CONTENT, p.isUseContentMerge());
|
||||||
|
|
||||||
Set<AccountGroup.UUID> keepGroups = new HashSet<AccountGroup.UUID>();
|
Set<AccountGroup.UUID> keepGroups = new HashSet<AccountGroup.UUID>();
|
||||||
|
AccessSection capability = accessSections.get(AccessSection.GLOBAL_CAPABILITIES);
|
||||||
|
if (capability != null) {
|
||||||
|
Set<String> have = new HashSet<String>();
|
||||||
|
for (Permission permission : sort(capability.getPermissions())) {
|
||||||
|
have.add(permission.getName().toLowerCase());
|
||||||
|
|
||||||
|
boolean needRange = GlobalCapability.hasRange(permission.getName());
|
||||||
|
List<String> rules = new ArrayList<String>();
|
||||||
|
for (PermissionRule rule : sort(permission.getRules())) {
|
||||||
|
GroupReference group = rule.getGroup();
|
||||||
|
if (group.getUUID() != null) {
|
||||||
|
keepGroups.add(group.getUUID());
|
||||||
|
}
|
||||||
|
rules.add(rule.asString(needRange));
|
||||||
|
}
|
||||||
|
rc.setStringList(CAPABILITY, null, permission.getName(), rules);
|
||||||
|
}
|
||||||
|
for (String varName : rc.getNames(CAPABILITY)) {
|
||||||
|
if (GlobalCapability.isCapability(varName)
|
||||||
|
&& !have.contains(varName.toLowerCase())) {
|
||||||
|
rc.unset(CAPABILITY, null, varName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rc.unsetSection(CAPABILITY, null);
|
||||||
|
}
|
||||||
|
|
||||||
for (AccessSection as : sort(accessSections.values())) {
|
for (AccessSection as : sort(accessSections.values())) {
|
||||||
String refName = as.getRefPattern();
|
String refName = as.getName();
|
||||||
|
if (AccessSection.GLOBAL_CAPABILITIES.equals(refName)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
StringBuilder doNotInherit = new StringBuilder();
|
StringBuilder doNotInherit = new StringBuilder();
|
||||||
for (Permission perm : sort(as.getPermissions())) {
|
for (Permission perm : sort(as.getPermissions())) {
|
||||||
|
|||||||
@@ -234,7 +234,7 @@ public class ProjectControl {
|
|||||||
// that would render this to be false.
|
// that would render this to be false.
|
||||||
//
|
//
|
||||||
if (groups.contains(rule.getGroup().getUUID())
|
if (groups.contains(rule.getGroup().getUUID())
|
||||||
&& controlForRef(section.getRefPattern()).canPerform(permissionName)) {
|
&& controlForRef(section.getName()).canPerform(permissionName)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -267,7 +267,7 @@ public class ProjectControl {
|
|||||||
for (AccessSection section : access()) {
|
for (AccessSection section : access()) {
|
||||||
Permission permission = section.getPermission(permissionName);
|
Permission permission = section.getPermission(permissionName);
|
||||||
if (permission != null) {
|
if (permission != null) {
|
||||||
all.add(section.getRefPattern());
|
all.add(section.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return all;
|
return all;
|
||||||
|
|||||||
@@ -389,7 +389,7 @@ public class RefControl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean appliesToRef(AccessSection section) {
|
private boolean appliesToRef(AccessSection section) {
|
||||||
String refPattern = section.getRefPattern();
|
String refPattern = section.getName();
|
||||||
|
|
||||||
if (isTemplate(refPattern)) {
|
if (isTemplate(refPattern)) {
|
||||||
ParamertizedString template = new ParamertizedString(refPattern);
|
ParamertizedString template = new ParamertizedString(refPattern);
|
||||||
@@ -476,7 +476,7 @@ public class RefControl {
|
|||||||
final AccountGroup.UUID group;
|
final AccountGroup.UUID group;
|
||||||
|
|
||||||
SeenRule(AccessSection section, Permission permission, PermissionRule rule) {
|
SeenRule(AccessSection section, Permission permission, PermissionRule rule) {
|
||||||
refPattern = section.getRefPattern();
|
refPattern = section.getName();
|
||||||
permissionName = permission.getName();
|
permissionName = permission.getName();
|
||||||
group = rule.getGroup().getUUID();
|
group = rule.getGroup().getUUID();
|
||||||
}
|
}
|
||||||
@@ -540,7 +540,7 @@ public class RefControl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int compare(AccessSection a, AccessSection b) {
|
public int compare(AccessSection a, AccessSection b) {
|
||||||
return compare(a.getRefPattern(), b.getRefPattern());
|
return compare(a.getName(), b.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
private int compare(final String pattern1, final String pattern2) {
|
private int compare(final String pattern1, final String pattern2) {
|
||||||
|
|||||||
@@ -14,13 +14,17 @@
|
|||||||
|
|
||||||
package com.google.gerrit.server.query.change;
|
package com.google.gerrit.server.query.change;
|
||||||
|
|
||||||
|
import com.google.gerrit.common.data.GlobalCapability;
|
||||||
|
import com.google.gerrit.common.data.PermissionRange;
|
||||||
import com.google.gerrit.reviewdb.Change;
|
import com.google.gerrit.reviewdb.Change;
|
||||||
import com.google.gerrit.reviewdb.PatchSet;
|
import com.google.gerrit.reviewdb.PatchSet;
|
||||||
import com.google.gerrit.reviewdb.ReviewDb;
|
import com.google.gerrit.reviewdb.ReviewDb;
|
||||||
import com.google.gerrit.server.CurrentUser;
|
import com.google.gerrit.server.CurrentUser;
|
||||||
|
import com.google.gerrit.server.account.CapabilityControl;
|
||||||
import com.google.gerrit.server.events.ChangeAttribute;
|
import com.google.gerrit.server.events.ChangeAttribute;
|
||||||
import com.google.gerrit.server.events.EventFactory;
|
import com.google.gerrit.server.events.EventFactory;
|
||||||
import com.google.gerrit.server.events.QueryStats;
|
import com.google.gerrit.server.events.QueryStats;
|
||||||
|
import com.google.gerrit.server.project.NoSuchProjectException;
|
||||||
import com.google.gerrit.server.query.Predicate;
|
import com.google.gerrit.server.query.Predicate;
|
||||||
import com.google.gerrit.server.query.QueryParseException;
|
import com.google.gerrit.server.query.QueryParseException;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
@@ -65,7 +69,7 @@ public class QueryProcessor {
|
|||||||
private final ChangeQueryRewriter queryRewriter;
|
private final ChangeQueryRewriter queryRewriter;
|
||||||
private final Provider<ReviewDb> db;
|
private final Provider<ReviewDb> db;
|
||||||
|
|
||||||
private int defaultLimit = 500;
|
private int defaultLimit;
|
||||||
private OutputFormat outputFormat = OutputFormat.TEXT;
|
private OutputFormat outputFormat = OutputFormat.TEXT;
|
||||||
private boolean includePatchSets;
|
private boolean includePatchSets;
|
||||||
private boolean includeCurrentPatchSet;
|
private boolean includeCurrentPatchSet;
|
||||||
@@ -77,11 +81,19 @@ public class QueryProcessor {
|
|||||||
@Inject
|
@Inject
|
||||||
QueryProcessor(EventFactory eventFactory,
|
QueryProcessor(EventFactory eventFactory,
|
||||||
ChangeQueryBuilder.Factory queryBuilder, CurrentUser currentUser,
|
ChangeQueryBuilder.Factory queryBuilder, CurrentUser currentUser,
|
||||||
ChangeQueryRewriter queryRewriter, Provider<ReviewDb> db) {
|
ChangeQueryRewriter queryRewriter, Provider<ReviewDb> db,
|
||||||
|
CapabilityControl.Factory ctl) throws NoSuchProjectException {
|
||||||
this.eventFactory = eventFactory;
|
this.eventFactory = eventFactory;
|
||||||
this.queryBuilder = queryBuilder.create(currentUser);
|
this.queryBuilder = queryBuilder.create(currentUser);
|
||||||
this.queryRewriter = queryRewriter;
|
this.queryRewriter = queryRewriter;
|
||||||
this.db = db;
|
this.db = db;
|
||||||
|
|
||||||
|
PermissionRange range = ctl.controlFor().getRange(GlobalCapability.QUERY_LIMIT);
|
||||||
|
if (range != null) {
|
||||||
|
defaultLimit = range.getMax();
|
||||||
|
} else {
|
||||||
|
defaultLimit = GlobalCapability.getRange(GlobalCapability.QUERY_LIMIT).getDefaultMax();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setIncludePatchSets(boolean on) {
|
public void setIncludePatchSets(boolean on) {
|
||||||
@@ -106,6 +118,13 @@ public class QueryProcessor {
|
|||||||
new BufferedWriter( //
|
new BufferedWriter( //
|
||||||
new OutputStreamWriter(outputStream, "UTF-8")));
|
new OutputStreamWriter(outputStream, "UTF-8")));
|
||||||
try {
|
try {
|
||||||
|
if (defaultLimit == 0) {
|
||||||
|
ErrorMessage m = new ErrorMessage();
|
||||||
|
m.message = "query disabled";
|
||||||
|
show(m);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final QueryStats stats = new QueryStats();
|
final QueryStats stats = new QueryStats();
|
||||||
stats.runTimeMilliseconds = System.currentTimeMillis();
|
stats.runTimeMilliseconds = System.currentTimeMillis();
|
||||||
|
|||||||
@@ -16,7 +16,9 @@ package com.google.gerrit.server.schema;
|
|||||||
|
|
||||||
import com.google.gerrit.common.Version;
|
import com.google.gerrit.common.Version;
|
||||||
import com.google.gerrit.common.data.AccessSection;
|
import com.google.gerrit.common.data.AccessSection;
|
||||||
|
import com.google.gerrit.common.data.GlobalCapability;
|
||||||
import com.google.gerrit.common.data.Permission;
|
import com.google.gerrit.common.data.Permission;
|
||||||
|
import com.google.gerrit.common.data.PermissionRange;
|
||||||
import com.google.gerrit.common.data.PermissionRule;
|
import com.google.gerrit.common.data.PermissionRule;
|
||||||
import com.google.gerrit.reviewdb.AccountGroup;
|
import com.google.gerrit.reviewdb.AccountGroup;
|
||||||
import com.google.gerrit.reviewdb.AccountGroupName;
|
import com.google.gerrit.reviewdb.AccountGroupName;
|
||||||
@@ -235,6 +237,11 @@ public class SchemaCreator {
|
|||||||
p.setDescription("Rights inherited by all other projects");
|
p.setDescription("Rights inherited by all other projects");
|
||||||
p.setUseContributorAgreements(false);
|
p.setUseContributorAgreements(false);
|
||||||
|
|
||||||
|
AccessSection capabilities = config.getAccessSection(AccessSection.GLOBAL_CAPABILITIES, true);
|
||||||
|
PermissionRange.WithDefaults queryLimit = GlobalCapability.getRange(GlobalCapability.QUERY_LIMIT);
|
||||||
|
capabilities.getPermission(GlobalCapability.QUERY_LIMIT, true)
|
||||||
|
.add(rule(config, anonymous, queryLimit.getDefaultMax(), queryLimit.getDefaultMax()));
|
||||||
|
|
||||||
AccessSection all = config.getAccessSection(AccessSection.ALL, true);
|
AccessSection all = config.getAccessSection(AccessSection.ALL, true);
|
||||||
AccessSection heads = config.getAccessSection(AccessSection.HEADS, true);
|
AccessSection heads = config.getAccessSection(AccessSection.HEADS, true);
|
||||||
AccessSection meta = config.getAccessSection(GitRepositoryManager.REF_CONFIG, true);
|
AccessSection meta = config.getAccessSection(GitRepositoryManager.REF_CONFIG, true);
|
||||||
@@ -270,6 +277,13 @@ public class SchemaCreator {
|
|||||||
return new PermissionRule(config.resolve(group));
|
return new PermissionRule(config.resolve(group));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private PermissionRule rule(ProjectConfig config, AccountGroup group,
|
||||||
|
int min, int max) {
|
||||||
|
PermissionRule rule = new PermissionRule(config.resolve(group));
|
||||||
|
rule.setRange(min, max);
|
||||||
|
return rule;
|
||||||
|
}
|
||||||
|
|
||||||
private void initVerifiedCategory(final ReviewDb c) throws OrmException {
|
private void initVerifiedCategory(final ReviewDb c) throws OrmException {
|
||||||
final ApprovalCategory cat;
|
final ApprovalCategory cat;
|
||||||
final ArrayList<ApprovalCategoryValue> vals;
|
final ArrayList<ApprovalCategoryValue> vals;
|
||||||
|
|||||||
Reference in New Issue
Block a user