Make project and ref for each PermissionRule available to RefControl

This information is important to be able to allow ALLOW rules to
override BLOCK rules if they are defined on the same project. This
will be implemented in a follow-up change.

Change-Id: If22c1f0f8e13735e2e1e6e868e82b0d3617ef616
Signed-off-by: Edwin Kempin <edwin.kempin@sap.com>
Signed-off-by: Sasa Zivkov <sasa.zivkov@sap.com>
This commit is contained in:
Sasa Zivkov
2013-02-04 14:45:41 +01:00
parent d589f463e3
commit 272275343c
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;