Merge "Block inheritance by default on per-branch permissions."
This commit is contained in:
@@ -42,7 +42,9 @@ import com.google.gwtorm.client.OrmException;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
@@ -126,19 +128,31 @@ final class PatchSetPublishDetailFactory extends Handler<PatchSetPublishDetail>
|
||||
private void computeAllowed() {
|
||||
final Set<AccountGroup.Id> am = user.getEffectiveGroups();
|
||||
final ProjectState pe = projectCache.get(change.getProject());
|
||||
computeAllowed(am, pe.getLocalRights());
|
||||
computeAllowed(am, pe.getInheritedRights());
|
||||
List<RefRight> allRights = new ArrayList<RefRight>();
|
||||
allRights.addAll(filterMatching(pe.getLocalRights()));
|
||||
allRights.addAll(filterMatching(pe.getInheritedRights()));
|
||||
Collections.sort(allRights, RefRight.REF_PATTERN_ORDER);
|
||||
allRights = RefControl.filterMostSpecific(allRights);
|
||||
computeAllowed(am, allRights);
|
||||
}
|
||||
|
||||
private List<RefRight> filterMatching(Collection<RefRight> rights) {
|
||||
List<RefRight> result = new ArrayList<RefRight>();
|
||||
for (RefRight right : rights) {
|
||||
if (RefControl.matches(change.getDest().get(), right.getRefPattern())) {
|
||||
result.add(right);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void computeAllowed(final Set<AccountGroup.Id> am,
|
||||
final Collection<RefRight> list) {
|
||||
final List<RefRight> list) {
|
||||
|
||||
for (final RefRight r : list) {
|
||||
if (!am.contains(r.getAccountGroupId())) {
|
||||
continue;
|
||||
}
|
||||
if (!RefControl.matches(change.getDest().get(), r.getRefPattern())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Set<ApprovalCategoryValue.Id> s = allowed.get(r.getApprovalCategoryId());
|
||||
if (s == null) {
|
||||
|
@@ -18,6 +18,8 @@ import com.google.gwtorm.client.Column;
|
||||
import com.google.gwtorm.client.CompoundKey;
|
||||
import com.google.gwtorm.client.StringKey;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
/** Grant to use an {@link ApprovalCategory} in the scope of a git ref. */
|
||||
public final class RefRight {
|
||||
public static class RefPattern extends
|
||||
@@ -146,4 +148,20 @@ public final class RefRight {
|
||||
public void setMaxValue(final short m) {
|
||||
maxValue = m;
|
||||
}
|
||||
|
||||
private static class RefPatternOrder implements Comparator<RefRight> {
|
||||
|
||||
@Override
|
||||
public int compare(RefRight a, RefRight b) {
|
||||
int aLength = a.getRefPattern().length();
|
||||
int bLength = b.getRefPattern().length();
|
||||
if ((bLength - aLength) == 0) {
|
||||
return a.getApprovalCategoryId().get()
|
||||
.compareTo(b.getApprovalCategoryId().get());
|
||||
}
|
||||
return bLength - aLength;
|
||||
}
|
||||
}
|
||||
|
||||
public static final RefPatternOrder REF_PATTERN_ORDER = new RefPatternOrder();
|
||||
}
|
||||
|
@@ -40,6 +40,7 @@ import org.eclipse.jgit.revwalk.RevWalk;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -183,9 +184,19 @@ public class RefControl {
|
||||
private boolean canPerform(ApprovalCategory.Id actionId, short level) {
|
||||
final Set<AccountGroup.Id> groups = getCurrentUser().getEffectiveGroups();
|
||||
int val = Integer.MIN_VALUE;
|
||||
for (final RefRight right : getLocalRights()) {
|
||||
if (right.getApprovalCategoryId().equals(actionId)
|
||||
&& groups.contains(right.getAccountGroupId())) {
|
||||
|
||||
List<RefRight> allRights = new ArrayList<RefRight>();
|
||||
allRights.addAll(getLocalRights(actionId));
|
||||
|
||||
if (actionId.canInheritFromWildProject()) {
|
||||
allRights.addAll(getInheritedRights(actionId));
|
||||
}
|
||||
|
||||
// Sort in descending refPattern length
|
||||
Collections.sort(allRights, RefRight.REF_PATTERN_ORDER);
|
||||
|
||||
for (RefRight right : filterMostSpecific(allRights)) {
|
||||
if (groups.contains(right.getAccountGroupId())) {
|
||||
if (val < 0 && right.getMaxValue() > 0) {
|
||||
// If one of the user's groups had denied them access, but
|
||||
// this group grants them access, prefer the grant over
|
||||
@@ -200,31 +211,50 @@ public class RefControl {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (val == Integer.MIN_VALUE && actionId.canInheritFromWildProject()) {
|
||||
for (final RefRight pr : getInheritedRights()) {
|
||||
if (actionId.equals(pr.getApprovalCategoryId())
|
||||
&& groups.contains(pr.getAccountGroupId())) {
|
||||
val = Math.max(pr.getMaxValue(), val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return val >= level;
|
||||
}
|
||||
|
||||
private Collection<RefRight> getLocalRights() {
|
||||
return filter(projectControl.getProjectState().getLocalRights());
|
||||
public static List<RefRight> filterMostSpecific(List<RefRight> actionRights) {
|
||||
// Grab the first set of RefRight which have the same refPattern
|
||||
// those are the most specific RefRights we have, and are the
|
||||
// we will consider to verify if this action can be performed.
|
||||
// We do this so that one can override the ref rights for a specific
|
||||
// project on a specific branch
|
||||
boolean sameRefPattern = true;
|
||||
List<RefRight> mostSpecific = new ArrayList<RefRight>();
|
||||
String currentRefPattern = null;
|
||||
int i = 0;
|
||||
while (sameRefPattern && i < actionRights.size()) {
|
||||
if (currentRefPattern == null) {
|
||||
currentRefPattern = actionRights.get(i).getRefPattern();
|
||||
mostSpecific.add(actionRights.get(i));
|
||||
i++;
|
||||
} else {
|
||||
if (currentRefPattern.equals(actionRights.get(i).getRefPattern())) {
|
||||
mostSpecific.add(actionRights.get(i));
|
||||
i++;
|
||||
} else {
|
||||
sameRefPattern = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return mostSpecific;
|
||||
}
|
||||
|
||||
private Collection<RefRight> getInheritedRights() {
|
||||
return filter(projectControl.getProjectState().getInheritedRights());
|
||||
private List<RefRight> getLocalRights(ApprovalCategory.Id actionId) {
|
||||
return filter(projectControl.getProjectState().getLocalRights(), actionId);
|
||||
}
|
||||
|
||||
private Collection<RefRight> filter(Collection<RefRight> all) {
|
||||
private List<RefRight> getInheritedRights(ApprovalCategory.Id actionId) {
|
||||
return filter(projectControl.getProjectState().getInheritedRights(), actionId);
|
||||
}
|
||||
|
||||
private List<RefRight> filter(Collection<RefRight> all,
|
||||
ApprovalCategory.Id actionId) {
|
||||
List<RefRight> mine = new ArrayList<RefRight>(all.size());
|
||||
for (RefRight right : all) {
|
||||
if (matches(getRefName(), right.getRefPattern())) {
|
||||
if (matches(getRefName(), right.getRefPattern()) &&
|
||||
right.getApprovalCategoryId().equals(actionId)) {
|
||||
mine.add(right);
|
||||
}
|
||||
}
|
||||
|
@@ -58,10 +58,10 @@ public class FunctionState {
|
||||
new HashMap<ApprovalCategory.Id, Boolean>();
|
||||
private final Change change;
|
||||
private final ProjectState project;
|
||||
private final Map<ApprovalCategory.Id, Collection<RefRight>> allRights =
|
||||
new HashMap<ApprovalCategory.Id, Collection<RefRight>>();
|
||||
private Map<ApprovalCategory.Id, Collection<RefRight>> RefRights;
|
||||
private Map<ApprovalCategory.Id, Collection<RefRight>> inheritedRights;
|
||||
private final Map<ApprovalCategory.Id, List<RefRight>> allRights =
|
||||
new HashMap<ApprovalCategory.Id, List<RefRight>>();
|
||||
private Map<ApprovalCategory.Id, List<RefRight>> refRights;
|
||||
private Map<ApprovalCategory.Id, List<RefRight>> inheritedRights;
|
||||
private Set<PatchSetApproval> modified;
|
||||
|
||||
@Inject
|
||||
@@ -136,53 +136,46 @@ public class FunctionState {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
public Collection<RefRight> getRefRights(final ApprovalType at) {
|
||||
return getRefRights(id(at));
|
||||
}
|
||||
|
||||
public Collection<RefRight> getRefRights(final ApprovalCategory.Id id) {
|
||||
if (RefRights == null) {
|
||||
RefRights = index(project.getLocalRights());
|
||||
private List<RefRight> getRefRights(final ApprovalCategory.Id id) {
|
||||
if (refRights == null) {
|
||||
refRights = index(project.getLocalRights());
|
||||
}
|
||||
final Collection<RefRight> l = RefRights.get(id);
|
||||
return l != null ? l : Collections.<RefRight> emptySet();
|
||||
final List<RefRight> l = refRights.get(id);
|
||||
return l != null ? l : Collections.<RefRight> emptyList();
|
||||
}
|
||||
|
||||
public Collection<RefRight> getWildcardRights(final ApprovalType at) {
|
||||
return getWildcardRights(id(at));
|
||||
}
|
||||
|
||||
public Collection<RefRight> getWildcardRights(final ApprovalCategory.Id id) {
|
||||
private List<RefRight> getWildcardRights(final ApprovalCategory.Id id) {
|
||||
if (inheritedRights == null) {
|
||||
inheritedRights = index(project.getInheritedRights());
|
||||
}
|
||||
final Collection<RefRight> l = inheritedRights.get(id);
|
||||
return l != null ? l : Collections.<RefRight> emptySet();
|
||||
final List<RefRight> l = inheritedRights.get(id);
|
||||
return l != null ? l : Collections.<RefRight> emptyList();
|
||||
}
|
||||
|
||||
public Collection<RefRight> getAllRights(final ApprovalType at) {
|
||||
return getAllRights(id(at));
|
||||
}
|
||||
|
||||
public Collection<RefRight> getAllRights(final ApprovalCategory.Id id) {
|
||||
Collection<RefRight> l = allRights.get(id);
|
||||
public List<RefRight> getAllRights(final ApprovalCategory.Id id) {
|
||||
List<RefRight> l = allRights.get(id);
|
||||
if (l == null) {
|
||||
l = new ArrayList<RefRight>();
|
||||
l.addAll(getRefRights(id));
|
||||
l.addAll(getWildcardRights(id));
|
||||
l = Collections.unmodifiableCollection(l);
|
||||
Collections.sort(l, RefRight.REF_PATTERN_ORDER);
|
||||
l = Collections.unmodifiableList(RefControl.filterMostSpecific(l));
|
||||
allRights.put(id, l);
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
private Map<Id, Collection<RefRight>> index(final Collection<RefRight> rights) {
|
||||
final HashMap<ApprovalCategory.Id, Collection<RefRight>> r;
|
||||
private Map<Id, List<RefRight>> index(final Collection<RefRight> rights) {
|
||||
final HashMap<ApprovalCategory.Id, List<RefRight>> r;
|
||||
|
||||
r = new HashMap<ApprovalCategory.Id, Collection<RefRight>>();
|
||||
r = new HashMap<ApprovalCategory.Id, List<RefRight>>();
|
||||
for (final RefRight pr : rights) {
|
||||
if (RefControl.matches(change.getDest().get(), pr.getRefPattern())) {
|
||||
Collection<RefRight> l = r.get(pr.getApprovalCategoryId());
|
||||
List<RefRight> l = r.get(pr.getApprovalCategoryId());
|
||||
if (l == null) {
|
||||
l = new ArrayList<RefRight>();
|
||||
r.put(pr.getApprovalCategoryId(), l);
|
||||
|
Reference in New Issue
Block a user