RefPatternMatcher: Pass in CurrentUser instead of username

This will allow us to expand more user-specific parameters then just
${username}, e.g. we may want to expand ${userid} to the sharded
account ID so that we can assign each user permissions on its own user
branch in the All-Users repository.

Change-Id: I003d5d3b247f3fb2f4613e368cd37f1afb7616e5
Signed-off-by: Edwin Kempin <ekempin@google.com>
This commit is contained in:
Edwin Kempin
2016-05-02 15:27:01 +02:00
parent 0940e12e38
commit 60a0c991ca
5 changed files with 53 additions and 51 deletions

View File

@@ -413,7 +413,7 @@ public class ChangeControl {
private boolean match(String destBranch, String refPattern) {
return RefPatternMatcher.getMatcher(refPattern).match(destBranch,
getUser().getUserName());
getUser());
}
private ChangeData changeData(ReviewDb db, @Nullable ChangeData cd) {

View File

@@ -26,12 +26,11 @@ 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.gerrit.server.CurrentUser;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -65,22 +64,21 @@ public class PermissionCollection {
* priority order (project specific definitions must appear before
* inherited ones).
* @param ref reference being accessed.
* @param usernameProvider if the reference is a per-user reference, access
* sections using the parameter variable "${username}" will first
* have each of {@code usernames} inserted into them before seeing if
* they apply to the reference named by {@code ref}.
* @param user if the reference is a per-user reference, e.g. access
* sections using the parameter variable "${username}" will have
* each username inserted into them to see if they apply to the
* reference named by {@code ref}.
* @return map of permissions that apply to this reference, keyed by
* permission name.
*/
PermissionCollection filter(Iterable<SectionMatcher> matcherList,
String ref, Provider<? extends Collection<String>> usernameProvider) {
String ref, CurrentUser user) {
if (isRE(ref)) {
ref = RefControl.shortestExample(ref);
} else if (ref.endsWith("/*")) {
ref = ref.substring(0, ref.length() - 1);
}
Collection<String> usernames = null;
boolean perUser = false;
Map<AccessSection, Project.NameKey> sectionToProject = new LinkedHashMap<>();
for (SectionMatcher sm : matcherList) {
@@ -101,14 +99,9 @@ public class PermissionCollection {
continue;
}
perUser = true;
if (usernames == null) {
usernames = usernameProvider.get();
}
for (String username : usernames) {
if (sm.match(ref, username)) {
sectionToProject.put(sm.section, sm.project);
break;
}
if (sm.match(ref, user)) {
sectionToProject.put(sm.section, sm.project);
break;
}
} else if (sm.match(ref, null)) {
sectionToProject.put(sm.section, sm.project);

View File

@@ -227,25 +227,8 @@ public class ProjectControl {
}
RefControl ctl = refControls.get(refName);
if (ctl == null) {
Provider<List<String>> usernames = new Provider<List<String>>() {
@Override
public List<String> get() {
List<String> r;
if (user.isIdentifiedUser()) {
Set<String> emails = user.asIdentifiedUser().getEmailAddresses();
r = new ArrayList<>(emails.size() + 1);
r.addAll(emails);
} else {
r = new ArrayList<>(1);
}
if (user.getUserName() != null) {
r.add(user.getUserName());
}
return r;
}
};
PermissionCollection relevant =
permissionFilter.filter(access(), refName, usernames);
permissionFilter.filter(access(), refName, user);
ctl = new RefControl(this, refName, relevant);
refControls.put(refName, ctl);
}

View File

@@ -16,11 +16,15 @@ package com.google.gerrit.server.project;
import static com.google.gerrit.server.project.RefControl.isRE;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.gerrit.common.data.ParameterizedString;
import com.google.gerrit.server.CurrentUser;
import dk.brics.automaton.Automaton;
import java.util.Collections;
import java.util.Set;
import java.util.regex.Pattern;
public abstract class RefPatternMatcher {
@@ -36,7 +40,7 @@ public abstract class RefPatternMatcher {
}
}
public abstract boolean match(String ref, String username);
public abstract boolean match(String ref, CurrentUser user);
private static class Exact extends RefPatternMatcher {
private final String expect;
@@ -46,7 +50,7 @@ public abstract class RefPatternMatcher {
}
@Override
public boolean match(String ref, String username) {
public boolean match(String ref, CurrentUser user) {
return expect.equals(ref);
}
}
@@ -59,7 +63,7 @@ public abstract class RefPatternMatcher {
}
@Override
public boolean match(String ref, String username) {
public boolean match(String ref, CurrentUser user) {
return ref.startsWith(prefix);
}
}
@@ -72,7 +76,7 @@ public abstract class RefPatternMatcher {
}
@Override
public boolean match(String ref, String username) {
public boolean match(String ref, CurrentUser user) {
return pattern.matcher(ref).matches();
}
}
@@ -101,20 +105,41 @@ public abstract class RefPatternMatcher {
}
@Override
public boolean match(String ref, String username) {
if (!ref.startsWith(prefix) || username == null) {
public boolean match(String ref, CurrentUser user) {
if (!ref.startsWith(prefix)) {
return false;
}
String u;
if (isRE(template.getPattern())) {
u = Pattern.quote(username);
} else {
u = username;
}
for (String username : getUsernames(user)) {
String u;
if (isRE(template.getPattern())) {
u = Pattern.quote(username);
} else {
u = username;
}
RefPatternMatcher next = getMatcher(expand(template, u));
return next != null ? next.match(expand(ref, u), username) : false;
RefPatternMatcher next = getMatcher(expand(template, u));
if (next != null && next.match(expand(ref, u), user)) {
return true;
}
}
return false;
}
private Iterable<String> getUsernames(CurrentUser user) {
if (user.isIdentifiedUser()) {
Set<String> emails = user.asIdentifiedUser().getEmailAddresses();
if (user.getUserName() == null) {
return emails;
} else if (emails.isEmpty()) {
return ImmutableSet.of(user.getUserName());
}
Iterables.concat(emails, ImmutableSet.of(user.getUserName()));
}
if (user.getUserName() != null) {
return ImmutableSet.of(user.getUserName());
}
return ImmutableSet.of();
}
boolean matchPrefix(String ref) {

View File

@@ -16,6 +16,7 @@ package com.google.gerrit.server.project;
import com.google.gerrit.common.data.AccessSection;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.CurrentUser;
/**
* Matches an AccessSection against a reference name.
@@ -45,7 +46,7 @@ class SectionMatcher extends RefPatternMatcher {
}
@Override
public boolean match(String ref, String username) {
return this.matcher.match(ref, username);
public boolean match(String ref, CurrentUser user) {
return this.matcher.match(ref, user);
}
}