Merge "Make project and ref for each PermissionRule available to RefControl"

This commit is contained in:
Shawn Pearce
2013-03-07 15:36:12 +00:00
committed by Gerrit Code Review
4 changed files with 89 additions and 22 deletions

View File

@@ -16,10 +16,13 @@ package com.google.gerrit.server.project;
import static com.google.gerrit.server.project.RefControl.isRE;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.gerrit.common.data.AccessSection;
import com.google.gerrit.common.data.Permission;
import com.google.gerrit.common.data.PermissionRule;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.Project;
import com.google.inject.Inject;
import com.google.inject.Singleton;
@@ -73,7 +76,7 @@ public class PermissionCollection {
}
boolean perUser = false;
List<AccessSection> sections = new ArrayList<AccessSection>();
Map<AccessSection, Project.NameKey> sectionToProject = Maps.newLinkedHashMap();
for (SectionMatcher matcher : matcherList) {
// If the matcher has to expand parameters and its prefix matches the
// reference there is a very good chance the reference is actually user
@@ -93,9 +96,10 @@ public class PermissionCollection {
}
if (matcher.match(ref, username)) {
sections.add(matcher.section);
sectionToProject.put(matcher.section, matcher.project);
}
}
List<AccessSection> sections = Lists.newArrayList(sectionToProject.keySet());
sorter.sort(ref, sections);
Set<SeenRule> seen = new HashSet<SeenRule>();
@@ -104,7 +108,9 @@ public class PermissionCollection {
HashMap<String, List<PermissionRule>> permissions =
new HashMap<String, List<PermissionRule>>();
Map<PermissionRule, ProjectRef> ruleProps = Maps.newIdentityHashMap();
for (AccessSection section : sections) {
Project.NameKey project = sectionToProject.get(section);
for (Permission permission : section.getPermissions()) {
boolean exclusivePermissionExists =
exclusiveGroupPermissions.contains(permission.getName());
@@ -124,6 +130,7 @@ public class PermissionCollection {
permissions.put(permission.getName(), r);
}
r.add(rule);
ruleProps.put(rule, new ProjectRef(project, section.getName()));
}
}
@@ -133,16 +140,20 @@ public class PermissionCollection {
}
}
return new PermissionCollection(permissions, perUser ? username : null);
return new PermissionCollection(permissions, ruleProps,
perUser ? username : null);
}
}
private final Map<String, List<PermissionRule>> rules;
private final Map<PermissionRule, ProjectRef> ruleProps;
private final String username;
private PermissionCollection(Map<String, List<PermissionRule>> rules,
Map<PermissionRule, ProjectRef> ruleProps,
String username) {
this.rules = rules;
this.ruleProps = ruleProps;
this.username = username;
}
@@ -167,6 +178,10 @@ public class PermissionCollection {
return r != null ? r : Collections.<PermissionRule> emptyList();
}
ProjectRef getRuleProps(PermissionRule rule) {
return ruleProps.get(rule);
}
/**
* Obtain all declared permission rules that match the reference.
*

View File

@@ -0,0 +1,45 @@
// Copyright (C) 2013 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.project;
import com.google.gerrit.reviewdb.client.Project;
class ProjectRef {
final Project.NameKey project;
final String ref;
ProjectRef(Project.NameKey project, String ref) {
this.project = project;
this.ref = ref;
}
@Override
public boolean equals(Object other) {
return other instanceof ProjectRef
&& project.equals(((ProjectRef) other).project)
&& ref.equals(((ProjectRef) other).ref);
}
@Override
public int hashCode() {
return project.hashCode() * 31 + ref.hashCode();
}
@Override
public String toString() {
return project + ", " + ref;
}
}

View File

@@ -212,7 +212,8 @@ public class ProjectState {
section.setPermissions(copy);
}
SectionMatcher matcher = SectionMatcher.wrap(section);
SectionMatcher matcher = SectionMatcher.wrap(getProject().getNameKey(),
section);
if (matcher != null) {
sm.add(matcher);
}
@@ -350,4 +351,4 @@ public class ProjectState {
}
return false;
}
}
}

View File

@@ -18,6 +18,7 @@ import static com.google.gerrit.server.project.RefControl.isRE;
import com.google.gerrit.common.data.AccessSection;
import com.google.gerrit.common.data.ParameterizedString;
import com.google.gerrit.reviewdb.client.Project;
import dk.brics.automaton.Automaton;
@@ -31,33 +32,37 @@ import java.util.regex.Pattern;
* faster selection of which sections are relevant to any given input reference.
*/
abstract class SectionMatcher {
static SectionMatcher wrap(AccessSection section) {
static SectionMatcher wrap(Project.NameKey project, AccessSection section) {
String ref = section.getName();
if (AccessSection.isValid(ref)) {
return wrap(ref, section);
return wrap(project, ref, section);
} else {
return null;
}
}
static SectionMatcher wrap(String pattern, AccessSection section) {
static SectionMatcher wrap(Project.NameKey project, String pattern,
AccessSection section) {
if (pattern.contains("${")) {
return new ExpandParameters(pattern, section);
return new ExpandParameters(project, pattern, section);
} else if (isRE(pattern)) {
return new Regexp(pattern, section);
return new Regexp(project, pattern, section);
} else if (pattern.endsWith("/*")) {
return new Prefix(pattern.substring(0, pattern.length() - 1), section);
return new Prefix(project, pattern.substring(0, pattern.length() - 1),
section);
} else {
return new Exact(pattern, section);
return new Exact(project, pattern, section);
}
}
final Project.NameKey project;
final AccessSection section;
SectionMatcher(AccessSection section) {
SectionMatcher(Project.NameKey project, AccessSection section) {
this.project = project;
this.section = section;
}
@@ -66,8 +71,8 @@ abstract class SectionMatcher {
private static class Exact extends SectionMatcher {
private final String expect;
Exact(String name, AccessSection section) {
super(section);
Exact(Project.NameKey project, String name, AccessSection section) {
super(project, section);
expect = name;
}
@@ -80,8 +85,8 @@ abstract class SectionMatcher {
private static class Prefix extends SectionMatcher {
private final String prefix;
Prefix(String pfx, AccessSection section) {
super(section);
Prefix(Project.NameKey project, String pfx, AccessSection section) {
super(project, section);
prefix = pfx;
}
@@ -94,8 +99,8 @@ abstract class SectionMatcher {
private static class Regexp extends SectionMatcher {
private final Pattern pattern;
Regexp(String re, AccessSection section) {
super(section);
Regexp(Project.NameKey project, String re, AccessSection section) {
super(project, section);
pattern = Pattern.compile(re);
}
@@ -109,8 +114,9 @@ abstract class SectionMatcher {
private final ParameterizedString template;
private final String prefix;
ExpandParameters(String pattern, AccessSection section) {
super(section);
ExpandParameters(Project.NameKey project, String pattern,
AccessSection section) {
super(project, section);
template = new ParameterizedString(pattern);
if (isRE(pattern)) {
@@ -141,7 +147,7 @@ abstract class SectionMatcher {
u = username;
}
SectionMatcher next = wrap(
SectionMatcher next = wrap(project,
template.replace(Collections.singletonMap("username", u)),
section);
return next != null ? next.match(ref, username) : false;